blob: 402a22f4bfa9f85d2148a5f66248b1d74605489f [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
11#include <iostream>
12#include <vector>
13
Tom Joseph1e5a76a2017-01-30 19:25:06 +053014#include <gtest/gtest.h>
15
16TEST(IntegrityAlgo, HMAC_SHA1_96_GenerateIntegrityDataCheck)
17{
18 /*
19 * Step-1 Generate Integrity Data for the packet, using the implemented API
20 */
21 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -070022 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053023
24 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -070025 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
26 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053027
28 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
29
30 ASSERT_EQ(true, (algoPtr != NULL));
31
32 // Generate the Integrity Data
33 auto response = algoPtr->generateIntegrityData(packet);
34
35 EXPECT_EQ(true, (response.size() ==
Vernon Mauery9e801a22018-10-12 13:20:49 -070036 cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH));
Tom Joseph1e5a76a2017-01-30 19:25:06 +053037
38 /*
39 * Step-2 Generate Integrity data using OpenSSL SHA1 algorithm
40 */
Vernon Mauery9b307be2017-11-22 09:28:16 -080041 std::vector<uint8_t> k1(SHA_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -070042 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
43 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
44 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053045
46 // Generated K1 for the integrity algorithm with the additional key keyed
47 // with SIK.
48 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -070049 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
50 k1.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +053051 {
52 FAIL() << "Generating Key1 failed";
53 }
54
55 mdLen = 0;
Vernon Mauery70fd29c2017-11-30 13:11:43 -080056 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +053057 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
58
Vernon Mauery9b307be2017-11-22 09:28:16 -080059 if (HMAC(EVP_sha1(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -070060 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Tom Joseph1e5a76a2017-01-30 19:25:06 +053061 output.data(), &mdLen) == NULL)
62 {
63 FAIL() << "Generating integrity data failed";
64 }
65
66 output.resize(cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH);
67
68 /*
69 * Step-3 Check if the integrity data we generated using the implemented API
70 * matches with one generated by OpenSSL SHA1 algorithm.
71 */
72 auto check = std::equal(output.begin(), output.end(), response.begin());
73 EXPECT_EQ(true, check);
74}
75
76TEST(IntegrityAlgo, HMAC_SHA1_96_VerifyIntegrityDataPass)
77{
78 /*
79 * Step-1 Generate Integrity data using OpenSSL SHA1 algorithm
80 */
81
82 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -070083 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053084
85 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -070086 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
87 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053088
Vernon Mauery9b307be2017-11-22 09:28:16 -080089 std::vector<uint8_t> k1(SHA_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -070090 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
91 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
92 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Tom Joseph1e5a76a2017-01-30 19:25:06 +053093
94 // Generated K1 for the integrity algorithm with the additional key keyed
95 // with SIK.
96 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -070097 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
98 k1.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +053099 {
100 FAIL() << "Generating Key1 failed";
101 }
102
103 mdLen = 0;
Vernon Mauery70fd29c2017-11-30 13:11:43 -0800104 std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530105 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
106
Vernon Mauery9b307be2017-11-22 09:28:16 -0800107 if (HMAC(EVP_sha1(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700108 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530109 output.data(), &mdLen) == NULL)
110 {
111 FAIL() << "Generating integrity data failed";
112 }
113
114 output.resize(cipher::integrity::AlgoSHA1::SHA1_96_AUTHCODE_LENGTH);
115
116 /*
117 * Step-2 Insert the integrity data into the packet
118 */
119 auto packetSize = packet.size();
120 packet.insert(packet.end(), output.begin(), output.end());
121
Vernon Mauery9e801a22018-10-12 13:20:49 -0700122 // Point to the integrity data in the packet
123 auto integrityIter = packet.cbegin();
124 std::advance(integrityIter, packetSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530125
Vernon Mauery9e801a22018-10-12 13:20:49 -0700126 /*
127 * Step-3 Invoke the verifyIntegrityData API and validate the response
128 */
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530129
Vernon Mauery9e801a22018-10-12 13:20:49 -0700130 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
131 ASSERT_EQ(true, (algoPtr != NULL));
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530132
Vernon Mauery9e801a22018-10-12 13:20:49 -0700133 auto check = algoPtr->verifyIntegrityData(
134 packet, packetSize - message::parser::RMCP_SESSION_HEADER_SIZE,
135 integrityIter);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530136
Vernon Mauery9e801a22018-10-12 13:20:49 -0700137 EXPECT_EQ(true, check);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530138}
139
140TEST(IntegrityAlgo, HMAC_SHA1_96_VerifyIntegrityDataFail)
141{
142 /*
143 * Step-1 Add hardcoded Integrity data to the packet
144 */
145
146 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700147 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530148
Vernon Mauery9e801a22018-10-12 13:20:49 -0700149 std::vector<uint8_t> integrity = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530150
151 packet.insert(packet.end(), integrity.begin(), integrity.end());
152
153 // Point to the integrity data in the packet
154 auto integrityIter = packet.cbegin();
155 std::advance(integrityIter, packet.size());
156
157 /*
158 * Step-2 Invoke the verifyIntegrityData API and validate the response
159 */
160
161 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700162 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
163 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530164
165 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA1>(sik);
166
167 ASSERT_EQ(true, (algoPtr != NULL));
168
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530169 // Verify the Integrity Data
170 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700171 packet, packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE,
172 integrityIter);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530173
174 EXPECT_EQ(false, check);
175}
176
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800177TEST(IntegrityAlgo, HMAC_SHA256_128_GenerateIntegrityDataCheck)
178{
179 /*
180 * Step-1 Generate Integrity Data for the packet, using the implemented API
181 */
182 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700183 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800184
185 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700186 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
187 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
188 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800189
190 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
191
192 ASSERT_EQ(true, (algoPtr != NULL));
193
194 // Generate the Integrity Data
195 auto response = algoPtr->generateIntegrityData(packet);
196
Vernon Mauery9e801a22018-10-12 13:20:49 -0700197 EXPECT_EQ(true,
198 (response.size() ==
199 cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH));
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800200
201 /*
202 * Step-2 Generate Integrity data using OpenSSL SHA256 algorithm
203 */
204 std::vector<uint8_t> k1(SHA256_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700205 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
206 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
207 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800208
209 // Generated K1 for the integrity algorithm with the additional key keyed
210 // with SIK.
211 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700212 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const1.data(), const1.size(),
213 k1.data(), &mdLen) == NULL)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800214 {
215 FAIL() << "Generating Key1 failed";
216 }
217
218 mdLen = 0;
219 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
220 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
221
222 if (HMAC(EVP_sha256(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700223 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800224 output.data(), &mdLen) == NULL)
225 {
226 FAIL() << "Generating integrity data failed";
227 }
228
229 output.resize(cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH);
230
231 /*
232 * Step-3 Check if the integrity data we generated using the implemented API
233 * matches with one generated by OpenSSL SHA256 algorithm.
234 */
235 auto check = std::equal(output.begin(), output.end(), response.begin());
236 EXPECT_EQ(true, check);
237}
238
239TEST(IntegrityAlgo, HMAC_SHA256_128_VerifyIntegrityDataPass)
240{
241 /*
242 * Step-1 Generate Integrity data using OpenSSL SHA256 algorithm
243 */
244
245 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700246 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800247
248 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700249 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
250 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
251 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800252
253 std::vector<uint8_t> k1(SHA256_DIGEST_LENGTH);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700254 constexpr rmcp::Const_n const1 = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
255 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
256 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800257
258 // Generated K1 for the integrity algorithm with the additional key keyed
259 // with SIK.
260 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700261 if (HMAC(EVP_sha256(), sik.data(), sik.size(), const1.data(), const1.size(),
262 k1.data(), &mdLen) == NULL)
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800263 {
264 FAIL() << "Generating Key1 failed";
265 }
266
267 mdLen = 0;
268 std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
269 size_t length = packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE;
270
271 if (HMAC(EVP_sha256(), k1.data(), k1.size(),
Vernon Mauery9e801a22018-10-12 13:20:49 -0700272 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, length,
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800273 output.data(), &mdLen) == NULL)
274 {
275 FAIL() << "Generating integrity data failed";
276 }
277
278 output.resize(cipher::integrity::AlgoSHA256::SHA256_128_AUTHCODE_LENGTH);
279
280 /*
281 * Step-2 Insert the integrity data into the packet
282 */
283 auto packetSize = packet.size();
284 packet.insert(packet.end(), output.begin(), output.end());
285
286 // Point to the integrity data in the packet
287 auto integrityIter = packet.cbegin();
288 std::advance(integrityIter, packetSize);
289
290 /*
291 * Step-3 Invoke the verifyIntegrityData API and validate the response
292 */
293
294 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
295 ASSERT_EQ(true, (algoPtr != NULL));
296
297 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700298 packet, packetSize - message::parser::RMCP_SESSION_HEADER_SIZE,
299 integrityIter);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800300
301 EXPECT_EQ(true, check);
302}
303
304TEST(IntegrityAlgo, HMAC_SHA256_128_VerifyIntegrityDataFail)
305{
306 /*
307 * Step-1 Add hardcoded Integrity data to the packet
308 */
309
310 // Packet = RMCP Session Header (4 bytes) + Packet (8 bytes)
Vernon Mauery9e801a22018-10-12 13:20:49 -0700311 std::vector<uint8_t> packet = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800312
Vernon Mauery9e801a22018-10-12 13:20:49 -0700313 std::vector<uint8_t> integrity = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800314
315 packet.insert(packet.end(), integrity.begin(), integrity.end());
316
317 // Point to the integrity data in the packet
318 auto integrityIter = packet.cbegin();
319 std::advance(integrityIter, packet.size());
320
321 /*
322 * Step-2 Invoke the verifyIntegrityData API and validate the response
323 */
324
325 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700326 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
327 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
328 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800329
330 auto algoPtr = std::make_unique<cipher::integrity::AlgoSHA256>(sik);
331
332 ASSERT_EQ(true, (algoPtr != NULL));
333
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800334 // Verify the Integrity Data
335 auto check = algoPtr->verifyIntegrityData(
Vernon Mauery9e801a22018-10-12 13:20:49 -0700336 packet, packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE,
337 integrityIter);
Vernon Mauery7e9e2ef2017-11-29 08:36:29 -0800338
339 EXPECT_EQ(false, check);
340}
341
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530342TEST(CryptAlgo, AES_CBC_128_EncryptPayloadValidate)
343{
344 /*
345 * Step-1 Generate the encrypted data using the implemented API for
346 * AES-CBC-128
347 */
Vernon Mauery9e801a22018-10-12 13:20:49 -0700348 std::vector<uint8_t> payload = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530349
350 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700351 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
352 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530353
Vernon Mauery9b307be2017-11-22 09:28:16 -0800354 std::vector<uint8_t> k2(SHA_DIGEST_LENGTH);
355 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700356 constexpr rmcp::Const_n const1 = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
357 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
358 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
Vernon Mauery9b307be2017-11-22 09:28:16 -0800359
360 // Generated K2 for the confidentiality algorithm with the additional key
361 // keyed with SIK.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700362 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
363 k2.data(), &mdLen) == NULL)
Vernon Mauery9b307be2017-11-22 09:28:16 -0800364 {
365 FAIL() << "Generating K2 for confidentiality algorithm failed";
366 }
367
368 auto cryptPtr = std::make_unique<cipher::crypt::AlgoAES128>(k2);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530369
370 ASSERT_EQ(true, (cryptPtr != NULL));
371
372 auto cipher = cryptPtr->encryptPayload(payload);
373
374 /*
375 * Step-2 Decrypt the encrypted payload using OpenSSL EVP_aes_128_cbc()
376 * implementation
377 */
378
Adriana Kobylak584fa882018-09-06 15:52:05 -0500379 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
380 if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k2.data(),
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530381 cipher.data()))
382 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500383 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530384 FAIL() << "EVP_DecryptInit_ex failed for type AES-CBC-128";
385 }
386
Adriana Kobylak584fa882018-09-06 15:52:05 -0500387 EVP_CIPHER_CTX_set_padding(ctx, 0);
Vernon Mauery9e801a22018-10-12 13:20:49 -0700388 std::vector<uint8_t> output(cipher.size() +
389 cipher::crypt::AlgoAES128::AESCBC128BlockSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530390 int outputLen = 0;
391
Vernon Mauery9e801a22018-10-12 13:20:49 -0700392 if (!EVP_DecryptUpdate(
393 ctx, output.data(), &outputLen,
394 cipher.data() + cipher::crypt::AlgoAES128::AESCBC128ConfHeader,
395 cipher.size() - cipher::crypt::AlgoAES128::AESCBC128ConfHeader))
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530396 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500397 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530398 FAIL() << "EVP_DecryptUpdate failed";
399 }
400
401 output.resize(outputLen);
Adriana Kobylak584fa882018-09-06 15:52:05 -0500402 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530403
404 /*
405 * Step -3 Check if the plain payload matches with the decrypted one
406 */
407 auto check = std::equal(payload.begin(), payload.end(), output.begin());
408 EXPECT_EQ(true, check);
409}
410
411TEST(CryptAlgo, AES_CBC_128_DecryptPayloadValidate)
412{
413 /*
414 * Step-1 Encrypt the payload using OpenSSL EVP_aes_128_cbc()
415 * implementation
416 */
417
Vernon Mauery9e801a22018-10-12 13:20:49 -0700418 std::vector<uint8_t> payload = {1, 2, 3, 4, 5, 6, 7, 8,
419 9, 10, 11, 12, 13, 14, 15, 16};
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530420 payload.resize(payload.size() + 1);
421 payload.back() = 0;
422
423 // Hardcoded Session Integrity Key
Vernon Mauery9e801a22018-10-12 13:20:49 -0700424 std::vector<uint8_t> sik = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
425 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
Adriana Kobylak584fa882018-09-06 15:52:05 -0500426 EVP_CIPHER_CTX* ctx;
427 ctx = EVP_CIPHER_CTX_new();
Vernon Mauery9b307be2017-11-22 09:28:16 -0800428 std::vector<uint8_t> k2(SHA_DIGEST_LENGTH);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530429 unsigned int mdLen = 0;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700430 constexpr rmcp::Const_n const1 = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
431 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
432 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
433 std::vector<uint8_t> output(payload.size() +
434 cipher::crypt::AlgoAES128::AESCBC128BlockSize);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530435
436 if (!RAND_bytes(output.data(),
437 cipher::crypt::AlgoAES128::AESCBC128ConfHeader))
438 {
439 FAIL() << "RAND_bytes failed";
440 }
441
442 // Generated K2 for the confidentiality algorithm with the additional key
443 // keyed with SIK.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700444 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const1.data(), const1.size(),
445 k2.data(), &mdLen) == NULL)
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530446 {
447 FAIL() << "Generating K2 for confidentiality algorithm failed";
448 }
449
Adriana Kobylak584fa882018-09-06 15:52:05 -0500450 if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k2.data(),
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530451 output.data()))
452 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500453 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530454 FAIL() << "EVP_EncryptInit_ex failed for type AES-CBC-128";
455 }
456
Adriana Kobylak584fa882018-09-06 15:52:05 -0500457 EVP_CIPHER_CTX_set_padding(ctx, 0);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530458 int outputLen = 0;
459
Vernon Mauery9e801a22018-10-12 13:20:49 -0700460 if (!EVP_EncryptUpdate(
461 ctx, output.data() + cipher::crypt::AlgoAES128::AESCBC128ConfHeader,
462 &outputLen, payload.data(), payload.size()))
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530463 {
Adriana Kobylak584fa882018-09-06 15:52:05 -0500464 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530465 FAIL() << "EVP_EncryptUpdate failed";
466 }
467
468 output.resize(cipher::crypt::AlgoAES128::AESCBC128ConfHeader + outputLen);
Adriana Kobylak584fa882018-09-06 15:52:05 -0500469 EVP_CIPHER_CTX_free(ctx);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530470
471 /*
472 * Step-2 Decrypt the encrypted payload using the implemented API for
473 * AES-CBC-128
474 */
475
Vernon Mauery9b307be2017-11-22 09:28:16 -0800476 auto cryptPtr = std::make_unique<cipher::crypt::AlgoAES128>(k2);
Tom Joseph1e5a76a2017-01-30 19:25:06 +0530477
478 ASSERT_EQ(true, (cryptPtr != NULL));
479
480 auto plain = cryptPtr->decryptPayload(output, 0, output.size());
481
482 /*
483 * Step -3 Check if the plain payload matches with the decrypted one
484 */
485 auto check = std::equal(payload.begin(), payload.end(), plain.begin());
486 EXPECT_EQ(true, check);
487}