blob: 09bd479ed21ff0fabc02191b51c9e8c6c22ee90f [file] [log] [blame]
Tom Joseph1e5a76a2017-01-30 19:25:06 +05301#include "crypt_algo.hpp"
2#include "integrity_algo.hpp"
3#include "message_parsers.hpp"
Vernon Mauery9b307be2017-11-22 09:28:16 -08004#include "rmcp.hpp"
Vernon Mauery9e801a22018-10-12 13:20:49 -07005
6#include <openssl/evp.h>
7#include <openssl/hmac.h>
8#include <openssl/rand.h>
9#include <openssl/sha.h>
10
Vernon Mauery9e801a22018-10-12 13:20:49 -070011#include <vector>
12
Tom Joseph1e5a76a2017-01-30 19:25:06 +053013#include <gtest/gtest.h>
14
15TEST(IntegrityAlgo, HMAC_SHA1_96_GenerateIntegrityDataCheck)
16{
17 /*
18 * Step-1 Generate Integrity Data for the packet, using the implemented API
19 */
20 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -070021 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053022
23 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -070024 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
25 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053026
27 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
28
29 ASSERT_EQ(true, (algoPtr != NULL));
30
31 // Generate the Integrity Data
32 auto response = algoPtr->generateIntegrityData(packet);
33
34 EXPECT_EQ(true, (response.size() ==
Vernon Mauery9e801a22018-10-12 13:20:49 -070035 cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH));
Tom Joseph1e5a76a2017-01-30 19:25:06 +053036
37 /*
38 * Step-2 Generate Integrity data using OpenSSL SHA1 algorithm
39 */
Vernon Mauery9b307be2017-11-22 09:28:16 -080040 std::vector<uint8_t> k1(SHA_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -070041 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
42 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
43 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053044
45 // Generated K1 for the integrity algorithm with the additional key keyed
46 // with SIK.
47 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -070048 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
49 k1.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +053050 {
51 FAIL() << "Generating Key1 failed";
52 }
53
54 mdLen = 0;
Vernon Mauery70fd29c2017-11-30 13:11:43 -080055 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +053056 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
57
Vernon Mauery9b307be2017-11-22 09:28:16 -080058 if (HMAC(EVP_sha1(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -070059 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Tom Joseph1e5a76a2017-01-30 19:25:06 +053060 output.data(), &mdLen) == NULL)
61 {
62 FAIL() << "Generating integrity data failed";
63 }
64
65 output.resize(cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH);
66
67 /*
68 * Step-3 Check if the integrity data we generated using the implemented API
69 * matches with one generated by OpenSSL SHA1 algorithm.
70 */
71 auto check = std::equal(output.begin(), output.end(), response.begin());
72 EXPECT_EQ(true, check);
73}
74
75TEST(IntegrityAlgo, HMAC_SHA1_96_VerifyIntegrityDataPass)
76{
77 /*
78 * Step-1 Generate Integrity data using OpenSSL SHA1 algorithm
79 */
80
81 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -070082 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053083
84 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -070085 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
86 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053087
Vernon Mauery9b307be2017-11-22 09:28:16 -080088 std::vector<uint8_t> k1(SHA_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -070089 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
90 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
91 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053092
93 // Generated K1 for the integrity algorithm with the additional key keyed
94 // with SIK.
95 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -070096 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
97 k1.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +053098 {
99 FAIL() << "Generating Key1 failed";
100 }
101
102 mdLen = 0;
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800103 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530104 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
105
Vernon Mauery9b307be2017-11-22 09:28:16 -0800106 if (HMAC(EVP_sha1(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700107 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530108 output.data(), &mdLen) == NULL)
109 {
110 FAIL() << "Generating integrity data failed";
111 }
112
113 output.resize(cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH);
114
115 /*
116 * Step-2 Insert the integrity data into the packet
117 */
118 auto packetSize = packet.size();
119 packet.insert(packet.end(), output.begin(), output.end());
120
Vernon Mauery9e801a22018-10-12 13:20:49 -0700121 // Point to the integrity data in the packet
122 auto integrityIter = packet.cbegin();
123 std::advance(integrityIter, packetSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530124
Vernon Mauery9e801a22018-10-12 13:20:49 -0700125 /*
126 * Step-3 Invoke the verifyIntegrityData API and validate the response
127 */
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530128
Vernon Mauery9e801a22018-10-12 13:20:49 -0700129 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
130 ASSERT_EQ(true, (algoPtr != NULL));
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530131
Vernon Mauery9e801a22018-10-12 13:20:49 -0700132 auto check = algoPtr->verifyIntegrityData(
133 packet, packetSize - message::parser::RMCP_SESSION_HEADER_SIZE,
134 integrityIter);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530135
Vernon Mauery9e801a22018-10-12 13:20:49 -0700136 EXPECT_EQ(true, check);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530137}
138
139TEST(IntegrityAlgo, HMAC_SHA1_96_VerifyIntegrityDataFail)
140{
141 /*
142 * Step-1 Add hardcoded Integrity data to the packet
143 */
144
145 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700146 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530147
Vernon Mauery9e801a22018-10-12 13:20:49 -0700148 std::vector<uint8_t> integrity = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530149
150 packet.insert(packet.end(), integrity.begin(), integrity.end());
151
152 // Point to the integrity data in the packet
153 auto integrityIter = packet.cbegin();
154 std::advance(integrityIter, packet.size());
155
156 /*
157 * Step-2 Invoke the verifyIntegrityData API and validate the response
158 */
159
160 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700161 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
162 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530163
164 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
165
166 ASSERT_EQ(true, (algoPtr != NULL));
167
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530168 // Verify the Integrity Data
169 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700170 packet, packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE,
171 integrityIter);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530172
173 EXPECT_EQ(false, check);
174}
175
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800176TEST(IntegrityAlgo, HMAC_SHA256_128_GenerateIntegrityDataCheck)
177{
178 /*
179 * Step-1 Generate Integrity Data for the packet, using the implemented API
180 */
181 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700182 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800183
184 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700185 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
186 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
187 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800188
189 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
190
191 ASSERT_EQ(true, (algoPtr != NULL));
192
193 // Generate the Integrity Data
194 auto response = algoPtr->generateIntegrityData(packet);
195
Vernon Mauery9e801a22018-10-12 13:20:49 -0700196 EXPECT_EQ(true,
197 (response.size() ==
198 cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH));
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800199
200 /*
201 * Step-2 Generate Integrity data using OpenSSL SHA256 algorithm
202 */
203 std::vector<uint8_t> k1(SHA256_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
205 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
206 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800207
208 // Generated K1 for the integrity algorithm with the additional key keyed
209 // with SIK.
210 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700211 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const1.data(), const1.size(),
212 k1.data(), &mdLen) == NULL)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800213 {
214 FAIL() << "Generating Key1 failed";
215 }
216
217 mdLen = 0;
218 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
219 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
220
221 if (HMAC(EVP_sha256(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700222 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800223 output.data(), &mdLen) == NULL)
224 {
225 FAIL() << "Generating integrity data failed";
226 }
227
228 output.resize(cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH);
229
230 /*
231 * Step-3 Check if the integrity data we generated using the implemented API
232 * matches with one generated by OpenSSL SHA256 algorithm.
233 */
234 auto check = std::equal(output.begin(), output.end(), response.begin());
235 EXPECT_EQ(true, check);
236}
237
238TEST(IntegrityAlgo, HMAC_SHA256_128_VerifyIntegrityDataPass)
239{
240 /*
241 * Step-1 Generate Integrity data using OpenSSL SHA256 algorithm
242 */
243
244 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700245 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800246
247 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700248 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
249 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
250 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800251
252 std::vector<uint8_t> k1(SHA256_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700253 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
254 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
255 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800256
257 // Generated K1 for the integrity algorithm with the additional key keyed
258 // with SIK.
259 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700260 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const1.data(), const1.size(),
261 k1.data(), &mdLen) == NULL)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800262 {
263 FAIL() << "Generating Key1 failed";
264 }
265
266 mdLen = 0;
267 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
268 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
269
270 if (HMAC(EVP_sha256(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700271 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800272 output.data(), &mdLen) == NULL)
273 {
274 FAIL() << "Generating integrity data failed";
275 }
276
277 output.resize(cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH);
278
279 /*
280 * Step-2 Insert the integrity data into the packet
281 */
282 auto packetSize = packet.size();
283 packet.insert(packet.end(), output.begin(), output.end());
284
285 // Point to the integrity data in the packet
286 auto integrityIter = packet.cbegin();
287 std::advance(integrityIter, packetSize);
288
289 /*
290 * Step-3 Invoke the verifyIntegrityData API and validate the response
291 */
292
293 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
294 ASSERT_EQ(true, (algoPtr != NULL));
295
296 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700297 packet, packetSize - message::parser::RMCP_SESSION_HEADER_SIZE,
298 integrityIter);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800299
300 EXPECT_EQ(true, check);
301}
302
303TEST(IntegrityAlgo, HMAC_SHA256_128_VerifyIntegrityDataFail)
304{
305 /*
306 * Step-1 Add hardcoded Integrity data to the packet
307 */
308
309 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700310 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800311
Vernon Mauery9e801a22018-10-12 13:20:49 -0700312 std::vector<uint8_t> integrity = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800313
314 packet.insert(packet.end(), integrity.begin(), integrity.end());
315
316 // Point to the integrity data in the packet
317 auto integrityIter = packet.cbegin();
318 std::advance(integrityIter, packet.size());
319
320 /*
321 * Step-2 Invoke the verifyIntegrityData API and validate the response
322 */
323
324 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700325 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
326 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
327 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800328
329 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
330
331 ASSERT_EQ(true, (algoPtr != NULL));
332
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800333 // Verify the Integrity Data
334 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700335 packet, packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE,
336 integrityIter);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800337
338 EXPECT_EQ(false, check);
339}
340
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530341TEST(CryptAlgo, AES_CBC_128_EncryptPayloadValidate)
342{
343 /*
344 * Step-1 Generate the encrypted data using the implemented API for
345 * AES-CBC-128
346 */
Vernon Mauery9e801a22018-10-12 13:20:49 -0700347 std::vector<uint8_t> payload = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530348
349 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700350 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
351 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530352
Vernon Mauery9b307be2017-11-22 09:28:16 -0800353 std::vector<uint8_t> k2(SHA_DIGEST_LENGTH);
354 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700355 constexpr rmcp::Const_n const1 = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
356 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
357 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
Vernon Mauery9b307be2017-11-22 09:28:16 -0800358
359 // Generated K2 for the confidentiality algorithm with the additional key
360 // keyed with SIK.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700361 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
362 k2.data(), &mdLen) == NULL)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800363 {
364 FAIL() << "Generating K2 for confidentiality algorithm failed";
365 }
366
367 auto cryptPtr = std::make_unique<cipher::crypt::AlgoAES128>(k2);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530368
369 ASSERT_EQ(true, (cryptPtr != NULL));
370
371 auto cipher = cryptPtr->encryptPayload(payload);
372
373 /*
374 * Step-2 Decrypt the encrypted payload using OpenSSL EVP_aes_128_cbc()
375 * implementation
376 */
377
Adriana Kobylak584fa882018-09-06 15:52:05 -0500378 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
379 if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k2.data(),
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530380 cipher.data()))
381 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500382 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530383 FAIL() << "EVP_DecryptInit_ex failed for type AES-CBC-128";
384 }
385
Adriana Kobylak584fa882018-09-06 15:52:05 -0500386 EVP_CIPHER_CTX_set_padding(ctx, 0);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700387 std::vector<uint8_t> output(cipher.size() +
388 cipher::crypt::AlgoAES128::AESCBC128BlockSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530389 int outputLen = 0;
390
Vernon Mauery9e801a22018-10-12 13:20:49 -0700391 if (!EVP_DecryptUpdate(
392 ctx, output.data(), &outputLen,
393 cipher.data() + cipher::crypt::AlgoAES128::AESCBC128ConfHeader,
394 cipher.size() - cipher::crypt::AlgoAES128::AESCBC128ConfHeader))
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530395 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500396 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530397 FAIL() << "EVP_DecryptUpdate failed";
398 }
399
400 output.resize(outputLen);
Adriana Kobylak584fa882018-09-06 15:52:05 -0500401 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530402
403 /*
404 * Step -3 Check if the plain payload matches with the decrypted one
405 */
406 auto check = std::equal(payload.begin(), payload.end(), output.begin());
407 EXPECT_EQ(true, check);
408}
409
410TEST(CryptAlgo, AES_CBC_128_DecryptPayloadValidate)
411{
412 /*
413 * Step-1 Encrypt the payload using OpenSSL EVP_aes_128_cbc()
414 * implementation
415 */
416
Vernon Mauery9e801a22018-10-12 13:20:49 -0700417 std::vector<uint8_t> payload = {1, 2, 3, 4, 5, 6, 7, 8,
418 9, 10, 11, 12, 13, 14, 15, 16};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530419 payload.resize(payload.size() + 1);
420 payload.back() = 0;
421
422 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700423 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
424 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Adriana Kobylak584fa882018-09-06 15:52:05 -0500425 EVP_CIPHER_CTX* ctx;
426 ctx = EVP_CIPHER_CTX_new();
Vernon Mauery9b307be2017-11-22 09:28:16 -0800427 std::vector<uint8_t> k2(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530428 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700429 constexpr rmcp::Const_n const1 = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
430 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
431 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
432 std::vector<uint8_t> output(payload.size() +
433 cipher::crypt::AlgoAES128::AESCBC128BlockSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530434
435 if (!RAND_bytes(output.data(),
436 cipher::crypt::AlgoAES128::AESCBC128ConfHeader))
437 {
438 FAIL() << "RAND_bytes failed";
439 }
440
441 // Generated K2 for the confidentiality algorithm with the additional key
442 // keyed with SIK.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700443 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
444 k2.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530445 {
446 FAIL() << "Generating K2 for confidentiality algorithm failed";
447 }
448
Adriana Kobylak584fa882018-09-06 15:52:05 -0500449 if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k2.data(),
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530450 output.data()))
451 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500452 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530453 FAIL() << "EVP_EncryptInit_ex failed for type AES-CBC-128";
454 }
455
Adriana Kobylak584fa882018-09-06 15:52:05 -0500456 EVP_CIPHER_CTX_set_padding(ctx, 0);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530457 int outputLen = 0;
458
Vernon Mauery9e801a22018-10-12 13:20:49 -0700459 if (!EVP_EncryptUpdate(
460 ctx, output.data() + cipher::crypt::AlgoAES128::AESCBC128ConfHeader,
461 &outputLen, payload.data(), payload.size()))
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530462 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500463 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530464 FAIL() << "EVP_EncryptUpdate failed";
465 }
466
467 output.resize(cipher::crypt::AlgoAES128::AESCBC128ConfHeader + outputLen);
Adriana Kobylak584fa882018-09-06 15:52:05 -0500468 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530469
470 /*
471 * Step-2 Decrypt the encrypted payload using the implemented API for
472 * AES-CBC-128
473 */
474
Vernon Mauery9b307be2017-11-22 09:28:16 -0800475 auto cryptPtr = std::make_unique<cipher::crypt::AlgoAES128>(k2);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530476
477 ASSERT_EQ(true, (cryptPtr != NULL));
478
479 auto plain = cryptPtr->decryptPayload(output, 0, output.size());
480
481 /*
482 * Step -3 Check if the plain payload matches with the decrypted one
483 */
484 auto check = std::equal(payload.begin(), payload.end(), plain.begin());
485 EXPECT_EQ(true, check);
486}