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