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