1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Crypto Component */
17 /** */
18 /** CCM Mode */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_ccm.h"
24
25 /**************************************************************************/
26 /* */
27 /* FUNCTION RELEASE */
28 /* */
29 /* _nx_crypto_ccm_xor PORTABLE C */
30 /* 6.1 */
31 /* AUTHOR */
32 /* */
33 /* Timothy Stapko, Microsoft Corporation */
34 /* */
35 /* DESCRIPTION */
36 /* */
37 /* This function performs XOR operation on the output buffer. */
38 /* */
39 /* INPUT */
40 /* */
41 /* plaintext Pointer to input plantext */
42 /* key Value to be xor'ed */
43 /* ciphertext Output buffer of 16 bytes */
44 /* */
45 /* OUTPUT */
46 /* */
47 /* None */
48 /* */
49 /* CALLS */
50 /* */
51 /* None */
52 /* */
53 /* CALLED BY */
54 /* */
55 /* _nx_crypto_ccm_cbc_pad Compute CBC-MAC value with */
56 /* padding for CCM mode */
57 /* */
58 /* RELEASE HISTORY */
59 /* */
60 /* DATE NAME DESCRIPTION */
61 /* */
62 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
63 /* 09-30-2020 Timothy Stapko Modified comment(s), disabled */
64 /* unaligned access by default,*/
65 /* resulting in version 6.1 */
66 /* */
67 /**************************************************************************/
_nx_crypto_ccm_xor(UCHAR * plaintext,UCHAR * key,UCHAR * ciphertext)68 NX_CRYPTO_KEEP static VOID _nx_crypto_ccm_xor(UCHAR *plaintext, UCHAR *key, UCHAR *ciphertext)
69 {
70 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
71 UINT *p = (UINT *)plaintext;
72 UINT *c = (UINT *)ciphertext;
73 UINT *k = (UINT *)key;
74
75 c[0] = p[0] ^ k[0];
76 c[1] = p[1] ^ k[1];
77 c[2] = p[2] ^ k[2];
78 c[3] = p[3] ^ k[3];
79 #else
80 ciphertext[0] = plaintext[0] ^ key[0];
81 ciphertext[1] = plaintext[1] ^ key[1];
82 ciphertext[2] = plaintext[2] ^ key[2];
83 ciphertext[3] = plaintext[3] ^ key[3];
84 ciphertext[4] = plaintext[4] ^ key[4];
85 ciphertext[5] = plaintext[5] ^ key[5];
86 ciphertext[6] = plaintext[6] ^ key[6];
87 ciphertext[7] = plaintext[7] ^ key[7];
88 ciphertext[8] = plaintext[8] ^ key[8];
89 ciphertext[9] = plaintext[9] ^ key[9];
90 ciphertext[10] = plaintext[10] ^ key[10];
91 ciphertext[11] = plaintext[11] ^ key[11];
92 ciphertext[12] = plaintext[12] ^ key[12];
93 ciphertext[13] = plaintext[13] ^ key[13];
94 ciphertext[14] = plaintext[14] ^ key[14];
95 ciphertext[15] = plaintext[15] ^ key[15];
96 #endif
97 }
98
99 /**************************************************************************/
100 /* */
101 /* FUNCTION RELEASE */
102 /* */
103 /* _nx_crypto_ccm_cbc_pad PORTABLE C */
104 /* 6.1 */
105 /* AUTHOR */
106 /* */
107 /* Timothy Stapko, Microsoft Corporation */
108 /* */
109 /* DESCRIPTION */
110 /* */
111 /* This function compute CBC-MAC value with padding for CCM mode. */
112 /* */
113 /* INPUT */
114 /* */
115 /* crypto_metadata Pointer to crypto metadata */
116 /* crypto_function Pointer to crypto function */
117 /* input Pointer to clear text input */
118 /* output Pointer to encrypted output */
119 /* The output is the last */
120 /* 16 bytes cipher. */
121 /* length Length of the input message. */
122 /* iv Initial Vector */
123 /* block_size Block size */
124 /* */
125 /* OUTPUT */
126 /* */
127 /* status Completion status */
128 /* */
129 /* CALLS */
130 /* */
131 /* _nx_crypto_ccm_xor Perform CCM XOR operation */
132 /* */
133 /* CALLED BY */
134 /* */
135 /* _nx_crypto_ccm_authentication Perform CCM authentication */
136 /* */
137 /* RELEASE HISTORY */
138 /* */
139 /* DATE NAME DESCRIPTION */
140 /* */
141 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
142 /* 09-30-2020 Timothy Stapko Modified comment(s), */
143 /* verified memcpy use cases, */
144 /* resulting in version 6.1 */
145 /* */
146 /**************************************************************************/
_nx_crypto_ccm_cbc_pad(VOID * crypto_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UCHAR * iv,UINT block_size)147 NX_CRYPTO_KEEP static VOID _nx_crypto_ccm_cbc_pad(VOID *crypto_metadata,
148 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
149 UCHAR *input, UCHAR *output, UINT length, UCHAR *iv, UINT block_size)
150 {
151 UINT i = 0;
152 UCHAR last_cipher[NX_CRYPTO_CCM_BLOCK_SIZE];
153
154 NX_CRYPTO_MEMCPY(last_cipher, iv, block_size); /* Use case of memcpy is verified. */
155 for (i = 0; i < length; i += block_size)
156 {
157
158 /* XOR */
159 if ((length - i) < block_size)
160 {
161
162 /* If the length of this block is less than block size, pad it with zero. */
163 NX_CRYPTO_MEMCPY(output, input + i, length - i); /* Use case of memcpy is verified. */
164 NX_CRYPTO_MEMSET(output + length - i, 0, block_size - (length - i));
165 _nx_crypto_ccm_xor(output, last_cipher, output);
166 }
167 else
168 {
169 _nx_crypto_ccm_xor(input + i, last_cipher, output);
170 }
171
172 /* Encrypt the block. */
173 crypto_function(crypto_metadata, output, last_cipher, block_size);
174 }
175
176 /* Return last block of the cipher. */
177 NX_CRYPTO_MEMCPY(output, last_cipher, block_size); /* Use case of memcpy is verified. */
178
179 #ifdef NX_SECURE_KEY_CLEAR
180 NX_CRYPTO_MEMSET(last_cipher, 0, sizeof(last_cipher));
181 #endif /* NX_SECURE_KEY_CLEAR */
182 }
183
_nx_crypto_ccm_authentication_init(VOID * crypto_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * a_data,UINT a_len,UINT m_len,UCHAR * X,UCHAR * Nonce,UCHAR L,USHORT M,UINT block_size)184 NX_CRYPTO_KEEP static VOID _nx_crypto_ccm_authentication_init(VOID *crypto_metadata,
185 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
186 UCHAR *a_data, UINT a_len, UINT m_len,
187 UCHAR *X, UCHAR *Nonce, UCHAR L,
188 USHORT M, UINT block_size)
189 {
190 UCHAR Flags = 0;
191 UCHAR B[NX_CRYPTO_CCM_BLOCK_SIZE];
192 UCHAR temp_len = 0;
193
194 NX_CRYPTO_MEMSET(B, 0, NX_CRYPTO_CCM_BLOCK_SIZE);
195 NX_CRYPTO_MEMSET(X, 0, NX_CRYPTO_CCM_BLOCK_SIZE);
196
197 /* AddAuthData: Right-concatenate the l(a) with the string a,
198 and pad it with zero so that the AddAuthData has length divisible by 16. */
199 /* PlaintextData: Pad string m with zero so that the PlaintextData has length divisible by 16. */
200 /* AuthData = AddAuthData||PlaintextData. */
201 /* Parse the AuthData as B(1)||B(2)||...||B(t), where the block B(i) is a 16-bytes string. */
202
203 /* CBC-MAC value X(i + 1) = E(Key, X(i) ^ B(i)), for i = 0, 1,..., t. */
204
205 /* Create Flag for B(0). */
206 if (a_len > 0)
207 {
208 Flags = 1 << 6;
209 }
210 else
211 {
212 Flags = 0;
213 }
214 Flags |= (UCHAR)(((M - 2) >> 1) << 3);
215 Flags |= (UCHAR)(L - 1);
216
217 /* B(0) = Flags||Nonce||l(m) */
218 B[0] = Flags;
219 NX_CRYPTO_MEMCPY(B + 1, Nonce, (UINT)15 - L); /* Use case of memcpy is verified. */
220 B[14] = (UCHAR)(m_len >> 8);
221 B[15] = (UCHAR)(m_len);
222
223 /* Get the CBC-MAC value X(1). */
224 _nx_crypto_ccm_cbc_pad(crypto_metadata, crypto_function, B, X, block_size, X, block_size);
225
226 /* B(1) = 2 bytes l(a) + leftmost 14 bytes of string a. */
227 B[0] = (UCHAR)(a_len >> 8);
228 B[1] = (UCHAR)(a_len);
229
230 /* If the length of string a is less than 14, pad B(1) with 0. */
231 temp_len = (UCHAR)((a_len > (block_size - 2)) ? (block_size - 2) : a_len);
232 NX_CRYPTO_MEMCPY(B + 2, a_data, (UINT)temp_len); /* Use case of memcpy is verified. */
233
234 /* Get the CBC-MAC value X(2). */
235 _nx_crypto_ccm_cbc_pad(crypto_metadata, crypto_function, B, X, (UINT)(temp_len + 2), X, block_size);
236
237 /* Get the CBC-MAC value X(i), for i = 3,...,t + 1. */
238 if (a_len > (block_size - 2))
239 {
240 _nx_crypto_ccm_cbc_pad(crypto_metadata, crypto_function, a_data + block_size - 2, X, a_len - (block_size - 2), X, block_size);
241 }
242
243 #ifdef NX_SECURE_KEY_CLEAR
244 NX_CRYPTO_MEMSET(B, 0, sizeof(B));
245 #endif /* NX_SECURE_KEY_CLEAR */
246 }
247
248 /**************************************************************************/
249 /* */
250 /* FUNCTION RELEASE */
251 /* */
252 /* _nx_crypto_ccm_encrypt_init PORTABLE C */
253 /* 6.1 */
254 /* AUTHOR */
255 /* */
256 /* Timothy Stapko, Microsoft Corporation */
257 /* */
258 /* DESCRIPTION */
259 /* */
260 /* This function initialize the CCM mode for encryption. */
261 /* */
262 /* Note, the first byte of iv represents the length of IV excluding its*/
263 /* first byte. For example, 0x0401020304 indicates the length of IV is */
264 /* 4 bytes and the content of IV is 0x01020304. */
265 /* */
266 /* INPUT */
267 /* */
268 /* crypto_metadata Pointer to crypto metadata */
269 /* ccm_metadata Pointer to CCM metadata */
270 /* crypto_function Pointer to crypto function */
271 /* additional_data Pointer to additional data */
272 /* additional_len Length of additional data */
273 /* length Total length of plain/cipher */
274 /* iv Pointer to Initial Vector */
275 /* icv_len Length of TAG */
276 /* block_size Block size of crypto algorithm*/
277 /* */
278 /* OUTPUT */
279 /* */
280 /* status */
281 /* */
282 /* CALLS */
283 /* */
284 /* _nx_crypto_ccm_authentication_init Initialize authentication */
285 /* */
286 /* CALLED BY */
287 /* */
288 /* _nx_crypto_method_aes_ccm_operation Handle AES encrypt or decrypt */
289 /* */
290 /* RELEASE HISTORY */
291 /* */
292 /* DATE NAME DESCRIPTION */
293 /* */
294 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
295 /* 09-30-2020 Timothy Stapko Modified comment(s), */
296 /* verified memcpy use cases, */
297 /* resulting in version 6.1 */
298 /* */
299 /**************************************************************************/
_nx_crypto_ccm_encrypt_init(VOID * crypto_metadata,NX_CRYPTO_CCM * ccm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),VOID * additional_data,UINT additional_len,UINT length,UCHAR * iv,USHORT icv_len,USHORT block_size)300 NX_CRYPTO_KEEP UINT _nx_crypto_ccm_encrypt_init(VOID *crypto_metadata, NX_CRYPTO_CCM *ccm_metadata,
301 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
302 VOID *additional_data, UINT additional_len,
303 UINT length, UCHAR *iv, USHORT icv_len, USHORT block_size)
304 {
305 UCHAR L = (UCHAR)(15 - iv[0]);
306 UCHAR *Nonce = iv + 1;
307
308 UCHAR Flags = 0;
309 UCHAR *A = ccm_metadata -> nx_crypto_ccm_A;
310
311 /* Check the block size. */
312 /* Accroding to RFC 3610, valid values of L range between 2 octets and 8 octets, iv[0] range between 7 octets and 13 octets. */
313 if (block_size != NX_CRYPTO_CCM_BLOCK_SIZE || iv[0] > 13 || iv[0] < 7)
314 {
315 return(NX_CRYPTO_PTR_ERROR);
316 }
317
318 ccm_metadata -> nx_crypto_ccm_icv_length = icv_len;
319
320 /* Data authentication. */
321 if (icv_len > 0)
322 {
323
324 /* Compute authentication tag T. */
325 _nx_crypto_ccm_authentication_init(crypto_metadata, crypto_function,
326 (UCHAR *)additional_data, additional_len, length,
327 ccm_metadata -> nx_crypto_ccm_X,
328 Nonce, L, icv_len, block_size);
329 }
330
331 NX_CRYPTO_MEMSET(A, 0, sizeof(ccm_metadata -> nx_crypto_ccm_A));
332
333 /* Create A(i) = Flags||Nonce||Counter i, for i = 0, 1, 2,.... */
334 Flags = (UCHAR)(L - 1);
335 A[0] = Flags;
336 NX_CRYPTO_MEMCPY(A + 1, Nonce, (UINT)(15 - L)); /* Use case of memcpy is verified. */
337
338 return(NX_CRYPTO_SUCCESS);
339 }
340
341 /**************************************************************************/
342 /* */
343 /* FUNCTION RELEASE */
344 /* */
345 /* _nx_crypto_ccm_encrypt_update PORTABLE C */
346 /* 6.1 */
347 /* AUTHOR */
348 /* */
349 /* Timothy Stapko, Microsoft Corporation */
350 /* */
351 /* DESCRIPTION */
352 /* */
353 /* This function updates data for GCM encryption or decryption. */
354 /* */
355 /* INPUT */
356 /* */
357 /* crypto_metadata Pointer to crypto metadata */
358 /* ccm_metadata Pointer to CCM metadata */
359 /* crypto_function Pointer to crypto function */
360 /* input Pointer to bytes of input */
361 /* output Pointer to output buffer */
362 /* length Length of bytes of input */
363 /* block_size Block size of crypto algorithm*/
364 /* */
365 /* OUTPUT */
366 /* */
367 /* status */
368 /* */
369 /* CALLS */
370 /* */
371 /* _nx_crypto_ccm_cbc_pad Update data for CCM mode */
372 /* */
373 /* CALLED BY */
374 /* */
375 /* _nx_crypto_method_aes_ccm_operation Handle AES encrypt or decrypt */
376 /* */
377 /* RELEASE HISTORY */
378 /* */
379 /* DATE NAME DESCRIPTION */
380 /* */
381 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
382 /* 09-30-2020 Timothy Stapko Modified comment(s), */
383 /* resulting in version 6.1 */
384 /* */
385 /**************************************************************************/
_nx_crypto_ccm_encrypt_update(UINT op,VOID * crypto_metadata,NX_CRYPTO_CCM * ccm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UINT block_size)386 NX_CRYPTO_KEEP UINT _nx_crypto_ccm_encrypt_update(UINT op, VOID *crypto_metadata, NX_CRYPTO_CCM *ccm_metadata,
387 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
388 UCHAR *input, UCHAR *output, UINT length, UINT block_size)
389 {
390 UCHAR *A = ccm_metadata -> nx_crypto_ccm_A;
391 UCHAR X[NX_CRYPTO_CCM_BLOCK_SIZE];
392 UINT i = 0, k = 0;
393
394 /* Check the block size. */
395 if (block_size != NX_CRYPTO_CCM_BLOCK_SIZE)
396 {
397 return(NX_CRYPTO_PTR_ERROR);
398 }
399
400 if (op == NX_CRYPTO_ENCRYPT_UPDATE)
401 {
402
403 /* Data authentication. */
404 if (ccm_metadata -> nx_crypto_ccm_icv_length > 0)
405 {
406
407 /* Compute authentication tag T. */
408 _nx_crypto_ccm_cbc_pad(crypto_metadata, crypto_function, input,
409 ccm_metadata -> nx_crypto_ccm_X, length,
410 ccm_metadata -> nx_crypto_ccm_X, block_size);
411 }
412 }
413
414 /* Data encryption. */
415 if (length > 0)
416 {
417
418 /* Parse the plain text as M(1)||M(2)||..., where the block M(i) is a 16-byte string. */
419 /* Cipher text block: C(i) = E(Key, A(i)) ^ M(i) */
420 for (i = 0; i < length; i += block_size)
421 {
422 A[15] = (UCHAR)(A[15] + 1);
423 crypto_function(crypto_metadata, A, X, block_size);
424
425 for (k = 0; (k < block_size) && ((i + k) < length); k++)
426 {
427 output[i + k] = X[k] ^ input[i + k];
428 }
429 }
430 }
431
432 if (op == NX_CRYPTO_DECRYPT_UPDATE)
433 {
434
435 /* Data authentication. */
436 if (ccm_metadata -> nx_crypto_ccm_icv_length > 0)
437 {
438
439 /* Compute authentication tag T. */
440 _nx_crypto_ccm_cbc_pad(crypto_metadata, crypto_function, output,
441 ccm_metadata -> nx_crypto_ccm_X, length,
442 ccm_metadata -> nx_crypto_ccm_X, block_size);
443 }
444 }
445
446 #ifdef NX_SECURE_KEY_CLEAR
447 NX_CRYPTO_MEMSET(X, 0, sizeof(X));
448 #endif
449
450 return(NX_CRYPTO_SUCCESS);
451 }
452
453 /**************************************************************************/
454 /* */
455 /* FUNCTION RELEASE */
456 /* */
457 /* _nx_crypto_ccm_encrypt_calculate PORTABLE C */
458 /* 6.1 */
459 /* AUTHOR */
460 /* */
461 /* Timothy Stapko, Microsoft Corporation */
462 /* */
463 /* DESCRIPTION */
464 /* */
465 /* This function calculates TAG for CCM mode. */
466 /* */
467 /* INPUT */
468 /* */
469 /* crypto_metadata Pointer to crypto metadata */
470 /* gcm_metadata Pointer to GCM metadata */
471 /* crypto_function Pointer to crypto function */
472 /* icv Pointer to TAG buffer */
473 /* block_size Block size of crypto algorithm*/
474 /* */
475 /* OUTPUT */
476 /* */
477 /* status */
478 /* */
479 /* CALLS */
480 /* */
481 /* None */
482 /* */
483 /* CALLED BY */
484 /* */
485 /* _nx_crypto_method_aes_ccm_operation Handle AES encrypt or decrypt */
486 /* */
487 /* RELEASE HISTORY */
488 /* */
489 /* DATE NAME DESCRIPTION */
490 /* */
491 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
492 /* 09-30-2020 Timothy Stapko Modified comment(s), */
493 /* verified memcpy use cases, */
494 /* resulting in version 6.1 */
495 /* */
496 /**************************************************************************/
_nx_crypto_ccm_encrypt_calculate(VOID * crypto_metadata,NX_CRYPTO_CCM * ccm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * icv,UINT block_size)497 NX_CRYPTO_KEEP UINT _nx_crypto_ccm_encrypt_calculate(VOID *crypto_metadata, NX_CRYPTO_CCM *ccm_metadata,
498 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
499 UCHAR *icv, UINT block_size)
500 {
501 UCHAR *A = ccm_metadata -> nx_crypto_ccm_A;
502 UINT i;
503
504 /* Check the block size. */
505 if (block_size != NX_CRYPTO_CCM_BLOCK_SIZE)
506 {
507 return(NX_CRYPTO_PTR_ERROR);
508 }
509
510 /* Data authentication. */
511 if (ccm_metadata -> nx_crypto_ccm_icv_length > 0)
512 {
513
514 /* The authentication tag T is the leftmost M bytes of the CBC-MAC value X(t + 1). */
515 NX_CRYPTO_MEMCPY(icv, ccm_metadata -> nx_crypto_ccm_X, ccm_metadata -> nx_crypto_ccm_icv_length); /* Use case of memcpy is verified. */
516
517 /* Get encryption block X. */
518 A[15] = 0;
519 crypto_function(crypto_metadata, A, A, block_size);
520
521 /* Encrypt authentication tag. */
522 for (i = 0; i < ccm_metadata -> nx_crypto_ccm_icv_length; i++)
523 {
524 icv[i] = A[i] ^ icv[i];
525 }
526 }
527
528 #ifdef NX_SECURE_KEY_CLEAR
529 NX_CRYPTO_MEMSET(ccm_metadata, 0, sizeof(NX_CRYPTO_CCM));
530 #endif
531
532 return(NX_CRYPTO_SUCCESS);
533 }
534
535 /**************************************************************************/
536 /* */
537 /* FUNCTION RELEASE */
538 /* */
539 /* _nx_crypto_ccm_decrypt_calculate PORTABLE C */
540 /* 6.1 */
541 /* AUTHOR */
542 /* */
543 /* Timothy Stapko, Microsoft Corporation */
544 /* */
545 /* DESCRIPTION */
546 /* */
547 /* This function verifies the TAG for CCM mode. */
548 /* */
549 /* INPUT */
550 /* */
551 /* crypto_metadata Pointer to crypto metadata */
552 /* gcm_metadata Pointer to GCM metadata */
553 /* crypto_function Pointer to crypto function */
554 /* icv Pointer to TAG buffer */
555 /* block_size Block size of crypto algorithm*/
556 /* */
557 /* OUTPUT */
558 /* */
559 /* status */
560 /* */
561 /* CALLS */
562 /* */
563 /* None */
564 /* */
565 /* CALLED BY */
566 /* */
567 /* _nx_crypto_method_aes_ccm_operation Handle AES encrypt or decrypt */
568 /* */
569 /* RELEASE HISTORY */
570 /* */
571 /* DATE NAME DESCRIPTION */
572 /* */
573 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
574 /* 09-30-2020 Timothy Stapko Modified comment(s), */
575 /* verified memcpy use cases, */
576 /* resulting in version 6.1 */
577 /* */
578 /**************************************************************************/
_nx_crypto_ccm_decrypt_calculate(VOID * crypto_metadata,NX_CRYPTO_CCM * ccm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * icv,UINT block_size)579 NX_CRYPTO_KEEP UINT _nx_crypto_ccm_decrypt_calculate(VOID *crypto_metadata, NX_CRYPTO_CCM *ccm_metadata,
580 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
581 UCHAR *icv, UINT block_size)
582 {
583 UCHAR temp[NX_CRYPTO_CCM_BLOCK_SIZE];
584 UINT i;
585
586 /* Check the block size. */
587 if (block_size != NX_CRYPTO_CCM_BLOCK_SIZE)
588 {
589 return(NX_CRYPTO_PTR_ERROR);
590 }
591
592 /* Data authentication. */
593 if (ccm_metadata -> nx_crypto_ccm_icv_length > 0)
594 {
595
596 NX_CRYPTO_MEMCPY(temp, ccm_metadata -> nx_crypto_ccm_A, block_size); /* Use case of memcpy is verified. */
597 temp[15] = 0;
598 crypto_function(crypto_metadata, temp, temp, block_size);
599
600 /* Encrypt authentication tag. */
601 for (i = 0; i < ccm_metadata -> nx_crypto_ccm_icv_length; i++)
602 {
603 temp[i] = temp[i] ^ icv[i];
604 }
605
606 /* The authentication tag T is the leftmost M bytes of the CBC-MAC value X(t + 1). */
607 if (NX_CRYPTO_MEMCMP(temp, ccm_metadata -> nx_crypto_ccm_X, ccm_metadata -> nx_crypto_ccm_icv_length))
608 {
609
610 /* Authentication failed. */
611 return(NX_CRYPTO_AUTHENTICATION_FAILED);
612 }
613 }
614
615 #ifdef NX_SECURE_KEY_CLEAR
616 NX_CRYPTO_MEMSET(ccm_metadata, 0, sizeof(NX_CRYPTO_CCM));
617 #endif
618
619 return(NX_CRYPTO_SUCCESS);
620 }
621