f2838x_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file f2838x_crypto_cipher.c
3  * @brief TMS320F2838xD 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_aes.h"
40 #include "driverlib_cm/aes.h"
41 #include "core/crypto.h"
46 #include "aead/aead_algorithms.h"
47 #include "debug.h"
48 
49 //Check crypto library configuration
50 #if (F2838X_CRYPTO_CIPHER_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
51 
52 
53 /**
54  * @brief Set AES operation mode
55  * @param[in] mode Mode of operation
56  **/
57 
58 void aesSetMode(uint32_t mode)
59 {
60  //Perform a software reset
61  AES_SYSCONFIG_R |= AES_SYSCONFIG_SOFTRESET;
62 
63  //Wait for the reset to complete
64  while((AES_SYSSTATUS_R & AES_SYSSTATUS_RESETDONE) == 0)
65  {
66  }
67 
68  //Backup the save context field before updating the register
69  if((AES_CTRL_R & AES_CTRL_SAVE_CONTEXT) != 0)
70  {
71  mode |= AES_CTRL_SAVE_CONTEXT;
72  }
73 
74  //Write control register
75  AES_CTRL_R = mode;
76 }
77 
78 
79 /**
80  * @brief Load AES key
81  * @param[in] context AES algorithm context
82  **/
83 
84 void aesLoadKey(AesContext *context)
85 {
86  uint32_t temp;
87 
88  //Read control register
89  temp = AES_CTRL_R & ~AES_CTRL_KEY_SIZE_M;
90 
91  //Check the length of the key
92  if(context->nr == 10)
93  {
94  //10 rounds are required for 128-bit key
95  AES_CTRL_R = temp | AES_KEY_SIZE_128BIT;
96 
97  //Set the 128-bit encryption key
98  AES_KEY1_0_R = context->ek[0];
99  AES_KEY1_1_R = context->ek[1];
100  AES_KEY1_2_R = context->ek[2];
101  AES_KEY1_3_R = context->ek[3];
102  }
103  else if(context->nr == 12)
104  {
105  //12 rounds are required for 192-bit key
106  AES_CTRL_R = temp | AES_KEY_SIZE_192BIT;
107 
108  //Set the 192-bit encryption key
109  AES_KEY1_0_R = context->ek[0];
110  AES_KEY1_1_R = context->ek[1];
111  AES_KEY1_2_R = context->ek[2];
112  AES_KEY1_3_R = context->ek[3];
113  AES_KEY1_4_R = context->ek[4];
114  AES_KEY1_5_R = context->ek[5];
115  }
116  else
117  {
118  //14 rounds are required for 256-bit key
119  AES_CTRL_R = temp | AES_KEY_SIZE_256BIT;
120 
121  //Set the 256-bit encryption key
122  AES_KEY1_0_R = context->ek[0];
123  AES_KEY1_1_R = context->ek[1];
124  AES_KEY1_2_R = context->ek[2];
125  AES_KEY1_3_R = context->ek[3];
126  AES_KEY1_4_R = context->ek[4];
127  AES_KEY1_5_R = context->ek[5];
128  AES_KEY1_6_R = context->ek[6];
129  AES_KEY1_7_R = context->ek[7];
130  }
131 }
132 
133 
134 /**
135  * @brief Perform AES encryption or decryption
136  * @param[in] context AES algorithm context
137  * @param[in,out] iv Initialization vector
138  * @param[in] input Data to be encrypted/decrypted
139  * @param[out] output Data resulting from the encryption/decryption process
140  * @param[in] length Total number of data bytes to be processed
141  * @param[in] mode Operation mode
142  **/
143 
144 void aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input,
145  uint8_t *output, size_t length, uint32_t mode)
146 {
147  uint32_t temp;
148 
149  //Acquire exclusive access to the AES module
151 
152  //Set operation mode
153  aesSetMode(mode);
154  //Set encryption key
155  aesLoadKey(context);
156 
157  //Valid initialization vector?
158  if(iv != NULL)
159  {
160  //Set initialization vector
164  AES_IV_IN_OUT_3_R = LOAD32LE(iv + 12);
165  }
166 
167  //Process data
168  while(length >= AES_BLOCK_SIZE)
169  {
170  //Wait for the AES engine to be ready to accept data
171  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
172  {
173  }
174 
175  //Write input block
176  AES_DATA_IN_OUT_3_R = LOAD32LE(input);
177  AES_DATA_IN_OUT_2_R = LOAD32LE(input + 4);
178  AES_DATA_IN_OUT_1_R = LOAD32LE(input + 8);
179  AES_DATA_IN_OUT_0_R = LOAD32LE(input + 12);
180 
181  //Wait for the output to be ready
182  while((AES_CTRL_R & AES_CTRL_OUTPUT_READY) == 0)
183  {
184  }
185 
186  //Read output block
187  temp = AES_DATA_IN_OUT_3_R;
188  STORE32LE(temp, output);
189  temp = AES_DATA_IN_OUT_2_R;
190  STORE32LE(temp, output + 4);
191  temp = AES_DATA_IN_OUT_1_R;
192  STORE32LE(temp, output + 8);
193  temp = AES_DATA_IN_OUT_0_R;
194  STORE32LE(temp, output + 12);
195 
196  //Next block
197  input += AES_BLOCK_SIZE;
198  output += AES_BLOCK_SIZE;
200  }
201 
202  //Process final block of data
203  if(length > 0)
204  {
205  uint32_t buffer[4];
206 
207  //Copy partial block
208  osMemset(buffer, 0, AES_BLOCK_SIZE);
209  osMemcpy(buffer, input, length);
210 
211  //Wait for the AES engine to be ready to accept data
212  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
213  {
214  }
215 
216  //Write input block
217  AES_DATA_IN_OUT_3_R = buffer[0];
218  AES_DATA_IN_OUT_2_R = buffer[1];
219  AES_DATA_IN_OUT_1_R = buffer[2];
220  AES_DATA_IN_OUT_0_R = buffer[3];
221 
222  //Wait for the output to be ready
223  while((AES_CTRL_R & AES_CTRL_OUTPUT_READY) == 0)
224  {
225  }
226 
227  //Read output block
228  buffer[0] = AES_DATA_IN_OUT_3_R;
229  buffer[1] = AES_DATA_IN_OUT_2_R;
230  buffer[2] = AES_DATA_IN_OUT_1_R;
231  buffer[3] = AES_DATA_IN_OUT_0_R;
232 
233  //Copy partial block
234  osMemcpy(output, buffer, length);
235  }
236 
237  //Valid initialization vector?
238  if(iv != NULL)
239  {
240  //Update the value of the initialization vector
241  temp = AES_IV_IN_OUT_0_R;
242  STORE32LE(temp, iv);
243  temp = AES_IV_IN_OUT_1_R;
244  STORE32LE(temp, iv + 4);
245  temp = AES_IV_IN_OUT_2_R;
246  STORE32LE(temp, iv + 8);
247  temp = AES_IV_IN_OUT_3_R;
248  STORE32LE(temp, iv + 12);
249  }
250 
251  //Release exclusive access to the AES module
253 }
254 
255 
256 /**
257  * @brief Key expansion
258  * @param[in] context Pointer to the AES context to initialize
259  * @param[in] key Pointer to the key
260  * @param[in] keyLen Length of the key
261  * @return Error code
262  **/
263 
264 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
265 {
266  //Check parameters
267  if(context == NULL || key == NULL)
269 
270  //Check the length of the key
271  if(keyLen == 16)
272  {
273  //10 rounds are required for 128-bit key
274  context->nr = 10;
275  }
276  else if(keyLen == 24)
277  {
278  //12 rounds are required for 192-bit key
279  context->nr = 12;
280  }
281  else if(keyLen == 32)
282  {
283  //14 rounds are required for 256-bit key
284  context->nr = 14;
285  }
286  else
287  {
288  //Report an error
290  }
291 
292  //Copy the original key
293  osMemcpy(context->ek, key, keyLen);
294 
295  //No error to report
296  return NO_ERROR;
297 }
298 
299 
300 /**
301  * @brief Encrypt a 16-byte block using AES algorithm
302  * @param[in] context Pointer to the AES context
303  * @param[in] input Plaintext block to encrypt
304  * @param[out] output Ciphertext block resulting from encryption
305  **/
306 
307 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
308 {
309  //Perform AES encryption
310  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
311  AES_DIRECTION_ENCRYPT | AES_OPMODE_ECB);
312 }
313 
314 
315 /**
316  * @brief Decrypt a 16-byte block using AES algorithm
317  * @param[in] context Pointer to the AES context
318  * @param[in] input Ciphertext block to decrypt
319  * @param[out] output Plaintext block resulting from decryption
320  **/
321 
322 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
323 {
324  //Perform AES decryption
325  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
326  AES_DIRECTION_DECRYPT | AES_OPMODE_ECB);
327 }
328 
329 
330 #if (ECB_SUPPORT == ENABLED)
331 
332 /**
333  * @brief ECB encryption
334  * @param[in] cipher Cipher algorithm
335  * @param[in] context Cipher algorithm context
336  * @param[in] p Plaintext to be encrypted
337  * @param[out] c Ciphertext resulting from the encryption
338  * @param[in] length Total number of data bytes to be encrypted
339  * @return Error code
340  **/
341 
342 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
343  const uint8_t *p, uint8_t *c, size_t length)
344 {
345  error_t error;
346 
347  //Initialize status code
348  error = NO_ERROR;
349 
350  //AES cipher algorithm?
351  if(cipher == AES_CIPHER_ALGO)
352  {
353  //Check the length of the payload
354  if(length == 0)
355  {
356  //No data to process
357  }
358  else if((length % AES_BLOCK_SIZE) == 0)
359  {
360  //Encrypt payload data
361  aesProcessData(context, NULL, p, c, length, AES_DIRECTION_ENCRYPT |
362  AES_OPMODE_ECB);
363  }
364  else
365  {
366  //The length of the payload must be a multiple of the block size
367  error = ERROR_INVALID_LENGTH;
368  }
369  }
370  else
371  {
372  //ECB mode operates in a block-by-block fashion
373  while(length >= cipher->blockSize)
374  {
375  //Encrypt current block
376  cipher->encryptBlock(context, p, c);
377 
378  //Next block
379  p += cipher->blockSize;
380  c += cipher->blockSize;
381  length -= cipher->blockSize;
382  }
383 
384  //The length of the payload must be a multiple of the block size
385  if(length != 0)
386  {
387  error = ERROR_INVALID_LENGTH;
388  }
389  }
390 
391  //Return status code
392  return error;
393 }
394 
395 
396 /**
397  * @brief ECB decryption
398  * @param[in] cipher Cipher algorithm
399  * @param[in] context Cipher algorithm context
400  * @param[in] c Ciphertext to be decrypted
401  * @param[out] p Plaintext resulting from the decryption
402  * @param[in] length Total number of data bytes to be decrypted
403  * @return Error code
404  **/
405 
406 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
407  const uint8_t *c, uint8_t *p, size_t length)
408 {
409  error_t error;
410 
411  //Initialize status code
412  error = NO_ERROR;
413 
414  //AES cipher algorithm?
415  if(cipher == AES_CIPHER_ALGO)
416  {
417  //Check the length of the payload
418  if(length == 0)
419  {
420  //No data to process
421  }
422  else if((length % AES_BLOCK_SIZE) == 0)
423  {
424  //Decrypt payload data
425  aesProcessData(context, NULL, c, p, length, AES_DIRECTION_DECRYPT |
426  AES_OPMODE_ECB);
427  }
428  else
429  {
430  //The length of the payload must be a multiple of the block size
431  error = ERROR_INVALID_LENGTH;
432  }
433  }
434  else
435  {
436  //ECB mode operates in a block-by-block fashion
437  while(length >= cipher->blockSize)
438  {
439  //Decrypt current block
440  cipher->decryptBlock(context, c, p);
441 
442  //Next block
443  c += cipher->blockSize;
444  p += cipher->blockSize;
445  length -= cipher->blockSize;
446  }
447 
448  //The length of the payload must be a multiple of the block size
449  if(length != 0)
450  {
451  error = ERROR_INVALID_LENGTH;
452  }
453  }
454 
455  //Return status code
456  return error;
457 }
458 
459 #endif
460 #if (CBC_SUPPORT == ENABLED)
461 
462 /**
463  * @brief CBC encryption
464  * @param[in] cipher Cipher algorithm
465  * @param[in] context Cipher algorithm context
466  * @param[in,out] iv Initialization vector
467  * @param[in] p Plaintext to be encrypted
468  * @param[out] c Ciphertext resulting from the encryption
469  * @param[in] length Total number of data bytes to be encrypted
470  * @return Error code
471  **/
472 
473 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
474  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
475 {
476  error_t error;
477 
478  //Initialize status code
479  error = NO_ERROR;
480 
481  //AES cipher algorithm?
482  if(cipher == AES_CIPHER_ALGO)
483  {
484  //Check the length of the payload
485  if(length == 0)
486  {
487  //No data to process
488  }
489  else if((length % AES_BLOCK_SIZE) == 0)
490  {
491  //Encrypt payload data
492  aesProcessData(context, iv, p, c, length, AES_DIRECTION_ENCRYPT |
493  AES_OPMODE_CBC);
494  }
495  else
496  {
497  //The length of the payload must be a multiple of the block size
498  error = ERROR_INVALID_LENGTH;
499  }
500  }
501  else
502  {
503  size_t i;
504 
505  //CBC mode operates in a block-by-block fashion
506  while(length >= cipher->blockSize)
507  {
508  //XOR input block with IV contents
509  for(i = 0; i < cipher->blockSize; i++)
510  {
511  c[i] = p[i] ^ iv[i];
512  }
513 
514  //Encrypt the current block based upon the output of the previous
515  //encryption
516  cipher->encryptBlock(context, c, c);
517 
518  //Update IV with output block contents
519  osMemcpy(iv, c, cipher->blockSize);
520 
521  //Next block
522  p += cipher->blockSize;
523  c += cipher->blockSize;
524  length -= cipher->blockSize;
525  }
526 
527  //The length of the payload must be a multiple of the block size
528  if(length != 0)
529  {
530  error = ERROR_INVALID_LENGTH;
531  }
532  }
533 
534  //Return status code
535  return error;
536 }
537 
538 
539 /**
540  * @brief CBC decryption
541  * @param[in] cipher Cipher algorithm
542  * @param[in] context Cipher algorithm context
543  * @param[in,out] iv Initialization vector
544  * @param[in] c Ciphertext to be decrypted
545  * @param[out] p Plaintext resulting from the decryption
546  * @param[in] length Total number of data bytes to be decrypted
547  * @return Error code
548  **/
549 
550 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
551  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
552 {
553  error_t error;
554 
555  //Initialize status code
556  error = NO_ERROR;
557 
558  //AES cipher algorithm?
559  if(cipher == AES_CIPHER_ALGO)
560  {
561  //Check the length of the payload
562  if(length == 0)
563  {
564  //No data to process
565  }
566  else if((length % AES_BLOCK_SIZE) == 0)
567  {
568  //Decrypt payload data
569  aesProcessData(context, iv, c, p, length, AES_DIRECTION_DECRYPT |
570  AES_OPMODE_CBC);
571  }
572  else
573  {
574  //The length of the payload must be a multiple of the block size
575  error = ERROR_INVALID_LENGTH;
576  }
577  }
578  else
579  {
580  size_t i;
581  uint8_t t[16];
582 
583  //CBC mode operates in a block-by-block fashion
584  while(length >= cipher->blockSize)
585  {
586  //Save input block
587  osMemcpy(t, c, cipher->blockSize);
588 
589  //Decrypt the current block
590  cipher->decryptBlock(context, c, p);
591 
592  //XOR output block with IV contents
593  for(i = 0; i < cipher->blockSize; i++)
594  {
595  p[i] ^= iv[i];
596  }
597 
598  //Update IV with input block contents
599  osMemcpy(iv, t, cipher->blockSize);
600 
601  //Next block
602  c += cipher->blockSize;
603  p += cipher->blockSize;
604  length -= cipher->blockSize;
605  }
606 
607  //The length of the payload must be a multiple of the block size
608  if(length != 0)
609  {
610  error = ERROR_INVALID_LENGTH;
611  }
612  }
613 
614  //Return status code
615  return error;
616 }
617 
618 #endif
619 #if (CFB_SUPPORT == ENABLED)
620 
621 /**
622  * @brief CFB encryption
623  * @param[in] cipher Cipher algorithm
624  * @param[in] context Cipher algorithm context
625  * @param[in] s Size of the plaintext and ciphertext segments
626  * @param[in,out] iv Initialization vector
627  * @param[in] p Plaintext to be encrypted
628  * @param[out] c Ciphertext resulting from the encryption
629  * @param[in] length Total number of data bytes to be encrypted
630  * @return Error code
631  **/
632 
633 error_t cfbEncrypt(const CipherAlgo *cipher, void *context, uint_t s,
634  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
635 {
636  error_t error;
637 
638  //Initialize status code
639  error = NO_ERROR;
640 
641  //AES cipher algorithm?
642  if(cipher == AES_CIPHER_ALGO)
643  {
644  //Check the value of the parameter
645  if(s == (AES_BLOCK_SIZE * 8))
646  {
647  //Check the length of the payload
648  if(length > 0)
649  {
650  //Encrypt payload data
651  aesProcessData(context, iv, p, c, length, AES_DIRECTION_ENCRYPT |
652  AES_OPMODE_CFB);
653  }
654  else
655  {
656  //No data to process
657  }
658  }
659  else
660  {
661  //The value of the parameter is not valid
662  error = ERROR_INVALID_PARAMETER;
663  }
664  }
665  else
666  {
667  //Check the value of the parameter
668  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
669  {
670  size_t i;
671  size_t n;
672  uint8_t o[16];
673 
674  //Determine the size, in bytes, of the plaintext and ciphertext segments
675  s = s / 8;
676 
677  //Process each plaintext segment
678  while(length > 0)
679  {
680  //Compute the number of bytes to process at a time
681  n = MIN(length, s);
682 
683  //Compute O(j) = CIPH(I(j))
684  cipher->encryptBlock(context, iv, o);
685 
686  //Compute C(j) = P(j) XOR MSB(O(j))
687  for(i = 0; i < n; i++)
688  {
689  c[i] = p[i] ^ o[i];
690  }
691 
692  //Compute I(j+1) = LSB(I(j)) | C(j)
693  osMemmove(iv, iv + s, cipher->blockSize - s);
694  osMemcpy(iv + cipher->blockSize - s, c, s);
695 
696  //Next block
697  p += n;
698  c += n;
699  length -= n;
700  }
701  }
702  else
703  {
704  //The value of the parameter is not valid
705  error = ERROR_INVALID_PARAMETER;
706  }
707  }
708 
709  //Return status code
710  return error;
711 }
712 
713 
714 /**
715  * @brief CFB decryption
716  * @param[in] cipher Cipher algorithm
717  * @param[in] context Cipher algorithm context
718  * @param[in] s Size of the plaintext and ciphertext segments
719  * @param[in,out] iv Initialization vector
720  * @param[in] c Ciphertext to be decrypted
721  * @param[out] p Plaintext resulting from the decryption
722  * @param[in] length Total number of data bytes to be decrypted
723  * @return Error code
724  **/
725 
726 error_t cfbDecrypt(const CipherAlgo *cipher, void *context, uint_t s,
727  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
728 {
729  error_t error;
730 
731  //Initialize status code
732  error = NO_ERROR;
733 
734  //AES cipher algorithm?
735  if(cipher == AES_CIPHER_ALGO)
736  {
737  //Check the value of the parameter
738  if(s == (AES_BLOCK_SIZE * 8))
739  {
740  //Check the length of the payload
741  if(length > 0)
742  {
743  //Decrypt payload data
744  aesProcessData(context, iv, c, p, length, AES_DIRECTION_DECRYPT |
745  AES_OPMODE_CFB);
746  }
747  else
748  {
749  //No data to process
750  }
751  }
752  else
753  {
754  //The value of the parameter is not valid
755  error = ERROR_INVALID_PARAMETER;
756  }
757  }
758  else
759  {
760  //Check the value of the parameter
761  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
762  {
763  size_t i;
764  size_t n;
765  uint8_t o[16];
766 
767  //Determine the size, in bytes, of the plaintext and ciphertext segments
768  s = s / 8;
769 
770  //Process each ciphertext segment
771  while(length > 0)
772  {
773  //Compute the number of bytes to process at a time
774  n = MIN(length, s);
775 
776  //Compute O(j) = CIPH(I(j))
777  cipher->encryptBlock(context, iv, o);
778 
779  //Compute I(j+1) = LSB(I(j)) | C(j)
780  osMemmove(iv, iv + s, cipher->blockSize - s);
781  osMemcpy(iv + cipher->blockSize - s, c, s);
782 
783  //Compute P(j) = C(j) XOR MSB(O(j))
784  for(i = 0; i < n; i++)
785  {
786  p[i] = c[i] ^ o[i];
787  }
788 
789  //Next block
790  c += n;
791  p += n;
792  length -= n;
793  }
794  }
795  else
796  {
797  //The value of the parameter is not valid
798  error = ERROR_INVALID_PARAMETER;
799  }
800  }
801 
802  //Return status code
803  return error;
804 }
805 
806 #endif
807 #if (CTR_SUPPORT == ENABLED)
808 
809 /**
810  * @brief CTR encryption
811  * @param[in] cipher Cipher algorithm
812  * @param[in] context Cipher algorithm context
813  * @param[in] m Size in bits of the specific part of the block to be incremented
814  * @param[in,out] t Initial counter block
815  * @param[in] p Plaintext to be encrypted
816  * @param[out] c Ciphertext resulting from the encryption
817  * @param[in] length Total number of data bytes to be encrypted
818  * @return Error code
819  **/
820 
821 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
822  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
823 {
824  error_t error;
825 
826  //Initialize status code
827  error = NO_ERROR;
828 
829  //Check the value of the parameter
830  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
831  {
832  //Determine the size, in bytes, of the specific part of the block to be
833  //incremented
834  m = m / 8;
835 
836  //AES cipher algorithm?
837  if(cipher == AES_CIPHER_ALGO)
838  {
839  size_t k;
840  size_t n;
841  uint8_t iv[AES_BLOCK_SIZE];
842 
843  //Process plaintext
844  while(length > 0)
845  {
846  //Limit the number of blocks to process at a time
847  k = 256 - t[AES_BLOCK_SIZE - 1];
848  n = MIN(length, k * AES_BLOCK_SIZE);
849  k = (n + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
850 
851  //Copy initial counter value
853 
854  //Encrypt payload data
855  aesProcessData(context, iv, p, c, n, AES_DIRECTION_ENCRYPT |
856  AES_OPMODE_CTR | AES_CTR_WIDTH_128BIT);
857 
858  //Standard incrementing function
860 
861  //Next block
862  p += n;
863  c += n;
864  length -= n;
865  }
866  }
867  else
868  {
869  size_t i;
870  size_t n;
871  uint8_t o[16];
872 
873  //Process plaintext
874  while(length > 0)
875  {
876  //CTR mode operates in a block-by-block fashion
877  n = MIN(length, cipher->blockSize);
878 
879  //Compute O(j) = CIPH(T(j))
880  cipher->encryptBlock(context, t, o);
881 
882  //Compute C(j) = P(j) XOR T(j)
883  for(i = 0; i < n; i++)
884  {
885  c[i] = p[i] ^ o[i];
886  }
887 
888  //Standard incrementing function
889  ctrIncBlock(t, 1, cipher->blockSize, m);
890 
891  //Next block
892  p += n;
893  c += n;
894  length -= n;
895  }
896  }
897  }
898  else
899  {
900  //The value of the parameter is not valid
901  error = ERROR_INVALID_PARAMETER;
902  }
903 
904  //Return status code
905  return error;
906 }
907 
908 #endif
909 #if (GCM_SUPPORT == ENABLED)
910 
911 /**
912  * @brief Perform AES-GCM encryption or decryption
913  * @param[in] context AES algorithm context
914  * @param[in] iv Initialization vector
915  * @param[in] a Additional authenticated data
916  * @param[in] aLen Length of the additional data
917  * @param[in] input Data to be encrypted/decrypted
918  * @param[out] output Data resulting from the encryption/decryption process
919  * @param[in] length Total number of data bytes to be processed
920  * @param[out] t Authentication tag
921  * @param[in] mode Operation mode
922  **/
923 
924 void gcmProcessData(AesContext *context, const uint8_t *iv,
925  const uint8_t *a, size_t aLen, const uint8_t *input, uint8_t *output,
926  size_t length, uint8_t *t, uint32_t mode)
927 {
928  uint32_t temp;
929  uint32_t buffer[4];
930 
931  //Acquire exclusive access to the AES module
933 
934  //Check parameters
935  if(aLen > 0 || length > 0)
936  {
937  //Set GCM operation mode
938  aesSetMode(AES_OPMODE_GCM_HY0CALC | mode);
939  //Set encryption key
940  aesLoadKey(context);
941 
942  //When the length of the IV is 96 bits, the padding string is appended to
943  //the IV to form the pre-counter block
948 
949  //Set data length
951  AES_C_LENGTH_1_R = 0;
952 
953  //Set additional authenticated data length
954  AES_AUTH_LENGTH_R = aLen;
955 
956  //Process additional authenticated data
957  while(aLen >= AES_BLOCK_SIZE)
958  {
959  //Wait for the AES engine to be ready to accept data
960  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
961  {
962  }
963 
964  //Write block
969 
970  //Next block
971  a += AES_BLOCK_SIZE;
972  aLen -= AES_BLOCK_SIZE;
973  }
974 
975  //Process final block of additional authenticated data
976  if(aLen > 0)
977  {
978  //Copy partial block
979  osMemset(buffer, 0, AES_BLOCK_SIZE);
980  osMemcpy(buffer, a, aLen);
981 
982  //Wait for the AES engine to be ready to accept data
983  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
984  {
985  }
986 
987  //Write block
988  AES_DATA_IN_OUT_3_R = buffer[0];
989  AES_DATA_IN_OUT_2_R = buffer[1];
990  AES_DATA_IN_OUT_1_R = buffer[2];
991  AES_DATA_IN_OUT_0_R = buffer[3];
992  }
993 
994  //Process data
995  while(length >= AES_BLOCK_SIZE)
996  {
997  //Wait for the AES engine to be ready to accept data
998  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
999  {
1000  }
1001 
1002  //Write input block
1003  AES_DATA_IN_OUT_3_R = LOAD32LE(input);
1004  AES_DATA_IN_OUT_2_R = LOAD32LE(input + 4);
1005  AES_DATA_IN_OUT_1_R = LOAD32LE(input + 8);
1006  AES_DATA_IN_OUT_0_R = LOAD32LE(input + 12);
1007 
1008  //Wait for the output to be ready
1009  while((AES_CTRL_R & AES_CTRL_OUTPUT_READY) == 0)
1010  {
1011  }
1012 
1013  //Read output block
1014  temp = AES_DATA_IN_OUT_3_R;
1015  STORE32LE(temp, output);
1016  temp = AES_DATA_IN_OUT_2_R;
1017  STORE32LE(temp, output + 4);
1018  temp = AES_DATA_IN_OUT_1_R;
1019  STORE32LE(temp, output + 8);
1020  temp = AES_DATA_IN_OUT_0_R;
1021  STORE32LE(temp, output + 12);
1022 
1023  //Next block
1024  input += AES_BLOCK_SIZE;
1025  output += AES_BLOCK_SIZE;
1027  }
1028 
1029  //Process final block of data
1030  if(length > 0)
1031  {
1032  //Copy partial block
1033  osMemset(buffer, 0, AES_BLOCK_SIZE);
1034  osMemcpy(buffer, input, length);
1035 
1036  //Wait for the AES engine to be ready to accept data
1037  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
1038  {
1039  }
1040 
1041  //Write input block
1042  AES_DATA_IN_OUT_3_R = buffer[0];
1043  AES_DATA_IN_OUT_2_R = buffer[1];
1044  AES_DATA_IN_OUT_1_R = buffer[2];
1045  AES_DATA_IN_OUT_0_R = buffer[3];
1046 
1047  //Wait for the output to be ready
1048  while((AES_CTRL_R & AES_CTRL_OUTPUT_READY) == 0)
1049  {
1050  }
1051 
1052  //Read output block
1053  buffer[0] = AES_DATA_IN_OUT_3_R;
1054  buffer[1] = AES_DATA_IN_OUT_2_R;
1055  buffer[2] = AES_DATA_IN_OUT_1_R;
1056  buffer[3] = AES_DATA_IN_OUT_0_R;
1057 
1058  //Copy partial block
1059  osMemcpy(output, buffer, length);
1060  }
1061 
1062  //Wait for the output context to be ready
1063  while((AES_CTRL_R & AES_CTRL_SVCTXTRDY) == 0)
1064  {
1065  }
1066 
1067  //Read the authentication tag
1068  temp = AES_TAG_OUT_0_R;
1069  STORE32LE(temp, t);
1070  temp = AES_TAG_OUT_1_R;
1071  STORE32LE(temp, t + 4);
1072  temp = AES_TAG_OUT_2_R;
1073  STORE32LE(temp, t + 8);
1074  temp = AES_TAG_OUT_3_R;
1075  STORE32LE(temp, t + 12);
1076  }
1077  else
1078  {
1079  //Set CTR operation mode
1080  aesSetMode(AES_DIRECTION_ENCRYPT | AES_OPMODE_CTR |
1081  AES_CTR_WIDTH_32BIT);
1082 
1083  //Set encryption key
1084  aesLoadKey(context);
1085 
1086  //When the length of the IV is 96 bits, the padding string is appended to
1087  //the IV to form the pre-counter block
1089  AES_IV_IN_OUT_1_R = LOAD32LE(iv + 4);
1090  AES_IV_IN_OUT_2_R = LOAD32LE(iv + 8);
1092 
1093  //Wait for the AES engine to be ready to accept data
1094  while((AES_CTRL_R & AES_CTRL_INPUT_READY) == 0)
1095  {
1096  }
1097 
1098  //Write input block
1099  AES_DATA_IN_OUT_3_R = 0;
1100  AES_DATA_IN_OUT_2_R = 0;
1101  AES_DATA_IN_OUT_1_R = 0;
1102  AES_DATA_IN_OUT_0_R = 0;
1103 
1104  //Wait for the output to be ready
1105  while((AES_CTRL_R & AES_CTRL_OUTPUT_READY) == 0)
1106  {
1107  }
1108 
1109  //Read output block
1110  temp = AES_DATA_IN_OUT_3_R;
1111  STORE32LE(temp, t);
1112  temp = AES_DATA_IN_OUT_2_R;
1113  STORE32LE(temp, t + 4);
1114  temp = AES_DATA_IN_OUT_1_R;
1115  STORE32LE(temp, t + 8);
1116  temp = AES_DATA_IN_OUT_0_R;
1117  STORE32LE(temp, t + 12);
1118  }
1119 
1120  //Release exclusive access to the AES module
1122 }
1123 
1124 
1125 /**
1126  * @brief Initialize GCM context
1127  * @param[in] context Pointer to the GCM context
1128  * @param[in] cipherAlgo Cipher algorithm
1129  * @param[in] cipherContext Pointer to the cipher algorithm context
1130  * @return Error code
1131  **/
1132 
1133 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1134  void *cipherContext)
1135 {
1136  //Check parameters
1137  if(context == NULL || cipherContext == NULL)
1138  return ERROR_INVALID_PARAMETER;
1139 
1140  //The CRYP module only supports AES cipher algorithm
1141  if(cipherAlgo != AES_CIPHER_ALGO)
1142  return ERROR_INVALID_PARAMETER;
1143 
1144  //Save cipher algorithm context
1145  context->cipherAlgo = cipherAlgo;
1146  context->cipherContext = cipherContext;
1147 
1148  //Successful initialization
1149  return NO_ERROR;
1150 }
1151 
1152 
1153 /**
1154  * @brief Authenticated encryption using GCM
1155  * @param[in] context Pointer to the GCM context
1156  * @param[in] iv Initialization vector
1157  * @param[in] ivLen Length of the initialization vector
1158  * @param[in] a Additional authenticated data
1159  * @param[in] aLen Length of the additional data
1160  * @param[in] p Plaintext to be encrypted
1161  * @param[out] c Ciphertext resulting from the encryption
1162  * @param[in] length Total number of data bytes to be encrypted
1163  * @param[out] t Authentication tag
1164  * @param[in] tLen Length of the authentication tag
1165  * @return Error code
1166  **/
1167 
1168 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1169  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1170  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1171 {
1172  uint8_t authTag[16];
1173 
1174  //Make sure the GCM context is valid
1175  if(context == NULL)
1176  return ERROR_INVALID_PARAMETER;
1177 
1178  //Check whether the length of the IV is 96 bits
1179  if(ivLen != 12)
1180  return ERROR_INVALID_LENGTH;
1181 
1182  //Check the length of the authentication tag
1183  if(tLen < 4 || tLen > 16)
1184  return ERROR_INVALID_LENGTH;
1185 
1186  //Perform AES-GCM encryption
1187  gcmProcessData(context->cipherContext, iv, a, aLen, p, c, length, authTag,
1188  AES_DIRECTION_ENCRYPT);
1189 
1190  //Copy the resulting authentication tag
1191  osMemcpy(t, authTag, tLen);
1192 
1193  //Successful processing
1194  return NO_ERROR;
1195 }
1196 
1197 
1198 /**
1199  * @brief Authenticated decryption using GCM
1200  * @param[in] context Pointer to the GCM context
1201  * @param[in] iv Initialization vector
1202  * @param[in] ivLen Length of the initialization vector
1203  * @param[in] a Additional authenticated data
1204  * @param[in] aLen Length of the additional data
1205  * @param[in] c Ciphertext to be decrypted
1206  * @param[out] p Plaintext resulting from the decryption
1207  * @param[in] length Total number of data bytes to be decrypted
1208  * @param[in] t Authentication tag
1209  * @param[in] tLen Length of the authentication tag
1210  * @return Error code
1211  **/
1212 
1213 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1214  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1215  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1216 {
1217  size_t i;
1218  uint8_t mask;
1219  uint8_t authTag[16];
1220 
1221  //Make sure the GCM context is valid
1222  if(context == NULL)
1223  return ERROR_INVALID_PARAMETER;
1224 
1225  //Check whether the length of the IV is 96 bits
1226  if(ivLen != 12)
1227  return ERROR_INVALID_LENGTH;
1228 
1229  //Check the length of the authentication tag
1230  if(tLen < 4 || tLen > 16)
1231  return ERROR_INVALID_LENGTH;
1232 
1233  //Perform AES-GCM decryption
1234  gcmProcessData(context->cipherContext, iv, a, aLen, c, p, length, authTag,
1235  AES_DIRECTION_DECRYPT);
1236 
1237  //The calculated tag is bitwise compared to the received tag
1238  for(mask = 0, i = 0; i < tLen; i++)
1239  {
1240  mask |= authTag[i] ^ t[i];
1241  }
1242 
1243  //The message is authenticated if and only if the tags match
1244  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1245 }
1246 
1247 #endif
1248 #endif
TMS320F2838xD hardware cryptographic accelerator.
#define AES_KEY1_7_R
#define AES_KEY1_3_R
#define AES_TAG_OUT_2_R
uint8_t a
Definition: ndp.h:411
error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1077
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
#define AES_DATA_IN_OUT_0_R
#define AES_TAG_OUT_3_R
uint8_t p
Definition: ndp.h:300
#define AES_KEY1_2_R
uint8_t t
Definition: lldp_ext_med.h:212
#define AES_IV_IN_OUT_2_R
uint8_t o
Collection of AEAD algorithms.
void aesSetMode(uint32_t mode)
Set AES operation mode.
#define STORE32LE(a, p)
Definition: cpu_endian.h:279
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.
size_t blockSize
Definition: crypto.h:1072
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.
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
#define BETOH32(value)
Definition: cpu_endian.h:451
#define AES_SYSCONFIG_R
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1076
#define AES_KEY1_0_R
AES algorithm context.
Definition: aes.h:58
#define AES_BLOCK_SIZE
Definition: aes.h:43
#define AES_KEY1_6_R
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
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 aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
error_t
Error codes.
Definition: error.h:43
#define AES_DATA_IN_OUT_3_R
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
#define AES_C_LENGTH_1_R
#define AES_TAG_OUT_0_R
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
TMS320F2838xD cipher hardware accelerator.
#define AES_IV_IN_OUT_1_R
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.
@ 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
#define AES_IV_IN_OUT_3_R
uint8_t mask
Definition: web_socket.h:319
uint8_t iv[]
Definition: ike.h:1502
Block cipher modes of operation.
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
uint8_t length
Definition: tcp.h:368
#define AES_KEY1_5_R
#define MIN(a, b)
Definition: os_port.h:63
void aesLoadKey(AesContext *context)
Load AES key.
#define AES_CTRL_R
#define AES_KEY1_4_R
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 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.
GCM context.
Definition: gcm.h:64
uint8_t m
Definition: ndp.h:304
uint8_t n
#define AES_DATA_IN_OUT_1_R
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
#define AES_IV_IN_OUT_0_R
Common interface for encryption algorithms.
Definition: crypto.h:1068
#define AES_KEY1_1_R
#define AES_CIPHER_ALGO
Definition: aes.h:45
uint8_t s
Definition: igmp_common.h:234
#define AES_C_LENGTH_0_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.
#define AES_DATA_IN_OUT_2_R
#define LOAD32LE(p)
Definition: cpu_endian.h:203
uint32_t ek[60]
Definition: aes.h:60
#define AES_SYSSTATUS_R
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
#define AES_AUTH_LENGTH_R
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:66
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
OsMutex f2838xCryptoMutex
Definition: f2838x_crypto.c:43