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