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