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