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