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