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