1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_CC_API
8 
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "cc_pal_abort.h"
12 #include "aesccm_driver.h"
13 #include "cc_common.h"
14 #include "mbedtls_ccm_internal.h"
15 #include "mbedtls_ccm_common.h"
16 #include "mbedtls_common.h"
17 #include "cc_aesccm_error.h"
18 
19 /************************ Type definitions **********************/
20 
21 /* AES-CCM* Security levels (ieee-802.15.4-2011, Table 58) */
22 #define AESCCM_STAR_SECURITY_LEVEL_ENC          4
23 #define AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_32   5
24 #define AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_64   6
25 #define AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_128  7
26 
27 /************************ Type definitions **********************/
28 
29 
30 /************************ static functions **********************/
ccm_init(mbedtls_ccm_context * ctx,cryptoDirection_t encryptDecryptFlag,size_t assocDataSize,size_t textDataSize,const uint8_t * pNonce,uint8_t sizeOfN,uint8_t sizeOfT,uint32_t ccmMode)31 static int ccm_init(mbedtls_ccm_context *ctx,
32                     cryptoDirection_t encryptDecryptFlag,
33                     size_t assocDataSize,
34                     size_t textDataSize,
35                     const uint8_t *pNonce,
36                     uint8_t sizeOfN,
37                     uint8_t sizeOfT,
38                     uint32_t ccmMode)
39 {
40 
41     AesCcmContext_t *pAesCcmCtx = NULL;
42     uint8_t ctrStateBuf[CC_AES_BLOCK_SIZE_IN_BYTES] = { 0 };
43     uint8_t qFieldSize = 15 - sizeOfN;
44     uint8_t *tempBuff;
45     drvError_t rc;
46     CCBuffInfo_t inBuffInfo;
47     CCBuffInfo_t outBuffInfo;
48     uint8_t securityLevelField = 0;
49 
50     /* check the Encrypt / Decrypt flag validity */
51     if (encryptDecryptFlag >= CRYPTO_DIRECTION_NUM_OF_ENC_MODES)
52     {
53         return MBEDTLS_ERR_CCM_BAD_INPUT;
54     }
55 
56     /* check Nonce pointer */
57     if (pNonce == NULL)
58     {
59         return MBEDTLS_ERR_CCM_BAD_INPUT;
60     }
61 
62     if (ccmMode == MBEDTLS_AESCCM_MODE_CCM) {
63         /* check CCM MAC size: [4,6,8,10,12,14,16] */
64         if ((sizeOfT < 4) || (sizeOfT > 16) || ((sizeOfT & 1) != 0)) {
65             return MBEDTLS_ERR_CCM_BAD_INPUT;
66         }
67     }
68     else if (ccmMode == MBEDTLS_AESCCM_MODE_STAR) {
69         /* check CCM STAR MAC size */
70         if (mbedtls_ccm_get_security_level(sizeOfT, &securityLevelField) != CC_OK) {
71             return MBEDTLS_ERR_CCM_BAD_INPUT;
72         }
73 
74         /* check CCM STAR Nonce size. sizeOfN == 13 */
75         if (sizeOfN != MBEDTLS_AESCCM_STAR_NONCE_SIZE_BYTES) {
76             return MBEDTLS_ERR_CCM_BAD_INPUT;
77         }
78 
79         /* check CCM STAR Security level field */
80         if (pNonce[MBEDTLS_AESCCM_STAR_NONCE_SIZE_BYTES - 1] != securityLevelField) {
81             return MBEDTLS_ERR_CCM_BAD_INPUT;
82         }
83     }
84     else {
85         return MBEDTLS_ERR_CCM_BAD_INPUT;
86     }
87 
88     /* check the Q field size: according to our implementation qFieldSize <= 4*/
89     if ((qFieldSize < 2) || (qFieldSize > 8))
90     {
91         return MBEDTLS_ERR_CCM_BAD_INPUT;
92     }
93 
94     /* check, that actual size of TextData is not great, than its control field size */
95     if ((qFieldSize < 4) && ((textDataSize >> (qFieldSize * 8)) > 0))
96     {
97         return MBEDTLS_ERR_CCM_BAD_INPUT;
98     }
99 
100     /* check Nonce size. */
101     if (sizeOfN < 7 || sizeOfN >= CC_AES_BLOCK_SIZE_IN_BYTES)
102     {
103         return MBEDTLS_ERR_CCM_BAD_INPUT;
104     }
105 
106     /* set pointer to user context */
107     pAesCcmCtx = (AesCcmContext_t *) ctx;
108 
109     /* set current AES operation mode for AES_MAC operation on first block B0 and next blocks */
110     pAesCcmCtx->mode = CIPHER_CBC_MAC;
111     pAesCcmCtx->sizeOfN = sizeOfN;
112     pAesCcmCtx->sizeOfT = sizeOfT;
113     pAesCcmCtx->dir = encryptDecryptFlag;
114 
115     /* clear initial vector */
116     mbedtls_zeroize_internal(pAesCcmCtx->ivBuf, sizeof(pAesCcmCtx->ivBuf));
117 
118     /*clear intenal buffers*/
119     mbedtls_zeroize_internal(pAesCcmCtx->ctrStateBuf, sizeof(pAesCcmCtx->ctrStateBuf));
120     mbedtls_zeroize_internal(pAesCcmCtx->tempBuff, sizeof(pAesCcmCtx->tempBuff));
121 
122     /* formatting the first block of CCM input B0, and encrypt with CBC-MAC */
123     tempBuff = pAesCcmCtx->tempBuff;
124 
125     /* set Adata flag (bit 6 for big endian form) */
126     if (assocDataSize > 0)
127     {
128         tempBuff[0] = 1 << 6;
129     }
130 
131     /* next flag bits: (t-2)/2 concatenated with (q-1) */
132     tempBuff[0] |= ((sizeOfT - 2) / 2) << 3; /* bits 3 - 5 */
133     tempBuff[0] |= (qFieldSize - 1); /* bits 0 - 2 */
134 
135     /* set N and Q (in big endian form) into B0 */
136     CC_PalMemCopy(tempBuff + 1, pNonce, sizeOfN);
137     CC_CommonReverseMemcpy(tempBuff + 16 - min(qFieldSize, 4), (uint8_t*) &textDataSize, min(qFieldSize, 4));
138 
139     /* set data buffers structures */
140     rc = SetDataBuffersInfo(tempBuff, CC_AES_BLOCK_SIZE_IN_BYTES, &inBuffInfo,
141     NULL,
142                             0, &outBuffInfo);
143     if (rc != 0)
144     {
145         CC_PAL_LOG_ERR("illegal data buffers\n");
146         return MBEDTLS_ERR_CCM_AUTH_FAILED;
147     }
148 
149     /* calculating MAC */
150     rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, CC_AES_BLOCK_SIZE_IN_BYTES);
151     if (rc != AES_DRV_OK)
152     {
153         CC_PAL_LOG_ERR("calculating MAC failed with error code %d\n", rc);
154         return MBEDTLS_ERR_CCM_AUTH_FAILED;
155     }
156 
157     /* set initial Counter value into ctrStateBuf buffer for AES CTR operations on text data */
158 
159     /* Flags byte = (qFieldSize - 1) */
160     ctrStateBuf[0] = qFieldSize - 1;
161     /* copy Nonce into bytes 1...(15-qFieldSize) in big endian form */
162     CC_PalMemCopy(ctrStateBuf + 1, pNonce, sizeOfN);
163     /* set counter i = 1 (in byte 15) */
164     ctrStateBuf[15] = 1; /* Note: value i = 0 reserved for encoding MAC value */
165     CC_PalMemCopy((uint8_t * )pAesCcmCtx->ctrStateBuf, ctrStateBuf, CC_AES_BLOCK_SIZE_IN_BYTES);
166 
167     return (0);
168 }
169 
ccm_ass_data(mbedtls_ccm_context * ctx,const uint8_t * pAssocData,size_t assocDataSize)170 static int ccm_ass_data(mbedtls_ccm_context *ctx, const uint8_t *pAssocData, size_t assocDataSize)
171 {
172 
173     AesCcmContext_t *pAesCcmCtx;
174     uint32_t firstBlockRemSize = 0;
175     uint8_t Asize = 0;
176     drvError_t rc;
177     CCBuffInfo_t inBuffInfo;
178     CCBuffInfo_t outBuffInfo;
179 
180     if (pAssocData == NULL)
181     {
182         return MBEDTLS_ERR_CCM_BAD_INPUT;
183     }
184 
185     /* set pointer to user context */
186     pAesCcmCtx = (AesCcmContext_t *) ctx;
187 
188     /* formatting ASize and setting it into AES tempBuff buffer */
189     /* clean working tempBuff */
190     mbedtls_zeroize_internal(pAesCcmCtx->tempBuff, CC_AES_BLOCK_SIZE_IN_BYTES);
191 
192     /* set formatted ASize into temp buffer.
193      Note: case ASize > 2^32 is not allowed by implementation */
194     if (assocDataSize > 0xFFFFFFFF)
195     {
196         return MBEDTLS_ERR_CCM_BAD_INPUT;
197     }
198 
199     /* if ASize > 2^16-2^8, then set 6 bytes = 0xff||0xfe||ASize */
200     if (assocDataSize >= 0xff00)
201     { /* if ASize >= 2^16 - 2^8, then set 0xff||0xfe||ASize */
202         pAesCcmCtx->tempBuff[0] = 0xff;
203         pAesCcmCtx->tempBuff[1] = 0xfe;
204         /* reverse copy 4 bytes */
205         CC_CommonReverseMemcpy(pAesCcmCtx->tempBuff + 6 - 4, (uint8_t*) &assocDataSize, 4);
206         Asize = 6;
207     }
208     else if (assocDataSize > 0)
209     { /* else if 0 < ASize < 2^16 - 2^8, then set 2 bytes = ASize */
210         /* reverse copy 2 bytes */
211         CC_CommonReverseMemcpy(pAesCcmCtx->tempBuff + 2 - 2, (uint8_t*) &assocDataSize, 2);
212         Asize = 2;
213     }
214     else
215     { /* no Adata */
216         Asize = 0;
217     }
218 
219     firstBlockRemSize = CC_AES_BLOCK_SIZE_IN_BYTES - Asize;
220 
221     if (assocDataSize < firstBlockRemSize)
222     {
223         firstBlockRemSize = assocDataSize;
224     }
225 
226     CC_PalMemCopy(pAesCcmCtx->tempBuff + Asize, pAssocData, firstBlockRemSize);
227 
228     assocDataSize -= firstBlockRemSize;
229     pAssocData += firstBlockRemSize;
230     pAesCcmCtx->mode = CIPHER_CBC_MAC;
231 
232     /* set data buffers structures */
233     rc = SetDataBuffersInfo(pAesCcmCtx->tempBuff, CC_AES_BLOCK_SIZE_IN_BYTES, &inBuffInfo,
234     NULL,
235                             0, &outBuffInfo);
236     if (rc != 0)
237     {
238         CC_PAL_LOG_ERR("illegal data buffers\n");
239         return MBEDTLS_ERR_CCM_AUTH_FAILED;
240     }
241 
242     /* encrypt a0 concatenated with the beginning of Associated data */
243     rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, CC_AES_BLOCK_SIZE_IN_BYTES);
244     if (rc != AES_DRV_OK)
245     {
246         CC_PAL_LOG_ERR("encrypt a0 concatenated with the beginning of Associated data failed with error code %d\n", rc);
247         return MBEDTLS_ERR_CCM_AUTH_FAILED;
248     }
249 
250     if (assocDataSize)
251     {
252         /* set data buffers structures */
253         rc = SetDataBuffersInfo(pAssocData, assocDataSize, &inBuffInfo,
254         NULL,
255                                 0, &outBuffInfo);
256         if (rc != 0)
257         {
258             CC_PAL_LOG_ERR("illegal data buffers\n");
259             return MBEDTLS_ERR_CCM_AUTH_FAILED;
260         }
261 
262         /* encrypt remaining Associated data */
263         rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, assocDataSize);
264         if (rc != AES_DRV_OK)
265         {
266             CC_PAL_LOG_ERR("encrypt remaining Associated data failed with error code %d\n", rc);
267             return MBEDTLS_ERR_CCM_AUTH_FAILED;
268         }
269     }
270 
271     return (0);
272 }
273 
ccm_text_data(mbedtls_ccm_context * ctx,const uint8_t * pTextDataIn,size_t textDataSize,uint8_t * pTextDataOut)274 static int ccm_text_data(mbedtls_ccm_context *ctx, const uint8_t *pTextDataIn, size_t textDataSize, uint8_t *pTextDataOut)
275 {
276 
277     AesCcmContext_t *pAesCcmCtx = NULL;
278     drvError_t rc;
279     CCBuffInfo_t inBuffInfo;
280     CCBuffInfo_t outBuffInfo;
281 
282     /* if the users Data In pointer is illegal return an error */
283     if ((pTextDataIn == NULL) && (textDataSize != 0))
284     {
285         return MBEDTLS_ERR_CCM_BAD_INPUT;
286     }
287 
288     if (textDataSize > 0xFFFFFFFF)
289     {
290         return MBEDTLS_ERR_CCM_BAD_INPUT;
291     }
292 
293     /* if the users Data Out pointer is illegal return an error */
294     if ((pTextDataOut == NULL) && (textDataSize != 0))
295     {
296         return MBEDTLS_ERR_CCM_BAD_INPUT;
297     }
298 
299     /* check overlapping of input-output buffers:
300      1. in-placement operation is permitted, i.e. pTextDataIn = pTextDataOut
301      2. If pTextDataIn > pTextDataOut, operation is valid since HW reads the block,
302            perform operation and write the result to output which will not overwrite the next input operation block.
303            And the tag/mac result is written to another temporary buffer see in ccm_finish()
304      3. BUT,  pTextDataIn < pTextDataOut, operation is NOT valid since the output result will  overwrite the next input block,
305            or expected tag/mac */
306     if ((pTextDataIn < pTextDataOut) &&
307         (pTextDataIn + textDataSize > pTextDataOut))
308     {
309         return MBEDTLS_ERR_CCM_BAD_INPUT;
310     }
311 
312     /* set pointer to user context */
313     pAesCcmCtx = (AesCcmContext_t *) ctx;
314 
315     /* set data buffers structures */
316     rc = SetDataBuffersInfo(pTextDataIn, textDataSize, &inBuffInfo, pTextDataOut, textDataSize, &outBuffInfo);
317     if (rc != 0)
318     {
319         CC_PAL_LOG_ERR("illegal data buffers\n");
320         return MBEDTLS_ERR_CCM_AUTH_FAILED;
321     }
322 
323 #ifndef AES_NO_TUNNEL
324 
325     /* use HW tunnel to process CCMPE/PD on text data */
326 
327     if (pAesCcmCtx->dir == CRYPTO_DIRECTION_DECRYPT)
328     {
329         pAesCcmCtx->mode = CIPHER_CCMPD;
330     }
331     else
332     {
333         pAesCcmCtx->mode = CIPHER_CCMPE;
334     }
335 
336     rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, textDataSize);
337     if (rc != AES_DRV_OK)
338     {
339         CC_PAL_LOG_ERR("HW tunnel processing CCMPE/PD on text data failed with error code %d\n", rc);
340         return MBEDTLS_ERR_CCM_AUTH_FAILED;
341     }
342 
343 #else
344 
345     /* invoke two separate operations in case of no tunneling is supported by HW */
346 
347     if (pAesCcmCtx->dir == CRYPTO_DIRECTION_ENCRYPT)
348     {
349         /* set operation mode to CBC_MAC */
350         pAesCcmCtx->mode = CIPHER_CBC_MAC;
351 
352         rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, textDataSize);
353         if ( rc != AES_DRV_OK )
354         {
355             CC_PAL_LOG_ERR("CBC_MAC on text data failed with error code %d\n", rc);
356             return MBEDTLS_ERR_CCM_AUTH_FAILED;
357         }
358     }
359 
360     /* Encrypt(decrypt) text data by AES-CTR, starting from CTR = CTR0+1 */
361     pAesCcmCtx->mode = CIPHER_CTR;
362     rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, textDataSize);
363     if ( rc != AES_DRV_OK)
364     {
365         CC_PAL_LOG_ERR("AES-CTR on text data failed with error code %d\n", rc);
366         return MBEDTLS_ERR_CCM_AUTH_FAILED;
367     }
368 
369     if (pAesCcmCtx->dir == CRYPTO_DIRECTION_DECRYPT)
370     {
371         /* execute the AES-MAC on decrypt mode */
372         pAesCcmCtx->mode = CIPHER_CBC_MAC;
373 
374         /* set data buffers structures */
375         rc = SetDataBuffersInfo(pTextDataOut, textDataSize, &inBuffInfo,
376                         NULL, 0, &outBuffInfo);
377         if (rc != 0)
378         {
379             CC_PAL_LOG_ERR("illegal data buffers\n");
380             return MBEDTLS_ERR_CCM_AUTH_FAILED;
381         }
382 
383         if (ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, textDataSize) != AES_DRV_OK )
384         {
385             CC_PAL_LOG_ERR("AES-MAC on decrypt data failed with error code %d\n", rc);
386             return MBEDTLS_ERR_CCM_AUTH_FAILED;
387         }
388     }
389 
390 #endif
391 
392     return (0);
393 }
394 
ccm_finish(mbedtls_ccm_context * ctx,unsigned char * macBuf,size_t * sizeOfT)395 static int ccm_finish(mbedtls_ccm_context *ctx, unsigned char * macBuf, size_t *sizeOfT)
396 {
397 
398     AesCcmContext_t *pAesCcmCtx;
399     uint8_t *tempBuff;
400     uint8_t qFieldSize;
401     drvError_t rc;
402     /* important to define different buffer for mac to support CCM with TextData in-place
403      * and pTextDataIn > pTextDataOut overlapping addresses, see comment in ccm_text_data()*/
404     uint8_t localMacBuf[CC_AES_BLOCK_SIZE_IN_BYTES];
405     CCBuffInfo_t inBuffInfo;
406     CCBuffInfo_t outBuffInfo;
407 
408     if (sizeOfT == NULL)
409     {
410         return MBEDTLS_ERR_CCM_BAD_INPUT;
411     }
412 
413     /* if the users Data In pointer is illegal return an error */
414     if (macBuf == NULL)
415     {
416         return MBEDTLS_ERR_CCM_BAD_INPUT;
417     }
418 
419     /* set pointer to user context */
420     pAesCcmCtx = (AesCcmContext_t *) ctx;
421 
422     qFieldSize = 15 - pAesCcmCtx->sizeOfN;
423 
424     /* encrypt (decrypt) the CCM-MAC value */
425     /* ------------------------------------------------------------------------- */
426 
427     /* set operation to CTR mode */
428     pAesCcmCtx->mode = CIPHER_CTR;
429 
430     /* set CTR value = CTR0 for encrypt(decrypt) CCM-MAC */
431     mbedtls_zeroize_internal((uint8_t*) pAesCcmCtx->ctrStateBuf + CC_AES_BLOCK_SIZE_IN_BYTES - qFieldSize, qFieldSize);
432 
433     /* on CCM encrypt mode*/
434     if (pAesCcmCtx->dir == CRYPTO_DIRECTION_ENCRYPT)
435     {
436         /* set data buffers structures */
437         rc = SetDataBuffersInfo((uint8_t*) pAesCcmCtx->ivBuf, CC_AES_BLOCK_SIZE_IN_BYTES, &inBuffInfo, localMacBuf, CC_AES_BLOCK_SIZE_IN_BYTES, &outBuffInfo);
438         if (rc != 0)
439         {
440             CC_PAL_LOG_ERR("illegal data buffers\n");
441             return MBEDTLS_ERR_CCM_AUTH_FAILED;
442         }
443 
444         rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, CC_AES_BLOCK_SIZE_IN_BYTES);
445         if (rc != AES_DRV_OK)
446         {
447             CC_PAL_LOG_ERR("encryption of IV buf failed with error code %d\n", rc);
448             return MBEDTLS_ERR_CCM_AUTH_FAILED;
449         }
450 
451         CC_PalMemCopy(macBuf, localMacBuf, pAesCcmCtx->sizeOfT);
452 
453     }
454     else
455     {/* on CCM decrypt mode*/
456         tempBuff = pAesCcmCtx->tempBuff;
457         mbedtls_zeroize_internal(tempBuff, sizeof(pAesCcmCtx->tempBuff));
458 
459         /* copy encrypted CCM-MAC from input to temp buff padded with zeros */
460         CC_PalMemCopy(tempBuff, macBuf, pAesCcmCtx->sizeOfT);
461 
462         /* set data buffers structures */
463         rc = SetDataBuffersInfo(tempBuff, CC_AES_BLOCK_SIZE_IN_BYTES, &inBuffInfo, tempBuff, CC_AES_BLOCK_SIZE_IN_BYTES, &outBuffInfo);
464         if (rc != 0)
465         {
466             CC_PAL_LOG_ERR("illegal data buffers\n");
467             return MBEDTLS_ERR_CCM_AUTH_FAILED;
468         }
469 
470         /* decrypt the MAC value and save it in the pAesCcmCtx->temp buffer */
471         rc = ProcessAesCcmDrv(pAesCcmCtx, &inBuffInfo, &outBuffInfo, CC_AES_BLOCK_SIZE_IN_BYTES);
472         if (rc != AES_DRV_OK)
473         {
474             CC_PAL_LOG_ERR("decryption of MAC buf failed with error code %d\n", rc);
475             return MBEDTLS_ERR_CCM_AUTH_FAILED;
476         }
477         /* compare calculated and decrypted MAC results */
478         if (CC_PalMemCmp(pAesCcmCtx->ivBuf, tempBuff, pAesCcmCtx-> sizeOfT ) != 0)
479         {
480             /* if MAC results are different, return an Error */
481             CC_PAL_LOG_ERR("calculated and decrypted MAC results are different \n");
482             return MBEDTLS_ERR_CCM_AUTH_FAILED;
483         }
484     }
485 
486     *sizeOfT = pAesCcmCtx->sizeOfT;
487 
488     return (0);
489 }
490 
ccm_auth_crypt(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len,cryptoDirection_t dir,uint32_t ccmMode)491 static int ccm_auth_crypt(mbedtls_ccm_context *ctx,
492                           size_t length,
493                           const unsigned char *iv,
494                           size_t iv_len,
495                           const unsigned char *add,
496                           size_t add_len,
497                           const unsigned char *input,
498                           unsigned char *output,
499                           unsigned char *tag,
500                           size_t tag_len,
501                           cryptoDirection_t dir,
502                           uint32_t ccmMode)
503 {
504     int rc;
505 
506     /* check for  user context */
507     if (ctx == NULL)
508     {
509         return MBEDTLS_ERR_CCM_BAD_INPUT;
510     }
511 
512     rc = ccm_init(ctx, dir, add_len, length, iv, iv_len, tag_len, ccmMode);
513     if (rc != 0)
514     {
515         return rc;
516     }
517 
518     /* if there's no associated data, skip a0 encryption */
519     if (add_len != 0)
520     {
521         rc = ccm_ass_data(ctx, add, add_len);
522         if (rc != 0)
523         {
524             return rc;
525         }
526     }
527 
528     /* if there's no payload data, skip to authentication */
529     if (length != 0)
530     {
531         rc = ccm_text_data(ctx, input, length, output);
532         if (rc != 0)
533         {
534             return rc;
535         }
536     }
537 
538     rc = ccm_finish(ctx, tag, &tag_len);
539     if (0 != rc)
540     {
541         mbedtls_zeroize_internal(output, length);
542     }
543 
544     return rc;
545 }
546 
547 /****************************** PUBLIC **************************/
mbedtls_ccm_get_security_level(uint8_t sizeOfT,uint8_t * pSecurityLevel)548 int mbedtls_ccm_get_security_level(uint8_t sizeOfT, uint8_t *pSecurityLevel)
549 {
550     if (pSecurityLevel == NULL)
551     {
552         return MBEDTLS_ERR_CCM_BAD_INPUT;
553     }
554 
555     /*
556      The security level field for AES-CCM* as defined in ieee-802.15.4-2011, Table 58.
557      System spec requirement CCM*-3: The CCM* shall support only the security levels that include encryption (1XX values).
558      */
559     switch (sizeOfT)
560     {
561         case 0:
562             *pSecurityLevel = AESCCM_STAR_SECURITY_LEVEL_ENC;
563             break;
564         case 4:
565             *pSecurityLevel = AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_32;
566             break;
567         case 8:
568             *pSecurityLevel = AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_64;
569             break;
570         case 16:
571             *pSecurityLevel = AESCCM_STAR_SECURITY_LEVEL_ENC_MIC_128;
572             break;
573         default:
574             return MBEDTLS_ERR_CCM_BAD_INPUT;
575     }
576 
577     return CC_OK;
578 }
579 
mbedtls_ccm_init_int(mbedtls_ccm_context * ctx)580 void mbedtls_ccm_init_int(mbedtls_ccm_context *ctx)
581 {
582     if (ctx == NULL)
583     {
584         CC_PalAbort("!!!!CCM context is NULL!!!\n");
585     }
586     /* check size of structs match , memory allocated must be at least the size of AesCcmContext_t*/
587     if (sizeof(mbedtls_ccm_context) < sizeof(AesCcmContext_t))
588     {
589         CC_PalAbort("!!!!CCM context sizes mismatch!!!\n");
590     }
591     mbedtls_zeroize_internal(ctx, sizeof(mbedtls_ccm_context));
592 
593 }
594 
mbedtls_ccm_setkey_int(mbedtls_ccm_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits)595 int mbedtls_ccm_setkey_int(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits)
596 {
597 
598     AesCcmContext_t *aes_ccm_ctx;
599 
600     if (ctx == NULL || key == NULL)
601     {
602         CC_PAL_LOG_ERR("Null pointer, ctx or key are NULL\n");
603         return MBEDTLS_ERR_CCM_BAD_INPUT;
604     }
605 
606     if (cipher != MBEDTLS_CIPHER_ID_AES)
607     {
608         /* No real use case for CCM other then AES*/
609         CC_PAL_LOG_ERR("Only AES cipher id is supported\n");
610         return MBEDTLS_ERR_CCM_BAD_INPUT;
611     }
612     aes_ccm_ctx = (AesCcmContext_t *) ctx;
613     switch (keybits)
614     {
615         case 128:
616 
617             aes_ccm_ctx->keySizeId = KEY_SIZE_128_BIT;
618             break;
619 
620         case 192:
621 
622             aes_ccm_ctx->keySizeId = KEY_SIZE_192_BIT;
623             break;
624 
625         case 256:
626 
627             aes_ccm_ctx->keySizeId = KEY_SIZE_256_BIT;
628             break;
629 
630         default:
631             return MBEDTLS_ERR_CCM_BAD_INPUT;
632     }
633 
634     /* Copy user key to context */
635     CC_PalMemCopy(aes_ccm_ctx->keyBuf, key, keybits / 8);
636 
637     return (0);
638 }
639 
mbedtls_ccm_free_int(mbedtls_ccm_context * ctx)640 void mbedtls_ccm_free_int(mbedtls_ccm_context *ctx)
641 {
642     if (ctx != NULL)
643     {
644         mbedtls_zeroize_internal(ctx, sizeof(mbedtls_ccm_context));
645     }
646 }
647 
mbedtls_ccm_encrypt_and_tag_int(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len,uint32_t ccmMode)648 int mbedtls_ccm_encrypt_and_tag_int(mbedtls_ccm_context *ctx,
649                                     size_t length,
650                                     const unsigned char *iv,
651                                     size_t iv_len,
652                                     const unsigned char *add,
653                                     size_t add_len,
654                                     const unsigned char *input,
655                                     unsigned char *output,
656                                     unsigned char *tag,
657                                     size_t tag_len,
658                                     uint32_t ccmMode)
659 {
660     return ccm_auth_crypt(ctx, length, iv, iv_len, add, add_len, input, output, tag, tag_len, CRYPTO_DIRECTION_ENCRYPT, ccmMode);
661 }
662 
mbedtls_ccm_auth_decrypt_int(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,const unsigned char * tag,size_t tag_len,uint32_t ccmMode)663 int mbedtls_ccm_auth_decrypt_int(mbedtls_ccm_context *ctx,
664                                  size_t length,
665                                  const unsigned char *iv,
666                                  size_t iv_len,
667                                  const unsigned char *add,
668                                  size_t add_len,
669                                  const unsigned char *input,
670                                  unsigned char *output,
671                                  const unsigned char *tag,
672                                  size_t tag_len,
673                                  uint32_t ccmMode)
674 {
675 
676     uint8_t localMacBuf[CC_AES_BLOCK_SIZE_IN_BYTES];
677 
678     if (tag_len > CC_AES_BLOCK_SIZE_IN_BYTES)
679     {
680         CC_PAL_LOG_ERR("parameter tag_len is bigger then %d\n", CC_AES_BLOCK_SIZE_IN_BYTES);
681         return MBEDTLS_ERR_CCM_BAD_INPUT;
682     }
683     if (tag == NULL)
684     {
685         CC_PAL_LOG_ERR("\ntag NULL pointer\n");
686         return MBEDTLS_ERR_CCM_BAD_INPUT;
687     }
688 
689     CC_PalMemCopy(localMacBuf, tag, tag_len);
690     return ccm_auth_crypt(ctx, length, iv, iv_len, add, add_len, input, output, localMacBuf, tag_len, CRYPTO_DIRECTION_DECRYPT, ccmMode);
691 }
692 
693 
mbedtls_ccm_star_nonce_generate(unsigned char * src_addr,uint32_t frame_counter,uint8_t size_of_t,unsigned char * nonce_buf)694 int mbedtls_ccm_star_nonce_generate(unsigned char * src_addr, uint32_t frame_counter, uint8_t size_of_t, unsigned char * nonce_buf)
695 {
696     int rc = 0;
697     uint8_t securityLevelField = 0;
698 
699     if ((src_addr == NULL) || (nonce_buf == NULL))
700     {
701         return MBEDTLS_ERR_CCM_BAD_INPUT;
702     }
703 
704     if ((rc = mbedtls_ccm_get_security_level(size_of_t, &securityLevelField)) != 0)
705     {
706         return rc;
707     }
708 
709     /*
710      The nonce structure for AES-CCM* is defined in ieee-802.15.4-2011, Figure 61:
711      Source address (8) | Frame counter (4) | Security lvel (1)
712      */
713 
714     CC_PalMemCopy(nonce_buf, src_addr, MBEDTLS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES);
715     CC_PalMemCopy(nonce_buf + MBEDTLS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES, &frame_counter, sizeof(uint32_t));
716     nonce_buf[MBEDTLS_AESCCM_STAR_NONCE_SIZE_BYTES - 1] = securityLevelField;
717 
718     return 0;
719 }
720