esp32_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file esp32_crypto_cipher.c
3  * @brief ESP32 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 "soc/hwcrypto_reg.h"
36 #include "soc/dport_access.h"
37 #include "esp_private/periph_ctrl.h"
38 #include "core/crypto.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (ESP32_CRYPTO_CIPHER_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief AES module initialization
51  **/
52 
53 void esp32AesInit(void)
54 {
55  //Enable AES module
56  periph_module_enable(PERIPH_AES_MODULE);
57 }
58 
59 
60 /**
61  * @brief Load AES key
62  * @param[in] context AES algorithm context
63  * @param[in] mode Operation mode
64  **/
65 
66 void aesLoadKey(AesContext *context, uint32_t mode)
67 {
68  //Configure endianness
69  DPORT_REG_WRITE(AES_ENDIAN, AES_ENDIAN_DEFAULT);
70 
71  //Check the length of the key
72  if(context->nr == 10)
73  {
74  //Configure operation mode
75  DPORT_REG_WRITE(AES_MODE_REG, AES_MODE_128_BITS | mode);
76 
77  //Load the 128-bit key
78  DPORT_REG_WRITE(AES_KEY_BASE, context->ek[0]);
79  DPORT_REG_WRITE(AES_KEY_BASE + 4, context->ek[1]);
80  DPORT_REG_WRITE(AES_KEY_BASE + 8, context->ek[2]);
81  DPORT_REG_WRITE(AES_KEY_BASE + 12, context->ek[3]);
82  }
83  else if(context->nr == 12)
84  {
85  //Configure operation mode
86  DPORT_REG_WRITE(AES_MODE_REG, AES_MODE_192_BITS | mode);
87 
88  //Load the 192-bit key
89  DPORT_REG_WRITE(AES_KEY_BASE, context->ek[0]);
90  DPORT_REG_WRITE(AES_KEY_BASE + 4, context->ek[1]);
91  DPORT_REG_WRITE(AES_KEY_BASE + 8, context->ek[2]);
92  DPORT_REG_WRITE(AES_KEY_BASE + 12, context->ek[3]);
93  DPORT_REG_WRITE(AES_KEY_BASE + 16, context->ek[4]);
94  DPORT_REG_WRITE(AES_KEY_BASE + 20, context->ek[5]);
95  }
96  else
97  {
98  //Configure operation mode
99  DPORT_REG_WRITE(AES_MODE_REG, AES_MODE_256_BITS | mode);
100 
101  //Load the 256-bit key
102  DPORT_REG_WRITE(AES_KEY_BASE, context->ek[0]);
103  DPORT_REG_WRITE(AES_KEY_BASE + 4, context->ek[1]);
104  DPORT_REG_WRITE(AES_KEY_BASE + 8, context->ek[2]);
105  DPORT_REG_WRITE(AES_KEY_BASE + 12, context->ek[3]);
106  DPORT_REG_WRITE(AES_KEY_BASE + 16, context->ek[4]);
107  DPORT_REG_WRITE(AES_KEY_BASE + 20, context->ek[5]);
108  DPORT_REG_WRITE(AES_KEY_BASE + 24, context->ek[6]);
109  DPORT_REG_WRITE(AES_KEY_BASE + 28, context->ek[7]);
110  }
111 }
112 
113 
114 /**
115  * @brief Encrypt/decrypt a 16-byte block using AES algorithm
116  * @param[in] input Input block to be encrypted/decrypted
117  * @param[out] output Resulting block
118  **/
119 
120 void aesProcessDataBlock(const uint8_t *input, uint8_t *output)
121 {
122  uint32_t *p;
123 
124  //Write plaintext
125  p = (uint32_t *) input;
126  DPORT_REG_WRITE(AES_TEXT_BASE, p[0]);
127  DPORT_REG_WRITE(AES_TEXT_BASE + 4, p[1]);
128  DPORT_REG_WRITE(AES_TEXT_BASE + 8, p[2]);
129  DPORT_REG_WRITE(AES_TEXT_BASE + 12, p[3]);
130 
131  //Start AES encryption
132  DPORT_REG_WRITE(AES_START_REG, 1);
133 
134  //Wait for the operation to complete
135  while(DPORT_REG_READ(AES_IDLE_REG) == 0)
136  {
137  }
138 
139  //Read ciphertext
140  p = (uint32_t *) output;
141  DPORT_INTERRUPT_DISABLE();
142  p[0] = DPORT_SEQUENCE_REG_READ(AES_TEXT_BASE);
143  p[1] = DPORT_SEQUENCE_REG_READ(AES_TEXT_BASE + 4);
144  p[2] = DPORT_SEQUENCE_REG_READ(AES_TEXT_BASE + 8);
145  p[3] = DPORT_SEQUENCE_REG_READ(AES_TEXT_BASE + 12);
146  DPORT_INTERRUPT_RESTORE();
147 }
148 
149 
150 /**
151  * @brief Key expansion
152  * @param[in] context Pointer to the AES context to initialize
153  * @param[in] key Pointer to the key
154  * @param[in] keyLen Length of the key
155  * @return Error code
156  **/
157 
158 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
159 {
160  //Check parameters
161  if(context == NULL || key == NULL)
163 
164  //Check the length of the key
165  if(keyLen == 16)
166  {
167  //10 rounds are required for 128-bit key
168  context->nr = 10;
169  }
170  else if(keyLen == 24)
171  {
172  //12 rounds are required for 192-bit key
173  context->nr = 12;
174  }
175  else if(keyLen == 32)
176  {
177  //14 rounds are required for 256-bit key
178  context->nr = 14;
179  }
180  else
181  {
182  //Report an error
184  }
185 
186  //Copy the original key
187  osMemcpy(context->ek, key, keyLen);
188 
189  //No error to report
190  return NO_ERROR;
191 }
192 
193 
194 /**
195  * @brief Encrypt a 16-byte block using AES algorithm
196  * @param[in] context Pointer to the AES context
197  * @param[in] input Plaintext block to encrypt
198  * @param[out] output Ciphertext block resulting from encryption
199  **/
200 
201 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
202 {
203  //Acquire exclusive access to the AES module
205 
206  //Load AES key
207  aesLoadKey(context, AES_MODE_ENC);
208  //Perform AES encryption
209  aesProcessDataBlock(input, output);
210 
211  //Release exclusive access to the AES module
213 }
214 
215 
216 /**
217  * @brief Decrypt a 16-byte block using AES algorithm
218  * @param[in] context Pointer to the AES context
219  * @param[in] input Ciphertext block to decrypt
220  * @param[out] output Plaintext block resulting from decryption
221  **/
222 
223 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
224 {
225  //Acquire exclusive access to the AES module
227 
228  //Load AES key
229  aesLoadKey(context, AES_MODE_DEC);
230  //Perform AES decryption
231  aesProcessDataBlock(input, output);
232 
233  //Release exclusive access to the AES module
235 }
236 
237 
238 #if (ECB_SUPPORT == ENABLED)
239 
240 /**
241  * @brief ECB encryption
242  * @param[in] cipher Cipher algorithm
243  * @param[in] context Cipher algorithm context
244  * @param[in] p Plaintext to be encrypted
245  * @param[out] c Ciphertext resulting from the encryption
246  * @param[in] length Total number of data bytes to be encrypted
247  * @return Error code
248  **/
249 
250 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
251  const uint8_t *p, uint8_t *c, size_t length)
252 {
253  error_t error;
254 
255  //Initialize status code
256  error = NO_ERROR;
257 
258  //AES cipher algorithm?
259  if(cipher == AES_CIPHER_ALGO)
260  {
261  //Acquire exclusive access to the AES module
263 
264  //Load AES key
265  aesLoadKey(context, AES_MODE_ENC);
266 
267  //ECB mode operates in a block-by-block fashion
268  while(length >= AES_BLOCK_SIZE)
269  {
270  //Encrypt current block
272 
273  //Next block
274  p += AES_BLOCK_SIZE;
275  c += AES_BLOCK_SIZE;
277  }
278 
279  //Release exclusive access to the AES module
281 
282  //The length of the payload must be a multiple of the block size
283  if(length != 0)
284  {
285  error = ERROR_INVALID_LENGTH;
286  }
287  }
288  else
289  {
290  //ECB mode operates in a block-by-block fashion
291  while(length >= cipher->blockSize)
292  {
293  //Encrypt current block
294  cipher->encryptBlock(context, p, c);
295 
296  //Next block
297  p += cipher->blockSize;
298  c += cipher->blockSize;
299  length -= cipher->blockSize;
300  }
301 
302  //The length of the payload must be a multiple of the block size
303  if(length != 0)
304  {
305  error = ERROR_INVALID_LENGTH;
306  }
307  }
308 
309  //Return status code
310  return error;
311 }
312 
313 
314 /**
315  * @brief ECB decryption
316  * @param[in] cipher Cipher algorithm
317  * @param[in] context Cipher algorithm context
318  * @param[in] c Ciphertext to be decrypted
319  * @param[out] p Plaintext resulting from the decryption
320  * @param[in] length Total number of data bytes to be decrypted
321  * @return Error code
322  **/
323 
324 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
325  const uint8_t *c, uint8_t *p, size_t length)
326 {
327  error_t error;
328 
329  //Initialize status code
330  error = NO_ERROR;
331 
332  //AES cipher algorithm?
333  if(cipher == AES_CIPHER_ALGO)
334  {
335  //Acquire exclusive access to the AES module
337 
338  //Load AES key
339  aesLoadKey(context, AES_MODE_DEC);
340 
341  //ECB mode operates in a block-by-block fashion
342  while(length >= AES_BLOCK_SIZE)
343  {
344  //Decrypt current block
346 
347  //Next block
348  c += AES_BLOCK_SIZE;
349  p += AES_BLOCK_SIZE;
351  }
352 
353  //Release exclusive access to the AES module
355 
356  //The length of the payload must be a multiple of the block size
357  if(length != 0)
358  {
359  error = ERROR_INVALID_LENGTH;
360  }
361  }
362  else
363  {
364  //ECB mode operates in a block-by-block fashion
365  while(length >= cipher->blockSize)
366  {
367  //Decrypt current block
368  cipher->decryptBlock(context, c, p);
369 
370  //Next block
371  c += cipher->blockSize;
372  p += cipher->blockSize;
373  length -= cipher->blockSize;
374  }
375 
376  //The length of the payload must be a multiple of the block size
377  if(length != 0)
378  {
379  error = ERROR_INVALID_LENGTH;
380  }
381  }
382 
383  //Return status code
384  return error;
385 }
386 
387 #endif
388 #if (CBC_SUPPORT == ENABLED)
389 
390 /**
391  * @brief CBC encryption
392  * @param[in] cipher Cipher algorithm
393  * @param[in] context Cipher algorithm context
394  * @param[in,out] iv Initialization vector
395  * @param[in] p Plaintext to be encrypted
396  * @param[out] c Ciphertext resulting from the encryption
397  * @param[in] length Total number of data bytes to be encrypted
398  * @return Error code
399  **/
400 
401 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
402  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
403 {
404  error_t error;
405  size_t i;
406 
407  //Initialize status code
408  error = NO_ERROR;
409 
410  //AES cipher algorithm?
411  if(cipher == AES_CIPHER_ALGO)
412  {
413  //Acquire exclusive access to the AES module
415 
416  //Load AES key
417  aesLoadKey(context, AES_MODE_ENC);
418 
419  //CBC mode operates in a block-by-block fashion
420  while(length >= AES_BLOCK_SIZE)
421  {
422  //XOR input block with IV contents
423  for(i = 0; i < AES_BLOCK_SIZE; i++)
424  {
425  c[i] = p[i] ^ iv[i];
426  }
427 
428  //Encrypt the current block based upon the output of the previous
429  //encryption
431 
432  //Update IV with output block contents
434 
435  //Next block
436  p += AES_BLOCK_SIZE;
437  c += AES_BLOCK_SIZE;
439  }
440 
441  //Release exclusive access to the AES module
443 
444  //The length of the payload must be a multiple of the block size
445  if(length != 0)
446  {
447  error = ERROR_INVALID_LENGTH;
448  }
449  }
450  else
451  {
452  //CBC mode operates in a block-by-block fashion
453  while(length >= cipher->blockSize)
454  {
455  //XOR input block with IV contents
456  for(i = 0; i < cipher->blockSize; i++)
457  {
458  c[i] = p[i] ^ iv[i];
459  }
460 
461  //Encrypt the current block based upon the output of the previous
462  //encryption
463  cipher->encryptBlock(context, c, c);
464 
465  //Update IV with output block contents
466  osMemcpy(iv, c, cipher->blockSize);
467 
468  //Next block
469  p += cipher->blockSize;
470  c += cipher->blockSize;
471  length -= cipher->blockSize;
472  }
473 
474  //The length of the payload must be a multiple of the block size
475  if(length != 0)
476  {
477  error = ERROR_INVALID_LENGTH;
478  }
479  }
480 
481  //Return status code
482  return error;
483 }
484 
485 
486 /**
487  * @brief CBC decryption
488  * @param[in] cipher Cipher algorithm
489  * @param[in] context Cipher algorithm context
490  * @param[in,out] iv Initialization vector
491  * @param[in] c Ciphertext to be decrypted
492  * @param[out] p Plaintext resulting from the decryption
493  * @param[in] length Total number of data bytes to be decrypted
494  * @return Error code
495  **/
496 
497 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
498  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
499 {
500  error_t error;
501  size_t i;
502  uint8_t t[16];
503 
504  //Initialize status code
505  error = NO_ERROR;
506 
507  //AES cipher algorithm?
508  if(cipher == AES_CIPHER_ALGO)
509  {
510  //Acquire exclusive access to the AES module
512 
513  //Load AES key
514  aesLoadKey(context, AES_MODE_DEC);
515 
516  //CBC mode operates in a block-by-block fashion
517  while(length >= AES_BLOCK_SIZE)
518  {
519  //Save input block
521 
522  //Decrypt the current block
524 
525  //XOR output block with IV contents
526  for(i = 0; i < AES_BLOCK_SIZE; i++)
527  {
528  p[i] ^= iv[i];
529  }
530 
531  //Update IV with input block contents
533 
534  //Next block
535  c += AES_BLOCK_SIZE;
536  p += AES_BLOCK_SIZE;
538  }
539 
540  //Release exclusive access to the AES module
542 
543  //The length of the payload must be a multiple of the block size
544  if(length != 0)
545  {
546  error = ERROR_INVALID_LENGTH;
547  }
548  }
549  else
550  {
551  //CBC mode operates in a block-by-block fashion
552  while(length >= cipher->blockSize)
553  {
554  //Save input block
555  osMemcpy(t, c, cipher->blockSize);
556 
557  //Decrypt the current block
558  cipher->decryptBlock(context, c, p);
559 
560  //XOR output block with IV contents
561  for(i = 0; i < cipher->blockSize; i++)
562  {
563  p[i] ^= iv[i];
564  }
565 
566  //Update IV with input block contents
567  osMemcpy(iv, t, cipher->blockSize);
568 
569  //Next block
570  c += cipher->blockSize;
571  p += cipher->blockSize;
572  length -= cipher->blockSize;
573  }
574 
575  //The length of the payload must be a multiple of the block size
576  if(length != 0)
577  {
578  error = ERROR_INVALID_LENGTH;
579  }
580  }
581 
582  //Return status code
583  return error;
584 }
585 
586 #endif
587 #if (CFB_SUPPORT == ENABLED)
588 
589 /**
590  * @brief CFB encryption
591  * @param[in] cipher Cipher algorithm
592  * @param[in] context Cipher algorithm context
593  * @param[in] s Size of the plaintext and ciphertext segments
594  * @param[in,out] iv Initialization vector
595  * @param[in] p Plaintext to be encrypted
596  * @param[out] c Ciphertext resulting from the encryption
597  * @param[in] length Total number of data bytes to be encrypted
598  * @return Error code
599  **/
600 
601 error_t cfbEncrypt(const CipherAlgo *cipher, void *context, uint_t s,
602  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
603 {
604  error_t error;
605 
606  //Initialize status code
607  error = NO_ERROR;
608 
609  //AES cipher algorithm?
610  if(cipher == AES_CIPHER_ALGO)
611  {
612  //Check the value of the parameter
613  if((s % 8) == 0 && s >= 1 && s <= (AES_BLOCK_SIZE * 8))
614  {
615  size_t i;
616  size_t n;
617  uint8_t o[16];
618 
619  //Determine the size, in bytes, of the plaintext and ciphertext segments
620  s = s / 8;
621 
622  //Acquire exclusive access to the AES module
624 
625  //Load AES key
626  aesLoadKey(context, AES_MODE_ENC);
627 
628  //Process each plaintext segment
629  while(length > 0)
630  {
631  //Compute the number of bytes to process at a time
632  n = MIN(length, s);
633 
634  //Compute O(j) = CIPH(I(j))
636 
637  //Compute C(j) = P(j) XOR MSB(O(j))
638  for(i = 0; i < n; i++)
639  {
640  c[i] = p[i] ^ o[i];
641  }
642 
643  //Compute I(j+1) = LSB(I(j)) | C(j)
644  osMemmove(iv, iv + s, AES_BLOCK_SIZE - s);
645  osMemcpy(iv + AES_BLOCK_SIZE - s, c, s);
646 
647  //Next block
648  p += n;
649  c += n;
650  length -= n;
651  }
652 
653  //Release exclusive access to the AES module
655  }
656  else
657  {
658  //The value of the parameter is not valid
659  error = ERROR_INVALID_PARAMETER;
660  }
661  }
662  else
663  {
664  //Check the value of the parameter
665  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
666  {
667  size_t i;
668  size_t n;
669  uint8_t o[16];
670 
671  //Determine the size, in bytes, of the plaintext and ciphertext segments
672  s = s / 8;
673 
674  //Process each plaintext segment
675  while(length > 0)
676  {
677  //Compute the number of bytes to process at a time
678  n = MIN(length, s);
679 
680  //Compute O(j) = CIPH(I(j))
681  cipher->encryptBlock(context, iv, o);
682 
683  //Compute C(j) = P(j) XOR MSB(O(j))
684  for(i = 0; i < n; i++)
685  {
686  c[i] = p[i] ^ o[i];
687  }
688 
689  //Compute I(j+1) = LSB(I(j)) | C(j)
690  osMemmove(iv, iv + s, cipher->blockSize - s);
691  osMemcpy(iv + cipher->blockSize - s, c, s);
692 
693  //Next block
694  p += n;
695  c += n;
696  length -= n;
697  }
698  }
699  else
700  {
701  //The value of the parameter is not valid
702  error = ERROR_INVALID_PARAMETER;
703  }
704  }
705 
706  //Return status code
707  return error;
708 }
709 
710 
711 /**
712  * @brief CFB decryption
713  * @param[in] cipher Cipher algorithm
714  * @param[in] context Cipher algorithm context
715  * @param[in] s Size of the plaintext and ciphertext segments
716  * @param[in,out] iv Initialization vector
717  * @param[in] c Ciphertext to be decrypted
718  * @param[out] p Plaintext resulting from the decryption
719  * @param[in] length Total number of data bytes to be decrypted
720  * @return Error code
721  **/
722 
723 error_t cfbDecrypt(const CipherAlgo *cipher, void *context, uint_t s,
724  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
725 {
726  error_t error;
727 
728  //Initialize status code
729  error = NO_ERROR;
730 
731  //AES cipher algorithm?
732  if(cipher == AES_CIPHER_ALGO)
733  {
734  //Check the value of the parameter
735  if((s % 8) == 0 && s >= 1 && s <= (AES_BLOCK_SIZE * 8))
736  {
737  size_t i;
738  size_t n;
739  uint8_t o[16];
740 
741  //Determine the size, in bytes, of the plaintext and ciphertext segments
742  s = s / 8;
743 
744  //Acquire exclusive access to the AES module
746 
747  //Load AES key
748  aesLoadKey(context, AES_MODE_ENC);
749 
750  //Process each ciphertext segment
751  while(length > 0)
752  {
753  //Compute the number of bytes to process at a time
754  n = MIN(length, s);
755 
756  //Compute O(j) = CIPH(I(j))
758 
759  //Compute I(j+1) = LSB(I(j)) | C(j)
760  osMemmove(iv, iv + s, AES_BLOCK_SIZE - s);
761  osMemcpy(iv + AES_BLOCK_SIZE - s, c, s);
762 
763  //Compute P(j) = C(j) XOR MSB(O(j))
764  for(i = 0; i < n; i++)
765  {
766  p[i] = c[i] ^ o[i];
767  }
768 
769  //Next block
770  c += n;
771  p += n;
772  length -= n;
773  }
774 
775  //Release exclusive access to the AES module
777  }
778  else
779  {
780  //The value of the parameter is not valid
781  error = ERROR_INVALID_PARAMETER;
782  }
783  }
784  else
785  {
786  //Check the value of the parameter
787  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
788  {
789  size_t i;
790  size_t n;
791  uint8_t o[16];
792 
793  //Determine the size, in bytes, of the plaintext and ciphertext segments
794  s = s / 8;
795 
796  //Process each ciphertext segment
797  while(length > 0)
798  {
799  //Compute the number of bytes to process at a time
800  n = MIN(length, s);
801 
802  //Compute O(j) = CIPH(I(j))
803  cipher->encryptBlock(context, iv, o);
804 
805  //Compute I(j+1) = LSB(I(j)) | C(j)
806  osMemmove(iv, iv + s, cipher->blockSize - s);
807  osMemcpy(iv + cipher->blockSize - s, c, s);
808 
809  //Compute P(j) = C(j) XOR MSB(O(j))
810  for(i = 0; i < n; i++)
811  {
812  p[i] = c[i] ^ o[i];
813  }
814 
815  //Next block
816  c += n;
817  p += n;
818  length -= n;
819  }
820  }
821  else
822  {
823  //The value of the parameter is not valid
824  error = ERROR_INVALID_PARAMETER;
825  }
826  }
827 
828  //Return status code
829  return error;
830 }
831 
832 #endif
833 #if (OFB_SUPPORT == ENABLED)
834 
835 /**
836  * @brief OFB encryption
837  * @param[in] cipher Cipher algorithm
838  * @param[in] context Cipher algorithm context
839  * @param[in] s Size of the plaintext and ciphertext segments
840  * @param[in,out] iv Initialization vector
841  * @param[in] p Plaintext to be encrypted
842  * @param[out] c Ciphertext resulting from the encryption
843  * @param[in] length Total number of data bytes to be encrypted
844  * @return Error code
845  **/
846 
847 error_t ofbEncrypt(const CipherAlgo *cipher, void *context, uint_t s,
848  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
849 {
850  error_t error;
851 
852  //Initialize status code
853  error = NO_ERROR;
854 
855  //AES cipher algorithm?
856  if(cipher == AES_CIPHER_ALGO)
857  {
858  //Check the value of the parameter
859  if((s % 8) == 0 && s >= 1 && s <= (AES_BLOCK_SIZE * 8))
860  {
861  size_t i;
862  size_t n;
863  uint8_t o[16];
864 
865  //Determine the size, in bytes, of the plaintext and ciphertext segments
866  s = s / 8;
867 
868  //Acquire exclusive access to the AES module
870 
871  //Load AES key
872  aesLoadKey(context, AES_MODE_ENC);
873 
874  //Process each plaintext segment
875  while(length > 0)
876  {
877  //Compute the number of bytes to process at a time
878  n = MIN(length, s);
879 
880  //Compute O(j) = CIPH(I(j))
882 
883  //Compute C(j) = P(j) XOR MSB(O(j))
884  for(i = 0; i < n; i++)
885  {
886  c[i] = p[i] ^ o[i];
887  }
888 
889  //Compute I(j+1) = LSB(I(j)) | O(j)
890  osMemmove(iv, iv + s, AES_BLOCK_SIZE - s);
891  osMemcpy(iv + AES_BLOCK_SIZE - s, o, s);
892 
893  //Next block
894  p += n;
895  c += n;
896  length -= n;
897  }
898 
899  //Release exclusive access to the AES module
901  }
902  else
903  {
904  //The value of the parameter is not valid
905  error = ERROR_INVALID_PARAMETER;
906  }
907  }
908  else
909  {
910  //Check the value of the parameter
911  if((s % 8) == 0 && s >= 1 && s <= (cipher->blockSize * 8))
912  {
913  size_t i;
914  size_t n;
915  uint8_t o[16];
916 
917  //Determine the size, in bytes, of the plaintext and ciphertext segments
918  s = s / 8;
919 
920  //Process each plaintext segment
921  while(length > 0)
922  {
923  //Compute the number of bytes to process at a time
924  n = MIN(length, s);
925 
926  //Compute O(j) = CIPH(I(j))
927  cipher->encryptBlock(context, iv, o);
928 
929  //Compute C(j) = P(j) XOR MSB(O(j))
930  for(i = 0; i < n; i++)
931  {
932  c[i] = p[i] ^ o[i];
933  }
934 
935  //Compute I(j+1) = LSB(I(j)) | O(j)
936  osMemmove(iv, iv + s, cipher->blockSize - s);
937  osMemcpy(iv + cipher->blockSize - s, o, s);
938 
939  //Next block
940  p += n;
941  c += n;
942  length -= n;
943  }
944  }
945  else
946  {
947  //The value of the parameter is not valid
948  error = ERROR_INVALID_PARAMETER;
949  }
950  }
951 
952  //Return status code
953  return error;
954 }
955 
956 #endif
957 #if (CTR_SUPPORT == ENABLED)
958 
959 /**
960  * @brief CTR encryption
961  * @param[in] cipher Cipher algorithm
962  * @param[in] context Cipher algorithm context
963  * @param[in] m Size in bits of the specific part of the block to be incremented
964  * @param[in,out] t Initial counter block
965  * @param[in] p Plaintext to be encrypted
966  * @param[out] c Ciphertext resulting from the encryption
967  * @param[in] length Total number of data bytes to be encrypted
968  * @return Error code
969  **/
970 
971 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
972  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
973 {
974  error_t error;
975 
976  //Initialize status code
977  error = NO_ERROR;
978 
979  //AES cipher algorithm?
980  if(cipher == AES_CIPHER_ALGO)
981  {
982  //Check the value of the parameter
983  if((m % 8) == 0 && m <= (AES_BLOCK_SIZE * 8))
984  {
985  size_t i;
986  size_t n;
987  uint16_t temp;
988  uint8_t o[16];
989 
990  //Determine the size, in bytes, of the specific part of the block
991  //to be incremented
992  m = m / 8;
993 
994  //Acquire exclusive access to the AES module
996 
997  //Load AES key
998  aesLoadKey(context, AES_MODE_ENC);
999 
1000  //Process plaintext
1001  while(length > 0)
1002  {
1003  //CTR mode operates in a block-by-block fashion
1004  n = MIN(length, AES_BLOCK_SIZE);
1005 
1006  //Compute O(j) = CIPH(T(j))
1008 
1009  //Compute C(j) = P(j) XOR T(j)
1010  for(i = 0; i < n; i++)
1011  {
1012  c[i] = p[i] ^ o[i];
1013  }
1014 
1015  //Standard incrementing function
1016  for(temp = 1, i = 1; i <= m; i++)
1017  {
1018  //Increment the current byte and propagate the carry
1019  temp += t[AES_BLOCK_SIZE - i];
1020  t[AES_BLOCK_SIZE - i] = temp & 0xFF;
1021  temp >>= 8;
1022  }
1023 
1024  //Next block
1025  p += n;
1026  c += n;
1027  length -= n;
1028  }
1029 
1030  //Release exclusive access to the AES module
1032  }
1033  else
1034  {
1035  //The value of the parameter is not valid
1036  error = ERROR_INVALID_PARAMETER;
1037  }
1038  }
1039  else
1040  {
1041  //Check the value of the parameter
1042  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
1043  {
1044  size_t i;
1045  size_t n;
1046  uint16_t temp;
1047  uint8_t o[16];
1048 
1049  //Determine the size, in bytes, of the specific part of the block
1050  //to be incremented
1051  m = m / 8;
1052 
1053  //Process plaintext
1054  while(length > 0)
1055  {
1056  //CTR mode operates in a block-by-block fashion
1057  n = MIN(length, cipher->blockSize);
1058 
1059  //Compute O(j) = CIPH(T(j))
1060  cipher->encryptBlock(context, t, o);
1061 
1062  //Compute C(j) = P(j) XOR T(j)
1063  for(i = 0; i < n; i++)
1064  {
1065  c[i] = p[i] ^ o[i];
1066  }
1067 
1068  //Standard incrementing function
1069  for(temp = 1, i = 1; i <= m; i++)
1070  {
1071  //Increment the current byte and propagate the carry
1072  temp += t[cipher->blockSize - i];
1073  t[cipher->blockSize - i] = temp & 0xFF;
1074  temp >>= 8;
1075  }
1076 
1077  //Next block
1078  p += n;
1079  c += n;
1080  length -= n;
1081  }
1082  }
1083  else
1084  {
1085  //The value of the parameter is not valid
1086  error = ERROR_INVALID_PARAMETER;
1087  }
1088  }
1089 
1090  //Return status code
1091  return error;
1092 }
1093 
1094 #endif
1095 #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
General definitions for cryptographic algorithms.
Debugging facilities.
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_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
OsMutex esp32CryptoMutex
Definition: esp32_crypto.c:45
ESP32 hardware cryptographic accelerator.
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
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_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
error_t cfbDecrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CFB decryption.
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
void esp32AesInit(void)
AES module initialization.
void aesLoadKey(AesContext *context, uint32_t mode)
Load AES key.
error_t cfbEncrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CFB encryption.
void aesProcessDataBlock(const uint8_t *input, uint8_t *output)
Encrypt/decrypt a 16-byte block using AES algorithm.
error_t ofbEncrypt(const CipherAlgo *cipher, void *context, uint_t s, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
OFB encryption.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
ESP32 cipher hardware accelerator.
#define AES_ENDIAN_DEFAULT
#define AES_MODE_256_BITS
#define AES_MODE_192_BITS
#define AES_MODE_DEC
#define AES_MODE_ENC
#define AES_MODE_128_BITS
uint8_t iv[]
Definition: ike.h:1502
uint8_t t
Definition: lldp_ext_med.h:212
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
#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
uint8_t length
Definition: tcp.h:368