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