sam9x60_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file sam9x60_crypto_cipher.c
3  * @brief SAM9X60 cipher hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2023 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.3.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "sam9x60.h"
36 #include "core/crypto.h"
41 #include "aead/aead_algorithms.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (SAM9X60_CRYPTO_CIPHER_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Encrypt/decrypt a 16-byte block using DES algorithm
50  * @param[in] input Input block to be encrypted/decrypted
51  * @param[out] output Resulting block
52  **/
53 
54 void desProcessDataBlock(const uint8_t *input, uint8_t *output)
55 {
56  uint32_t temp;
57 
58  //Write input block
59  TDES->TDES_IDATAR[0] = LOAD32LE(input);
60  TDES->TDES_IDATAR[1] = LOAD32LE(input + 4);
61 
62  //Start encryption/decryption
63  TDES->TDES_CR = TDES_CR_START;
64 
65  //When processing completes, the DATRDY flag is raised
66  while((TDES->TDES_ISR & TDES_ISR_DATRDY) == 0)
67  {
68  }
69 
70  //Read output block
71  temp = TDES->TDES_ODATAR[0];
72  STORE32LE(temp, output);
73  temp = TDES->TDES_ODATAR[1];
74  STORE32LE(temp, output + 4);
75 }
76 
77 
78 #if (DES_SUPPORT == ENABLED)
79 
80 /**
81  * @brief Perform DES encryption or decryption
82  * @param[in] context DES algorithm context
83  * @param[in,out] iv Initialization vector
84  * @param[in] input Data to be encrypted/decrypted
85  * @param[out] output Data resulting from the encryption/decryption process
86  * @param[in] length Total number of data bytes to be processed
87  * @param[in] mode Operation mode
88  **/
89 
90 void desProcessData(DesContext *context, uint8_t *iv, const uint8_t *input,
91  uint8_t *output, size_t length, uint32_t mode)
92 {
93  //Acquire exclusive access to the TDES module
95 
96  //Perform software reset
97  TDES->TDES_CR = TDES_CR_SWRST;
98 
99  //Set operation mode
100  TDES->TDES_MR = TDES_MR_SMOD_MANUAL_START | TDES_MR_TDESMOD(0) | mode;
101 
102  //Set encryption key
103  TDES->TDES_KEY1WR[0] = context->ks[0];
104  TDES->TDES_KEY1WR[1] = context->ks[1];
105 
106  //Valid initialization vector?
107  if(iv != NULL)
108  {
109  //Set initialization vector
110  TDES->TDES_IVR[0] = LOAD32LE(iv);
111  TDES->TDES_IVR[1] = LOAD32LE(iv + 4);
112  }
113 
114  //Process data
115  while(length >= DES_BLOCK_SIZE)
116  {
117  //The data is encrypted block by block
118  desProcessDataBlock(input, output);
119 
120  //Next block
121  input += DES_BLOCK_SIZE;
122  output += DES_BLOCK_SIZE;
124  }
125 
126  //Process final block of data
127  if(length > 0)
128  {
129  uint8_t buffer[DES_BLOCK_SIZE];
130 
131  //Copy input data
132  osMemset(buffer, 0, DES_BLOCK_SIZE);
133  osMemcpy(buffer, input, length);
134 
135  //Encrypt the final block of data
136  desProcessDataBlock(buffer, buffer);
137 
138  //Copy output data
139  osMemcpy(output, buffer, length);
140  }
141 
142  //Release exclusive access to the TDES module
144 }
145 
146 
147 /**
148  * @brief Initialize a DES context using the supplied key
149  * @param[in] context Pointer to the DES context to initialize
150  * @param[in] key Pointer to the key
151  * @param[in] keyLen Length of the key (must be set to 8)
152  * @return Error code
153  **/
154 
155 error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
156 {
157  //Check parameters
158  if(context == NULL || key == NULL)
160 
161  //Invalid key length?
162  if(keyLen != 8)
164 
165  //Copy the key
166  osMemcpy(context->ks, key, keyLen);
167 
168  //No error to report
169  return NO_ERROR;
170 }
171 
172 
173 /**
174  * @brief Encrypt a 8-byte block using DES algorithm
175  * @param[in] context Pointer to the DES context
176  * @param[in] input Plaintext block to encrypt
177  * @param[out] output Ciphertext block resulting from encryption
178  **/
179 
180 void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
181 {
182  //Perform DES encryption
183  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE, TDES_MR_CIPHER |
184  TDES_MR_OPMOD_ECB);
185 }
186 
187 
188 /**
189  * @brief Decrypt a 8-byte block using DES algorithm
190  * @param[in] context Pointer to the DES context
191  * @param[in] input Ciphertext block to decrypt
192  * @param[out] output Plaintext block resulting from decryption
193  **/
194 
195 void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
196 {
197  //Perform DES decryption
198  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE,
199  TDES_MR_OPMOD_ECB);
200 }
201 
202 #endif
203 #if (DES3_SUPPORT == ENABLED)
204 
205 /**
206  * @brief Perform Triple DES encryption or decryption
207  * @param[in] context DES algorithm context
208  * @param[in,out] iv Initialization vector
209  * @param[in] input Data to be encrypted/decrypted
210  * @param[out] output Data resulting from the encryption/decryption process
211  * @param[in] length Total number of data bytes to be processed
212  * @param[in] mode Operation mode
213  **/
214 
215 void des3ProcessData(Des3Context *context, uint8_t *iv, const uint8_t *input,
216  uint8_t *output, size_t length, uint32_t mode)
217 {
218  //Acquire exclusive access to the TDES module
220 
221  //Perform software reset
222  TDES->TDES_CR = TDES_CR_SWRST;
223 
224  //Set operation mode
225  TDES->TDES_MR = TDES_MR_SMOD_MANUAL_START | TDES_MR_TDESMOD(1) | mode;
226 
227  //Set encryption key
228  TDES->TDES_KEY1WR[0] = context->k1.ks[0];
229  TDES->TDES_KEY1WR[1] = context->k1.ks[1];
230  TDES->TDES_KEY2WR[0] = context->k2.ks[0];
231  TDES->TDES_KEY2WR[1] = context->k2.ks[1];
232  TDES->TDES_KEY3WR[0] = context->k3.ks[0];
233  TDES->TDES_KEY3WR[1] = context->k3.ks[1];
234 
235  //Valid initialization vector?
236  if(iv != NULL)
237  {
238  //Set initialization vector
239  TDES->TDES_IVR[0] = LOAD32LE(iv);
240  TDES->TDES_IVR[1] = LOAD32LE(iv + 4);
241  }
242 
243  //Process data
244  while(length >= DES3_BLOCK_SIZE)
245  {
246  //The data is encrypted block by block
247  desProcessDataBlock(input, output);
248 
249  //Next block
250  input += DES3_BLOCK_SIZE;
251  output += DES3_BLOCK_SIZE;
253  }
254 
255  //Process final block of data
256  if(length > 0)
257  {
258  uint8_t buffer[DES3_BLOCK_SIZE];
259 
260  //Copy input data
261  osMemset(buffer, 0, DES3_BLOCK_SIZE);
262  osMemcpy(buffer, input, length);
263 
264  //Encrypt the final block of data
265  desProcessDataBlock(buffer, buffer);
266 
267  //Copy output data
268  osMemcpy(output, buffer, length);
269  }
270 
271  //Release exclusive access to the TDES module
273 }
274 
275 
276 /**
277  * @brief Initialize a Triple DES context using the supplied key
278  * @param[in] context Pointer to the Triple DES context to initialize
279  * @param[in] key Pointer to the key
280  * @param[in] keyLen Length of the key
281  * @return Error code
282  **/
283 
284 error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
285 {
286  //Check parameters
287  if(context == NULL || key == NULL)
289 
290  //Check key length
291  if(keyLen == 8)
292  {
293  //This option provides backward compatibility with DES, because the
294  //first and second DES operations cancel out
295  osMemcpy(context->k1.ks, key, 8);
296  osMemcpy(context->k2.ks, key, 8);
297  osMemcpy(context->k3.ks, key, 8);
298  }
299  else if(keyLen == 16)
300  {
301  //If the key length is 128 bits including parity, the first 8 bytes of the
302  //encoding represent the key used for the two outer DES operations, and
303  //the second 8 bytes represent the key used for the inner DES operation
304  osMemcpy(context->k1.ks, key, 8);
305  osMemcpy(context->k2.ks, key + 8, 8);
306  osMemcpy(context->k3.ks, key, 8);
307  }
308  else if(keyLen == 24)
309  {
310  //If the key length is 192 bits including parity, then 3 independent DES
311  //keys are represented, in the order in which they are used for encryption
312  osMemcpy(context->k1.ks, key, 8);
313  osMemcpy(context->k2.ks, key + 8, 8);
314  osMemcpy(context->k3.ks, key + 16, 8);
315  }
316  else
317  {
318  //The length of the key is not valid
320  }
321 
322  //No error to report
323  return NO_ERROR;
324 }
325 
326 
327 /**
328  * @brief Encrypt a 8-byte block using Triple DES algorithm
329  * @param[in] context Pointer to the Triple DES context
330  * @param[in] input Plaintext block to encrypt
331  * @param[out] output Ciphertext block resulting from encryption
332  **/
333 
334 void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
335 {
336  //Perform Triple DES encryption
337  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE, TDES_MR_CIPHER |
338  TDES_MR_OPMOD_ECB);
339 }
340 
341 
342 /**
343  * @brief Decrypt a 8-byte block using Triple DES algorithm
344  * @param[in] context Pointer to the Triple DES context
345  * @param[in] input Ciphertext block to decrypt
346  * @param[out] output Plaintext block resulting from decryption
347  **/
348 
349 void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
350 {
351  //Perform Triple DES decryption
352  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE,
353  TDES_MR_OPMOD_ECB);
354 }
355 
356 #endif
357 #if (AES_SUPPORT == ENABLED)
358 
359 /**
360  * @brief Load AES key
361  * @param[in] context AES algorithm context
362  **/
363 
364 void aesLoadKey(AesContext *context)
365 {
366  uint32_t temp;
367 
368  //Read mode register
369  temp = AES->AES_MR & ~AES_MR_KEYSIZE_Msk;
370 
371  //Check the length of the key
372  if(context->nr == 10)
373  {
374  //10 rounds are required for 128-bit key
375  AES->AES_MR = temp | AES_MR_KEYSIZE_AES128;
376 
377  //Set the 128-bit encryption key
378  AES->AES_KEYWR[0] = context->ek[0];
379  AES->AES_KEYWR[1] = context->ek[1];
380  AES->AES_KEYWR[2] = context->ek[2];
381  AES->AES_KEYWR[3] = context->ek[3];
382  }
383  else if(context->nr == 12)
384  {
385  //12 rounds are required for 192-bit key
386  AES->AES_MR = temp | AES_MR_KEYSIZE_AES192;
387 
388  //Set the 192-bit encryption key
389  AES->AES_KEYWR[0] = context->ek[0];
390  AES->AES_KEYWR[1] = context->ek[1];
391  AES->AES_KEYWR[2] = context->ek[2];
392  AES->AES_KEYWR[3] = context->ek[3];
393  AES->AES_KEYWR[4] = context->ek[4];
394  AES->AES_KEYWR[5] = context->ek[5];
395  }
396  else
397  {
398  //14 rounds are required for 256-bit key
399  AES->AES_MR = temp | AES_MR_KEYSIZE_AES256;
400 
401  //Set the 256-bit encryption key
402  AES->AES_KEYWR[0] = context->ek[0];
403  AES->AES_KEYWR[1] = context->ek[1];
404  AES->AES_KEYWR[2] = context->ek[2];
405  AES->AES_KEYWR[3] = context->ek[3];
406  AES->AES_KEYWR[4] = context->ek[4];
407  AES->AES_KEYWR[5] = context->ek[5];
408  AES->AES_KEYWR[6] = context->ek[6];
409  AES->AES_KEYWR[7] = context->ek[7];
410  }
411 }
412 
413 
414 /**
415  * @brief Encrypt/decrypt a 16-byte block using AES algorithm
416  * @param[in] input Input block to be encrypted/decrypted
417  * @param[out] output Resulting block
418  **/
419 
420 void aesProcessDataBlock(const uint8_t *input, uint8_t *output)
421 {
422  uint32_t temp;
423 
424  //Write input block
425  AES->AES_IDATAR[0] = LOAD32LE(input);
426  AES->AES_IDATAR[1] = LOAD32LE(input + 4);
427  AES->AES_IDATAR[2] = LOAD32LE(input + 8);
428  AES->AES_IDATAR[3] = LOAD32LE(input + 12);
429 
430  //Start encryption/decryption
431  AES->AES_CR = AES_CR_START;
432 
433  //When processing completes, the DATRDY flag is raised
434  while((AES->AES_ISR & AES_ISR_DATRDY) == 0)
435  {
436  }
437 
438  //Read output block
439  temp = AES->AES_ODATAR[0];
440  STORE32LE(temp, output);
441  temp = AES->AES_ODATAR[1];
442  STORE32LE(temp, output + 4);
443  temp = AES->AES_ODATAR[2];
444  STORE32LE(temp, output + 8);
445  temp = AES->AES_ODATAR[3];
446  STORE32LE(temp, output + 12);
447 }
448 
449 
450 /**
451  * @brief Perform AES encryption or decryption
452  * @param[in] context AES algorithm context
453  * @param[in] 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  //Acquire exclusive access to the AES module
465 
466  //Perform software reset
467  AES->AES_CR = AES_CR_SWRST;
468 
469  //Set operation mode
470  AES->AES_MR = AES_MR_SMOD_MANUAL_START | mode;
471  //Set encryption key
472  aesLoadKey(context);
473 
474  //Valid initialization vector?
475  if(iv != NULL)
476  {
477  //Set initialization vector
478  AES->AES_IVR[0] = LOAD32LE(iv);
479  AES->AES_IVR[1] = LOAD32LE(iv + 4);
480  AES->AES_IVR[2] = LOAD32LE(iv + 8);
481  AES->AES_IVR[3] = LOAD32LE(iv + 12);
482  }
483 
484  //Process data
485  while(length >= AES_BLOCK_SIZE)
486  {
487  //The data is encrypted block by block
488  aesProcessDataBlock(input, output);
489 
490  //Next block
491  input += AES_BLOCK_SIZE;
492  output += AES_BLOCK_SIZE;
494  }
495 
496  //Process final block of data
497  if(length > 0)
498  {
499  uint8_t buffer[AES_BLOCK_SIZE];
500 
501  //Copy input data
502  osMemset(buffer, 0, AES_BLOCK_SIZE);
503  osMemcpy(buffer, input, length);
504 
505  //Encrypt the final block of data
506  aesProcessDataBlock(buffer, buffer);
507 
508  //Copy output data
509  osMemcpy(output, buffer, length);
510  }
511 
512  //Release exclusive access to the AES module
514 }
515 
516 
517 /**
518  * @brief Key expansion
519  * @param[in] context Pointer to the AES context to initialize
520  * @param[in] key Pointer to the key
521  * @param[in] keyLen Length of the key
522  * @return Error code
523  **/
524 
525 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
526 {
527  //Check parameters
528  if(context == NULL || key == NULL)
530 
531  //Check the length of the key
532  if(keyLen == 16)
533  {
534  //10 rounds are required for 128-bit key
535  context->nr = 10;
536  }
537  else if(keyLen == 24)
538  {
539  //12 rounds are required for 192-bit key
540  context->nr = 12;
541  }
542  else if(keyLen == 32)
543  {
544  //14 rounds are required for 256-bit key
545  context->nr = 14;
546  }
547  else
548  {
549  //Report an error
551  }
552 
553  //Copy the original key
554  osMemcpy(context->ek, key, keyLen);
555 
556  //No error to report
557  return NO_ERROR;
558 }
559 
560 
561 /**
562  * @brief Encrypt a 16-byte block using AES algorithm
563  * @param[in] context Pointer to the AES context
564  * @param[in] input Plaintext block to encrypt
565  * @param[out] output Ciphertext block resulting from encryption
566  **/
567 
568 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
569 {
570  //Perform AES encryption
571  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE, AES_MR_CIPHER |
572  AES_MR_OPMOD_ECB);
573 }
574 
575 
576 /**
577  * @brief Decrypt a 16-byte block using AES algorithm
578  * @param[in] context Pointer to the AES context
579  * @param[in] input Ciphertext block to decrypt
580  * @param[out] output Plaintext block resulting from decryption
581  **/
582 
583 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
584 {
585  //Perform AES decryption
586  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
587  AES_MR_OPMOD_ECB);
588 }
589 
590 #endif
591 #if (ECB_SUPPORT == ENABLED)
592 
593 /**
594  * @brief ECB encryption
595  * @param[in] cipher Cipher algorithm
596  * @param[in] context Cipher algorithm context
597  * @param[in] p Plaintext to be encrypted
598  * @param[out] c Ciphertext resulting from the encryption
599  * @param[in] length Total number of data bytes to be encrypted
600  * @return Error code
601  **/
602 
603 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
604  const uint8_t *p, uint8_t *c, size_t length)
605 {
606  error_t error;
607 
608  //Initialize status code
609  error = NO_ERROR;
610 
611 #if (DES_SUPPORT == ENABLED)
612  //DES cipher algorithm?
613  if(cipher == DES_CIPHER_ALGO)
614  {
615  //Check the length of the payload
616  if(length == 0)
617  {
618  //No data to process
619  }
620  else if((length % DES_BLOCK_SIZE) == 0)
621  {
622  //Encrypt payload data
623  desProcessData(context, NULL, p, c, length, TDES_MR_CIPHER |
624  TDES_MR_OPMOD_ECB);
625  }
626  else
627  {
628  //The length of the payload must be a multiple of the block size
629  error = ERROR_INVALID_LENGTH;
630  }
631  }
632  else
633 #endif
634 #if (DES3_SUPPORT == ENABLED)
635  //Triple DES cipher algorithm?
636  if(cipher == DES3_CIPHER_ALGO)
637  {
638  //Check the length of the payload
639  if(length == 0)
640  {
641  //No data to process
642  }
643  else if((length % DES3_BLOCK_SIZE) == 0)
644  {
645  //Encrypt payload data
646  des3ProcessData(context, NULL, p, c, length, TDES_MR_CIPHER |
647  TDES_MR_OPMOD_ECB);
648  }
649  else
650  {
651  //The length of the payload must be a multiple of the block size
652  error = ERROR_INVALID_LENGTH;
653  }
654  }
655  else
656 #endif
657 #if (AES_SUPPORT == ENABLED)
658  //AES cipher algorithm?
659  if(cipher == AES_CIPHER_ALGO)
660  {
661  //Check the length of the payload
662  if(length == 0)
663  {
664  //No data to process
665  }
666  else if((length % AES_BLOCK_SIZE) == 0)
667  {
668  //Encrypt payload data
669  aesProcessData(context, NULL, p, c, length, AES_MR_CIPHER |
670  AES_MR_OPMOD_ECB);
671  }
672  else
673  {
674  //The length of the payload must be a multiple of the block size
675  error = ERROR_INVALID_LENGTH;
676  }
677  }
678  else
679 #endif
680  //Unknown cipher algorithm?
681  {
682  //ECB mode operates in a block-by-block fashion
683  while(length >= cipher->blockSize)
684  {
685  //Encrypt current block
686  cipher->encryptBlock(context, p, c);
687 
688  //Next block
689  p += cipher->blockSize;
690  c += cipher->blockSize;
691  length -= cipher->blockSize;
692  }
693 
694  //The length of the payload must be a multiple of the block size
695  if(length != 0)
696  {
697  error = ERROR_INVALID_LENGTH;
698  }
699  }
700 
701  //Return status code
702  return error;
703 }
704 
705 
706 /**
707  * @brief ECB decryption
708  * @param[in] cipher Cipher algorithm
709  * @param[in] context Cipher algorithm context
710  * @param[in] c Ciphertext to be decrypted
711  * @param[out] p Plaintext resulting from the decryption
712  * @param[in] length Total number of data bytes to be decrypted
713  * @return Error code
714  **/
715 
716 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
717  const uint8_t *c, uint8_t *p, size_t length)
718 {
719  error_t error;
720 
721  //Initialize status code
722  error = NO_ERROR;
723 
724 #if (DES_SUPPORT == ENABLED)
725  //DES cipher algorithm?
726  if(cipher == DES_CIPHER_ALGO)
727  {
728  //Check the length of the payload
729  if(length == 0)
730  {
731  //No data to process
732  }
733  else if((length % DES_BLOCK_SIZE) == 0)
734  {
735  //Decrypt payload data
736  desProcessData(context, NULL, c, p, length, TDES_MR_OPMOD_ECB);
737  }
738  else
739  {
740  //The length of the payload must be a multiple of the block size
741  error = ERROR_INVALID_LENGTH;
742  }
743  }
744  else
745 #endif
746 #if (DES3_SUPPORT == ENABLED)
747  //Triple DES cipher algorithm?
748  if(cipher == DES3_CIPHER_ALGO)
749  {
750  //Check the length of the payload
751  if(length == 0)
752  {
753  //No data to process
754  }
755  else if((length % DES3_BLOCK_SIZE) == 0)
756  {
757  //Decrypt payload data
758  des3ProcessData(context, NULL, c, p, length, TDES_MR_OPMOD_ECB);
759  }
760  else
761  {
762  //The length of the payload must be a multiple of the block size
763  error = ERROR_INVALID_LENGTH;
764  }
765  }
766  else
767 #endif
768 #if (AES_SUPPORT == ENABLED)
769  //AES cipher algorithm?
770  if(cipher == AES_CIPHER_ALGO)
771  {
772  //Check the length of the payload
773  if(length == 0)
774  {
775  //No data to process
776  }
777  else if((length % AES_BLOCK_SIZE) == 0)
778  {
779  //Decrypt payload data
780  aesProcessData(context, NULL, c, p, length, AES_MR_OPMOD_ECB);
781  }
782  else
783  {
784  //The length of the payload must be a multiple of the block size
785  error = ERROR_INVALID_LENGTH;
786  }
787  }
788  else
789 #endif
790  //Unknown cipher algorithm?
791  {
792  //ECB mode operates in a block-by-block fashion
793  while(length >= cipher->blockSize)
794  {
795  //Decrypt current block
796  cipher->decryptBlock(context, c, p);
797 
798  //Next block
799  c += cipher->blockSize;
800  p += cipher->blockSize;
801  length -= cipher->blockSize;
802  }
803 
804  //The length of the payload must be a multiple of the block size
805  if(length != 0)
806  {
807  error = ERROR_INVALID_LENGTH;
808  }
809  }
810 
811  //Return status code
812  return error;
813 }
814 
815 #endif
816 #if (CBC_SUPPORT == ENABLED)
817 
818 /**
819  * @brief CBC encryption
820  * @param[in] cipher Cipher algorithm
821  * @param[in] context Cipher algorithm context
822  * @param[in,out] iv Initialization vector
823  * @param[in] p Plaintext to be encrypted
824  * @param[out] c Ciphertext resulting from the encryption
825  * @param[in] length Total number of data bytes to be encrypted
826  * @return Error code
827  **/
828 
829 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
830  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
831 {
832  error_t error;
833 
834  //Initialize status code
835  error = NO_ERROR;
836 
837 #if (DES_SUPPORT == ENABLED)
838  //DES cipher algorithm?
839  if(cipher == DES_CIPHER_ALGO)
840  {
841  //Check the length of the payload
842  if(length == 0)
843  {
844  //No data to process
845  }
846  else if((length % DES_BLOCK_SIZE) == 0)
847  {
848  //Encrypt payload data
849  desProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
850  TDES_MR_OPMOD_CBC);
851 
852  //Update the value of the initialization vector
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 (DES3_SUPPORT == ENABLED)
864  //Triple DES cipher algorithm?
865  if(cipher == DES3_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 % DES3_BLOCK_SIZE) == 0)
873  {
874  //Encrypt payload data
875  des3ProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
876  TDES_MR_OPMOD_CBC);
877 
878  //Update the value of the initialization vector
880  }
881  else
882  {
883  //The length of the payload must be a multiple of the block size
884  error = ERROR_INVALID_LENGTH;
885  }
886  }
887  else
888 #endif
889 #if (AES_SUPPORT == ENABLED)
890  //AES cipher algorithm?
891  if(cipher == AES_CIPHER_ALGO)
892  {
893  //Check the length of the payload
894  if(length == 0)
895  {
896  //No data to process
897  }
898  else if((length % AES_BLOCK_SIZE) == 0)
899  {
900  //Encrypt payload data
901  aesProcessData(context, iv, p, c, length, AES_MR_CIPHER |
902  AES_MR_OPMOD_CBC);
903 
904  //Update the value of the initialization vector
906  }
907  else
908  {
909  //The length of the payload must be a multiple of the block size
910  error = ERROR_INVALID_LENGTH;
911  }
912  }
913  else
914 #endif
915  //Unknown cipher algorithm?
916  {
917  size_t i;
918 
919  //CBC mode operates in a block-by-block fashion
920  while(length >= cipher->blockSize)
921  {
922  //XOR input block with IV contents
923  for(i = 0; i < cipher->blockSize; i++)
924  {
925  c[i] = p[i] ^ iv[i];
926  }
927 
928  //Encrypt the current block based upon the output of the previous
929  //encryption
930  cipher->encryptBlock(context, c, c);
931 
932  //Update IV with output block contents
933  osMemcpy(iv, c, cipher->blockSize);
934 
935  //Next block
936  p += cipher->blockSize;
937  c += cipher->blockSize;
938  length -= cipher->blockSize;
939  }
940 
941  //The length of the payload must be a multiple of the block size
942  if(length != 0)
943  {
944  error = ERROR_INVALID_LENGTH;
945  }
946  }
947 
948  //Return status code
949  return error;
950 }
951 
952 
953 /**
954  * @brief CBC decryption
955  * @param[in] cipher Cipher algorithm
956  * @param[in] context Cipher algorithm context
957  * @param[in,out] iv Initialization vector
958  * @param[in] c Ciphertext to be decrypted
959  * @param[out] p Plaintext resulting from the decryption
960  * @param[in] length Total number of data bytes to be decrypted
961  * @return Error code
962  **/
963 
964 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
965  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
966 {
967  error_t error;
968 
969  //Initialize status code
970  error = NO_ERROR;
971 
972 #if (DES_SUPPORT == ENABLED)
973  //DES cipher algorithm?
974  if(cipher == DES_CIPHER_ALGO)
975  {
976  //Check the length of the payload
977  if(length == 0)
978  {
979  //No data to process
980  }
981  else if((length % DES_BLOCK_SIZE) == 0)
982  {
983  uint8_t block[DES_BLOCK_SIZE];
984 
985  //Save the last input block
987 
988  //Decrypt payload data
989  desProcessData(context, iv, c, p, length, TDES_MR_OPMOD_CBC);
990 
991  //Update the value of the initialization vector
993  }
994  else
995  {
996  //The length of the payload must be a multiple of the block size
997  error = ERROR_INVALID_LENGTH;
998  }
999  }
1000  else
1001 #endif
1002 #if (DES3_SUPPORT == ENABLED)
1003  //Triple DES cipher algorithm?
1004  if(cipher == DES3_CIPHER_ALGO)
1005  {
1006  //Check the length of the payload
1007  if(length == 0)
1008  {
1009  //No data to process
1010  }
1011  else if((length % DES3_BLOCK_SIZE) == 0)
1012  {
1013  uint8_t block[DES3_BLOCK_SIZE];
1014 
1015  //Save the last input block
1017 
1018  //Decrypt payload data
1019  des3ProcessData(context, iv, c, p, length, TDES_MR_OPMOD_CBC);
1020 
1021  //Update the value of the initialization vector
1023  }
1024  else
1025  {
1026  //The length of the payload must be a multiple of the block size
1027  error = ERROR_INVALID_LENGTH;
1028  }
1029  }
1030  else
1031 #endif
1032 #if (AES_SUPPORT == ENABLED)
1033  //AES cipher algorithm?
1034  if(cipher == AES_CIPHER_ALGO)
1035  {
1036  //Check the length of the payload
1037  if(length == 0)
1038  {
1039  //No data to process
1040  }
1041  else if((length % AES_BLOCK_SIZE) == 0)
1042  {
1043  uint8_t block[AES_BLOCK_SIZE];
1044 
1045  //Save the last input block
1047 
1048  //Decrypt payload data
1049  aesProcessData(context, iv, c, p, length, AES_MR_OPMOD_CBC);
1050 
1051  //Update the value of the initialization vector
1053  }
1054  else
1055  {
1056  //The length of the payload must be a multiple of the block size
1057  error = ERROR_INVALID_LENGTH;
1058  }
1059  }
1060  else
1061 #endif
1062  //Unknown cipher algorithm?
1063  {
1064  size_t i;
1065  uint8_t t[16];
1066 
1067  //CBC mode operates in a block-by-block fashion
1068  while(length >= cipher->blockSize)
1069  {
1070  //Save input block
1071  osMemcpy(t, c, cipher->blockSize);
1072 
1073  //Decrypt the current block
1074  cipher->decryptBlock(context, c, p);
1075 
1076  //XOR output block with IV contents
1077  for(i = 0; i < cipher->blockSize; i++)
1078  {
1079  p[i] ^= iv[i];
1080  }
1081 
1082  //Update IV with input block contents
1083  osMemcpy(iv, t, cipher->blockSize);
1084 
1085  //Next block
1086  c += cipher->blockSize;
1087  p += cipher->blockSize;
1088  length -= cipher->blockSize;
1089  }
1090 
1091  //The length of the payload must be a multiple of the block size
1092  if(length != 0)
1093  {
1094  error = ERROR_INVALID_LENGTH;
1095  }
1096  }
1097 
1098  //Return status code
1099  return error;
1100 }
1101 
1102 #endif
1103 #if (CFB_SUPPORT == ENABLED)
1104 
1105 /**
1106  * @brief CFB encryption
1107  * @param[in] cipher Cipher algorithm
1108  * @param[in] context Cipher algorithm context
1109  * @param[in] s Size of the plaintext and ciphertext segments
1110  * @param[in,out] iv Initialization vector
1111  * @param[in] p Plaintext to be encrypted
1112  * @param[out] c Ciphertext resulting from the encryption
1113  * @param[in] length Total number of data bytes to be encrypted
1114  * @return Error code
1115  **/
1116 
1117 error_t cfbEncrypt(const CipherAlgo *cipher, void *context, uint_t s,
1118  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
1119 {
1120  error_t error;
1121 
1122  //Initialize status code
1123  error = NO_ERROR;
1124 
1125 #if (DES_SUPPORT == ENABLED)
1126  //DES cipher algorithm?
1127  if(cipher == DES_CIPHER_ALGO)
1128  {
1129  //Check the value of the parameter
1130  if(s == (DES_BLOCK_SIZE * 8))
1131  {
1132  //Check the length of the payload
1133  if(length > 0)
1134  {
1135  //Encrypt payload data
1136  desProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
1137  TDES_MR_OPMOD_CFB | TDES_MR_CFBS_SIZE_64BIT);
1138  }
1139  else
1140  {
1141  //No data to process
1142  }
1143  }
1144  else
1145  {
1146  //The value of the parameter is not valid
1147  error = ERROR_INVALID_PARAMETER;
1148  }
1149  }
1150  else
1151 #endif
1152 #if (DES3_SUPPORT == ENABLED)
1153  //Triple DES cipher algorithm?
1154  if(cipher == DES3_CIPHER_ALGO)
1155  {
1156  //Check the value of the parameter
1157  if(s == (DES3_BLOCK_SIZE * 8))
1158  {
1159  //Check the length of the payload
1160  if(length > 0)
1161  {
1162  //Encrypt payload data
1163  des3ProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
1164  TDES_MR_OPMOD_CFB | TDES_MR_CFBS_SIZE_64BIT);
1165  }
1166  else
1167  {
1168  //No data to process
1169  }
1170  }
1171  else
1172  {
1173  //The value of the parameter is not valid
1174  error = ERROR_INVALID_PARAMETER;
1175  }
1176  }
1177  else
1178 #endif
1179 #if (AES_SUPPORT == ENABLED)
1180  //AES cipher algorithm?
1181  if(cipher == AES_CIPHER_ALGO)
1182  {
1183  //Check the value of the parameter
1184  if(s == (AES_BLOCK_SIZE * 8))
1185  {
1186  //Check the length of the payload
1187  if(length > 0)
1188  {
1189  //Encrypt payload data
1190  aesProcessData(context, iv, p, c, length, AES_MR_CIPHER |
1191  AES_MR_OPMOD_CFB | AES_MR_CFBS_SIZE_128BIT);
1192  }
1193  else
1194  {
1195  //No data to process
1196  }
1197  }
1198  else
1199  {
1200  //The value of the parameter is not valid
1201  error = ERROR_INVALID_PARAMETER;
1202  }
1203  }
1204  else
1205 #endif
1206  //Unknown cipher algorithm?
1207  {
1208  //Check the value of the parameter
1209  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
1210  {
1211  size_t i;
1212  size_t n;
1213  uint8_t o[16];
1214 
1215  //Determine the size, in bytes, of the plaintext and ciphertext segments
1216  s = s / 8;
1217 
1218  //Process each plaintext segment
1219  while(length > 0)
1220  {
1221  //Compute the number of bytes to process at a time
1222  n = MIN(length, s);
1223 
1224  //Compute O(j) = CIPH(I(j))
1225  cipher->encryptBlock(context, iv, o);
1226 
1227  //Compute C(j) = P(j) XOR MSB(O(j))
1228  for(i = 0; i < n; i++)
1229  {
1230  c[i] = p[i] ^ o[i];
1231  }
1232 
1233  //Compute I(j+1) = LSB(I(j)) | C(j)
1234  osMemmove(iv, iv + s, cipher->blockSize - s);
1235  osMemcpy(iv + cipher->blockSize - s, c, s);
1236 
1237  //Next block
1238  p += n;
1239  c += n;
1240  length -= n;
1241  }
1242  }
1243  else
1244  {
1245  //The value of the parameter is not valid
1246  error = ERROR_INVALID_PARAMETER;
1247  }
1248  }
1249 
1250  //Return status code
1251  return error;
1252 }
1253 
1254 
1255 /**
1256  * @brief CFB decryption
1257  * @param[in] cipher Cipher algorithm
1258  * @param[in] context Cipher algorithm context
1259  * @param[in] s Size of the plaintext and ciphertext segments
1260  * @param[in,out] iv Initialization vector
1261  * @param[in] c Ciphertext to be decrypted
1262  * @param[out] p Plaintext resulting from the decryption
1263  * @param[in] length Total number of data bytes to be decrypted
1264  * @return Error code
1265  **/
1266 
1267 error_t cfbDecrypt(const CipherAlgo *cipher, void *context, uint_t s,
1268  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
1269 {
1270  error_t error;
1271 
1272  //Initialize status code
1273  error = NO_ERROR;
1274 
1275 #if (DES_SUPPORT == ENABLED)
1276  //DES cipher algorithm?
1277  if(cipher == DES_CIPHER_ALGO)
1278  {
1279  //Check the value of the parameter
1280  if(s == (DES_BLOCK_SIZE * 8))
1281  {
1282  //Check the length of the payload
1283  if(length > 0)
1284  {
1285  //Decrypt payload data
1286  desProcessData(context, iv, c, p, length, TDES_MR_OPMOD_CFB |
1287  TDES_MR_CFBS_SIZE_64BIT);
1288  }
1289  else
1290  {
1291  //No data to process
1292  }
1293  }
1294  else
1295  {
1296  //The value of the parameter is not valid
1297  error = ERROR_INVALID_PARAMETER;
1298  }
1299  }
1300  else
1301 #endif
1302 #if (DES3_SUPPORT == ENABLED)
1303  //Triple DES cipher algorithm?
1304  if(cipher == DES3_CIPHER_ALGO)
1305  {
1306  //Check the value of the parameter
1307  if(s == (DES3_BLOCK_SIZE * 8))
1308  {
1309  //Check the length of the payload
1310  if(length > 0)
1311  {
1312  //Decrypt payload data
1313  des3ProcessData(context, iv, c, p, length, TDES_MR_OPMOD_CFB |
1314  TDES_MR_CFBS_SIZE_64BIT);
1315  }
1316  else
1317  {
1318  //No data to process
1319  }
1320  }
1321  else
1322  {
1323  //The value of the parameter is not valid
1324  error = ERROR_INVALID_PARAMETER;
1325  }
1326  }
1327  else
1328 #endif
1329 #if (AES_SUPPORT == ENABLED)
1330  //AES cipher algorithm?
1331  if(cipher == AES_CIPHER_ALGO)
1332  {
1333  //Check the value of the parameter
1334  if(s == (AES_BLOCK_SIZE * 8))
1335  {
1336  //Check the length of the payload
1337  if(length > 0)
1338  {
1339  //Decrypt payload data
1340  aesProcessData(context, iv, c, p, length, AES_MR_OPMOD_CFB |
1341  AES_MR_CFBS_SIZE_128BIT);
1342  }
1343  else
1344  {
1345  //No data to process
1346  }
1347  }
1348  else
1349  {
1350  //The value of the parameter is not valid
1351  error = ERROR_INVALID_PARAMETER;
1352  }
1353  }
1354  else
1355 #endif
1356  //Unknown cipher algorithm?
1357  {
1358  //Check the value of the parameter
1359  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
1360  {
1361  size_t i;
1362  size_t n;
1363  uint8_t o[16];
1364 
1365  //Determine the size, in bytes, of the plaintext and ciphertext segments
1366  s = s / 8;
1367 
1368  //Process each ciphertext segment
1369  while(length > 0)
1370  {
1371  //Compute the number of bytes to process at a time
1372  n = MIN(length, s);
1373 
1374  //Compute O(j) = CIPH(I(j))
1375  cipher->encryptBlock(context, iv, o);
1376 
1377  //Compute I(j+1) = LSB(I(j)) | C(j)
1378  osMemmove(iv, iv + s, cipher->blockSize - s);
1379  osMemcpy(iv + cipher->blockSize - s, c, s);
1380 
1381  //Compute P(j) = C(j) XOR MSB(O(j))
1382  for(i = 0; i < n; i++)
1383  {
1384  p[i] = c[i] ^ o[i];
1385  }
1386 
1387  //Next block
1388  c += n;
1389  p += n;
1390  length -= n;
1391  }
1392  }
1393  else
1394  {
1395  //The value of the parameter is not valid
1396  error = ERROR_INVALID_PARAMETER;
1397  }
1398  }
1399 
1400  //Return status code
1401  return error;
1402 }
1403 
1404 #endif
1405 #if (OFB_SUPPORT == ENABLED)
1406 
1407 /**
1408  * @brief OFB encryption
1409  * @param[in] cipher Cipher algorithm
1410  * @param[in] context Cipher algorithm context
1411  * @param[in] s Size of the plaintext and ciphertext segments
1412  * @param[in,out] iv Initialization vector
1413  * @param[in] p Plaintext to be encrypted
1414  * @param[out] c Ciphertext resulting from the encryption
1415  * @param[in] length Total number of data bytes to be encrypted
1416  * @return Error code
1417  **/
1418 
1419 error_t ofbEncrypt(const CipherAlgo *cipher, void *context, uint_t s,
1420  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
1421 {
1422  error_t error;
1423 
1424  //Initialize status code
1425  error = NO_ERROR;
1426 
1427 #if (DES_SUPPORT == ENABLED)
1428  //DES cipher algorithm?
1429  if(cipher == DES_CIPHER_ALGO)
1430  {
1431  //Check the value of the parameter
1432  if(s == (DES_BLOCK_SIZE * 8))
1433  {
1434  //Check the length of the payload
1435  if(length > 0)
1436  {
1437  //Encrypt payload data
1438  desProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
1439  TDES_MR_OPMOD_OFB);
1440  }
1441  else
1442  {
1443  //No data to process
1444  }
1445  }
1446  else
1447  {
1448  //The value of the parameter is not valid
1449  error = ERROR_INVALID_PARAMETER;
1450  }
1451  }
1452  else
1453 #endif
1454 #if (DES3_SUPPORT == ENABLED)
1455  //Triple DES cipher algorithm?
1456  if(cipher == DES3_CIPHER_ALGO)
1457  {
1458  //Check the value of the parameter
1459  if(s == (DES3_BLOCK_SIZE * 8))
1460  {
1461  //Check the length of the payload
1462  if(length > 0)
1463  {
1464  //Encrypt payload data
1465  des3ProcessData(context, iv, p, c, length, TDES_MR_CIPHER |
1466  TDES_MR_OPMOD_OFB);
1467  }
1468  else
1469  {
1470  //No data to process
1471  }
1472  }
1473  else
1474  {
1475  //The value of the parameter is not valid
1476  error = ERROR_INVALID_PARAMETER;
1477  }
1478  }
1479  else
1480 #endif
1481 #if (AES_SUPPORT == ENABLED)
1482  //AES cipher algorithm?
1483  if(cipher == AES_CIPHER_ALGO)
1484  {
1485  //Check the value of the parameter
1486  if(s == (AES_BLOCK_SIZE * 8))
1487  {
1488  //Check the length of the payload
1489  if(length > 0)
1490  {
1491  //Encrypt payload data
1492  aesProcessData(context, iv, p, c, length, AES_MR_CIPHER |
1493  AES_MR_OPMOD_OFB);
1494  }
1495  else
1496  {
1497  //No data to process
1498  }
1499  }
1500  else
1501  {
1502  //The value of the parameter is not valid
1503  error = ERROR_INVALID_PARAMETER;
1504  }
1505  }
1506  else
1507 #endif
1508  //Unknown cipher algorithm?
1509  {
1510  //Check the value of the parameter
1511  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
1512  {
1513  size_t i;
1514  size_t n;
1515  uint8_t o[16];
1516 
1517  //Determine the size, in bytes, of the plaintext and ciphertext segments
1518  s = s / 8;
1519 
1520  //Process each plaintext segment
1521  while(length > 0)
1522  {
1523  //Compute the number of bytes to process at a time
1524  n = MIN(length, s);
1525 
1526  //Compute O(j) = CIPH(I(j))
1527  cipher->encryptBlock(context, iv, o);
1528 
1529  //Compute C(j) = P(j) XOR MSB(O(j))
1530  for(i = 0; i < n; i++)
1531  {
1532  c[i] = p[i] ^ o[i];
1533  }
1534 
1535  //Compute I(j+1) = LSB(I(j)) | O(j)
1536  osMemmove(iv, iv + s, cipher->blockSize - s);
1537  osMemcpy(iv + cipher->blockSize - s, o, s);
1538 
1539  //Next block
1540  p += n;
1541  c += n;
1542  length -= n;
1543  }
1544  }
1545  else
1546  {
1547  //The value of the parameter is not valid
1548  error = ERROR_INVALID_PARAMETER;
1549  }
1550  }
1551 
1552  //Return status code
1553  return error;
1554 }
1555 
1556 #endif
1557 #if (GCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1558 
1559 /**
1560  * @brief Update GHASH value
1561  * @param[in] data Input block of data
1562  **/
1563 
1564 void gcmUpdateGhash(const uint8_t *data)
1565 {
1566  //Write data block
1567  AES->AES_IDATAR[0] = LOAD32LE(data);
1568  AES->AES_IDATAR[1] = LOAD32LE(data + 4);
1569  AES->AES_IDATAR[2] = LOAD32LE(data + 8);
1570  AES->AES_IDATAR[3] = LOAD32LE(data + 12);
1571 
1572  //Process data
1573  AES->AES_CR = AES_CR_START;
1574 
1575  //The DATRDY bit indicates when the data have been processed. However, no
1576  //output data are generated when processing AAD
1577  while((AES->AES_ISR & AES_ISR_DATRDY) == 0)
1578  {
1579  }
1580 }
1581 
1582 
1583 /**
1584  * @brief Perform AES-GCM encryption or decryption
1585  * @param[in] context AES algorithm context
1586  * @param[in] iv Initialization vector
1587  * @param[in] a Additional authenticated data
1588  * @param[in] aLen Length of the additional data
1589  * @param[in] input Data to be encrypted/decrypted
1590  * @param[out] output Data resulting from the encryption/decryption process
1591  * @param[in] length Total number of data bytes to be processed
1592  * @param[out] t Authentication tag
1593  * @param[in] mode Operation mode
1594  **/
1595 
1596 void gcmProcessData(AesContext *context, const uint8_t *iv,
1597  const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output,
1598  size_t length, uint8_t *t, uint32_t mode)
1599 {
1600  uint32_t temp;
1601  uint8_t buffer[16];
1602 
1603  //Acquire exclusive access to the AES module
1605 
1606  //Perform software reset
1607  AES->AES_CR = AES_CR_SWRST;
1608 
1609  //Check parameters
1610  if(aLen > 0 || length > 0)
1611  {
1612  //Select GCM operation mode
1613  AES->AES_MR |= AES_MR_SMOD_MANUAL_START | AES_MR_OPMOD_GCM |
1614  AES_MR_GTAGEN | mode;
1615 
1616  //Whenever a new key is written to the hardware, the hash subkey is
1617  //automatically generated. The hash subkey generation must be complete
1618  //before doing any other action
1619  aesLoadKey(context);
1620 
1621  //The DATRDY bit of the AES_ISR indicates when the subkey generation is
1622  //complete
1623  while((AES->AES_ISR & AES_ISR_DATRDY) == 0)
1624  {
1625  }
1626 
1627  //When the length of the IV is 96 bits, the padding string is appended to
1628  //the IV to form the pre-counter block
1629  AES->AES_IVR[0] = LOAD32LE(iv);
1630  AES->AES_IVR[1] = LOAD32LE(iv + 4);
1631  AES->AES_IVR[2] = LOAD32LE(iv + 8);
1632  AES->AES_IVR[3] = BETOH32(2);
1633 
1634  //Set AADLEN field in AES_AADLENR and CLEN field in AES_CLENR
1635  AES->AES_AADLENR = aLen;
1636  AES->AES_CLENR = length;
1637 
1638  //Process additional authenticated data
1639  while(aLen > 16)
1640  {
1641  //Additional authenticated data is written block by block
1642  gcmUpdateGhash(a);
1643 
1644  //Next block
1645  a += 16;
1646  aLen -= 16;
1647  }
1648 
1649  //Process final block of additional authenticated data
1650  if(aLen > 0)
1651  {
1652  //Copy partial block
1653  osMemset(buffer, 0, 16);
1654  osMemcpy(buffer, a, aLen);
1655 
1656  //Write the resulting block
1657  gcmUpdateGhash(buffer);
1658  }
1659 
1660  //Process data
1661  while(length >= AES_BLOCK_SIZE)
1662  {
1663  //The data is encrypted block by block
1664  aesProcessDataBlock(input, output);
1665 
1666  //Next block
1667  input += AES_BLOCK_SIZE;
1668  output += AES_BLOCK_SIZE;
1670  }
1671 
1672  //Process final block of data
1673  if(length > 0)
1674  {
1675  //Copy input data
1676  osMemset(buffer, 0, AES_BLOCK_SIZE);
1677  osMemcpy(buffer, input, length);
1678 
1679  //Encrypt the final block of data
1680  aesProcessDataBlock(buffer, buffer);
1681 
1682  //Copy output data
1683  osMemcpy(output, buffer, length);
1684  }
1685 
1686  //Wait for TAGRDY to be set
1687  while((AES->AES_ISR & AES_ISR_TAGRDY) == 0)
1688  {
1689  }
1690 
1691  //Read the value from AES_TAGR registers to obtain the authentication tag
1692  //of the message
1693  temp = AES->AES_TAGR[0];
1694  STORE32LE(temp, t);
1695  temp = AES->AES_TAGR[1];
1696  STORE32LE(temp, t + 4);
1697  temp = AES->AES_TAGR[2];
1698  STORE32LE(temp, t + 8);
1699  temp = AES->AES_TAGR[3];
1700  STORE32LE(temp, t + 12);
1701  }
1702  else
1703  {
1704  //Select CTR operation mode
1705  AES->AES_MR |= AES_MR_SMOD_MANUAL_START | AES_MR_OPMOD_CTR |
1706  AES_MR_CIPHER;
1707 
1708  //Set encryption key
1709  aesLoadKey(context);
1710 
1711  //When the length of the IV is 96 bits, the padding string is appended to
1712  //the IV to form the pre-counter block
1713  AES->AES_IVR[0] = LOAD32LE(iv);
1714  AES->AES_IVR[1] = LOAD32LE(iv + 4);
1715  AES->AES_IVR[2] = LOAD32LE(iv + 8);
1716  AES->AES_IVR[3] = BETOH32(1);
1717 
1718  //Clear data block
1719  osMemset(buffer, 0, AES_BLOCK_SIZE);
1720 
1721  //Generate authentication tag
1722  aesProcessDataBlock(buffer, t);
1723  }
1724 
1725  //Release exclusive access to the AES module
1727 }
1728 
1729 
1730 /**
1731  * @brief Initialize GCM context
1732  * @param[in] context Pointer to the GCM context
1733  * @param[in] cipherAlgo Cipher algorithm
1734  * @param[in] cipherContext Pointer to the cipher algorithm context
1735  * @return Error code
1736  **/
1737 
1738 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1739  void *cipherContext)
1740 {
1741  //Check parameters
1742  if(context == NULL || cipherContext == NULL)
1743  return ERROR_INVALID_PARAMETER;
1744 
1745  //The CRYP module only supports AES cipher algorithm
1746  if(cipherAlgo != AES_CIPHER_ALGO)
1747  return ERROR_INVALID_PARAMETER;
1748 
1749  //Save cipher algorithm context
1750  context->cipherAlgo = cipherAlgo;
1751  context->cipherContext = cipherContext;
1752 
1753  //Successful initialization
1754  return NO_ERROR;
1755 }
1756 
1757 
1758 /**
1759  * @brief Authenticated encryption using GCM
1760  * @param[in] context Pointer to the GCM context
1761  * @param[in] iv Initialization vector
1762  * @param[in] ivLen Length of the initialization vector
1763  * @param[in] a Additional authenticated data
1764  * @param[in] aLen Length of the additional data
1765  * @param[in] p Plaintext to be encrypted
1766  * @param[out] c Ciphertext resulting from the encryption
1767  * @param[in] length Total number of data bytes to be encrypted
1768  * @param[out] t Authentication tag
1769  * @param[in] tLen Length of the authentication tag
1770  * @return Error code
1771  **/
1772 
1773 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1774  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1775  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1776 {
1777  uint8_t authTag[16];
1778 
1779  //Make sure the GCM context is valid
1780  if(context == NULL)
1781  return ERROR_INVALID_PARAMETER;
1782 
1783  //Check whether the length of the IV is 96 bits
1784  if(ivLen != 12)
1785  return ERROR_INVALID_LENGTH;
1786 
1787  //Check the length of the authentication tag
1788  if(tLen < 4 || tLen > 16)
1789  return ERROR_INVALID_LENGTH;
1790 
1791  //Perform AES-GCM encryption
1792  gcmProcessData(context->cipherContext, iv, a, aLen, p, c, length,
1793  authTag, AES_MR_CIPHER);
1794 
1795  //Copy the resulting authentication tag
1796  osMemcpy(t, authTag, tLen);
1797 
1798  //Successful processing
1799  return NO_ERROR;
1800 }
1801 
1802 
1803 /**
1804  * @brief Authenticated decryption using GCM
1805  * @param[in] context Pointer to the GCM context
1806  * @param[in] iv Initialization vector
1807  * @param[in] ivLen Length of the initialization vector
1808  * @param[in] a Additional authenticated data
1809  * @param[in] aLen Length of the additional data
1810  * @param[in] c Ciphertext to be decrypted
1811  * @param[out] p Plaintext resulting from the decryption
1812  * @param[in] length Total number of data bytes to be decrypted
1813  * @param[in] t Authentication tag
1814  * @param[in] tLen Length of the authentication tag
1815  * @return Error code
1816  **/
1817 
1818 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1819  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1820  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1821 {
1822  size_t i;
1823  uint8_t mask;
1824  uint8_t authTag[16];
1825 
1826  //Make sure the GCM context is valid
1827  if(context == NULL)
1828  return ERROR_INVALID_PARAMETER;
1829 
1830  //Check whether the length of the IV is 96 bits
1831  if(ivLen != 12)
1832  return ERROR_INVALID_LENGTH;
1833 
1834  //Check the length of the authentication tag
1835  if(tLen < 4 || tLen > 16)
1836  return ERROR_INVALID_LENGTH;
1837 
1838  //Perform AES-GCM decryption
1839  gcmProcessData(context->cipherContext, iv, a, aLen, c, p, length,
1840  authTag, 0);
1841 
1842  //The calculated tag is bitwise compared to the received tag
1843  for(mask = 0, i = 0; i < tLen; i++)
1844  {
1845  mask |= authTag[i] ^ t[i];
1846  }
1847 
1848  //The message is authenticated if and only if the tags match
1849  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1850 }
1851 
1852 #endif
1853 #endif
#define AES_CIPHER_ALGO
Definition: aes.h:45
#define AES_BLOCK_SIZE
Definition: aes.h:43
Collection of AEAD algorithms.
Block cipher modes of operation.
unsigned int uint_t
Definition: compiler_port.h:50
#define BETOH32(value)
Definition: cpu_endian.h:451
#define LOAD32LE(p)
Definition: cpu_endian.h:203
#define STORE32LE(a, p)
Definition: cpu_endian.h:279
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 data[]
Definition: ethernet.h:220
uint8_t iv[]
Definition: ike.h:1501
uint8_t t
Definition: lldp_ext_med.h:210
uint8_t c
Definition: ndp.h:512
uint8_t s
Definition: ndp.h:343
uint8_t p
Definition: ndp.h:298
uint8_t a
Definition: ndp.h:409
#define osMemset(p, value, length)
Definition: os_port.h:137
#define osMemmove(dest, src, length)
Definition: os_port.h:149
#define osMemcpy(dest, src, length)
Definition: os_port.h:143
#define MIN(a, b)
Definition: os_port.h:65
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
OsMutex sam9x60CryptoMutex
SAM9X60 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 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.
void desProcessDataBlock(const uint8_t *input, uint8_t *output)
Encrypt/decrypt a 16-byte block using DES algorithm.
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 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.
error_t cfbDecrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CFB decryption.
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.
error_t cfbEncrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CFB encryption.
void aesProcessDataBlock(const uint8_t *input, uint8_t *output)
Encrypt/decrypt a 16-byte block using AES algorithm.
void gcmUpdateGhash(const uint8_t *data)
Update GHASH value.
error_t ofbEncrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
OFB encryption.
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.
SAM9X60 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:1029
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1037
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1038
size_t blockSize
Definition: crypto.h:1033
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:366
uint16_t block
Definition: tftp_common.h:113
uint8_t mask
Definition: web_socket.h:317