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