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