blob: 0c3efe83fb81f8319269481e913de599dd27a94b [file] [log] [blame]
Vernon Mauery9b307be2017-11-22 09:28:16 -08001#include <openssl/evp.h>
Tom Joseph77531db2017-01-10 15:44:44 +05302#include <openssl/hmac.h>
3#include <openssl/sha.h>
4#include "integrity_algo.hpp"
5#include "message_parsers.hpp"
6
7namespace cipher
8{
9
10namespace integrity
11{
12
Vernon Mauery9b307be2017-11-22 09:28:16 -080013AlgoSHA1::AlgoSHA1(const std::vector<uint8_t>& sik)
14 : Interface(SHA1_96_AUTHCODE_LENGTH)
Tom Joseph77531db2017-01-10 15:44:44 +053015{
Vernon Mauery9b307be2017-11-22 09:28:16 -080016 k1 = generateKn(sik, rmcp::const_1);
Tom Joseph77531db2017-01-10 15:44:44 +053017}
18
Vernon Mauery70fd29c2017-11-30 13:11:43 -080019std::vector<uint8_t> AlgoSHA1::generateHMAC(const uint8_t* input,
20 const size_t len) const
Tom Josephd212a6d2017-01-10 15:48:40 +053021{
Vernon Mauery70fd29c2017-11-30 13:11:43 -080022 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Josephd212a6d2017-01-10 15:48:40 +053023 unsigned int mdLen = 0;
24
Vernon Mauery9b307be2017-11-22 09:28:16 -080025 if (HMAC(EVP_sha1(), k1.data(), k1.size(), input, len,
Tom Josephd212a6d2017-01-10 15:48:40 +053026 output.data(), &mdLen) == NULL)
27 {
28 throw std::runtime_error("Generating integrity data failed");
29 }
30
31 // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the
32 // AuthCode field length is based on the integrity algorithm. So we are
33 // interested only in the AuthCode field length of the generated Message
34 // digest.
35 output.resize(authCodeLength);
36
37 return output;
38}
39
Vernon Mauery70fd29c2017-11-30 13:11:43 -080040bool AlgoSHA1::verifyIntegrityData(
41 const std::vector<uint8_t>& packet,
42 const size_t length,
43 std::vector<uint8_t>::const_iterator integrityData) const
Tom Josephd212a6d2017-01-10 15:48:40 +053044{
45
46 auto output = generateHMAC(
47 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
48 length);
49
50 // Verify if the generated integrity data for the packet and the received
51 // integrity data matches.
52 return (std::equal(output.begin(), output.end(), integrityData));
53}
54
Vernon Mauery70fd29c2017-11-30 13:11:43 -080055std::vector<uint8_t> AlgoSHA1::generateIntegrityData(
56 const std::vector<uint8_t>& packet) const
Tom Josephd212a6d2017-01-10 15:48:40 +053057{
58 return generateHMAC(
59 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
60 packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
61}
62
Vernon Mauery9b307be2017-11-22 09:28:16 -080063std::vector<uint8_t> AlgoSHA1::generateKn(const std::vector<uint8_t>& sik,
64 const rmcp::Const_n& const_n) const
65{
66 unsigned int mdLen = 0;
67 std::vector<uint8_t> Kn(sik.size());
68
69 // Generated Kn for the integrity algorithm with the additional key keyed
70 // with SIK.
71 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const_n.data(),
72 const_n.size(), Kn.data(), &mdLen) == NULL)
73 {
74 throw std::runtime_error("Generating KeyN for integrity "
75 "algorithm failed");
76 }
77 return Kn;
78}
79
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -080080AlgoSHA256::AlgoSHA256(const std::vector<uint8_t>& sik)
81 : Interface(SHA256_128_AUTHCODE_LENGTH)
82{
83 k1 = generateKn(sik, rmcp::const_1);
84}
85
86std::vector<uint8_t> AlgoSHA256::generateHMAC(const uint8_t* input,
87 const size_t len) const
88{
89 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
90 unsigned int mdLen = 0;
91
92 if (HMAC(EVP_sha256(), k1.data(), k1.size(), input, len,
93 output.data(), &mdLen) == NULL)
94 {
95 throw std::runtime_error("Generating HMAC_SHA256_128 failed");
96 }
97
98 // HMAC generates Message Digest to the size of SHA256_DIGEST_LENGTH, the
99 // AuthCode field length is based on the integrity algorithm. So we are
100 // interested only in the AuthCode field length of the generated Message
101 // digest.
102 output.resize(authCodeLength);
103
104 return output;
105}
106
107bool AlgoSHA256::verifyIntegrityData(
108 const std::vector<uint8_t>& packet,
109 const size_t length,
110 std::vector<uint8_t>::const_iterator integrityData) const
111{
112
113 auto output = generateHMAC(
114 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
115 length);
116
117 // Verify if the generated integrity data for the packet and the received
118 // integrity data matches.
119 return (std::equal(output.begin(), output.end(), integrityData));
120}
121
122std::vector<uint8_t> AlgoSHA256::generateIntegrityData(
123 const std::vector<uint8_t>& packet) const
124{
125 return generateHMAC(
126 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
127 packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
128}
129
130std::vector<uint8_t> AlgoSHA256::generateKn(const std::vector<uint8_t>& sik,
131 const rmcp::Const_n& const_n) const
132{
133 unsigned int mdLen = 0;
134 std::vector<uint8_t> Kn(sik.size());
135
136 // Generated Kn for the integrity algorithm with the additional key keyed
137 // with SIK.
138 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const_n.data(),
139 const_n.size(), Kn.data(), &mdLen) == NULL)
140 {
141 throw std::runtime_error("Generating KeyN for integrity "
142 "algorithm HMAC_SHA256 failed");
143 }
144 return Kn;
145}
146
Tom Joseph77531db2017-01-10 15:44:44 +0530147}// namespace integrity
148
149}// namespace cipher