1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <limits.h>
14 
15 /* mbedtls lib */
16 #include "mbedtls/md.h"
17 #include "cc_general_defs.h"
18 #include "mbedtls/cmac.h"
19 /* pal */
20 #include "test_pal_mem.h"
21 
22 /* local */
23 #include "run_integration_pal_log.h"
24 #include "run_integration_test.h"
25 #include "run_integration_helper.h"
26 
27 /************************************************************
28  *
29  * static function prototypes
30  *
31  ************************************************************/
32 static RunItError_t runIt_hmac(void);
33 static RunItError_t runIt_cmac(void);
34 static RunItError_t runIt_cmacProfiling(size_t data_len);
35 
36 /************************************************************
37  *
38  * static functions
39  *
40  ************************************************************/
runIt_hmac(void)41 static RunItError_t runIt_hmac(void)
42 {
43     RunItError_t rc = RUNIT_ERROR__OK;
44 
45     static uint8_t hmacTest_Key[] = { 0x15, 0xb2, 0x9a, 0xd8, 0xae, 0x2a, 0xad, 0x73, 0xa7, 0x26, 0x43, 0x50, 0x70, 0xe8, 0xe9, 0xda, 0x9b, 0x47, 0x69, 0xc3, 0xe3, 0xa4, 0xee, 0x99, 0x6e, 0x20, 0x6a, 0x9b, 0x4f, 0x0c, 0x35, 0xca, 0x4f, 0xa2, 0xf7, 0x43, 0xed, 0xf2, 0xc7, 0xcb, 0xa3, 0x1e, 0x94, 0xac, 0x6b, 0xca, 0xc4, 0xc0, 0x82, 0xcf, 0x1c, 0xcb, 0x6c, 0x2f, 0xe0, 0x0d, 0x38, 0x4e, 0x3b, 0x18, 0x05, 0x5f, 0xe0, 0xe0 };
46     static const uint16_t hmacTest_KeySize = sizeof(hmacTest_Key);
47     static uint8_t hmacTest_InputData[] = { 0x99, 0xfd, 0x18, 0xa3, 0x5d, 0x50, 0x81, 0x84, 0xa6, 0xf3, 0x61, 0xc6, 0x7c, 0xd9, 0xb1, 0x0b, 0x4c, 0xd1, 0xd8, 0xb2, 0x46, 0x57, 0x2a, 0x4d, 0x03, 0xb0, 0xae, 0x55, 0x6b, 0x36, 0x24, 0x1d, 0xd6, 0xf0, 0x46, 0x05, 0x71, 0x65, 0x4f, 0xf0, 0xe4, 0xb2, 0xba, 0xf8, 0x31, 0xdb, 0x4c, 0x60, 0xdf, 0x5f, 0x54, 0xc9, 0x59, 0x0f, 0x32, 0xa9, 0x91, 0x1f, 0x16, 0xfa, 0xe8, 0x7e, 0x0a, 0x2f, 0x52 };
48     static const uint32_t hmacTest_InputDataSize = sizeof(hmacTest_InputData);
49     static CCHashResultBuf_t hmacTest_ExpOutData = { 0xE0903CC8, 0x24C89469, 0x71B12528, 0x6DEFD88C, 0xF662C7FC, 0x971C4DD1, 0x5755CB85, 0x8E72FD6F };
50     static const uint32_t hmacTest_ExpOutDataSize = CC_HASH_SHA256_DIGEST_SIZE_IN_BYTES * sizeof(uint8_t);
51 
52     uint8_t *pDataInBuff = NULL;
53     uint8_t *pKey = NULL;
54 
55     RunItPtr dataInBuffPtr;
56     RunItPtr keyPtr;
57 
58     const mbedtls_md_info_t *md_info = NULL;
59     mbedtls_md_context_t ctx;
60     unsigned char hmacOutBuff[64] = { 0 };
61 
62     const char* TEST_NAME = "HMAC";
63     RUNIT_SUB_TEST_START(TEST_NAME);
64 
65     ALLOC_AND_COPY(dataInBuffPtr, pDataInBuff, hmacTest_InputData, hmacTest_InputDataSize);
66     ALLOC_AND_COPY(keyPtr, pKey, hmacTest_Key, hmacTest_KeySize);
67 
68     /***************************************************************************************
69      *
70      *                  Integrated operation
71      *
72      ***************************************************************************************/
73     RUNIT_API_ASSIGNMENT(md_info, mbedtls_md_info_from_string(HashAlgMode2mbedtlsString[CC_HASH_SHA256_mode]));
74     RUNIT_ASSERT(md_info != NULL);
75 
76     RUNIT_ASSERT_WITH_RESULT(mbedtls_md_hmac( md_info,
77                                               pKey,
78                                               hmacTest_KeySize,
79                                               pDataInBuff,
80                                               hmacTest_InputDataSize,
81                                               hmacOutBuff ), CC_OK);
82 
83     RUNIT_ASSERT(memcmp(hmacOutBuff, hmacTest_ExpOutData, hmacTest_ExpOutDataSize) == 0);
84 
85 
86     /***************************************************************************************
87      *
88      *                  Non integrated operation
89      *
90      ***************************************************************************************/
91     memset(hmacOutBuff, 0, 64);
92 
93     RUNIT_API(mbedtls_md_init(&ctx));
94 
95     RUNIT_ASSERT_WITH_RESULT(mbedtls_md_setup(&ctx, md_info, 1), CC_OK); // 1 = HMAC
96 
97     RUNIT_ASSERT_WITH_RESULT(mbedtls_md_hmac_starts(&ctx, pKey, hmacTest_KeySize), CC_OK);
98 
99     RUNIT_ASSERT_WITH_RESULT(mbedtls_md_hmac_update(&ctx, pDataInBuff, hmacTest_InputDataSize), CC_OK);
100 
101     RUNIT_ASSERT_WITH_RESULT(mbedtls_md_hmac_finish(&ctx, hmacOutBuff), CC_OK);
102 
103     RUNIT_ASSERT(memcmp(hmacOutBuff, hmacTest_ExpOutData, hmacTest_ExpOutDataSize) == 0);
104     /***************************************************************************************/
105 
106 bail:
107 
108     FREE_IF_NOT_NULL(dataInBuffPtr);
109     FREE_IF_NOT_NULL(keyPtr);
110 
111     mbedtls_md_free(&ctx);
112 
113     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "MODE[SHA256] KEY[%"PRIu32"b] PLAIN[%"PRIu32"B] ",
114                                    (uint32_t)hmacTest_KeySize * 8, (uint32_t)hmacTest_InputDataSize);
115     return rc;
116 }
117 
118 /**
119  * This test is meant to measure the execution times of the API.
120  * This test doesn't compare the results with expected result.
121  * I uses the return value to verify everything went well.
122  *
123  * @param block1_len
124  * @return
125  */
runIt_cmacProfiling(size_t data_len)126 static RunItError_t runIt_cmacProfiling(size_t data_len)
127 {
128     RunItError_t rc = RUNIT_ERROR__OK;
129 
130     mbedtls_cipher_type_t cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
131     const char *key_string = "2b7e151628aed2a6abf7158809cf4f3c";
132     int keybits = 128;
133 
134     unsigned char *key = NULL;
135     unsigned char *data = NULL;
136     const mbedtls_cipher_info_t *cipher_info = NULL;
137     mbedtls_cipher_context_t *ctx = NULL;
138     unsigned char *output = NULL;
139     char testParam[PARAM_LEN] = { 0 };
140 
141     RunItPtr ketPtr;
142     RunItPtr dataPtr;
143     RunItPtr ctxPtr;
144     RunItPtr outputPtr;
145 
146     const char* TEST_NAME = "CMAC-Profile";
147     RUNIT_SUB_TEST_START(TEST_NAME);
148 
149     ALLOC(ketPtr, key, keybits / 8);
150     ALLOC(dataPtr, data, data_len);
151     ALLOC_STRUCT(mbedtls_cipher_context_t, ctxPtr, ctx);
152     ALLOC(outputPtr, output, MBEDTLS_CIPHER_BLKSIZE_MAX);
153 
154     snprintf(testParam, PARAM_LEN - 1, "%"PRIu32"B", (uint32_t)data_len);
155 
156     /* Convert the test parameters to binary data */
157     runIt_unhexify( key, key_string );
158 
159     /* this is temporary patch */
160     RUNIT_API(mbedtls_cipher_init( ctx ));
161 
162     /* Set up */
163     RUNIT_API_ASSIGNMENT(cipher_info, mbedtls_cipher_info_from_type(cipher_type));
164     RUNIT_ASSERT(cipher_info != NULL);
165 
166     RUNIT_ASSERT_API(mbedtls_cipher_setup(ctx, cipher_info) == 0);
167 
168     RUNIT_ASSERT_API(mbedtls_cipher_cmac_starts(ctx, (const unsigned char* )key, keybits) == 0);
169 
170     RUNIT_ASSERT_API(mbedtls_cipher_cmac_reset(ctx) == 0);
171 
172     /* Multiple partial and complete blocks. A negative length means skip the
173      * update operation */
174     RUNIT_ASSERT_W_PARAM(testParam, mbedtls_cipher_cmac_update(ctx, (unsigned char* )data, data_len) == 0);
175 
176     RUNIT_ASSERT_API(mbedtls_cipher_cmac_finish(ctx, output) == 0);
177 
178 bail:
179 
180     RUNIT_API(mbedtls_cipher_free( ctx ));
181 
182     FREE_IF_NOT_NULL(ketPtr);
183     FREE_IF_NOT_NULL(dataPtr);
184     FREE_IF_NOT_NULL(ctxPtr);
185     FREE_IF_NOT_NULL(outputPtr);
186 
187     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "TYPE[AES_128_ECB] KEY[%"PRIu32"b] PLAIN[%"PRIu32"B] ",
188                                    (uint32_t)keybits, (uint32_t)data_len);
189     return rc;
190 }
191 
runIt_cmac(void)192 static RunItError_t runIt_cmac(void)
193 {
194     RunItError_t rc = RUNIT_ERROR__OK;
195 
196     mbedtls_cipher_type_t cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
197     const char *key_string = "2b7e151628aed2a6abf7158809cf4f3c";
198     int keybits = 128;
199     int block_size = 16;
200     const char *block1_string = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
201     int block1_len = 64;
202     const char *expected_result_string = "51f0bebf7e3b9d92fc49741779363cfe";
203 
204     unsigned char *key = NULL;
205     unsigned char *block1 = NULL;
206     unsigned char *expected_result = NULL;
207     const mbedtls_cipher_info_t *cipher_info = NULL;
208     mbedtls_cipher_context_t *ctx = NULL;
209     unsigned char *output = NULL;
210 
211     RunItPtr ketPtr;
212     RunItPtr block1Ptr;
213     RunItPtr expectedResultPtr;
214     RunItPtr ctxPtr;
215     RunItPtr outputPtr;
216 
217     const char* TEST_NAME = "CMAC";
218     RUNIT_SUB_TEST_START(TEST_NAME);
219 
220     ALLOC(ketPtr, key, keybits / 8);
221     ALLOC(block1Ptr, block1, block1_len);
222     ALLOC(expectedResultPtr, expected_result, block_size);
223     ALLOC_STRUCT(mbedtls_cipher_context_t, ctxPtr, ctx);
224     ALLOC(outputPtr, output, MBEDTLS_CIPHER_BLKSIZE_MAX);
225 
226     /* Convert the test parameters to binary data */
227     runIt_unhexify( key, key_string );
228     runIt_unhexify( block1, block1_string );
229     runIt_unhexify( expected_result, expected_result_string );
230 
231     RUNIT_API(mbedtls_cipher_init( ctx ));
232 
233     /* Set up */
234     RUNIT_API_ASSIGNMENT(cipher_info, mbedtls_cipher_info_from_type(cipher_type));
235     RUNIT_ASSERT(cipher_info != NULL);
236 
237     /*
238      * Non Integrated
239      */
240     RUNIT_ASSERT_API(mbedtls_cipher_setup(ctx, cipher_info) == 0);
241 
242     RUNIT_ASSERT_API(mbedtls_cipher_cmac_starts(ctx, (const unsigned char* )key, keybits) == 0);
243 
244     /* this is temporary patch */
245     RUNIT_ASSERT_API(mbedtls_cipher_cmac_reset(ctx) == 0);
246 
247     /* Multiple partial and complete blocks. A negative length means skip the
248      * update operation */
249     RUNIT_ASSERT_API(mbedtls_cipher_cmac_update(ctx, (unsigned char* )block1, block1_len) == 0);
250 
251     RUNIT_ASSERT_API(mbedtls_cipher_cmac_finish(ctx, output) == 0);
252 
253     RUNIT_PRINT_BUF(output, MBEDTLS_CIPHER_BLKSIZE_MAX, "output");
254     RUNIT_PRINT_BUF(expected_result, MBEDTLS_CIPHER_BLKSIZE_MAX, "expected_result");
255 
256     RUNIT_ASSERT(memcmp(output, expected_result, block_size) == 0);
257 
258     /*
259      * Integrated
260      */
261     memset(output, 0, MBEDTLS_CIPHER_BLKSIZE_MAX);
262 
263     RUNIT_ASSERT_API(mbedtls_cipher_cmac(cipher_info,
264                         key, keybits,
265                         block1, block1_len,
266                         output) == 0);
267 
268     RUNIT_ASSERT(memcmp(output, expected_result, block_size) == 0);
269 
270 bail:
271 
272     RUNIT_API(mbedtls_cipher_free( ctx ));
273 
274     FREE_IF_NOT_NULL(ketPtr);
275     FREE_IF_NOT_NULL(block1Ptr);
276     FREE_IF_NOT_NULL(expectedResultPtr);
277     FREE_IF_NOT_NULL(ctxPtr);
278     FREE_IF_NOT_NULL(outputPtr);
279 
280     RUNIT_SUB_TEST_RESULT_W_PARAMS(TEST_NAME, "TYPE[AES_128_ECB] KEY[%"PRIu32"b] PLAIN[%"PRIu32"B] ",
281                                    (uint32_t)keybits, (uint32_t)block1_len);
282     return rc;
283 }
284 
285 /************************************************************
286  *
287  * public functions
288  *
289  ************************************************************/
runIt_macTest(void)290 RunItError_t runIt_macTest(void)
291 {
292     RunItError_t rc = RUNIT_ERROR__OK;
293 
294     const char* TEST_NAME = "HMAC";
295     RUNIT_TEST_START(TEST_NAME);
296 
297     RUNIT_ASSERT(runIt_hmac() == RUNIT_ERROR__OK);
298     RUNIT_ASSERT(runIt_cmac() == RUNIT_ERROR__OK);
299     RUNIT_ASSERT(runIt_cmacProfiling(16) == RUNIT_ERROR__OK);
300     RUNIT_ASSERT(runIt_cmacProfiling(128) == RUNIT_ERROR__OK);
301     RUNIT_ASSERT(runIt_cmacProfiling(1024) == RUNIT_ERROR__OK);
302     RUNIT_ASSERT(runIt_cmacProfiling(8192) == RUNIT_ERROR__OK);
303     RUNIT_ASSERT(runIt_cmacProfiling(65535) == RUNIT_ERROR__OK);
304 
305 bail:
306 
307     RUNIT_TEST_RESULT(TEST_NAME);
308     return rc;
309 }
310