stm32h7xx_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file stm32h7xx_crypto_cipher.c
3  * @brief STM32H7 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 "stm32h7xx.h"
36 #include "stm32h7xx_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 (STM32H7XX_CRYPTO_CIPHER_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 #if (DES_SUPPORT == ENABLED)
65 
66 /**
67  * @brief Perform DES encryption or decryption
68  * @param[in] context DES algorithm context
69  * @param[in,out] iv Initialization vector
70  * @param[in] input Data to be encrypted/decrypted
71  * @param[out] output Data resulting from the encryption/decryption process
72  * @param[in] length Total number of data bytes to be processed
73  * @param[in] mode Operation mode
74  **/
75 
76 void desProcessData(DesContext *context, uint8_t *iv, const uint8_t *input,
77  uint8_t *output, size_t length, uint32_t mode)
78 {
79  uint32_t temp;
80 
81  //Acquire exclusive access to the CRYP module
83 
84  //Configure the data type
85  CRYP->CR = CRYP_CR_DATATYPE_8B;
86  //Configure the algorithm and chaining mode
87  CRYP->CR |= mode;
88 
89  //Set encryption key
90  CRYP->K1LR = context->ks[0];
91  CRYP->K1RR = context->ks[1];
92 
93  //Valid initialization vector?
94  if(iv != NULL)
95  {
96  //Set initialization vector
97  CRYP->IV0LR = LOAD32BE(iv);
98  CRYP->IV0RR = LOAD32BE(iv + 4);
99  }
100 
101  //Flush the input and output FIFOs
102  CRYP->CR |= CRYP_CR_FFLUSH;
103  //Enable the cryptographic processor
104  CRYP->CR |= CRYP_CR_CRYPEN;
105 
106  //Process data
107  while(length >= DES_BLOCK_SIZE)
108  {
109  //Wait for the input FIFO to be ready to accept data
110  while((CRYP->SR & CRYP_SR_IFNF) == 0)
111  {
112  }
113 
114  //Write the input FIFO
115  CRYP->DIN = __UNALIGNED_UINT32_READ(input);
116  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 4);
117 
118  //Wait for the output to be ready
119  while((CRYP->SR & CRYP_SR_OFNE) == 0)
120  {
121  }
122 
123  //Read the output FIFO
124  temp = CRYP->DOUT;
125  __UNALIGNED_UINT32_WRITE(output, temp);
126  temp = CRYP->DOUT;
127  __UNALIGNED_UINT32_WRITE(output + 4, temp);
128 
129  //Next block
130  input += DES_BLOCK_SIZE;
131  output += DES_BLOCK_SIZE;
133  }
134 
135  //Valid initialization vector?
136  if(iv != NULL)
137  {
138  //Update the value of the initialization vector
139  temp = CRYP->IV0LR;
140  STORE32BE(temp, iv);
141  temp = CRYP->IV0RR;
142  STORE32BE(temp, iv + 4);
143  }
144 
145  //Disable the cryptographic processor by clearing the CRYPEN bit
146  CRYP->CR = 0;
147 
148  //Release exclusive access to the CRYP module
150 }
151 
152 
153 /**
154  * @brief Initialize a DES context using the supplied key
155  * @param[in] context Pointer to the DES context to initialize
156  * @param[in] key Pointer to the key
157  * @param[in] keyLen Length of the key (must be set to 8)
158  * @return Error code
159  **/
160 
161 error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
162 {
163  //Check parameters
164  if(context == NULL || key == NULL)
166 
167  //Invalid key length?
168  if(keyLen != 8)
170 
171  //Copy the 64-bit key
172  context->ks[0] = LOAD32BE(key + 0);
173  context->ks[1] = LOAD32BE(key + 4);
174 
175  //No error to report
176  return NO_ERROR;
177 }
178 
179 
180 /**
181  * @brief Encrypt a 8-byte block using DES algorithm
182  * @param[in] context Pointer to the DES context
183  * @param[in] input Plaintext block to encrypt
184  * @param[out] output Ciphertext block resulting from encryption
185  **/
186 
187 void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
188 {
189  //Perform DES encryption
190  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE,
191  CRYP_CR_ALGOMODE_DES_ECB);
192 }
193 
194 
195 /**
196  * @brief Decrypt a 8-byte block using DES algorithm
197  * @param[in] context Pointer to the DES context
198  * @param[in] input Ciphertext block to decrypt
199  * @param[out] output Plaintext block resulting from decryption
200  **/
201 
202 void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
203 {
204  //Perform DES decryption
205  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE,
206  CRYP_CR_ALGOMODE_DES_ECB | CRYP_CR_ALGODIR);
207 }
208 
209 #endif
210 #if (DES3_SUPPORT == ENABLED)
211 
212 /**
213  * @brief Perform Triple DES encryption or decryption
214  * @param[in] context Triple DES algorithm context
215  * @param[in,out] iv Initialization vector
216  * @param[in] input Data to be encrypted/decrypted
217  * @param[out] output Data resulting from the encryption/decryption process
218  * @param[in] length Total number of data bytes to be processed
219  * @param[in] mode Operation mode
220  **/
221 
222 void des3ProcessData(Des3Context *context, uint8_t *iv, const uint8_t *input,
223  uint8_t *output, size_t length, uint32_t mode)
224 {
225  uint32_t temp;
226 
227  //Acquire exclusive access to the CRYP module
229 
230  //Configure the data type
231  CRYP->CR = CRYP_CR_DATATYPE_8B;
232  //Configure the algorithm and chaining mode
233  CRYP->CR |= mode;
234 
235  //Set encryption key
236  CRYP->K1LR = context->k1.ks[0];
237  CRYP->K1RR = context->k1.ks[1];
238  CRYP->K2LR = context->k2.ks[0];
239  CRYP->K2RR = context->k2.ks[1];
240  CRYP->K3LR = context->k3.ks[0];
241  CRYP->K3RR = context->k3.ks[1];
242 
243  //Valid initialization vector?
244  if(iv != NULL)
245  {
246  //Set initialization vector
247  CRYP->IV0LR = LOAD32BE(iv);
248  CRYP->IV0RR = LOAD32BE(iv + 4);
249  }
250 
251  //Flush the input and output FIFOs
252  CRYP->CR |= CRYP_CR_FFLUSH;
253  //Enable the cryptographic processor
254  CRYP->CR |= CRYP_CR_CRYPEN;
255 
256  //Process data
257  while(length >= DES3_BLOCK_SIZE)
258  {
259  //Wait for the input FIFO to be ready to accept data
260  while((CRYP->SR & CRYP_SR_IFNF) == 0)
261  {
262  }
263 
264  //Write the input FIFO
265  CRYP->DIN = __UNALIGNED_UINT32_READ(input);
266  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 4);
267 
268  //Wait for the output to be ready
269  while((CRYP->SR & CRYP_SR_OFNE) == 0)
270  {
271  }
272 
273  //Read the output FIFO
274  temp = CRYP->DOUT;
275  __UNALIGNED_UINT32_WRITE(output, temp);
276  temp = CRYP->DOUT;
277  __UNALIGNED_UINT32_WRITE(output + 4, temp);
278 
279  //Next block
280  input += DES3_BLOCK_SIZE;
281  output += DES3_BLOCK_SIZE;
283  }
284 
285  //Valid initialization vector?
286  if(iv != NULL)
287  {
288  //Update the value of the initialization vector
289  temp = CRYP->IV0LR;
290  STORE32BE(temp, iv);
291  temp = CRYP->IV0RR;
292  STORE32BE(temp, iv + 4);
293  }
294 
295  //Disable the cryptographic processor by clearing the CRYPEN bit
296  CRYP->CR = 0;
297 
298  //Release exclusive access to the CRYP module
300 }
301 
302 
303 /**
304  * @brief Initialize a Triple DES context using the supplied key
305  * @param[in] context Pointer to the Triple DES context to initialize
306  * @param[in] key Pointer to the key
307  * @param[in] keyLen Length of the key
308  * @return Error code
309  **/
310 
311 error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
312 {
313  //Check parameters
314  if(context == NULL || key == NULL)
316 
317  //Check key length
318  if(keyLen == 8)
319  {
320  //This option provides backward compatibility with DES, because the
321  //first and second DES operations cancel out
322  context->k1.ks[0] = LOAD32BE(key + 0);
323  context->k1.ks[1] = LOAD32BE(key + 4);
324  context->k2.ks[0] = LOAD32BE(key + 0);
325  context->k2.ks[1] = LOAD32BE(key + 4);
326  context->k3.ks[0] = LOAD32BE(key + 0);
327  context->k3.ks[1] = LOAD32BE(key + 4);
328  }
329  else if(keyLen == 16)
330  {
331  //If the key length is 128 bits including parity, the first 8 bytes of the
332  //encoding represent the key used for the two outer DES operations, and
333  //the second 8 bytes represent the key used for the inner DES operation
334  context->k1.ks[0] = LOAD32BE(key + 0);
335  context->k1.ks[1] = LOAD32BE(key + 4);
336  context->k2.ks[0] = LOAD32BE(key + 8);
337  context->k2.ks[1] = LOAD32BE(key + 12);
338  context->k3.ks[0] = LOAD32BE(key + 0);
339  context->k3.ks[1] = LOAD32BE(key + 4);
340  }
341  else if(keyLen == 24)
342  {
343  //If the key length is 192 bits including parity, then 3 independent DES
344  //keys are represented, in the order in which they are used for encryption
345  context->k1.ks[0] = LOAD32BE(key + 0);
346  context->k1.ks[1] = LOAD32BE(key + 4);
347  context->k2.ks[0] = LOAD32BE(key + 8);
348  context->k2.ks[1] = LOAD32BE(key + 12);
349  context->k3.ks[0] = LOAD32BE(key + 16);
350  context->k3.ks[1] = LOAD32BE(key + 20);
351  }
352  else
353  {
354  //The length of the key is not valid
356  }
357 
358  //No error to report
359  return NO_ERROR;
360 }
361 
362 
363 /**
364  * @brief Encrypt a 8-byte block using Triple DES algorithm
365  * @param[in] context Pointer to the Triple DES context
366  * @param[in] input Plaintext block to encrypt
367  * @param[out] output Ciphertext block resulting from encryption
368  **/
369 
370 void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
371 {
372  //Perform Triple DES encryption
373  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE,
374  CRYP_CR_ALGOMODE_TDES_ECB);
375 }
376 
377 
378 /**
379  * @brief Decrypt a 8-byte block using Triple DES algorithm
380  * @param[in] context Pointer to the Triple DES context
381  * @param[in] input Ciphertext block to decrypt
382  * @param[out] output Plaintext block resulting from decryption
383  **/
384 
385 void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
386 {
387  //Perform Triple DES decryption
388  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE,
389  CRYP_CR_ALGOMODE_TDES_ECB | CRYP_CR_ALGODIR);
390 }
391 
392 #endif
393 #if (AES_SUPPORT == ENABLED)
394 
395 /**
396  * @brief Load AES key
397  * @param[in] context AES algorithm context
398  **/
399 
400 void aesLoadKey(AesContext *context)
401 {
402  uint32_t temp;
403 
404  //Read control register
405  temp = CRYP->CR & ~CRYP_CR_KEYSIZE;
406 
407  //Check the length of the key
408  if(context->nr == 10)
409  {
410  //10 rounds are required for 128-bit key
411  CRYP->CR = temp | CRYP_CR_KEYSIZE_128B;
412 
413  //Set the 128-bit encryption key
414  CRYP->K2LR = context->ek[0];
415  CRYP->K2RR = context->ek[1];
416  CRYP->K3LR = context->ek[2];
417  CRYP->K3RR = context->ek[3];
418  }
419  else if(context->nr == 12)
420  {
421  //12 rounds are required for 192-bit key
422  CRYP->CR = temp | CRYP_CR_KEYSIZE_192B;
423 
424  //Set the 192-bit encryption key
425  CRYP->K1LR = context->ek[0];
426  CRYP->K1RR = context->ek[1];
427  CRYP->K2LR = context->ek[2];
428  CRYP->K2RR = context->ek[3];
429  CRYP->K3LR = context->ek[4];
430  CRYP->K3RR = context->ek[5];
431  }
432  else
433  {
434  //14 rounds are required for 256-bit key
435  CRYP->CR = temp | CRYP_CR_KEYSIZE_256B;
436 
437  //Set the 256-bit encryption key
438  CRYP->K0LR = context->ek[0];
439  CRYP->K0RR = context->ek[1];
440  CRYP->K1LR = context->ek[2];
441  CRYP->K1RR = context->ek[3];
442  CRYP->K2LR = context->ek[4];
443  CRYP->K2RR = context->ek[5];
444  CRYP->K3LR = context->ek[6];
445  CRYP->K3RR = context->ek[7];
446  }
447 }
448 
449 
450 /**
451  * @brief Perform AES encryption or decryption
452  * @param[in] context AES algorithm context
453  * @param[in,out] iv Initialization vector
454  * @param[in] input Data to be encrypted/decrypted
455  * @param[out] output Data resulting from the encryption/decryption process
456  * @param[in] length Total number of data bytes to be processed
457  * @param[in] mode Operation mode
458  **/
459 
460 void aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input,
461  uint8_t *output, size_t length, uint32_t mode)
462 {
463  uint32_t temp;
464 
465  //Acquire exclusive access to the CRYP module
467 
468  //Configure the data type
469  CRYP->CR = CRYP_CR_DATATYPE_8B;
470 
471  //AES-ECB or AES-CBC decryption?
472  if((mode & CRYP_CR_ALGODIR) != 0)
473  {
474  //Configure the key preparation mode by setting the ALGOMODE bits to '111'
475  CRYP->CR |= CRYP_CR_ALGOMODE_AES_KEY;
476  //Set encryption key
477  aesLoadKey(context);
478  //Write the CRYPEN bit to 1
479  CRYP->CR |= CRYP_CR_CRYPEN;
480 
481  //Wait until BUSY returns to 0
482  while((CRYP->SR & CRYP_SR_BUSY) != 0)
483  {
484  }
485 
486  //The algorithm must be configured once the key has been prepared
487  temp = CRYP->CR & ~CRYP_CR_ALGOMODE;
488  CRYP->CR = temp | mode;
489  }
490  else
491  {
492  //Configure the algorithm and chaining mode
493  CRYP->CR |= mode;
494  //Set encryption key
495  aesLoadKey(context);
496  }
497 
498  //Valid initialization vector?
499  if(iv != NULL)
500  {
501  //Set initialization vector
502  CRYP->IV0LR = LOAD32BE(iv);
503  CRYP->IV0RR = LOAD32BE(iv + 4);
504  CRYP->IV1LR = LOAD32BE(iv + 8);
505  CRYP->IV1RR = LOAD32BE(iv + 12);
506  }
507 
508  //Flush the input and output FIFOs
509  CRYP->CR |= CRYP_CR_FFLUSH;
510  //Enable the cryptographic processor
511  CRYP->CR |= CRYP_CR_CRYPEN;
512 
513  //Process data
514  while(length >= AES_BLOCK_SIZE)
515  {
516  //Wait for the input FIFO to be ready to accept data
517  while((CRYP->SR & CRYP_SR_IFNF) == 0)
518  {
519  }
520 
521  //Write the input FIFO
522  CRYP->DIN = __UNALIGNED_UINT32_READ(input);
523  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 4);
524  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 8);
525  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 12);
526 
527  //Wait for the output to be ready
528  while((CRYP->SR & CRYP_SR_OFNE) == 0)
529  {
530  }
531 
532  //Read the output FIFO
533  temp = CRYP->DOUT;
534  __UNALIGNED_UINT32_WRITE(output, temp);
535  temp = CRYP->DOUT;
536  __UNALIGNED_UINT32_WRITE(output + 4, temp);
537  temp = CRYP->DOUT;
538  __UNALIGNED_UINT32_WRITE(output + 8, temp);
539  temp = CRYP->DOUT;
540  __UNALIGNED_UINT32_WRITE(output + 12, temp);
541 
542  //Next block
543  input += AES_BLOCK_SIZE;
544  output += AES_BLOCK_SIZE;
546  }
547 
548  //Process final block of data
549  if(length > 0)
550  {
551  uint32_t buffer[4];
552 
553  //Copy partial block
554  osMemset(buffer, 0, AES_BLOCK_SIZE);
555  osMemcpy(buffer, input, length);
556 
557  //Wait for the input FIFO to be ready to accept data
558  while((CRYP->SR & CRYP_SR_IFNF) == 0)
559  {
560  }
561 
562  //Write input block
563  CRYP->DIN = buffer[0];
564  CRYP->DIN = buffer[1];
565  CRYP->DIN = buffer[2];
566  CRYP->DIN = buffer[3];
567 
568  //Wait for the output to be ready
569  while((CRYP->SR & CRYP_SR_OFNE) == 0)
570  {
571  }
572 
573  //Read output block
574  buffer[0] = CRYP->DOUT;
575  buffer[1] = CRYP->DOUT;
576  buffer[2] = CRYP->DOUT;
577  buffer[3] = CRYP->DOUT;
578 
579  //Copy partial block
580  osMemcpy(output, buffer, length);
581  }
582 
583  //Valid initialization vector?
584  if(iv != NULL)
585  {
586  //Update the value of the initialization vector
587  temp = CRYP->IV0LR;
588  STORE32BE(temp, iv);
589  temp = CRYP->IV0RR;
590  STORE32BE(temp, iv + 4);
591  temp = CRYP->IV1LR;
592  STORE32BE(temp, iv + 8);
593  temp = CRYP->IV1RR;
594  STORE32BE(temp, iv + 12);
595  }
596 
597  //Disable the cryptographic processor by clearing the CRYPEN bit
598  CRYP->CR = 0;
599 
600  //Release exclusive access to the CRYP module
602 }
603 
604 
605 /**
606  * @brief Key expansion
607  * @param[in] context Pointer to the AES context to initialize
608  * @param[in] key Pointer to the key
609  * @param[in] keyLen Length of the key
610  * @return Error code
611  **/
612 
613 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
614 {
615  size_t i;
616 
617  //Check parameters
618  if(context == NULL || key == NULL)
620 
621  //Check the length of the key
622  if(keyLen == 16)
623  {
624  //10 rounds are required for 128-bit key
625  context->nr = 10;
626  }
627  else if(keyLen == 24)
628  {
629  //12 rounds are required for 192-bit key
630  context->nr = 12;
631  }
632  else if(keyLen == 32)
633  {
634  //14 rounds are required for 256-bit key
635  context->nr = 14;
636  }
637  else
638  {
639  //Report an error
641  }
642 
643  //Determine the number of 32-bit words in the key
644  keyLen /= 4;
645 
646  //Copy the original key
647  for(i = 0; i < keyLen; i++)
648  {
649  context->ek[i] = LOAD32BE(key + (i * 4));
650  }
651 
652  //No error to report
653  return NO_ERROR;
654 }
655 
656 
657 /**
658  * @brief Encrypt a 16-byte block using AES algorithm
659  * @param[in] context Pointer to the AES context
660  * @param[in] input Plaintext block to encrypt
661  * @param[out] output Ciphertext block resulting from encryption
662  **/
663 
664 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
665 {
666  //Perform AES encryption
667  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
668  CRYP_CR_ALGOMODE_AES_ECB);
669 }
670 
671 
672 /**
673  * @brief Decrypt a 16-byte block using AES algorithm
674  * @param[in] context Pointer to the AES context
675  * @param[in] input Ciphertext block to decrypt
676  * @param[out] output Plaintext block resulting from decryption
677  **/
678 
679 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
680 {
681  //Perform AES decryption
682  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
683  CRYP_CR_ALGOMODE_AES_ECB | CRYP_CR_ALGODIR);
684 }
685 
686 #endif
687 #if (ECB_SUPPORT == ENABLED)
688 
689 /**
690  * @brief ECB encryption
691  * @param[in] cipher Cipher algorithm
692  * @param[in] context Cipher algorithm context
693  * @param[in] p Plaintext to be encrypted
694  * @param[out] c Ciphertext resulting from the encryption
695  * @param[in] length Total number of data bytes to be encrypted
696  * @return Error code
697  **/
698 
699 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
700  const uint8_t *p, uint8_t *c, size_t length)
701 {
702  error_t error;
703 
704  //Initialize status code
705  error = NO_ERROR;
706 
707 #if (DES_SUPPORT == ENABLED)
708  //DES cipher algorithm?
709  if(cipher == DES_CIPHER_ALGO)
710  {
711  //Check the length of the payload
712  if(length == 0)
713  {
714  //No data to process
715  }
716  else if((length % DES_BLOCK_SIZE) == 0)
717  {
718  //Encrypt payload data
719  desProcessData(context, NULL, p, c, length, CRYP_CR_ALGOMODE_DES_ECB);
720  }
721  else
722  {
723  //The length of the payload must be a multiple of the block size
724  error = ERROR_INVALID_LENGTH;
725  }
726  }
727  else
728 #endif
729 #if (DES3_SUPPORT == ENABLED)
730  //Triple DES cipher algorithm?
731  if(cipher == DES3_CIPHER_ALGO)
732  {
733  //Check the length of the payload
734  if(length == 0)
735  {
736  //No data to process
737  }
738  else if((length % DES3_BLOCK_SIZE) == 0)
739  {
740  //Encrypt payload data
741  des3ProcessData(context, NULL, p, c, length, CRYP_CR_ALGOMODE_TDES_ECB);
742  }
743  else
744  {
745  //The length of the payload must be a multiple of the block size
746  error = ERROR_INVALID_LENGTH;
747  }
748  }
749  else
750 #endif
751 #if (AES_SUPPORT == ENABLED)
752  //AES cipher algorithm?
753  if(cipher == AES_CIPHER_ALGO)
754  {
755  //Check the length of the payload
756  if(length == 0)
757  {
758  //No data to process
759  }
760  else if((length % AES_BLOCK_SIZE) == 0)
761  {
762  //Encrypt payload data
763  aesProcessData(context, NULL, p, c, length, CRYP_CR_ALGOMODE_AES_ECB);
764  }
765  else
766  {
767  //The length of the payload must be a multiple of the block size
768  error = ERROR_INVALID_LENGTH;
769  }
770  }
771  else
772 #endif
773  //Unknown cipher algorithm?
774  {
775  //ECB mode operates in a block-by-block fashion
776  while(length >= cipher->blockSize)
777  {
778  //Encrypt current block
779  cipher->encryptBlock(context, p, c);
780 
781  //Next block
782  p += cipher->blockSize;
783  c += cipher->blockSize;
784  length -= cipher->blockSize;
785  }
786 
787  //The length of the payload must be a multiple of the block size
788  if(length != 0)
789  {
790  error = ERROR_INVALID_LENGTH;
791  }
792  }
793 
794  //Return status code
795  return error;
796 }
797 
798 
799 /**
800  * @brief ECB decryption
801  * @param[in] cipher Cipher algorithm
802  * @param[in] context Cipher algorithm context
803  * @param[in] c Ciphertext to be decrypted
804  * @param[out] p Plaintext resulting from the decryption
805  * @param[in] length Total number of data bytes to be decrypted
806  * @return Error code
807  **/
808 
809 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
810  const uint8_t *c, uint8_t *p, size_t length)
811 {
812  error_t error;
813 
814  //Initialize status code
815  error = NO_ERROR;
816 
817 #if (DES_SUPPORT == ENABLED)
818  //DES cipher algorithm?
819  if(cipher == DES_CIPHER_ALGO)
820  {
821  //Check the length of the payload
822  if(length == 0)
823  {
824  //No data to process
825  }
826  else if((length % DES_BLOCK_SIZE) == 0)
827  {
828  //Decrypt payload data
829  desProcessData(context, NULL, c, p, length, CRYP_CR_ALGOMODE_DES_ECB |
830  CRYP_CR_ALGODIR);
831  }
832  else
833  {
834  //The length of the payload must be a multiple of the block size
835  error = ERROR_INVALID_LENGTH;
836  }
837  }
838  else
839 #endif
840 #if (DES3_SUPPORT == ENABLED)
841  //Triple DES cipher algorithm?
842  if(cipher == DES3_CIPHER_ALGO)
843  {
844  //Check the length of the payload
845  if(length == 0)
846  {
847  //No data to process
848  }
849  else if((length % DES3_BLOCK_SIZE) == 0)
850  {
851  //Decrypt payload data
852  des3ProcessData(context, NULL, c, p, length, CRYP_CR_ALGOMODE_TDES_ECB |
853  CRYP_CR_ALGODIR);
854  }
855  else
856  {
857  //The length of the payload must be a multiple of the block size
858  error = ERROR_INVALID_LENGTH;
859  }
860  }
861  else
862 #endif
863 #if (AES_SUPPORT == ENABLED)
864  //AES cipher algorithm?
865  if(cipher == AES_CIPHER_ALGO)
866  {
867  //Check the length of the payload
868  if(length == 0)
869  {
870  //No data to process
871  }
872  else if((length % AES_BLOCK_SIZE) == 0)
873  {
874  //Decrypt payload data
875  aesProcessData(context, NULL, c, p, length, CRYP_CR_ALGOMODE_AES_ECB |
876  CRYP_CR_ALGODIR);
877  }
878  else
879  {
880  //The length of the payload must be a multiple of the block size
881  error = ERROR_INVALID_LENGTH;
882  }
883  }
884  else
885 #endif
886  //Unknown cipher algorithm?
887  {
888  //ECB mode operates in a block-by-block fashion
889  while(length >= cipher->blockSize)
890  {
891  //Decrypt current block
892  cipher->decryptBlock(context, c, p);
893 
894  //Next block
895  c += cipher->blockSize;
896  p += cipher->blockSize;
897  length -= cipher->blockSize;
898  }
899 
900  //The length of the payload must be a multiple of the block size
901  if(length != 0)
902  {
903  error = ERROR_INVALID_LENGTH;
904  }
905  }
906 
907  //Return status code
908  return error;
909 }
910 
911 #endif
912 #if (CBC_SUPPORT == ENABLED)
913 
914 /**
915  * @brief CBC encryption
916  * @param[in] cipher Cipher algorithm
917  * @param[in] context Cipher algorithm context
918  * @param[in,out] iv Initialization vector
919  * @param[in] p Plaintext to be encrypted
920  * @param[out] c Ciphertext resulting from the encryption
921  * @param[in] length Total number of data bytes to be encrypted
922  * @return Error code
923  **/
924 
925 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
926  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
927 {
928  error_t error;
929 
930  //Initialize status code
931  error = NO_ERROR;
932 
933 #if (DES_SUPPORT == ENABLED)
934  //DES cipher algorithm?
935  if(cipher == DES_CIPHER_ALGO)
936  {
937  //Check the length of the payload
938  if(length == 0)
939  {
940  //No data to process
941  }
942  else if((length % DES_BLOCK_SIZE) == 0)
943  {
944  //Encrypt payload data
945  desProcessData(context, iv, p, c, length, CRYP_CR_ALGOMODE_DES_CBC);
946  }
947  else
948  {
949  //The length of the payload must be a multiple of the block size
950  error = ERROR_INVALID_LENGTH;
951  }
952  }
953  else
954 #endif
955 #if (DES3_SUPPORT == ENABLED)
956  //Triple DES cipher algorithm?
957  if(cipher == DES3_CIPHER_ALGO)
958  {
959  //Check the length of the payload
960  if(length == 0)
961  {
962  //No data to process
963  }
964  else if((length % DES3_BLOCK_SIZE) == 0)
965  {
966  //Encrypt payload data
967  des3ProcessData(context, iv, p, c, length, CRYP_CR_ALGOMODE_TDES_CBC);
968  }
969  else
970  {
971  //The length of the payload must be a multiple of the block size
972  error = ERROR_INVALID_LENGTH;
973  }
974  }
975  else
976 #endif
977 #if (AES_SUPPORT == ENABLED)
978  //AES cipher algorithm?
979  if(cipher == AES_CIPHER_ALGO)
980  {
981  //Check the length of the payload
982  if(length == 0)
983  {
984  //No data to process
985  }
986  else if((length % AES_BLOCK_SIZE) == 0)
987  {
988  //Encrypt payload data
989  aesProcessData(context, iv, p, c, length, CRYP_CR_ALGOMODE_AES_CBC);
990  }
991  else
992  {
993  //The length of the payload must be a multiple of the block size
994  error = ERROR_INVALID_LENGTH;
995  }
996  }
997  else
998 #endif
999  //Unknown cipher algorithm?
1000  {
1001  size_t i;
1002 
1003  //CBC mode operates in a block-by-block fashion
1004  while(length >= cipher->blockSize)
1005  {
1006  //XOR input block with IV contents
1007  for(i = 0; i < cipher->blockSize; i++)
1008  {
1009  c[i] = p[i] ^ iv[i];
1010  }
1011 
1012  //Encrypt the current block based upon the output of the previous
1013  //encryption
1014  cipher->encryptBlock(context, c, c);
1015 
1016  //Update IV with output block contents
1017  osMemcpy(iv, c, cipher->blockSize);
1018 
1019  //Next block
1020  p += cipher->blockSize;
1021  c += cipher->blockSize;
1022  length -= cipher->blockSize;
1023  }
1024 
1025  //The length of the payload must be a multiple of the block size
1026  if(length != 0)
1027  {
1028  error = ERROR_INVALID_LENGTH;
1029  }
1030  }
1031 
1032  //Return status code
1033  return error;
1034 }
1035 
1036 
1037 /**
1038  * @brief CBC decryption
1039  * @param[in] cipher Cipher algorithm
1040  * @param[in] context Cipher algorithm context
1041  * @param[in,out] iv Initialization vector
1042  * @param[in] c Ciphertext to be decrypted
1043  * @param[out] p Plaintext resulting from the decryption
1044  * @param[in] length Total number of data bytes to be decrypted
1045  * @return Error code
1046  **/
1047 
1048 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
1049  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
1050 {
1051  error_t error;
1052 
1053  //Initialize status code
1054  error = NO_ERROR;
1055 
1056 #if (DES_SUPPORT == ENABLED)
1057  //DES cipher algorithm?
1058  if(cipher == DES_CIPHER_ALGO)
1059  {
1060  //Check the length of the payload
1061  if(length == 0)
1062  {
1063  //No data to process
1064  }
1065  else if((length % DES_BLOCK_SIZE) == 0)
1066  {
1067  //Decrypt payload data
1068  desProcessData(context, iv, c, p, length, CRYP_CR_ALGOMODE_DES_CBC |
1069  CRYP_CR_ALGODIR);
1070  }
1071  else
1072  {
1073  //The length of the payload must be a multiple of the block size
1074  error = ERROR_INVALID_LENGTH;
1075  }
1076  }
1077  else
1078 #endif
1079 #if (DES3_SUPPORT == ENABLED)
1080  //Triple DES cipher algorithm?
1081  if(cipher == DES3_CIPHER_ALGO)
1082  {
1083  //Check the length of the payload
1084  if(length == 0)
1085  {
1086  //No data to process
1087  }
1088  else if((length % DES3_BLOCK_SIZE) == 0)
1089  {
1090  //Decrypt payload data
1091  des3ProcessData(context, iv, c, p, length, CRYP_CR_ALGOMODE_TDES_CBC |
1092  CRYP_CR_ALGODIR);
1093  }
1094  else
1095  {
1096  //The length of the payload must be a multiple of the block size
1097  error = ERROR_INVALID_LENGTH;
1098  }
1099  }
1100  else
1101 #endif
1102 #if (AES_SUPPORT == ENABLED)
1103  //AES cipher algorithm?
1104  if(cipher == AES_CIPHER_ALGO)
1105  {
1106  //Check the length of the payload
1107  if(length == 0)
1108  {
1109  //No data to process
1110  }
1111  else if((length % AES_BLOCK_SIZE) == 0)
1112  {
1113  //Decrypt payload data
1114  aesProcessData(context, iv, c, p, length, CRYP_CR_ALGOMODE_AES_CBC |
1115  CRYP_CR_ALGODIR);
1116  }
1117  else
1118  {
1119  //The length of the payload must be a multiple of the block size
1120  error = ERROR_INVALID_LENGTH;
1121  }
1122  }
1123  else
1124 #endif
1125  //Unknown cipher algorithm?
1126  {
1127  size_t i;
1128  uint8_t t[16];
1129 
1130  //CBC mode operates in a block-by-block fashion
1131  while(length >= cipher->blockSize)
1132  {
1133  //Save input block
1134  osMemcpy(t, c, cipher->blockSize);
1135 
1136  //Decrypt the current block
1137  cipher->decryptBlock(context, c, p);
1138 
1139  //XOR output block with IV contents
1140  for(i = 0; i < cipher->blockSize; i++)
1141  {
1142  p[i] ^= iv[i];
1143  }
1144 
1145  //Update IV with input block contents
1146  osMemcpy(iv, t, cipher->blockSize);
1147 
1148  //Next block
1149  c += cipher->blockSize;
1150  p += cipher->blockSize;
1151  length -= cipher->blockSize;
1152  }
1153 
1154  //The length of the payload must be a multiple of the block size
1155  if(length != 0)
1156  {
1157  error = ERROR_INVALID_LENGTH;
1158  }
1159  }
1160 
1161  //Return status code
1162  return error;
1163 }
1164 
1165 #endif
1166 #if (CTR_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1167 
1168 /**
1169  * @brief CTR encryption
1170  * @param[in] cipher Cipher algorithm
1171  * @param[in] context Cipher algorithm context
1172  * @param[in] m Size in bits of the specific part of the block to be incremented
1173  * @param[in,out] t Initial counter block
1174  * @param[in] p Plaintext to be encrypted
1175  * @param[out] c Ciphertext resulting from the encryption
1176  * @param[in] length Total number of data bytes to be encrypted
1177  * @return Error code
1178  **/
1179 
1180 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
1181  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
1182 {
1183  error_t error;
1184 
1185  //Initialize status code
1186  error = NO_ERROR;
1187 
1188  //AES cipher algorithm?
1189  if(cipher == AES_CIPHER_ALGO)
1190  {
1191  //Check the value of the parameter
1192  if(m == (AES_BLOCK_SIZE * 8))
1193  {
1194  //Check the length of the payload
1195  if(length > 0)
1196  {
1197  //Encrypt payload data
1198  aesProcessData(context, t, p, c, length, CRYP_CR_ALGOMODE_AES_CTR);
1199  }
1200  else
1201  {
1202  //No data to process
1203  }
1204  }
1205  else
1206  {
1207  //The value of the parameter is not valid
1208  error = ERROR_INVALID_PARAMETER;
1209  }
1210  }
1211  else
1212  {
1213  //Check the value of the parameter
1214  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
1215  {
1216  size_t i;
1217  size_t n;
1218  uint16_t temp;
1219  uint8_t o[16];
1220 
1221  //Determine the size, in bytes, of the specific part of the block
1222  //to be incremented
1223  m = m / 8;
1224 
1225  //Process plaintext
1226  while(length > 0)
1227  {
1228  //CTR mode operates in a block-by-block fashion
1229  n = MIN(length, cipher->blockSize);
1230 
1231  //Compute O(j) = CIPH(T(j))
1232  cipher->encryptBlock(context, t, o);
1233 
1234  //Compute C(j) = P(j) XOR T(j)
1235  for(i = 0; i < n; i++)
1236  {
1237  c[i] = p[i] ^ o[i];
1238  }
1239 
1240  //Standard incrementing function
1241  for(temp = 1, i = 1; i <= m; i++)
1242  {
1243  //Increment the current byte and propagate the carry
1244  temp += t[cipher->blockSize - i];
1245  t[cipher->blockSize - i] = temp & 0xFF;
1246  temp >>= 8;
1247  }
1248 
1249  //Next block
1250  p += n;
1251  c += n;
1252  length -= n;
1253  }
1254  }
1255  else
1256  {
1257  //The value of the parameter is not valid
1258  error = ERROR_INVALID_PARAMETER;
1259  }
1260  }
1261 
1262  //Return status code
1263  return error;
1264 }
1265 
1266 #endif
1267 #if (GCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1268 
1269 /**
1270  * @brief Perform AES-GCM encryption or decryption
1271  * @param[in] context AES algorithm context
1272  * @param[in] iv Initialization vector
1273  * @param[in] a Additional authenticated data
1274  * @param[in] aLen Length of the additional data
1275  * @param[in] input Data to be encrypted/decrypted
1276  * @param[out] output Data resulting from the encryption/decryption process
1277  * @param[in] length Total number of data bytes to be processed
1278  * @param[out] t Authentication tag
1279  * @param[in] mode Operation mode
1280  **/
1281 
1282 void gcmProcessData(AesContext *context, const uint8_t *iv,
1283  const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output,
1284  size_t length, uint8_t *t, uint32_t mode)
1285 {
1286  size_t n;
1287  uint64_t m;
1288  uint32_t temp;
1289  uint32_t buffer[4];
1290 #if !defined (CRYP_VER_2_2)
1291  uint32_t h[4];
1292 #endif
1293 
1294  //Acquire exclusive access to the CRYP module
1296 
1297  //Configure the data type
1298  CRYP->CR = CRYP_CR_DATATYPE_8B;
1299 
1300  //Select the GCM chaining mode by programming ALGOMODE bits to '01000'
1301  temp = CRYP->CR & ~CRYP_CR_ALGOMODE;
1302  CRYP->CR = temp | CRYP_CR_ALGOMODE_AES_GCM;
1303 
1304  //Configure GCM_CCMPH bits to '00' to start the GCM init phase
1305  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1306  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_INIT;
1307 
1308  //Set encryption key
1309  aesLoadKey(context);
1310 
1311  //Set initialization vector
1312  CRYP->IV0LR = LOAD32BE(iv);
1313  CRYP->IV0RR = LOAD32BE(iv + 4);
1314  CRYP->IV1LR = LOAD32BE(iv + 8);
1315  CRYP->IV1RR = 2;
1316 
1317  //Set CRYPEN bit to 1 to start the calculation of the HASH key
1318  CRYP->CR |= CRYP_CR_CRYPEN;
1319 
1320  //Wait for the CRYPEN bit to be cleared to 0 before moving on to the
1321  //next phase
1322  while((CRYP->CR & CRYP_CR_CRYPEN) != 0)
1323  {
1324  }
1325 
1326  //Configure GCM_CCMPH bits to '01' to start GCM header phase
1327  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1328  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_HEADER;
1329 
1330  //Flush the input and output FIFOs
1331  CRYP->CR |= CRYP_CR_FFLUSH;
1332  //Set the CRYPEN bit to 1 to start accepting data
1333  CRYP->CR |= CRYP_CR_CRYPEN;
1334 
1335  //Process additional authenticated data
1336  for(n = aLen; n >= AES_BLOCK_SIZE; n -= AES_BLOCK_SIZE)
1337  {
1338  //Wait for the input FIFO to be ready to accept data
1339  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1340  {
1341  }
1342 
1343  //Write the input FIFO
1344  CRYP->DIN = __UNALIGNED_UINT32_READ(a);
1345  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 4);
1346  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 8);
1347  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 12);
1348 
1349  //Next block
1350  a += AES_BLOCK_SIZE;
1351  }
1352 
1353  //Process final block of additional authenticated data
1354  if(n > 0)
1355  {
1356  //Copy partial block
1357  osMemset(buffer, 0, AES_BLOCK_SIZE);
1358  osMemcpy(buffer, a, n);
1359 
1360  //Wait for the input FIFO to be ready to accept data
1361  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1362  {
1363  }
1364 
1365  //Write the input FIFO
1366  CRYP->DIN = buffer[0];
1367  CRYP->DIN = buffer[1];
1368  CRYP->DIN = buffer[2];
1369  CRYP->DIN = buffer[3];
1370  }
1371 
1372  //Once all header data have been supplied, wait until the BUSY bit is
1373  //cleared
1374  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1375  {
1376  }
1377 
1378  //Set the CRYPEN bit to 0
1379  CRYP->CR &= ~CRYP_CR_CRYPEN;
1380 
1381  //Configure GCM_CCMPH bits to '10' to start GCM payload phase
1382  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1383  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_PAYLOAD;
1384 
1385  //Select the algorithm direction by using the ALGODIR bit
1386  temp = CRYP->CR & ~CRYP_CR_ALGODIR;
1387  CRYP->CR |= mode;
1388 
1389  //Set the CRYPEN bit to 1 to start accepting data
1390  CRYP->CR |= CRYP_CR_CRYPEN;
1391 
1392  //Process data
1393  for(n = length; n >= AES_BLOCK_SIZE; n -= AES_BLOCK_SIZE)
1394  {
1395  //Wait for the input FIFO to be ready to accept data
1396  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1397  {
1398  }
1399 
1400  //Write the input FIFO
1401  CRYP->DIN = __UNALIGNED_UINT32_READ(input);
1402  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 4);
1403  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 8);
1404  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 12);
1405 
1406  //Wait for the output to be ready
1407  while((CRYP->SR & CRYP_SR_OFNE) == 0)
1408  {
1409  }
1410 
1411  //Read the output FIFO
1412  temp = CRYP->DOUT;
1413  __UNALIGNED_UINT32_WRITE(output, temp);
1414  temp = CRYP->DOUT;
1415  __UNALIGNED_UINT32_WRITE(output + 4, temp);
1416  temp = CRYP->DOUT;
1417  __UNALIGNED_UINT32_WRITE(output + 8, temp);
1418  temp = CRYP->DOUT;
1419  __UNALIGNED_UINT32_WRITE(output + 12, temp);
1420 
1421  //Next block
1422  input += AES_BLOCK_SIZE;
1423  output += AES_BLOCK_SIZE;
1424  }
1425 
1426  //Process final block of data
1427  if(n > 0)
1428  {
1429  //Copy partial block
1430  osMemset(buffer, 0, AES_BLOCK_SIZE);
1431  osMemcpy(buffer, input, n);
1432 
1433 #if !defined (CRYP_VER_2_2)
1434  //Check revision ID
1435  if(HAL_GetREVID() < REV_ID_B)
1436  {
1437  //Workaround for GCM encryption mode
1438  if((mode & CRYP_CR_ALGODIR) == 0)
1439  {
1440  //Wait until the BUSY bit is cleared
1441  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1442  {
1443  }
1444 
1445  //Save the current GHASH value
1446  h[0] = CRYP->CSGCM0R;
1447  h[1] = CRYP->CSGCM1R;
1448  h[2] = CRYP->CSGCM2R;
1449  h[3] = CRYP->CSGCM3R;
1450  }
1451  }
1452  else
1453 #endif
1454  {
1455  //Specify the number of padding bytes in the last block
1456  temp = CRYP->CR & ~CRYP_CR_NPBLB;
1457  CRYP->CR = temp | ((AES_BLOCK_SIZE - n) << CRYP_CR_NPBLB_Pos);
1458  }
1459 
1460  //Wait for the input FIFO to be ready to accept data
1461  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1462  {
1463  }
1464 
1465  //Write the input FIFO
1466  CRYP->DIN = buffer[0];
1467  CRYP->DIN = buffer[1];
1468  CRYP->DIN = buffer[2];
1469  CRYP->DIN = buffer[3];
1470 
1471  //Wait for the output to be ready
1472  while((CRYP->SR & CRYP_SR_OFNE) == 0)
1473  {
1474  }
1475 
1476  //Read the output FIFO
1477  buffer[0] = CRYP->DOUT;
1478  buffer[1] = CRYP->DOUT;
1479  buffer[2] = CRYP->DOUT;
1480  buffer[3] = CRYP->DOUT;
1481 
1482  //Copy partial block
1483  osMemcpy(output, buffer, n);
1484 
1485 #if !defined (CRYP_VER_2_2)
1486  //Check revision ID
1487  if(HAL_GetREVID() < REV_ID_B)
1488  {
1489  //Workaround for GCM encryption mode
1490  if((mode & CRYP_CR_ALGODIR) == 0)
1491  {
1492  //Pad the final ciphertext block with zeroes
1493  osMemset((uint8_t *) buffer + n, 0, AES_BLOCK_SIZE - n);
1494 
1495  //Wait until the BUSY bit is cleared
1496  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1497  {
1498  }
1499 
1500  //Switch to decryption mode
1501  CRYP->CR |= CRYP_CR_ALGODIR;
1502 
1503  //Restore the previous GHASH value
1504  CRYP->CSGCM0R = h[0];
1505  CRYP->CSGCM1R = h[1];
1506  CRYP->CSGCM2R = h[2];
1507  CRYP->CSGCM3R = h[3];
1508 
1509  //Wait for the input FIFO to be ready to accept data
1510  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1511  {
1512  }
1513 
1514  //Write the input FIFO
1515  CRYP->DIN = buffer[0];
1516  CRYP->DIN = buffer[1];
1517  CRYP->DIN = buffer[2];
1518  CRYP->DIN = buffer[3];
1519 
1520  //Wait until the OFNE flag is set to 1 in the CRYP_SR register
1521  while((CRYP->SR & CRYP_SR_OFNE) == 0)
1522  {
1523  }
1524 
1525  //Read the output FIFO and discard the data
1526  buffer[0] = CRYP->DOUT;
1527  buffer[1] = CRYP->DOUT;
1528  buffer[2] = CRYP->DOUT;
1529  buffer[3] = CRYP->DOUT;
1530  }
1531  }
1532 #endif
1533  }
1534 
1535  //Once all payload data have been supplied, wait until the BUSY flag is
1536  //cleared
1537  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1538  {
1539  }
1540 
1541  //Configure GCM_CCMPH bits to '11' to start GCM final phase
1542  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1543  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_FINAL;
1544 
1545 #if !defined (CRYP_VER_2_2)
1546  //Check revision ID
1547  if(HAL_GetREVID() < REV_ID_B)
1548  {
1549  //Write the input into the CRYP_DIN register 4 times. The input must
1550  //contain the number of bits in the header (64 bits) concatenated with
1551  //the number of bits in the payload (64 bits)
1552  m = aLen * 8;
1553  CRYP->DIN = htobe32(m >> 32);
1554  CRYP->DIN = htobe32(m);
1555  m = length * 8;
1556  CRYP->DIN = htobe32(m >> 32);
1557  CRYP->DIN = htobe32(m);
1558  }
1559  else
1560 #endif
1561  {
1562  //For revision B and above, the data is written without swapping
1563  m = aLen * 8;
1564  CRYP->DIN = htole32(m >> 32);
1565  CRYP->DIN = htole32(m);
1566  m = length * 8;
1567  CRYP->DIN = htole32(m >> 32);
1568  CRYP->DIN = htole32(m);
1569  }
1570 
1571  //Wait until the OFNE flag is set to 1 in the CRYP_SR register
1572  while((CRYP->SR & CRYP_SR_OFNE) == 0)
1573  {
1574  }
1575 
1576  //Read the CRYP_DOUT register 4 times. The output corresponds to the
1577  //authentication tag
1578  temp = CRYP->DOUT;
1579  __UNALIGNED_UINT32_WRITE(t, temp);
1580  temp = CRYP->DOUT;
1581  __UNALIGNED_UINT32_WRITE(t + 4, temp);
1582  temp = CRYP->DOUT;
1583  __UNALIGNED_UINT32_WRITE(t + 8, temp);
1584  temp = CRYP->DOUT;
1585  __UNALIGNED_UINT32_WRITE(t + 12, temp);
1586 
1587  //Disable the cryptographic processor by clearing the CRYPEN bit
1588  CRYP->CR = 0;
1589 
1590  //Release exclusive access to the CRYP module
1592 }
1593 
1594 
1595 /**
1596  * @brief Initialize GCM context
1597  * @param[in] context Pointer to the GCM context
1598  * @param[in] cipherAlgo Cipher algorithm
1599  * @param[in] cipherContext Pointer to the cipher algorithm context
1600  * @return Error code
1601  **/
1602 
1603 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1604  void *cipherContext)
1605 {
1606  //Check parameters
1607  if(context == NULL || cipherContext == NULL)
1608  return ERROR_INVALID_PARAMETER;
1609 
1610  //The CRYP module only supports AES cipher algorithm
1611  if(cipherAlgo != AES_CIPHER_ALGO)
1612  return ERROR_INVALID_PARAMETER;
1613 
1614  //Save cipher algorithm context
1615  context->cipherAlgo = cipherAlgo;
1616  context->cipherContext = cipherContext;
1617 
1618  //Successful initialization
1619  return NO_ERROR;
1620 }
1621 
1622 
1623 /**
1624  * @brief Authenticated encryption using GCM
1625  * @param[in] context Pointer to the GCM context
1626  * @param[in] iv Initialization vector
1627  * @param[in] ivLen Length of the initialization vector
1628  * @param[in] a Additional authenticated data
1629  * @param[in] aLen Length of the additional data
1630  * @param[in] p Plaintext to be encrypted
1631  * @param[out] c Ciphertext resulting from the encryption
1632  * @param[in] length Total number of data bytes to be encrypted
1633  * @param[out] t Authentication tag
1634  * @param[in] tLen Length of the authentication tag
1635  * @return Error code
1636  **/
1637 
1638 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1639  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1640  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1641 {
1642  uint8_t authTag[16];
1643 
1644  //Make sure the GCM context is valid
1645  if(context == NULL)
1646  return ERROR_INVALID_PARAMETER;
1647 
1648  //Check whether the length of the IV is 96 bits
1649  if(ivLen != 12)
1650  return ERROR_INVALID_LENGTH;
1651 
1652  //Check the length of the authentication tag
1653  if(tLen < 4 || tLen > 16)
1654  return ERROR_INVALID_LENGTH;
1655 
1656  //Perform AES-GCM encryption
1657  gcmProcessData(context->cipherContext, iv, a, aLen, p, c, length,
1658  authTag, 0);
1659 
1660  //Copy the resulting authentication tag
1661  osMemcpy(t, authTag, tLen);
1662 
1663  //Successful processing
1664  return NO_ERROR;
1665 }
1666 
1667 
1668 /**
1669  * @brief Authenticated decryption using GCM
1670  * @param[in] context Pointer to the GCM context
1671  * @param[in] iv Initialization vector
1672  * @param[in] ivLen Length of the initialization vector
1673  * @param[in] a Additional authenticated data
1674  * @param[in] aLen Length of the additional data
1675  * @param[in] c Ciphertext to be decrypted
1676  * @param[out] p Plaintext resulting from the decryption
1677  * @param[in] length Total number of data bytes to be decrypted
1678  * @param[in] t Authentication tag
1679  * @param[in] tLen Length of the authentication tag
1680  * @return Error code
1681  **/
1682 
1683 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1684  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1685  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1686 {
1687  size_t i;
1688  uint8_t mask;
1689  uint8_t authTag[16];
1690 
1691  //Make sure the GCM context is valid
1692  if(context == NULL)
1693  return ERROR_INVALID_PARAMETER;
1694 
1695  //Check whether the length of the IV is 96 bits
1696  if(ivLen != 12)
1697  return ERROR_INVALID_LENGTH;
1698 
1699  //Check the length of the authentication tag
1700  if(tLen < 4 || tLen > 16)
1701  return ERROR_INVALID_LENGTH;
1702 
1703  //Perform AES-GCM decryption
1704  gcmProcessData(context->cipherContext, iv, a, aLen, c, p, length,
1705  authTag, CRYP_CR_ALGODIR);
1706 
1707  //The calculated tag is bitwise compared to the received tag
1708  for(mask = 0, i = 0; i < tLen; i++)
1709  {
1710  mask |= authTag[i] ^ t[i];
1711  }
1712 
1713  //The message is authenticated if and only if the tags match
1714  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1715 }
1716 
1717 #endif
1718 #if (CCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1719 
1720 /**
1721  * @brief Perform AES-CCM encryption or decryption
1722  * @param[in] context AES algorithm context
1723  * @param[in] b0 Pointer to the B0 block
1724  * @param[in] a Additional authenticated data
1725  * @param[in] aLen Length of the additional data
1726  * @param[in] input Data to be encrypted/decrypted
1727  * @param[out] output Data resulting from the encryption/decryption process
1728  * @param[in] length Total number of data bytes to be processed
1729  * @param[out] t Authentication tag
1730  * @param[in] mode Operation mode
1731  **/
1732 
1733 void ccmProcessData(AesContext *context, const uint8_t *b0, const uint8_t *a,
1734  size_t aLen, const uint8_t *input, uint8_t *output, size_t length,
1735  uint8_t *t, uint32_t mode)
1736 {
1737  size_t n;
1738  size_t qLen;
1739  uint32_t temp;
1740  uint8_t buffer[16];
1741 #if !defined (CRYP_VER_2_2)
1742  uint32_t y[4];
1743 #endif
1744 
1745  //Acquire exclusive access to the CRYP module
1747 
1748  //Configure the data type
1749  CRYP->CR = CRYP_CR_DATATYPE_8B;
1750 
1751  //Select the CCM chaining mode by programming ALGOMODE bits to '01001'
1752  temp = CRYP->CR & ~CRYP_CR_ALGOMODE;
1753  CRYP->CR = temp | CRYP_CR_ALGOMODE_AES_CCM;
1754 
1755  //Configure GCM_CCMPH bits to '00' to start the CCM init phase
1756  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1757  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_INIT;
1758 
1759  //Set encryption key
1760  aesLoadKey(context);
1761 
1762  //Retrieve the octet length of Q
1763  qLen = (b0[0] & 0x07) + 1;
1764 
1765  //Format CTR(1)
1766  osMemcpy(buffer, b0, 16 - qLen);
1767  osMemset(buffer + 16 - qLen, 0, qLen);
1768 
1769  //Set the leading octet
1770  buffer[0] = (uint8_t) (qLen - 1);
1771  //Set counter value
1772  buffer[15] = 1;
1773 
1774  //Initialize CRYP_IVRx registers with CTR(1)
1775  CRYP->IV0LR = LOAD32BE(buffer);
1776  CRYP->IV0RR = LOAD32BE(buffer + 4);
1777  CRYP->IV1LR = LOAD32BE(buffer + 8);
1778  CRYP->IV1RR = LOAD32BE(buffer + 12);
1779 
1780  //Set the CRYPEN bit to 1 in CRYP_CR to start accepting data
1781  CRYP->CR |= CRYP_CR_CRYPEN;
1782 
1783 #if !defined (CRYP_VER_2_2)
1784  //Check revision ID
1785  if(HAL_GetREVID() < REV_ID_B)
1786  {
1787  //Write the B0 packet into CRYP_DIN register
1788  CRYP->DIN = LOAD32LE(b0);
1789  CRYP->DIN = LOAD32LE(b0 + 4);
1790  CRYP->DIN = LOAD32LE(b0 + 8);
1791  CRYP->DIN = LOAD32LE(b0 + 12);
1792  }
1793  else
1794 #endif
1795  {
1796  //For revision B and above, B0 is written without swapping
1797  CRYP->DIN = LOAD32BE(b0);
1798  CRYP->DIN = LOAD32BE(b0 + 4);
1799  CRYP->DIN = LOAD32BE(b0 + 8);
1800  CRYP->DIN = LOAD32BE(b0 + 12);
1801  }
1802 
1803  //Wait for the CRYPEN bit to be cleared to 0 by the cryptographic processor
1804  //before moving on to the next phase
1805  while((CRYP->CR & CRYP_CR_CRYPEN) != 0)
1806  {
1807  }
1808 
1809  //Configure GCM_CCMPH bits to '01' to start CCM header phase
1810  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1811  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_HEADER;
1812 
1813  //Flush the input and output FIFOs
1814  CRYP->CR |= CRYP_CR_FFLUSH;
1815  //Set the CRYPEN bit to 1 to start accepting data
1816  CRYP->CR |= CRYP_CR_CRYPEN;
1817 
1818  //The header phase can be skipped if there is no associated data
1819  if(aLen > 0)
1820  {
1821  //The first block of the associated data (B1) must be formatted by
1822  //software, with the associated data length
1823  osMemset(buffer, 0, 16);
1824 
1825  //Check the length of the associated data string
1826  if(aLen < 0xFF00)
1827  {
1828  //The length is encoded as 2 octets
1829  STORE16BE(aLen, buffer);
1830 
1831  //Number of bytes to copy
1832  n = MIN(aLen, 16 - 2);
1833  //Concatenate the associated data A
1834  osMemcpy(buffer + 2, a, n);
1835  }
1836  else
1837  {
1838  //The length is encoded as 6 octets
1839  buffer[0] = 0xFF;
1840  buffer[1] = 0xFE;
1841 
1842  //MSB is stored first
1843  STORE32BE(aLen, buffer + 2);
1844 
1845  //Number of bytes to copy
1846  n = MIN(aLen, 16 - 6);
1847  //Concatenate the associated data A
1848  osMemcpy(buffer + 6, a, n);
1849  }
1850 
1851  //Wait for the input FIFO to be ready to accept data
1852  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1853  {
1854  }
1855 
1856  //Write the input FIFO
1857  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer);
1858  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 4);
1859  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 8);
1860  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 12);
1861 
1862  //Number of remaining data bytes
1863  aLen -= n;
1864  a += n;
1865  }
1866 
1867  //Process additional authenticated data
1868  while(aLen >= AES_BLOCK_SIZE)
1869  {
1870  //Wait for the input FIFO to be ready to accept data
1871  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1872  {
1873  }
1874 
1875  //Write the input FIFO
1876  CRYP->DIN = __UNALIGNED_UINT32_READ(a);
1877  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 4);
1878  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 8);
1879  CRYP->DIN = __UNALIGNED_UINT32_READ(a + 12);
1880 
1881  //Next block
1882  a += AES_BLOCK_SIZE;
1883  aLen -= AES_BLOCK_SIZE;
1884  }
1885 
1886  //Process final block of additional authenticated data
1887  if(aLen > 0)
1888  {
1889  //If the AAD size in the last block is inferior to 128 bits, pad the
1890  //remainder of the block with zeros
1891  osMemset(buffer, 0, AES_BLOCK_SIZE);
1892  osMemcpy(buffer, a, aLen);
1893 
1894  //Wait for the input FIFO to be ready to accept data
1895  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1896  {
1897  }
1898 
1899  //Write the input FIFO
1900  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer);
1901  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 4);
1902  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 8);
1903  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 12);
1904  }
1905 
1906  //Once all header data have been supplied, wait until the BUSY bit is
1907  //cleared
1908  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1909  {
1910  }
1911 
1912  //Set the CRYPEN bit to 0
1913  CRYP->CR &= ~CRYP_CR_CRYPEN;
1914 
1915  //Configure GCM_CCMPH bits to '10' to start CCM payload phase
1916  temp = CRYP->CR & ~CRYP_CR_GCM_CCMPH;
1917  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_PAYLOAD;
1918 
1919  //Select the algorithm direction by using the ALGODIR bit
1920  temp = CRYP->CR & ~CRYP_CR_ALGODIR;
1921  CRYP->CR |= mode;
1922 
1923  //Set the CRYPEN bit to 1 to start accepting data
1924  CRYP->CR |= CRYP_CR_CRYPEN;
1925 
1926  //Process data
1927  while(length >= AES_BLOCK_SIZE)
1928  {
1929  //Wait for the input FIFO to be ready to accept data
1930  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1931  {
1932  }
1933 
1934  //Write the input FIFO
1935  CRYP->DIN = __UNALIGNED_UINT32_READ(input);
1936  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 4);
1937  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 8);
1938  CRYP->DIN = __UNALIGNED_UINT32_READ(input + 12);
1939 
1940  //Wait for the output to be ready
1941  while((CRYP->SR & CRYP_SR_OFNE) == 0)
1942  {
1943  }
1944 
1945  //Read the output FIFO
1946  temp = CRYP->DOUT;
1947  __UNALIGNED_UINT32_WRITE(output, temp);
1948  temp = CRYP->DOUT;
1949  __UNALIGNED_UINT32_WRITE(output + 4, temp);
1950  temp = CRYP->DOUT;
1951  __UNALIGNED_UINT32_WRITE(output + 8, temp);
1952  temp = CRYP->DOUT;
1953  __UNALIGNED_UINT32_WRITE(output + 12, temp);
1954 
1955  //Next block
1956  input += AES_BLOCK_SIZE;
1957  output += AES_BLOCK_SIZE;
1959  }
1960 
1961  //Process final block of data
1962  if(length > 0)
1963  {
1964  //If it is the last block and the plaintext (encryption) or ciphertext
1965  //(decryption) size in the block is inferior to 128 bits, pad the
1966  //remainder of the block with zeros
1967  osMemset(buffer, 0, AES_BLOCK_SIZE);
1968  osMemcpy(buffer, input, length);
1969 
1970 #if !defined (CRYP_VER_2_2)
1971  //Check revision ID
1972  if(HAL_GetREVID() < REV_ID_B)
1973  {
1974  //Workaround for CCM decryption mode
1975  if((mode & CRYP_CR_ALGODIR) != 0)
1976  {
1977  //Wait until the BUSY bit is cleared
1978  while((CRYP->SR & CRYP_SR_BUSY) != 0)
1979  {
1980  }
1981 
1982  //Save the current value of Y
1983  y[0] = CRYP->CSGCMCCM0R;
1984  y[1] = CRYP->CSGCMCCM1R;
1985  y[2] = CRYP->CSGCMCCM2R;
1986  y[3] = CRYP->CSGCMCCM3R;
1987  }
1988  }
1989  else
1990 #endif
1991  {
1992  //Specify the number of padding bytes in the last block
1993  temp = CRYP->CR & ~CRYP_CR_NPBLB;
1994  CRYP->CR = temp | ((AES_BLOCK_SIZE - length) << CRYP_CR_NPBLB_Pos);
1995  }
1996 
1997  //Wait for the input FIFO to be ready to accept data
1998  while((CRYP->SR & CRYP_SR_IFNF) == 0)
1999  {
2000  }
2001 
2002  //Write the input FIFO
2003  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer);
2004  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 4);
2005  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 8);
2006  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 12);
2007 
2008  //Wait for the output to be ready
2009  while((CRYP->SR & CRYP_SR_OFNE) == 0)
2010  {
2011  }
2012 
2013  //Read the output FIFO
2014  temp = CRYP->DOUT;
2015  __UNALIGNED_UINT32_WRITE(buffer, temp);
2016  temp = CRYP->DOUT;
2017  __UNALIGNED_UINT32_WRITE(buffer + 4, temp);
2018  temp = CRYP->DOUT;
2019  __UNALIGNED_UINT32_WRITE(buffer + 8, temp);
2020  temp = CRYP->DOUT;
2021  __UNALIGNED_UINT32_WRITE(buffer + 12, temp);
2022 
2023  //Discard the bits that are not part of the payload when the last block
2024  //size is less than 16 bytes
2025  osMemcpy(output, buffer, length);
2026 
2027 #if !defined (CRYP_VER_2_2)
2028  //Check revision ID
2029  if(HAL_GetREVID() < REV_ID_B)
2030  {
2031  //Workaround for CCM decryption mode
2032  if((mode & CRYP_CR_ALGODIR) != 0)
2033  {
2034  //Pad the final plaintext block with zeroes
2035  osMemset(buffer + length, 0, AES_BLOCK_SIZE - length);
2036 
2037  //Wait until the BUSY bit is cleared
2038  while((CRYP->SR & CRYP_SR_BUSY) != 0)
2039  {
2040  }
2041 
2042  //Switch to encryption mode
2043  CRYP->CR &= ~CRYP_CR_ALGODIR;
2044 
2045  //Restore the previous value of Y
2046  CRYP->CSGCMCCM0R = y[0];
2047  CRYP->CSGCMCCM1R = y[1];
2048  CRYP->CSGCMCCM2R = y[2];
2049  CRYP->CSGCMCCM3R = y[3];
2050 
2051  //Wait for the input FIFO to be ready to accept data
2052  while((CRYP->SR & CRYP_SR_IFNF) == 0)
2053  {
2054  }
2055 
2056  //Write the input FIFO
2057  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer);
2058  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 4);
2059  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 8);
2060  CRYP->DIN = __UNALIGNED_UINT32_READ(buffer + 12);
2061 
2062  //Wait for the output to be ready
2063  while((CRYP->SR & CRYP_SR_OFNE) == 0)
2064  {
2065  }
2066 
2067  //Read the output FIFO and discard the data
2068  temp = CRYP->DOUT;
2069  temp = CRYP->DOUT;
2070  temp = CRYP->DOUT;
2071  temp = CRYP->DOUT;
2072  }
2073  }
2074 #endif
2075  }
2076 
2077  //Once all payload data have been supplied, wait until the BUSY flag is
2078  //cleared
2079  while((CRYP->SR & CRYP_SR_BUSY) != 0)
2080  {
2081  }
2082 
2083  //Configure GCM_CCMPH bits to '11' in CRYP_CR to indicate that the CCM final
2084  //phase is ongoing and set the ALGODIR bit to 0 in the same register
2085  temp = CRYP->CR & ~(CRYP_CR_GCM_CCMPH | CRYP_CR_ALGODIR);
2086  CRYP->CR = temp | CRYP_CR_GCM_CCMPH_FINAL;
2087 
2088  //Format CTR(0)
2089  osMemcpy(buffer, b0, 16 - qLen);
2090  osMemset(buffer + 16 - qLen, 0, qLen);
2091 
2092  //Set the leading octet
2093  buffer[0] = (uint8_t) (qLen - 1);
2094 
2095 #if !defined (CRYP_VER_2_2)
2096  //Check revision ID
2097  if(HAL_GetREVID() < REV_ID_B)
2098  {
2099  //Load in CRYP_DIN the CTR(0) information
2100  CRYP->DIN = LOAD32LE(buffer);
2101  CRYP->DIN = LOAD32LE(buffer + 4);
2102  CRYP->DIN = LOAD32LE(buffer + 8);
2103  CRYP->DIN = LOAD32LE(buffer + 12);
2104  }
2105  else
2106 #endif
2107  {
2108  //For revision B and above, CTR(0) is written without swapping
2109  CRYP->DIN = LOAD32BE(buffer);
2110  CRYP->DIN = LOAD32BE(buffer + 4);
2111  CRYP->DIN = LOAD32BE(buffer + 8);
2112  CRYP->DIN = LOAD32BE(buffer + 12);
2113  }
2114 
2115  //Wait until the OFNE flag is set to 1 in the CRYP_SR register
2116  while((CRYP->SR & CRYP_SR_OFNE) == 0)
2117  {
2118  }
2119 
2120  //Read the CRYP_DOUT register 4 times. The output corresponds to the
2121  //authentication tag
2122  temp = CRYP->DOUT;
2123  __UNALIGNED_UINT32_WRITE(t, temp);
2124  temp = CRYP->DOUT;
2125  __UNALIGNED_UINT32_WRITE(t + 4, temp);
2126  temp = CRYP->DOUT;
2127  __UNALIGNED_UINT32_WRITE(t + 8, temp);
2128  temp = CRYP->DOUT;
2129  __UNALIGNED_UINT32_WRITE(t + 12, temp);
2130 
2131  //Disable the cryptographic processor by clearing the CRYPEN bit
2132  CRYP->CR = 0;
2133 
2134  //Release exclusive access to the CRYP module
2136 }
2137 
2138 
2139 /**
2140  * @brief Authenticated encryption using CCM
2141  * @param[in] cipher Cipher algorithm
2142  * @param[in] context Cipher algorithm context
2143  * @param[in] n Nonce
2144  * @param[in] nLen Length of the nonce
2145  * @param[in] a Additional authenticated data
2146  * @param[in] aLen Length of the additional data
2147  * @param[in] p Plaintext to be encrypted
2148  * @param[out] c Ciphertext resulting from the encryption
2149  * @param[in] length Total number of data bytes to be encrypted
2150  * @param[out] t MAC resulting from the encryption process
2151  * @param[in] tLen Length of the MAC
2152  * @return Error code
2153  **/
2154 
2155 error_t ccmEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *n,
2156  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c,
2157  size_t length, uint8_t *t, size_t tLen)
2158 {
2159  error_t error;
2160  uint8_t b0[16];
2161  uint8_t authTag[16];
2162 
2163  //The CRYP module only supports AES cipher algorithm
2164  if(cipher != AES_CIPHER_ALGO)
2165  return ERROR_INVALID_PARAMETER;
2166 
2167  //Make sure the cipher context is valid
2168  if(context == NULL)
2169  return ERROR_INVALID_PARAMETER;
2170 
2171  //Format first block B(0)
2172  error = ccmFormatBlock0(length, n, nLen, aLen, tLen, b0);
2173  //Invalid parameters?
2174  if(error)
2175  return error;
2176 
2177  //Perform AES-CCM encryption
2178  ccmProcessData(context, b0, a, aLen, p, c, length, authTag, 0);
2179 
2180  //Copy the resulting authentication tag
2181  osMemcpy(t, authTag, tLen);
2182 
2183  //Successful processing
2184  return NO_ERROR;
2185 }
2186 
2187 
2188 /**
2189  * @brief Authenticated decryption using CCM
2190  * @param[in] cipher Cipher algorithm
2191  * @param[in] context Cipher algorithm context
2192  * @param[in] n Nonce
2193  * @param[in] nLen Length of the nonce
2194  * @param[in] a Additional authenticated data
2195  * @param[in] aLen Length of the additional data
2196  * @param[in] c Ciphertext to be decrypted
2197  * @param[out] p Plaintext resulting from the decryption
2198  * @param[in] length Total number of data bytes to be decrypted
2199  * @param[in] t MAC to be verified
2200  * @param[in] tLen Length of the MAC
2201  * @return Error code
2202  **/
2203 
2204 error_t ccmDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *n,
2205  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p,
2206  size_t length, const uint8_t *t, size_t tLen)
2207 {
2208  error_t error;
2209  size_t i;
2210  uint8_t mask;
2211  uint8_t b0[16];
2212  uint8_t authTag[16];
2213 
2214  //The CRYP module only supports AES cipher algorithm
2215  if(cipher != AES_CIPHER_ALGO)
2216  return ERROR_INVALID_PARAMETER;
2217 
2218  //Make sure the cipher context is valid
2219  if(context == NULL)
2220  return ERROR_INVALID_PARAMETER;
2221 
2222  //Format first block B(0)
2223  error = ccmFormatBlock0(length, n, nLen, aLen, tLen, b0);
2224  //Invalid parameters?
2225  if(error)
2226  return error;
2227 
2228  //Perform AES-CCM decryption
2229  ccmProcessData(context, b0, a, aLen, c, p, length, authTag, CRYP_CR_ALGODIR);
2230 
2231  //The calculated tag is bitwise compared to the received tag
2232  for(mask = 0, i = 0; i < tLen; i++)
2233  {
2234  mask |= authTag[i] ^ t[i];
2235  }
2236 
2237  //The message is authenticated if and only if the tags match
2238  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
2239 }
2240 
2241 #endif
2242 #endif
#define AES_CIPHER_ALGO
Definition: aes.h:45
#define AES_BLOCK_SIZE
Definition: aes.h:43
error_t ccmFormatBlock0(size_t q, const uint8_t *n, size_t nLen, size_t aLen, size_t tLen, uint8_t *b)
Format first block B(0)
Definition: ccm.c:353
Collection of AEAD algorithms.
Block cipher modes of operation.
unsigned int uint_t
Definition: compiler_port.h:50
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define htole32(value)
Definition: cpu_endian.h:430
#define LOAD32LE(p)
Definition: cpu_endian.h:203
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
#define htobe32(value)
Definition: cpu_endian.h:446
General definitions for cryptographic algorithms.
Debugging facilities.
#define DES3_CIPHER_ALGO
Definition: des3.h:46
#define DES3_BLOCK_SIZE
Definition: des3.h:44
#define DES_BLOCK_SIZE
Definition: des.h:43
#define DES_CIPHER_ALGO
Definition: des.h:45
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 h
Definition: ndp.h:302
uint8_t c
Definition: ndp.h:514
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
uint8_t a
Definition: ndp.h:411
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
#define CRYP_CR_KEYSIZE_192B
#define CRYP_CR_KEYSIZE_128B
#define CRYP_CR_DATATYPE_8B
#define CRYP_CR_KEYSIZE_256B
#define CRYP_CR_GCM_CCMPH_FINAL
#define CRYP_CR_GCM_CCMPH_INIT
#define CRYP_CR_GCM_CCMPH_PAYLOAD
#define CRYP_CR_GCM_CCMPH_HEADER
OsMutex stm32h7xxCryptoMutex
STM32H7 hardware cryptographic accelerator.
void des3ProcessData(Des3Context *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t mode)
Perform Triple DES encryption or decryption.
void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using Triple DES algorithm.
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
error_t ccmDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using CCM.
error_t gcmEncrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using GCM.
void aesLoadKey(AesContext *context)
Load AES key.
void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using DES algorithm.
error_t ccmEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using CCM.
error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
void aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t mode)
Perform AES encryption or decryption.
void gcmProcessData(AesContext *context, const uint8_t *iv, const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output, size_t length, uint8_t *t, uint32_t mode)
Perform AES-GCM encryption or decryption.
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
Initialize a Triple DES context using the supplied key.
void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using Triple DES algorithm.
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.
void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using DES algorithm.
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
void desProcessData(DesContext *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t mode)
Perform DES encryption or decryption.
error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
void ccmProcessData(AesContext *context, const uint8_t *b0, const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output, size_t length, uint8_t *t, uint32_t mode)
Perform AES-CCM encryption or decryption.
error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
Initialize a DES context using the supplied key.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
STM32H7 cipher hardware accelerator.
AES algorithm context.
Definition: aes.h:58
uint_t nr
Definition: aes.h:59
uint32_t ek[60]
Definition: aes.h:60
Common interface for encryption algorithms.
Definition: crypto.h:1036
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1044
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1045
size_t blockSize
Definition: crypto.h:1040
Triple DES algorithm context.
Definition: des3.h:59
DesContext k2
Definition: des3.h:61
DesContext k3
Definition: des3.h:62
DesContext k1
Definition: des3.h:60
DES algorithm context.
Definition: des.h:58
uint32_t ks[32]
Definition: des.h:59
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