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