blob: 43035dcbf7173b0f3361e82430005f3316324378 [file] [log] [blame]
Vernon Mauery9e801a22018-10-12 13:20:49 -07001#include "integrity_algo.hpp"
2
3#include "message_parsers.hpp"
4
Vernon Mauery9b307be2017-11-22 09:28:16 -08005#include <openssl/evp.h>
Tom Joseph77531db2017-01-10 15:44:44 +05306#include <openssl/hmac.h>
7#include <openssl/sha.h>
Tom Joseph77531db2017-01-10 15:44:44 +05308
9namespace cipher
10{
11
12namespace integrity
13{
14
Vernon Mauery9e801a22018-10-12 13:20:49 -070015AlgoSHA1::AlgoSHA1(const std::vector<uint8_t>& sik) :
16 Interface(SHA1_96_AUTHCODE_LENGTH)
Tom Joseph77531db2017-01-10 15:44:44 +053017{
Vernon Mauery9b307be2017-11-22 09:28:16 -080018 k1 = generateKn(sik, rmcp::const_1);
Tom Joseph77531db2017-01-10 15:44:44 +053019}
20
Vernon Mauery70fd29c2017-11-30 13:11:43 -080021std::vector<uint8_t> AlgoSHA1::generateHMAC(const uint8_t* input,
Vernon Mauery9e801a22018-10-12 13:20:49 -070022 const size_t len) const
Tom Josephd212a6d2017-01-10 15:48:40 +053023{
Vernon Mauery70fd29c2017-11-30 13:11:43 -080024 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Josephd212a6d2017-01-10 15:48:40 +053025 unsigned int mdLen = 0;
26
Vernon Mauery9e801a22018-10-12 13:20:49 -070027 if (HMAC(EVP_sha1(), k1.data(), k1.size(), input, len, output.data(),
28 &mdLen) == NULL)
Tom Josephd212a6d2017-01-10 15:48:40 +053029 {
30 throw std::runtime_error("Generating integrity data failed");
31 }
32
33 // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the
34 // AuthCode field length is based on the integrity algorithm. So we are
35 // interested only in the AuthCode field length of the generated Message
36 // digest.
37 output.resize(authCodeLength);
38
39 return output;
40}
41
Vernon Mauery70fd29c2017-11-30 13:11:43 -080042bool AlgoSHA1::verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -070043 const std::vector<uint8_t>& packet, const size_t length,
44 std::vector<uint8_t>::const_iterator integrityData) const
Tom Josephd212a6d2017-01-10 15:48:40 +053045{
Tom Josephd212a6d2017-01-10 15:48:40 +053046 auto output = generateHMAC(
Vernon Mauery9e801a22018-10-12 13:20:49 -070047 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length);
Tom Josephd212a6d2017-01-10 15:48:40 +053048
49 // Verify if the generated integrity data for the packet and the received
50 // integrity data matches.
51 return (std::equal(output.begin(), output.end(), integrityData));
52}
53
Vernon Mauery9e801a22018-10-12 13:20:49 -070054std::vector<uint8_t>
55 AlgoSHA1::generateIntegrityData(const std::vector<uint8_t>& packet) const
Tom Josephd212a6d2017-01-10 15:48:40 +053056{
57 return generateHMAC(
Vernon Mauery9e801a22018-10-12 13:20:49 -070058 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
59 packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
Tom Josephd212a6d2017-01-10 15:48:40 +053060}
61
Vernon Mauery9b307be2017-11-22 09:28:16 -080062std::vector<uint8_t> AlgoSHA1::generateKn(const std::vector<uint8_t>& sik,
Vernon Mauery9e801a22018-10-12 13:20:49 -070063 const rmcp::Const_n& const_n) const
Vernon Mauery9b307be2017-11-22 09:28:16 -080064{
65 unsigned int mdLen = 0;
66 std::vector<uint8_t> Kn(sik.size());
67
68 // Generated Kn for the integrity algorithm with the additional key keyed
69 // with SIK.
Vernon Mauery9e801a22018-10-12 13:20:49 -070070 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const_n.data(), const_n.size(),
71 Kn.data(), &mdLen) == NULL)
Vernon Mauery9b307be2017-11-22 09:28:16 -080072 {
73 throw std::runtime_error("Generating KeyN for integrity "
74 "algorithm failed");
75 }
76 return Kn;
77}
78
Vernon Mauery9e801a22018-10-12 13:20:49 -070079AlgoSHA256::AlgoSHA256(const std::vector<uint8_t>& sik) :
80 Interface(SHA256_128_AUTHCODE_LENGTH)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080081{
82 k1 = generateKn(sik, rmcp::const_1);
83}
84
85std::vector<uint8_t> AlgoSHA256::generateHMAC(const uint8_t* input,
Vernon Mauery9e801a22018-10-12 13:20:49 -070086 const size_t len) const
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080087{
88 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
89 unsigned int mdLen = 0;
90
Vernon Mauery9e801a22018-10-12 13:20:49 -070091 if (HMAC(EVP_sha256(), k1.data(), k1.size(), input, len, output.data(),
92 &mdLen) == NULL)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080093 {
94 throw std::runtime_error("Generating HMAC_SHA256_128 failed");
95 }
96
97 // HMAC generates Message Digest to the size of SHA256_DIGEST_LENGTH, the
98 // AuthCode field length is based on the integrity algorithm. So we are
99 // interested only in the AuthCode field length of the generated Message
100 // digest.
101 output.resize(authCodeLength);
102
103 return output;
104}
105
106bool AlgoSHA256::verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700107 const std::vector<uint8_t>& packet, const size_t length,
108 std::vector<uint8_t>::const_iterator integrityData) const
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800109{
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800110 auto output = generateHMAC(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700111 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800112
113 // Verify if the generated integrity data for the packet and the received
114 // integrity data matches.
115 return (std::equal(output.begin(), output.end(), integrityData));
116}
117
Vernon Mauery9e801a22018-10-12 13:20:49 -0700118std::vector<uint8_t>
119 AlgoSHA256::generateIntegrityData(const std::vector<uint8_t>& packet) const
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800120{
121 return generateHMAC(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
123 packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800124}
125
126std::vector<uint8_t> AlgoSHA256::generateKn(const std::vector<uint8_t>& sik,
Vernon Mauery9e801a22018-10-12 13:20:49 -0700127 const rmcp::Const_n& const_n) const
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800128{
129 unsigned int mdLen = 0;
130 std::vector<uint8_t> Kn(sik.size());
131
132 // Generated Kn for the integrity algorithm with the additional key keyed
133 // with SIK.
134 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const_n.data(),
135 const_n.size(), Kn.data(), &mdLen) == NULL)
136 {
137 throw std::runtime_error("Generating KeyN for integrity "
138 "algorithm HMAC_SHA256 failed");
139 }
140 return Kn;
141}
142
Vernon Mauery9e801a22018-10-12 13:20:49 -0700143} // namespace integrity
Tom Joseph77531db2017-01-10 15:44:44 +0530144
Vernon Mauery9e801a22018-10-12 13:20:49 -0700145} // namespace cipher