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