1 /*
2 * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * References:
9 *
10 * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
11 * CMAC Mode for Authentication
12 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
13 *
14 * - RFC 4493 - The AES-CMAC Algorithm
15 * https://tools.ietf.org/html/rfc4493
16 *
17 * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
18 * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
19 * Algorithm for the Internet Key Exchange Protocol (IKE)
20 * https://tools.ietf.org/html/rfc4615
21 *
22 * Additional test vectors: ISO/IEC 9797-1
23 *
24 */
25
26 #include "mbedtls/build_info.h"
27
28 #if defined(MBEDTLS_CMAC_C) && defined (MBEDTLS_CMAC_ALT)
29
30 #if defined(MBEDTLS_PLATFORM_C)
31 #include "mbedtls/platform.h"
32 #else
33 #include <stdio.h>
34 #define mbedtls_printf printf
35 #define mbedtls_calloc calloc
36 #define mbedtls_free free
37 #endif
38
39
40 #include "cc_pal_types.h"
41 #include "cc_pal_mem.h"
42 #include "cc_pal_abort.h"
43 #include "cc_common.h"
44 #include "aes_driver.h"
45 #include "cc_aes_defs.h"
46 #include "cc_aes_error.h"
47 #include "mbedtls_common.h"
48 #include "mbedtls/cmac.h"
49 #include "mbedtls/memory_buffer_alloc.h"
50
51
52 /**
53 * \brief CMAC control context structure
54 */
55 typedef struct {
56 /** Internal state of the CMAC algorithm */
57 unsigned char state[MBEDTLS_AES_BLOCK_SIZE];
58
59 /** Unprocessed data - either data that was not block aligned and is still
60 * pending to be processed, or the final block */
61 uint8_t unprocessed_block[MBEDTLS_AES_BLOCK_SIZE];
62
63 /** Length of data pending to be processed */
64 uint32_t unprocessed_len;
65 }
66 mbedtls_cmac_control_context_t;
67
68
69 /**
70 * \brief CMAC private context structure
71 */
72 typedef struct {
73 AesContext_t aes_ctx;
74 mbedtls_cmac_control_context_t cmac_ctrl_ctx;
75 }
76 mbedtls_cmac_private_context_t;
77
78 /*
79 * Initialize a context
80 */
cmac_init(AesContext_t * ctx)81 static int cmac_init( AesContext_t *ctx )
82 {
83 if( ctx == NULL )
84 {
85 CC_PAL_LOG_ERR("NULL pointer exception\n");
86 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
87 }
88
89 mbedtls_zeroize_internal(ctx, sizeof(AesContext_t));
90
91 ctx->mode = CIPHER_CMAC;
92 ctx->padType = CRYPTO_PADDING_NONE;
93 ctx->dir = CRYPTO_DIRECTION_ENCRYPT;
94 ctx->inputDataAddrType = DLLI_ADDR;
95 ctx->outputDataAddrType = DLLI_ADDR;
96 ctx->dataBlockType = FIRST_BLOCK;
97
98 return(0);
99 }
100
cmac_setkey(AesContext_t * ctx,const unsigned char * key,unsigned int keybits)101 static int cmac_setkey(AesContext_t *ctx,
102 const unsigned char *key,
103 unsigned int keybits)
104 {
105 if (ctx == NULL || key == NULL) {
106 CC_PAL_LOG_ERR("Null pointer, ctx or key are NULL\n");
107 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
108 }
109
110 switch (keybits) {
111 case 128:
112 ctx->keySizeId = KEY_SIZE_128_BIT;
113 break;
114 case 192:
115 ctx->keySizeId = KEY_SIZE_192_BIT;
116 break;
117 case 256:
118 ctx->keySizeId = KEY_SIZE_256_BIT;
119 break;
120 default:
121 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
122 }
123
124 /* update key information in the context */
125 ctx->cryptoKey = USER_KEY;
126
127 /* Copy user key to context */
128 CC_PalMemCopy(ctx->keyBuf, key, (keybits/8));
129
130 return(0);
131 }
132
133 //***************************************************************************************************//
mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t * ctx,const unsigned char * key,size_t keybits)134 int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits )
135 {
136 int retval;
137 mbedtls_cmac_context_t *cmac_ctx = NULL;
138
139 if( ctx == NULL )
140 {
141 CC_PAL_LOG_ERR("NULL pointer exception\n");
142 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
143 }
144
145 /* Allocated and initialize in the cipher context memory for the CMAC context */
146 cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_private_context_t ) );
147 if( cmac_ctx == NULL ) {
148 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
149 }
150
151 ctx->MBEDTLS_PRIVATE(cmac_ctx) = cmac_ctx;
152 mbedtls_zeroize_internal( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.state,
153 sizeof( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.state ) );
154
155 /* Init */
156 if( ( retval = cmac_init( &((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx ) ) != 0 )
157 {
158 CC_PAL_LOG_ERR(" 'cmac_init' failed with return code %d\n", retval);
159 return( retval );
160 }
161
162 /* Set key */
163 if( ( retval = cmac_setkey( &((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx, key, keybits) ) != 0 )
164 {
165 CC_PAL_LOG_ERR(" 'cmac_setkey' failed with return code %d\n", retval);
166 return( retval );
167 }
168
169 return (0);
170 }
171
mbedtls_cipher_cmac_update(mbedtls_cipher_context_t * ctx,const unsigned char * input,size_t ilen)172 int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen )
173 {
174 mbedtls_cmac_context_t *cmac_ctx = NULL;
175 drvError_t ret = 0;
176 unsigned int block_size;
177 size_t blocks_num;
178 size_t main_chunk_in_bytes = 0;
179 CCBuffInfo_t inBuffInfo;
180 CCBuffInfo_t outBuffInfo;
181
182 if( (ctx == NULL) || (input == NULL) )
183 {
184 CC_PAL_LOG_ERR("NULL pointer exception\n");
185 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
186 }
187
188 if( ctx == NULL || ctx->MBEDTLS_PRIVATE(cipher_info) == NULL || input == NULL ||
189 ctx->MBEDTLS_PRIVATE(cmac_ctx) == NULL )
190 {
191 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
192 }
193
194 cmac_ctx = ctx->MBEDTLS_PRIVATE(cmac_ctx);
195 block_size = ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);
196
197 /* Is there data still to process from the last call, that's greater in
198 * size than a block? */
199 if( (((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len > 0) &&
200 (ilen > (block_size - ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len)) )
201 {
202 CC_PalMemCopy( &((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block[((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len],
203 input,
204 block_size - ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len );
205
206 ret = SetDataBuffersInfo((const uint8_t*)&((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block,
207 block_size,
208 &inBuffInfo,
209 NULL,
210 0,
211 &outBuffInfo);
212 if (ret != 0)
213 {
214 CC_PAL_LOG_ERR("illegal data buffers\n");
215 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
216 }
217
218 ret = ProcessAesDrv(&((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx,
219 &inBuffInfo,
220 &outBuffInfo,
221 block_size);
222
223 if (AES_DRV_OK != ret)
224 {
225 CC_PAL_LOG_ERR("ProcessAesDrv failed with return code %d\n", ret);
226 return MBEDTLS_ERR_CIPHER_AUTH_FAILED;
227 }
228
229 input += (block_size - ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len);
230 ilen -= (block_size - ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len);
231 ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len = 0;
232 }
233
234 /* blocks_num is the number of blocks including any final partial block */
235 blocks_num = ( ilen + block_size - 1 ) / block_size;
236 if ( 1 < blocks_num )
237 {
238 main_chunk_in_bytes = (blocks_num - 1) * block_size;
239
240 ret = SetDataBuffersInfo(input,
241 main_chunk_in_bytes,
242 &inBuffInfo,
243 NULL,
244 0,
245 &outBuffInfo);
246 if (ret != 0)
247 {
248 CC_PAL_LOG_ERR("illegal data buffers\n");
249 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
250 }
251
252 /* Process the input data, excluding any final partial or complete block */
253 ret = ProcessAesDrv(&((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx,
254 &inBuffInfo,
255 &outBuffInfo,
256 main_chunk_in_bytes);
257 if (AES_DRV_OK != ret)
258 {
259 CC_PAL_LOG_ERR("ProcessAesDrv failed with return code %d\n",ret);
260 return MBEDTLS_ERR_CIPHER_AUTH_FAILED;
261 }
262
263 ilen -= main_chunk_in_bytes;
264 input += main_chunk_in_bytes;
265 }
266
267 /* If there is data left over that wasn't aligned to a block */
268 if( ilen > 0 )
269 {
270 CC_PalMemCopy( &((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block[((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len],
271 input,
272 ilen );
273 ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len += ilen;
274 }
275
276 return (0);
277 }
278
mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t * ctx,unsigned char * output)279 int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, unsigned char *output )
280 {
281 mbedtls_cmac_context_t *cmac_ctx = NULL;
282 drvError_t ret = 0;
283 CCBuffInfo_t inBuffInfo;
284 CCBuffInfo_t outBuffInfo;
285
286 if( ctx == NULL || ctx->MBEDTLS_PRIVATE(cipher_info) == NULL || ctx->MBEDTLS_PRIVATE(cmac_ctx) == NULL ||
287 output == NULL )
288 {
289 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
290 }
291
292 cmac_ctx = ctx->MBEDTLS_PRIVATE(cmac_ctx);
293
294 ret = SetDataBuffersInfo((const uint8_t*)&((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block,
295 ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len,
296 &inBuffInfo,
297 NULL,
298 0,
299 &outBuffInfo);
300 if (ret != 0)
301 {
302 CC_PAL_LOG_ERR("illegal data buffers\n");
303 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
304 }
305
306 ret = FinishAesDrv(&((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx,
307 &inBuffInfo,
308 &outBuffInfo,
309 (uint32_t)((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len);
310
311 if (AES_DRV_OK != ret)
312 {
313 CC_PAL_LOG_ERR("FinishAesDrv failed with return code 0x%x\n", ret);
314 return MBEDTLS_ERR_CIPHER_AUTH_FAILED;
315 }
316
317 CC_PalMemCopy(output, ((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx.ivBuf, AES_IV_SIZE);
318
319 mbedtls_zeroize_internal( ctx->MBEDTLS_PRIVATE(cmac_ctx), sizeof( mbedtls_cmac_private_context_t ) );
320
321 return (0);
322 }
323
mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t * ctx)324 int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
325 {
326 mbedtls_cmac_context_t* cmac_ctx = NULL;
327
328 if( ctx == NULL || ctx->MBEDTLS_PRIVATE(cipher_info) == NULL || ctx->MBEDTLS_PRIVATE(cmac_ctx) == NULL )
329 {
330 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
331 }
332
333 cmac_ctx = ctx->MBEDTLS_PRIVATE(cmac_ctx);
334
335 /* Reset the internal state */
336 ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_len = 0;
337 mbedtls_zeroize_internal( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block,
338 sizeof( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.unprocessed_block ) );
339 mbedtls_zeroize_internal( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.state,
340 sizeof( ((mbedtls_cmac_private_context_t*)cmac_ctx)->cmac_ctrl_ctx.state ) );
341
342 /* Zeroize the IV in the context */
343 mbedtls_zeroize_internal( ((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx.ivBuf,
344 sizeof( ((mbedtls_cmac_private_context_t*)cmac_ctx)->aes_ctx.ivBuf ) );
345
346 return( 0 );
347 }
348
mbedtls_cipher_cmac(const mbedtls_cipher_info_t * cipher_info,const unsigned char * key,size_t keylen,const unsigned char * input,size_t ilen,unsigned char * output)349 int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
350 const unsigned char *key, size_t keylen,
351 const unsigned char *input, size_t ilen,
352 unsigned char *output )
353 {
354 mbedtls_cipher_context_t ctx;
355 int ret;
356
357 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
358 {
359 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
360 }
361 if( cipher_info->MBEDTLS_PRIVATE(name) == NULL )
362 {
363 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
364 }
365 mbedtls_cipher_init( &ctx );
366 ret = mbedtls_cipher_setup( &ctx, cipher_info );
367 if( ret != 0 )
368 {
369 goto exit;
370 }
371
372 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
373 if( ret != 0 )
374 {
375 goto exit;
376 }
377
378 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
379 if( ret != 0 )
380 {
381 goto exit;
382 }
383
384 ret = mbedtls_cipher_cmac_finish( &ctx, output );
385
386 exit:
387 mbedtls_cipher_free( &ctx );
388
389 return( ret );
390 }
391
392 #if defined(MBEDTLS_AES_C)
393 /*
394 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
395 */
mbedtls_aes_cmac_prf_128(const unsigned char * key,size_t key_length,const unsigned char * input,size_t in_len,unsigned char * output)396 int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
397 const unsigned char *input, size_t in_len,
398 unsigned char *output )
399 {
400 int ret;
401 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
402 unsigned char zero_key[AES_BLOCK_SIZE];
403 unsigned char int_key[AES_BLOCK_SIZE];
404
405 if( key == NULL || input == NULL || output == NULL )
406 {
407 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
408 }
409
410 if( key_length == AES_BLOCK_SIZE )
411 {
412 /* Use key as is */
413 CC_PalMemCopy( int_key, key, AES_BLOCK_SIZE );
414 }
415 else
416 {
417 memset( zero_key, 0, AES_BLOCK_SIZE );
418
419 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
420 key_length, int_key );
421 if( ret != 0 )
422 goto exit;
423 }
424
425 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
426 output );
427
428 exit:
429 mbedtls_zeroize_internal( int_key, sizeof( int_key ) );
430
431 return( ret );
432 }
433 #endif /* MBEDTLS_AES_C */
434
435 #endif /* defined(MBEDTLS_CMAC_C) && defined (MBEDTLS_CMAC_ALT) */
436