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