mcxn547_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file mcxn547_crypto_cipher.c
3  * @brief NXP MCX N547 cipher hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include <mcuxClEls.h>
36 #include "core/crypto.h"
41 #include "aead/aead_algorithms.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (MCXN547_CRYPTO_CIPHER_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Perform AES encryption or decryption
50  * @param[in] context AES algorithm context
51  * @param[in,out] iv Initialization vector
52  * @param[in] input Data to be encrypted/decrypted
53  * @param[out] output Data resulting from the encryption/decryption process
54  * @param[in] length Total number of data bytes to be processed
55  * @param[in] algo Cipher algorithm
56  * @param[in] mode Operation mode
57  * @return Error code
58  **/
59 
60 error_t aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input,
61  uint8_t *output, size_t length, uint32_t algo, uint32_t mode)
62 {
63  error_t error;
64  size_t keyLen;
65  mcuxClEls_CipherOption_t options;
66 
67  //Initialize status code
68  error = NO_ERROR;
69 
70  //Check the length of the key
71  if(context->nr == 10)
72  {
73  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_128;
74  }
75  else if(context->nr == 12)
76  {
77  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_192;
78  }
79  else
80  {
81  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_256;
82  }
83 
84  //Configure cipher mode
85  options.word.value = 0;
86  options.bits.dcrpt = mode;
87  options.bits.cphmde = algo;
88  options.bits.extkey = MCUXCLELS_CIPHER_EXTERNAL_KEY;
89 
90  //Acquire exclusive access to the ELS module
92 
93  //Perform AES encryption/decryption
94  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Cipher_Async(
95  options, 0, (uint8_t *) context->ek, keyLen, input, length, iv, output));
96 
97  //Check the protection token and the return value
98  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Cipher_Async) ||
99  status != MCUXCLELS_STATUS_OK_WAIT)
100  {
101  error = ERROR_FAILURE;
102  }
103 
104  //End of function call
105  MCUX_CSSL_FP_FUNCTION_CALL_END();
106 
107  //Check status code
108  if(!error)
109  {
110  //Wait for the operation to complete
111  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
112  MCUXCLELS_ERROR_FLAGS_CLEAR));
113 
114  //Check the protection token and the return value
115  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
116  status != MCUXCLELS_STATUS_OK)
117  {
118  error = ERROR_FAILURE;
119  }
120 
121  //End of function call
122  MCUX_CSSL_FP_FUNCTION_CALL_END();
123  }
124 
125  //Release exclusive access to the ELS module
127 
128  //Return status code
129  return error;
130 }
131 
132 
133 /**
134  * @brief Key expansion
135  * @param[in] context Pointer to the AES context to initialize
136  * @param[in] key Pointer to the key
137  * @param[in] keyLen Length of the key
138  * @return Error code
139  **/
140 
141 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
142 {
143  //Check parameters
144  if(context == NULL || key == NULL)
146 
147  //Check the length of the key
148  if(keyLen == 16)
149  {
150  //10 rounds are required for 128-bit key
151  context->nr = 10;
152  }
153  else if(keyLen == 24)
154  {
155  //12 rounds are required for 192-bit key
156  context->nr = 12;
157  }
158  else if(keyLen == 32)
159  {
160  //14 rounds are required for 256-bit key
161  context->nr = 14;
162  }
163  else
164  {
165  //Report an error
167  }
168 
169  //Copy the key
170  osMemcpy(context->ek, key, keyLen);
171 
172  //No error to report
173  return NO_ERROR;
174 }
175 
176 
177 /**
178  * @brief Encrypt a 16-byte block using AES algorithm
179  * @param[in] context Pointer to the AES context
180  * @param[in] input Plaintext block to encrypt
181  * @param[out] output Ciphertext block resulting from encryption
182  **/
183 
184 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
185 {
186  //Perform AES encryption
187  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
188  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
189 }
190 
191 
192 /**
193  * @brief Decrypt a 16-byte block using AES algorithm
194  * @param[in] context Pointer to the AES context
195  * @param[in] input Ciphertext block to decrypt
196  * @param[out] output Plaintext block resulting from decryption
197  **/
198 
199 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
200 {
201  //Perform AES encryption
202  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
203  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_DECRYPT);
204 }
205 
206 
207 #if (ECB_SUPPORT == ENABLED)
208 
209 /**
210  * @brief ECB encryption
211  * @param[in] cipher Cipher algorithm
212  * @param[in] context Cipher algorithm context
213  * @param[in] p Plaintext to be encrypted
214  * @param[out] c Ciphertext resulting from the encryption
215  * @param[in] length Total number of data bytes to be encrypted
216  * @return Error code
217  **/
218 
219 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
220  const uint8_t *p, uint8_t *c, size_t length)
221 {
222  error_t error;
223 
224  //Initialize status code
225  error = NO_ERROR;
226 
227  //AES cipher algorithm?
228  if(cipher == AES_CIPHER_ALGO)
229  {
230  //Check the length of the payload
231  if(length == 0)
232  {
233  //No data to process
234  }
235  else if((length % AES_BLOCK_SIZE) == 0)
236  {
237  //Encrypt payload data
238  error = aesProcessData(context, NULL, p, c, length,
239  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
240  }
241  else
242  {
243  //The length of the payload must be a multiple of the block size
244  error = ERROR_INVALID_LENGTH;
245  }
246  }
247  else
248  {
249  //ECB mode operates in a block-by-block fashion
250  while(length >= cipher->blockSize)
251  {
252  //Encrypt current block
253  cipher->encryptBlock(context, p, c);
254 
255  //Next block
256  p += cipher->blockSize;
257  c += cipher->blockSize;
258  length -= cipher->blockSize;
259  }
260 
261  //The length of the payload must be a multiple of the block size
262  if(length != 0)
263  {
264  error = ERROR_INVALID_LENGTH;
265  }
266  }
267 
268  //Return status code
269  return error;
270 }
271 
272 
273 /**
274  * @brief ECB decryption
275  * @param[in] cipher Cipher algorithm
276  * @param[in] context Cipher algorithm context
277  * @param[in] c Ciphertext to be decrypted
278  * @param[out] p Plaintext resulting from the decryption
279  * @param[in] length Total number of data bytes to be decrypted
280  * @return Error code
281  **/
282 
283 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
284  const uint8_t *c, uint8_t *p, size_t length)
285 {
286  error_t error;
287 
288  //Initialize status code
289  error = NO_ERROR;
290 
291  //AES cipher algorithm?
292  if(cipher == AES_CIPHER_ALGO)
293  {
294  //Check the length of the payload
295  if(length == 0)
296  {
297  //No data to process
298  }
299  else if((length % AES_BLOCK_SIZE) == 0)
300  {
301  //Decrypt payload data
302  error = aesProcessData(context, NULL, c, p, length,
303  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_DECRYPT);
304  }
305  else
306  {
307  //The length of the payload must be a multiple of the block size
308  error = ERROR_INVALID_LENGTH;
309  }
310  }
311  else
312  {
313  //ECB mode operates in a block-by-block fashion
314  while(length >= cipher->blockSize)
315  {
316  //Decrypt current block
317  cipher->decryptBlock(context, c, p);
318 
319  //Next block
320  c += cipher->blockSize;
321  p += cipher->blockSize;
322  length -= cipher->blockSize;
323  }
324 
325  //The length of the payload must be a multiple of the block size
326  if(length != 0)
327  {
328  error = ERROR_INVALID_LENGTH;
329  }
330  }
331 
332  //Return status code
333  return error;
334 }
335 
336 #endif
337 #if (CBC_SUPPORT == ENABLED)
338 
339 /**
340  * @brief CBC encryption
341  * @param[in] cipher Cipher algorithm
342  * @param[in] context Cipher algorithm context
343  * @param[in,out] iv Initialization vector
344  * @param[in] p Plaintext to be encrypted
345  * @param[out] c Ciphertext resulting from the encryption
346  * @param[in] length Total number of data bytes to be encrypted
347  * @return Error code
348  **/
349 
350 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
351  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
352 {
353  error_t error;
354 
355  //Initialize status code
356  error = NO_ERROR;
357 
358  //AES cipher algorithm?
359  if(cipher == AES_CIPHER_ALGO)
360  {
361  //Check the length of the payload
362  if(length == 0)
363  {
364  //No data to process
365  }
366  else if((length % AES_BLOCK_SIZE) == 0)
367  {
368  //Encrypt payload data
369  error = aesProcessData(context, iv, p, c, length,
370  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CBC, MCUXCLELS_CIPHER_ENCRYPT);
371  }
372  else
373  {
374  //The length of the payload must be a multiple of the block size
375  error = ERROR_INVALID_LENGTH;
376  }
377  }
378  else
379  {
380  size_t i;
381 
382  //CBC mode operates in a block-by-block fashion
383  while(length >= cipher->blockSize)
384  {
385  //XOR input block with IV contents
386  for(i = 0; i < cipher->blockSize; i++)
387  {
388  c[i] = p[i] ^ iv[i];
389  }
390 
391  //Encrypt the current block based upon the output of the previous
392  //encryption
393  cipher->encryptBlock(context, c, c);
394 
395  //Update IV with output block contents
396  osMemcpy(iv, c, cipher->blockSize);
397 
398  //Next block
399  p += cipher->blockSize;
400  c += cipher->blockSize;
401  length -= cipher->blockSize;
402  }
403 
404  //The length of the payload must be a multiple of the block size
405  if(length != 0)
406  {
407  error = ERROR_INVALID_LENGTH;
408  }
409  }
410 
411  //Return status code
412  return error;
413 }
414 
415 
416 /**
417  * @brief CBC decryption
418  * @param[in] cipher Cipher algorithm
419  * @param[in] context Cipher algorithm context
420  * @param[in,out] iv Initialization vector
421  * @param[in] c Ciphertext to be decrypted
422  * @param[out] p Plaintext resulting from the decryption
423  * @param[in] length Total number of data bytes to be decrypted
424  * @return Error code
425  **/
426 
427 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
428  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
429 {
430  error_t error;
431 
432  //Initialize status code
433  error = NO_ERROR;
434 
435  //AES cipher algorithm?
436  if(cipher == AES_CIPHER_ALGO)
437  {
438  //Check the length of the payload
439  if(length == 0)
440  {
441  //No data to process
442  }
443  else if((length % AES_BLOCK_SIZE) == 0)
444  {
445  //Decrypt payload data
446  error = aesProcessData(context, iv, c, p, length,
447  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CBC, MCUXCLELS_CIPHER_DECRYPT);
448  }
449  else
450  {
451  //The length of the payload must be a multiple of the block size
452  error = ERROR_INVALID_LENGTH;
453  }
454  }
455  else
456  {
457  size_t i;
458  uint8_t t[16];
459 
460  //CBC mode operates in a block-by-block fashion
461  while(length >= cipher->blockSize)
462  {
463  //Save input block
464  osMemcpy(t, c, cipher->blockSize);
465 
466  //Decrypt the current block
467  cipher->decryptBlock(context, c, p);
468 
469  //XOR output block with IV contents
470  for(i = 0; i < cipher->blockSize; i++)
471  {
472  p[i] ^= iv[i];
473  }
474 
475  //Update IV with input block contents
476  osMemcpy(iv, t, cipher->blockSize);
477 
478  //Next block
479  c += cipher->blockSize;
480  p += cipher->blockSize;
481  length -= cipher->blockSize;
482  }
483 
484  //The length of the payload must be a multiple of the block size
485  if(length != 0)
486  {
487  error = ERROR_INVALID_LENGTH;
488  }
489  }
490 
491  //Return status code
492  return error;
493 }
494 
495 #endif
496 #if (CTR_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
497 
498 /**
499  * @brief CTR encryption
500  * @param[in] cipher Cipher algorithm
501  * @param[in] context Cipher algorithm context
502  * @param[in] m Size in bits of the specific part of the block to be incremented
503  * @param[in,out] t Initial counter block
504  * @param[in] p Plaintext to be encrypted
505  * @param[out] c Ciphertext resulting from the encryption
506  * @param[in] length Total number of data bytes to be encrypted
507  * @return Error code
508  **/
509 
510 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
511  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
512 {
513  error_t error;
514 
515  //Initialize status code
516  error = NO_ERROR;
517 
518  //Check the value of the parameter
519  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
520  {
521  //Determine the size, in bytes, of the specific part of the block
522  //to be incremented
523  m = m / 8;
524 
525  //AES cipher algorithm?
526  if(cipher == AES_CIPHER_ALGO)
527  {
528  size_t k;
529  size_t n;
530 
531  //Process plaintext
532  while(length > 0 && !error)
533  {
534  //Limit the number of blocks to process at a time
535  k = 256 - t[AES_BLOCK_SIZE - 1];
536  n = MIN(length, k * AES_BLOCK_SIZE);
537  k = (n + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
538 
539  //Encrypt payload data
540  error = aesProcessData(context, t, p, c, n,
541  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CTR,
542  MCUXCLELS_CIPHER_ENCRYPT);
543 
544  //Standard incrementing function
546 
547  //Next block
548  p += n;
549  c += n;
550  length -= n;
551  }
552  }
553  else
554  {
555  size_t i;
556  size_t n;
557  uint8_t o[16];
558 
559  //Process plaintext
560  while(length > 0)
561  {
562  //CTR mode operates in a block-by-block fashion
563  n = MIN(length, cipher->blockSize);
564 
565  //Compute O(j) = CIPH(T(j))
566  cipher->encryptBlock(context, t, o);
567 
568  //Compute C(j) = P(j) XOR T(j)
569  for(i = 0; i < n; i++)
570  {
571  c[i] = p[i] ^ o[i];
572  }
573 
574  //Standard incrementing function
575  ctrIncBlock(t, 1, cipher->blockSize, m);
576 
577  //Next block
578  p += n;
579  c += n;
580  length -= n;
581  }
582  }
583  }
584  else
585  {
586  //The value of the parameter is not valid
587  error = ERROR_INVALID_PARAMETER;
588  }
589 
590  //Return status code
591  return error;
592 }
593 
594 #endif
595 #if (GCM_SUPPORT == ENABLED)
596 
597 /**
598  * @brief Perform AES-GCM encryption or decryption
599  * @param[in] context AES algorithm context
600  * @param[in] iv Initialization vector
601  * @param[in] a Additional authenticated data
602  * @param[in] aLen Length of the additional data
603  * @param[in] input Data to be encrypted/decrypted
604  * @param[out] output Data resulting from the encryption/decryption process
605  * @param[in] length Total number of data bytes to be processed
606  * @param[out] t Authentication tag
607  * @param[in] mode Operation mode
608  * @return Error code
609  **/
610 
611 error_t gcmProcessData(AesContext *context, const uint8_t *iv,
612  const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output,
613  size_t length, uint8_t *t, uint32_t mode)
614 {
615  error_t error;
616  size_t i;
617  size_t n;
618  size_t keyLen;
619  mcuxClEls_AeadOption_t options;
620  uint8_t block[AES_BLOCK_SIZE];
621  uint8_t aeadContext[MCUXCLELS_AEAD_CONTEXT_SIZE];
622 
623  //Initialize status code
624  error = NO_ERROR;
625 
626  //Check the length of the key
627  if(context->nr == 10)
628  {
629  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_128;
630  }
631  else if(context->nr == 12)
632  {
633  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_192;
634  }
635  else
636  {
637  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_256;
638  }
639 
640  //Configure cipher mode
641  options.word.value = 0;
642  options.bits.dcrpt = mode;
643  options.bits.extkey = MCUXCLELS_CIPHER_EXTERNAL_KEY;
644 
645  //Set initialization vector
646  osMemcpy(block, iv, 12);
647  block[12] = 0;
648  block[13] = 0;
649  block[14] = 0;
650  block[15] = 1;
651 
652  //Acquire exclusive access to the ELS module
654 
655  //Initialize GCM encryption/decryption
656  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_Init_Async(
657  options, 0, (uint8_t *) context->ek, keyLen, block, AES_BLOCK_SIZE,
658  aeadContext));
659 
660  //Check the protection token and the return value
661  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_Init_Async) ||
662  status != MCUXCLELS_STATUS_OK_WAIT)
663  {
664  error = ERROR_FAILURE;
665  }
666 
667  //End of function call
668  MCUX_CSSL_FP_FUNCTION_CALL_END();
669 
670  //Check status code
671  if(!error)
672  {
673  //Wait for the operation to complete
674  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
675  MCUXCLELS_ERROR_FLAGS_CLEAR));
676 
677  //Check the protection token and the return value
678  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
679  status != MCUXCLELS_STATUS_OK)
680  {
681  error = ERROR_FAILURE;
682  }
683 
684  //End of function call
685  MCUX_CSSL_FP_FUNCTION_CALL_END();
686  }
687 
688  //Process additional authenticated data
689  for(i = 0; i < aLen && !error; i += n)
690  {
691  //Last block?
692  if((aLen - i) < AES_BLOCK_SIZE)
693  {
694  //Determine the length of the partial block
695  n = aLen - i;
696 
697  //Copy the partial block
699  osMemcpy(block, a + i, n);
700 
701  //Process data
702  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_UpdateAad_Async(
703  options, 0, (uint8_t *) context->ek, keyLen, block, AES_BLOCK_SIZE,
704  aeadContext));
705 
706  //Check the protection token and the return value
707  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_UpdateAad_Async) ||
708  status != MCUXCLELS_STATUS_OK_WAIT)
709  {
710  error = ERROR_FAILURE;
711  }
712 
713  //End of function call
714  MCUX_CSSL_FP_FUNCTION_CALL_END();
715  }
716  else
717  {
718  //Process complete blocks only
719  n = aLen - (aLen % AES_BLOCK_SIZE);
720 
721  //Process data
722  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_UpdateAad_Async(
723  options, 0, (uint8_t *) context->ek, keyLen, a, n, aeadContext));
724 
725  //Check the protection token and the return value
726  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_UpdateAad_Async) ||
727  status != MCUXCLELS_STATUS_OK_WAIT)
728  {
729  error = ERROR_FAILURE;
730  }
731 
732  //End of function call
733  MCUX_CSSL_FP_FUNCTION_CALL_END();
734  }
735 
736  //Check status code
737  if(!error)
738  {
739  //Wait for the operation to complete
740  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
741  MCUXCLELS_ERROR_FLAGS_CLEAR));
742 
743  //Check the protection token and the return value
744  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
745  status != MCUXCLELS_STATUS_OK)
746  {
747  error = ERROR_FAILURE;
748  }
749 
750  //End of function call
751  MCUX_CSSL_FP_FUNCTION_CALL_END();
752  }
753  }
754 
755  //Process payload data
756  for(i = 0; i < length && !error; i += n)
757  {
758  //Last block?
759  if((length - i) < AES_BLOCK_SIZE)
760  {
761  //Determine the length of the partial block
762  n = length - i;
763 
764  //Copy the partial block
766  osMemcpy(block, input + i, n);
767 
768  //Specify the number of bytes in the last block
769  options.bits.msgendw = n;
770 
771  //Process data
772  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_UpdateData_Async(
773  options, 0, (uint8_t *) context->ek, keyLen, block, AES_BLOCK_SIZE,
774  block, aeadContext));
775 
776  //Check the protection token and the return value
777  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_UpdateData_Async) ||
778  status != MCUXCLELS_STATUS_OK_WAIT)
779  {
780  error = ERROR_FAILURE;
781  }
782 
783  //End of function call
784  MCUX_CSSL_FP_FUNCTION_CALL_END();
785  }
786  else
787  {
788  //Process complete blocks only
789  n = length - (length % AES_BLOCK_SIZE);
790 
791  //Process data
792  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_UpdateData_Async(
793  options, 0, (uint8_t *) context->ek, keyLen, input, n, output,
794  aeadContext));
795 
796  //Check the protection token and the return value
797  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_UpdateData_Async) ||
798  status != MCUXCLELS_STATUS_OK_WAIT)
799  {
800  error = ERROR_FAILURE;
801  }
802 
803  //End of function call
804  MCUX_CSSL_FP_FUNCTION_CALL_END();
805  }
806 
807  //Check status code
808  if(!error)
809  {
810  //Wait for the operation to complete
811  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
812  MCUXCLELS_ERROR_FLAGS_CLEAR));
813 
814  //Check the protection token and the return value
815  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
816  status != MCUXCLELS_STATUS_OK)
817  {
818  error = ERROR_FAILURE;
819  }
820 
821  //End of function call
822  MCUX_CSSL_FP_FUNCTION_CALL_END();
823  }
824 
825  //Check status code
826  if(!error)
827  {
828  //Last block?
829  if((length - i) < AES_BLOCK_SIZE)
830  {
831  //Copy the partial block
832  osMemcpy(output + i, block, n);
833  }
834  }
835  }
836 
837  //Check status code
838  if(!error)
839  {
840  //Finalize GCM encryption/decryption
841  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Aead_Finalize_Async(
842  options, 0, (uint8_t *) context->ek, keyLen, aLen, length, t,
843  aeadContext));
844 
845  //Check the protection token and the return value
846  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Aead_Finalize_Async) ||
847  status != MCUXCLELS_STATUS_OK_WAIT)
848  {
849  error = ERROR_FAILURE;
850  }
851 
852  //End of function call
853  MCUX_CSSL_FP_FUNCTION_CALL_END();
854  }
855 
856  //Check status code
857  if(!error)
858  {
859  //Wait for the operation to complete
860  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
861  MCUXCLELS_ERROR_FLAGS_CLEAR));
862 
863  //Check the protection token and the return value
864  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
865  status != MCUXCLELS_STATUS_OK)
866  {
867  error = ERROR_FAILURE;
868  }
869 
870  //End of function call
871  MCUX_CSSL_FP_FUNCTION_CALL_END();
872  }
873 
874  //Release exclusive access to the ELS module
876 
877  //Return status code
878  return error;
879 }
880 
881 
882 /**
883  * @brief Initialize GCM context
884  * @param[in] context Pointer to the GCM context
885  * @param[in] cipherAlgo Cipher algorithm
886  * @param[in] cipherContext Pointer to the cipher algorithm context
887  * @return Error code
888  **/
889 
890 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
891  void *cipherContext)
892 {
893  //Check parameters
894  if(context == NULL || cipherContext == NULL)
896 
897  //The ELS module only supports AES cipher algorithm
898  if(cipherAlgo != AES_CIPHER_ALGO)
900 
901  //Save cipher algorithm context
902  context->cipherAlgo = cipherAlgo;
903  context->cipherContext = cipherContext;
904 
905  //Successful initialization
906  return NO_ERROR;
907 }
908 
909 
910 /**
911  * @brief Authenticated encryption using GCM
912  * @param[in] context Pointer to the GCM context
913  * @param[in] iv Initialization vector
914  * @param[in] ivLen Length of the initialization vector
915  * @param[in] a Additional authenticated data
916  * @param[in] aLen Length of the additional data
917  * @param[in] p Plaintext to be encrypted
918  * @param[out] c Ciphertext resulting from the encryption
919  * @param[in] length Total number of data bytes to be encrypted
920  * @param[out] t Authentication tag
921  * @param[in] tLen Length of the authentication tag
922  * @return Error code
923  **/
924 
925 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
926  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
927  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
928 {
929  error_t error;
930  uint8_t authTag[16];
931 
932  //Make sure the GCM context is valid
933  if(context == NULL)
935 
936  //Check whether the length of the IV is 96 bits
937  if(ivLen != 12)
938  return ERROR_INVALID_LENGTH;
939 
940  //Check the length of the authentication tag
941  if(tLen < 4 || tLen > 16)
942  return ERROR_INVALID_LENGTH;
943 
944  //Perform AES-GCM encryption
945  error = gcmProcessData(context->cipherContext, iv, a, aLen, p, c, length,
946  authTag, MCUXCLELS_AEAD_ENCRYPT);
947 
948  //Check status code
949  if(!error)
950  {
951  //Copy the resulting authentication tag
952  osMemcpy(t, authTag, tLen);
953  }
954 
955  //Return status code
956  return error;
957 }
958 
959 
960 /**
961  * @brief Authenticated decryption using GCM
962  * @param[in] context Pointer to the GCM context
963  * @param[in] iv Initialization vector
964  * @param[in] ivLen Length of the initialization vector
965  * @param[in] a Additional authenticated data
966  * @param[in] aLen Length of the additional data
967  * @param[in] c Ciphertext to be decrypted
968  * @param[out] p Plaintext resulting from the decryption
969  * @param[in] length Total number of data bytes to be decrypted
970  * @param[in] t Authentication tag
971  * @param[in] tLen Length of the authentication tag
972  * @return Error code
973  **/
974 
975 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
976  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
977  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
978 {
979  error_t error;
980  size_t i;
981  uint8_t mask;
982  uint8_t authTag[16];
983 
984  //Make sure the GCM context is valid
985  if(context == NULL)
987 
988  //Check whether the length of the IV is 96 bits
989  if(ivLen != 12)
990  return ERROR_INVALID_LENGTH;
991 
992  //Check the length of the authentication tag
993  if(tLen < 4 || tLen > 16)
994  return ERROR_INVALID_LENGTH;
995 
996  //Perform AES-GCM decryption
997  error = gcmProcessData(context->cipherContext, iv, a, aLen, c, p, length,
998  authTag, MCUXCLELS_AEAD_DECRYPT);
999 
1000  //Check status code
1001  if(!error)
1002  {
1003  //The calculated tag is bitwise compared to the received tag
1004  for(mask = 0, i = 0; i < tLen; i++)
1005  {
1006  mask |= authTag[i] ^ t[i];
1007  }
1008 
1009  //The message is authenticated if and only if the tags match
1010  error = (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1011  }
1012 
1013  //Return status code
1014  return error;
1015 }
1016 
1017 #endif
1018 #if (CCM_SUPPORT == ENABLED)
1019 
1020 /**
1021  * @brief Update CCM authentication tag
1022  * @param[in] context AES algorithm context
1023  * @param[in] input Data to be processed
1024  * @param[in] length Total number of data bytes to be processed
1025  * @param[in,out] t Authentication tag
1026  * @return Error code
1027  **/
1028 
1029 error_t ccmProcessData(AesContext *context, const uint8_t *input, size_t length,
1030  uint8_t *t)
1031 {
1032  error_t error;
1033  size_t keyLen;
1034  mcuxClEls_CmacOption_t cmacOptions;
1035 
1036  //Initialize status code
1037  error = NO_ERROR;
1038 
1039  //Check the length of the key
1040  if(context->nr == 10)
1041  {
1042  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_128;
1043  }
1044  else if(context->nr == 12)
1045  {
1046  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_192;
1047  }
1048  else
1049  {
1050  keyLen = MCUXCLELS_CIPHER_KEY_SIZE_AES_256;
1051  }
1052 
1053  //Configure CMAC operation
1054  cmacOptions.word.value = 0;
1055  cmacOptions.bits.initialize = MCUXCLELS_CMAC_INITIALIZE_DISABLE;
1056  cmacOptions.bits.finalize = MCUXCLELS_CMAC_FINALIZE_DISABLE;
1057  cmacOptions.bits.extkey = MCUXCLELS_CMAC_EXTERNAL_KEY_ENABLE;
1058 
1059  //Perform CMAC operation
1060  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_Cmac_Async(
1061  cmacOptions, 0, (uint8_t *) context->ek, keyLen, input, length, t));
1062 
1063  //Check the protection token and the return value
1064  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Cmac_Async) ||
1065  status != MCUXCLELS_STATUS_OK_WAIT)
1066  {
1067  error = ERROR_FAILURE;
1068  }
1069 
1070  //End of function call
1071  MCUX_CSSL_FP_FUNCTION_CALL_END();
1072 
1073  //Check status code
1074  if(!error)
1075  {
1076  //Wait for the operation to complete
1077  MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(status, token, mcuxClEls_WaitForOperation(
1078  MCUXCLELS_ERROR_FLAGS_CLEAR));
1079 
1080  //Check the protection token and the return value
1081  if(token != MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) ||
1082  status != MCUXCLELS_STATUS_OK)
1083  {
1084  error = ERROR_FAILURE;
1085  }
1086 
1087  //End of function call
1088  MCUX_CSSL_FP_FUNCTION_CALL_END();
1089  }
1090 
1091  //Return status code
1092  return error;
1093 }
1094 
1095 
1096 /**
1097  * @brief Authenticated encryption using CCM
1098  * @param[in] cipher Cipher algorithm
1099  * @param[in] context Cipher algorithm context
1100  * @param[in] n Nonce
1101  * @param[in] nLen Length of the nonce
1102  * @param[in] a Additional authenticated data
1103  * @param[in] aLen Length of the additional data
1104  * @param[in] p Plaintext to be encrypted
1105  * @param[out] c Ciphertext resulting from the encryption
1106  * @param[in] length Total number of data bytes to be encrypted
1107  * @param[out] t MAC resulting from the encryption process
1108  * @param[in] tLen Length of the MAC
1109  * @return Error code
1110  **/
1111 
1112 error_t ccmEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *n,
1113  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c,
1114  size_t length, uint8_t *t, size_t tLen)
1115 {
1116  error_t error;
1117  size_t i;
1118  size_t j;
1119  size_t m;
1120  uint8_t ctr[AES_BLOCK_SIZE];
1121  uint8_t block[AES_BLOCK_SIZE];
1122  uint8_t authTag[AES_BLOCK_SIZE];
1123 
1124  //The ELS module only supports AES cipher algorithm
1125  if(cipher != AES_CIPHER_ALGO)
1126  return ERROR_INVALID_PARAMETER;
1127 
1128  //Make sure the cipher context is valid
1129  if(context == NULL)
1130  return ERROR_INVALID_PARAMETER;
1131 
1132  //Format first block B(0)
1133  error = ccmFormatBlock0(length, n, nLen, aLen, tLen, block);
1134  //Invalid parameters?
1135  if(error)
1136  return error;
1137 
1138  //Acquire exclusive access to the ELS module
1140 
1141  //Calculate CIPH(B0)
1142  error = aesProcessData(context, NULL, block, authTag, AES_BLOCK_SIZE,
1143  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
1144 
1145  //Check status code
1146  if(!error)
1147  {
1148  //Any additional data?
1149  if(aLen > 0)
1150  {
1151  //Format the associated data
1152  osMemset(block, 0, 16);
1153 
1154  //Check the length of the associated data string
1155  if(aLen < 0xFF00)
1156  {
1157  //The length is encoded as 2 octets
1158  STORE16BE(aLen, block);
1159 
1160  //Number of bytes to copy
1161  m = MIN(aLen, 16 - 2);
1162  //Concatenate the associated data A
1163  osMemcpy(block + 2, a, m);
1164  }
1165  else
1166  {
1167  //The length is encoded as 6 octets
1168  block[0] = 0xFF;
1169  block[1] = 0xFE;
1170 
1171  //MSB is stored first
1172  STORE32BE(aLen, block + 2);
1173 
1174  //Number of bytes to copy
1175  m = MIN(aLen, 16 - 6);
1176  //Concatenate the associated data A
1177  osMemcpy(block + 6, a, m);
1178  }
1179 
1180  //Process data
1181  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1182  }
1183  else
1184  {
1185  //No additional data
1186  m = 0;
1187  }
1188  }
1189 
1190  //Process the remaining bytes of the associated data
1191  for(i = m; i < aLen && !error; i += m)
1192  {
1193  //Last block?
1194  if((aLen - i) < AES_BLOCK_SIZE)
1195  {
1196  //Determine the length of the partial block
1197  m = aLen - i;
1198 
1199  //Copy the partial block
1201  osMemcpy(block, a + i, m);
1202 
1203  //Process data
1204  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1205  }
1206  else
1207  {
1208  //Process complete blocks only
1209  m = (aLen - i) - ((aLen - i) % AES_BLOCK_SIZE);
1210 
1211  //Process data
1212  error = ccmProcessData(context, a + i, m, authTag);
1213  }
1214  }
1215 
1216  //Process payload data
1217  for(i = 0; i < length && !error; i += m)
1218  {
1219  //Last block?
1220  if((length - i) < AES_BLOCK_SIZE)
1221  {
1222  //Determine the length of the partial block
1223  m = length - i;
1224 
1225  //Copy the partial block
1227  osMemcpy(block, p + i, m);
1228 
1229  //Process data
1230  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1231  }
1232  else
1233  {
1234  //Process complete blocks only
1235  m = length - (length % AES_BLOCK_SIZE);
1236 
1237  //Process data
1238  error = ccmProcessData(context, p, m, authTag);
1239  }
1240  }
1241 
1242  //Check status code
1243  if(!error)
1244  {
1245  //Format initial counter value CTR(0)
1246  ccmFormatCounter0(n, nLen, ctr);
1247 
1248  //Calculate CIPH(CTR0)
1249  error = aesProcessData(context, NULL, ctr, block, AES_BLOCK_SIZE,
1250  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
1251  }
1252 
1253  //Check status code
1254  if(!error)
1255  {
1256  //Compute MAC
1257  ccmXorBlock(authTag, authTag, block, tLen);
1258  //Increment counter block
1259  ccmIncCounter(ctr, 15 - nLen);
1260  }
1261 
1262  //Encrypt plaintext
1263  for(i = 0; i < length && !error; i += m)
1264  {
1265  //Last block?
1266  if((length - i) < AES_BLOCK_SIZE)
1267  {
1268  //Determine the length of the partial block
1269  m = length - i;
1270 
1271  //Copy the partial block
1273  osMemcpy(block, p + i, m);
1274 
1275  //Process data
1276  error = aesProcessData(context, ctr, block, block, AES_BLOCK_SIZE,
1277  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CTR, MCUXCLELS_CIPHER_ENCRYPT);
1278 
1279  //Check status code
1280  if(!error)
1281  {
1282  //Copy the partial block
1283  osMemcpy(c + i, block, m);
1284  }
1285  }
1286  else
1287  {
1288  //Process complete blocks only
1289  m = length - (length % AES_BLOCK_SIZE);
1290 
1291  //Process data
1292  error = aesProcessData(context, ctr, p + i, c + i, m,
1293  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CTR, MCUXCLELS_CIPHER_ENCRYPT);
1294 
1295  //Increment counter block
1296  for(j = 0; j < m; j += AES_BLOCK_SIZE)
1297  {
1298  ccmIncCounter(ctr, 15 - nLen);
1299  }
1300  }
1301  }
1302 
1303  //Release exclusive access to the ELS module
1305 
1306  //Check status code
1307  if(!error)
1308  {
1309  //Copy the resulting authentication tag
1310  osMemcpy(t, authTag, tLen);
1311  }
1312 
1313  //Return status code
1314  return error;
1315 }
1316 
1317 
1318 /**
1319  * @brief Authenticated decryption using CCM
1320  * @param[in] cipher Cipher algorithm
1321  * @param[in] context Cipher algorithm context
1322  * @param[in] n Nonce
1323  * @param[in] nLen Length of the nonce
1324  * @param[in] a Additional authenticated data
1325  * @param[in] aLen Length of the additional data
1326  * @param[in] c Ciphertext to be decrypted
1327  * @param[out] p Plaintext resulting from the decryption
1328  * @param[in] length Total number of data bytes to be decrypted
1329  * @param[in] t MAC to be verified
1330  * @param[in] tLen Length of the MAC
1331  * @return Error code
1332  **/
1333 
1334 error_t ccmDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *n,
1335  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p,
1336  size_t length, const uint8_t *t, size_t tLen)
1337 {
1338  error_t error;
1339  size_t i;
1340  size_t j;
1341  size_t m;
1342  uint8_t ctr[AES_BLOCK_SIZE];
1343  uint8_t block[AES_BLOCK_SIZE];
1344  uint8_t authTag[AES_BLOCK_SIZE];
1345 
1346  //The ELS module only supports AES cipher algorithm
1347  if(cipher != AES_CIPHER_ALGO)
1348  return ERROR_INVALID_PARAMETER;
1349 
1350  //Make sure the cipher context is valid
1351  if(context == NULL)
1352  return ERROR_INVALID_PARAMETER;
1353 
1354  //Format first block B(0)
1355  error = ccmFormatBlock0(length, n, nLen, aLen, tLen, block);
1356  //Invalid parameters?
1357  if(error)
1358  return error;
1359 
1360  //Format initial counter value CTR(0)
1361  ccmFormatCounter0(n, nLen, ctr);
1362  //Increment counter block
1363  ccmIncCounter(ctr, 15 - nLen);
1364 
1365  //Acquire exclusive access to the ELS module
1367 
1368  //Calculate CIPH(B0)
1369  error = aesProcessData(context, NULL, block, authTag, AES_BLOCK_SIZE,
1370  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
1371 
1372  //Decrypt ciphertext
1373  for(i = 0; i < length && !error; i += m)
1374  {
1375  //Last block?
1376  if((length - i) < AES_BLOCK_SIZE)
1377  {
1378  //Determine the length of the partial block
1379  m = length - i;
1380 
1381  //Copy the partial block
1383  osMemcpy(block, c + i, m);
1384 
1385  //Process data
1386  error = aesProcessData(context, ctr, block, block, AES_BLOCK_SIZE,
1387  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CTR, MCUXCLELS_CIPHER_ENCRYPT);
1388 
1389  //Check status code
1390  if(!error)
1391  {
1392  //Copy the partial block
1393  osMemcpy(p + i, block, m);
1394  }
1395  }
1396  else
1397  {
1398  //Process complete blocks only
1399  m = length - (length % AES_BLOCK_SIZE);
1400 
1401  //Process data
1402  error = aesProcessData(context, ctr, c + i, p + i, m,
1403  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_CTR, MCUXCLELS_CIPHER_ENCRYPT);
1404 
1405  //Increment counter block
1406  for(j = 0; j < m; j += AES_BLOCK_SIZE)
1407  {
1408  ccmIncCounter(ctr, 15 - nLen);
1409  }
1410  }
1411  }
1412 
1413  //Check status code
1414  if(!error)
1415  {
1416  //Any additional data?
1417  if(aLen > 0)
1418  {
1419  //Format the associated data
1420  osMemset(block, 0, 16);
1421 
1422  //Check the length of the associated data string
1423  if(aLen < 0xFF00)
1424  {
1425  //The length is encoded as 2 octets
1426  STORE16BE(aLen, block);
1427 
1428  //Number of bytes to copy
1429  m = MIN(aLen, 16 - 2);
1430  //Concatenate the associated data A
1431  osMemcpy(block + 2, a, m);
1432  }
1433  else
1434  {
1435  //The length is encoded as 6 octets
1436  block[0] = 0xFF;
1437  block[1] = 0xFE;
1438 
1439  //MSB is stored first
1440  STORE32BE(aLen, block + 2);
1441 
1442  //Number of bytes to copy
1443  m = MIN(aLen, 16 - 6);
1444  //Concatenate the associated data A
1445  osMemcpy(block + 6, a, m);
1446  }
1447 
1448  //Process data
1449  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1450  }
1451  else
1452  {
1453  //No additional data
1454  m = 0;
1455  }
1456  }
1457 
1458  //Process the remaining bytes of the associated data
1459  for(i = m; i < aLen && !error; i += m)
1460  {
1461  //Last block?
1462  if((aLen - i) < AES_BLOCK_SIZE)
1463  {
1464  //Determine the length of the partial block
1465  m = aLen - i;
1466 
1467  //Copy the partial block
1469  osMemcpy(block, a + i, m);
1470 
1471  //Process data
1472  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1473  }
1474  else
1475  {
1476  //Process complete blocks only
1477  m = (aLen - i) - ((aLen - i) % AES_BLOCK_SIZE);
1478 
1479  //Process data
1480  error = ccmProcessData(context, a + i, m, authTag);
1481  }
1482  }
1483 
1484  //Process payload data
1485  for(i = 0; i < length && !error; i += m)
1486  {
1487  //Last block?
1488  if((length - i) < AES_BLOCK_SIZE)
1489  {
1490  //Determine the length of the partial block
1491  m = length - i;
1492 
1493  //Copy the partial block
1495  osMemcpy(block, p + i, m);
1496 
1497  //Process data
1498  error = ccmProcessData(context, block, AES_BLOCK_SIZE, authTag);
1499  }
1500  else
1501  {
1502  //Process complete blocks only
1503  m = length - (length % AES_BLOCK_SIZE);
1504 
1505  //Process data
1506  error = ccmProcessData(context, p, m, authTag);
1507  }
1508  }
1509 
1510  //Check status code
1511  if(!error)
1512  {
1513  //Format initial counter value CTR(0)
1514  ccmFormatCounter0(n, nLen, ctr);
1515 
1516  //Calculate CIPH(CTR0)
1517  error = aesProcessData(context, NULL, ctr, block, AES_BLOCK_SIZE,
1518  MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB, MCUXCLELS_CIPHER_ENCRYPT);
1519  }
1520 
1521  //Release exclusive access to the ELS module
1523 
1524  //Check status code
1525  if(!error)
1526  {
1527  uint8_t mask;
1528 
1529  //Compute MAC
1530  ccmXorBlock(authTag, authTag, block, tLen);
1531 
1532  //The calculated tag is bitwise compared to the received tag
1533  for(mask = 0, i = 0; i < tLen; i++)
1534  {
1535  mask |= authTag[i] ^ t[i];
1536  }
1537 
1538  //The message is authenticated if and only if the tags match
1539  error = (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1540  }
1541 
1542  //Return status code
1543  return error;
1544 }
1545 
1546 #endif
1547 #endif
uint16_t block
Definition: tftp_common.h:115
void ccmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: ccm.c:399
uint8_t a
Definition: ndp.h:411
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1173
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
uint8_t p
Definition: ndp.h:300
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t o
Collection of AEAD algorithms.
size_t blockSize
Definition: crypto.h:1168
error_t aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t algo, uint32_t mode)
Perform AES encryption or decryption.
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
void ccmFormatCounter0(const uint8_t *n, size_t nLen, uint8_t *ctr)
Format initial counter value CTR(0)
Definition: ccm.c:418
void ccmIncCounter(uint8_t *ctr, size_t n)
Increment counter block.
Definition: ccm.c:440
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1172
AES algorithm context.
Definition: aes.h:58
error_t ccmDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using CCM.
#define AES_BLOCK_SIZE
Definition: aes.h:43
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t gcmProcessData(AesContext *context, const uint8_t *iv, const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output, size_t length, uint8_t *t, uint32_t mode)
Perform AES-GCM encryption or decryption.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
error_t ccmProcessData(AesContext *context, const uint8_t *input, size_t length, uint8_t *t)
Update CCM authentication tag.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
error_t ccmFormatBlock0(size_t q, const uint8_t *n, size_t nLen, size_t aLen, size_t tLen, uint8_t *b)
Format first block B(0)
Definition: ccm.c:353
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t iv[]
Definition: ike.h:1659
Block cipher modes of operation.
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
uint8_t length
Definition: tcp.h:375
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
#define MIN(a, b)
Definition: os_port.h:63
error_t ccmEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using CCM.
uint_t nr
Definition: aes.h:59
error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
GCM context.
Definition: gcm.h:64
error_t gcmEncrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using GCM.
uint8_t m
Definition: ndp.h:304
OsMutex mcxn547CryptoMutex
uint8_t n
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
NXP MCX N547 cipher hardware accelerator.
Common interface for encryption algorithms.
Definition: crypto.h:1164
#define AES_CIPHER_ALGO
Definition: aes.h:45
uint8_t options[]
Definition: tcp.h:364
NXP MCX N547 hardware cryptographic accelerator.
uint32_t ek[60]
Definition: aes.h:60
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:66
error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
error_t gcmDecrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using GCM.
void ctrIncBlock(uint8_t *ctr, uint32_t inc, size_t blockSize, size_t m)
Increment counter block.
Definition: ctr.c:138
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
uint8_t token[]
Definition: coap_common.h:181