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