mimxrt1160_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file mimxrt1160_crypto_cipher.c
3  * @brief i.MX RT1160 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 "fsl_device_registers.h"
36 #include "fsl_caam.h"
37 #include "core/crypto.h"
42 #include "aead/aead_algorithms.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (MIMXRT1160_CRYPTO_CIPHER_SUPPORT == ENABLED)
47 
48 //IAR EWARM compiler?
49 #if defined(__ICCARM__)
50 
51 //CAAM input buffer
52 #pragma data_alignment = 16
53 uint8_t caamBufferIn[MIMXRT1160_CAAM_BUFFER_SIZE];
54 
55 //CAAM output buffer
56 #pragma data_alignment = 16
57 uint8_t caamBufferOut[MIMXRT1160_CAAM_BUFFER_SIZE];
58 
59 //CAAM initialization vector
60 #pragma data_alignment = 16
61 uint8_t caamInitVector[16];
62 
63 //ARM or GCC compiler?
64 #else
65 
66 //CAAM input buffer
67 uint8_t caamBufferIn[MIMXRT1160_CAAM_BUFFER_SIZE]
68  __attribute__((aligned(16)));
69 
70 //CAAM output buffer
71 uint8_t caamBufferOut[MIMXRT1160_CAAM_BUFFER_SIZE]
72  __attribute__((aligned(16)));
73 
74 //CAAM initialization vector
75 uint8_t caamInitVector[16]
76  __attribute__((aligned(16)));
77 
78 #endif
79 
80 #if (DES_SUPPORT == ENABLED)
81 
82 /**
83  * @brief Initialize a DES context using the supplied key
84  * @param[in] context Pointer to the DES context to initialize
85  * @param[in] key Pointer to the key
86  * @param[in] keyLen Length of the key (must be set to 8)
87  * @return Error code
88  **/
89 
90 error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
91 {
92  //Check parameters
93  if(context == NULL || key == NULL)
95 
96  //Invalid key length?
97  if(keyLen != 8)
99 
100  //Copy the 64-bit key
101  context->ks[0] = LOAD32LE(key);
102  context->ks[1] = LOAD32LE(key + 4);
103 
104  //No error to report
105  return NO_ERROR;
106 }
107 
108 #endif
109 #if (ECB_SUPPORT == ENABLED)
110 
111 /**
112  * @brief ECB encryption
113  * @param[in] cipher Cipher algorithm
114  * @param[in] context Cipher algorithm context
115  * @param[in] p Plaintext to be encrypted
116  * @param[out] c Ciphertext resulting from the encryption
117  * @param[in] length Total number of data bytes to be encrypted
118  * @return Error code
119  **/
120 
121 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
122  const uint8_t *p, uint8_t *c, size_t length)
123 {
124  status_t status;
125 
126  //Initialize status code
127  status = kStatus_Success;
128 
129 #if (DES_SUPPORT == ENABLED)
130  //DES cipher algorithm?
131  if(cipher == DES_CIPHER_ALGO)
132  {
133  //Check the length of the payload
134  if(length == 0)
135  {
136  //No data to process
137  }
138  else if((length % DES_BLOCK_SIZE) == 0)
139  {
140  size_t i;
141  size_t n;
142  DesContext *desContext;
143  caam_handle_t caamHandle;
144 
145  //Point to the DES context
146  desContext = (DesContext *) context;
147 
148  //Set CAAM job ring
149  caamHandle.jobRing = kCAAM_JobRing0;
150 
151  //Acquire exclusive access to the CAAM module
153 
154  //Perform DES-ECB encryption
155  for(i = 0; i < length && status == kStatus_Success; i += n)
156  {
157  //Limit the number of data to process at a time
159  //Copy the plaintext to the buffer
160  osMemcpy(caamBufferIn, p + i, n);
161 
162  //Encrypt data
163  status = CAAM_DES_EncryptEcb(CAAM, &caamHandle, caamBufferIn,
164  caamBufferOut, n, (const uint8_t *) desContext->ks);
165 
166  //Check status code
167  if(status == kStatus_Success)
168  {
169  //Copy the resulting ciphertext
170  osMemcpy(c + i, caamBufferOut, n);
171  }
172  }
173 
174  //Release exclusive access to the CAAM module
176  }
177  else
178  {
179  //The length of the payload must be a multiple of the block size
180  status = kStatus_InvalidArgument;
181  }
182  }
183  else
184 #endif
185 #if (DES3_SUPPORT == ENABLED)
186  //Triple DES cipher algorithm?
187  if(cipher == DES3_CIPHER_ALGO)
188  {
189  //Check the length of the payload
190  if(length == 0)
191  {
192  //No data to process
193  }
194  else if((length % DES3_BLOCK_SIZE) == 0)
195  {
196  size_t i;
197  size_t n;
198  Des3Context *des3Context;
199  caam_handle_t caamHandle;
200 
201  //Point to the Triple DES context
202  des3Context = (Des3Context *) context;
203 
204  //Set CAAM job ring
205  caamHandle.jobRing = kCAAM_JobRing0;
206 
207  //Acquire exclusive access to the CAAM module
209 
210  //Perform 3DES-CBC encryption
211  for(i = 0; i < length && status == kStatus_Success; i += n)
212  {
213  //Limit the number of data to process at a time
215  //Copy the plaintext to the buffer
216  osMemcpy(caamBufferIn, p + i, n);
217 
218  //Encrypt data
219  status = CAAM_DES3_EncryptEcb(CAAM, &caamHandle, caamBufferIn,
220  caamBufferOut, n, (const uint8_t *) des3Context->k1.ks,
221  (const uint8_t *) des3Context->k2.ks,
222  (const uint8_t *) des3Context->k3.ks);
223 
224  //Check status code
225  if(status == kStatus_Success)
226  {
227  //Copy the resulting ciphertext
228  osMemcpy(c + i, caamBufferOut, n);
229  }
230  }
231 
232  //Release exclusive access to the CAAM module
234  }
235  else
236  {
237  //The length of the payload must be a multiple of the block size
238  status = kStatus_InvalidArgument;
239  }
240  }
241  else
242 #endif
243 #if (AES_SUPPORT == ENABLED)
244  //AES cipher algorithm?
245  if(cipher == AES_CIPHER_ALGO)
246  {
247  //Check the length of the payload
248  if(length == 0)
249  {
250  //No data to process
251  }
252  else if((length % AES_BLOCK_SIZE) == 0)
253  {
254  size_t i;
255  size_t n;
256  size_t keySize;
257  AesContext *aesContext;
258  caam_handle_t caamHandle;
259 
260  //Point to the AES context
261  aesContext = (AesContext *) context;
262 
263  //Retrieve the length of the key
264  if(aesContext->nr == 10)
265  {
266  //10 rounds are required for 128-bit key
267  keySize = 16;
268  }
269  else if(aesContext->nr == 12)
270  {
271  //12 rounds are required for 192-bit key
272  keySize = 24;
273  }
274  else if(aesContext->nr == 14)
275  {
276  //14 rounds are required for 256-bit key
277  keySize = 32;
278  }
279  else
280  {
281  //Invalid key length
282  status = kStatus_Fail;
283  }
284 
285  //Check status code
286  if(status == kStatus_Success)
287  {
288  //Set CAAM job ring
289  caamHandle.jobRing = kCAAM_JobRing0;
290 
291  //Acquire exclusive access to the CAAM module
293 
294  //Perform AES-ECB encryption
295  for(i = 0; i < length && status == kStatus_Success; i += n)
296  {
297  //Limit the number of data to process at a time
299  //Copy the plaintext to the buffer
300  osMemcpy(caamBufferIn, p + i, n);
301 
302  //Encrypt data
303  status = CAAM_AES_EncryptEcb(CAAM, &caamHandle, caamBufferIn,
304  caamBufferOut, n, (const uint8_t *) aesContext->ek, keySize);
305 
306  //Check status code
307  if(status == kStatus_Success)
308  {
309  //Copy the resulting ciphertext
310  osMemcpy(c + i, caamBufferOut, n);
311  }
312  }
313 
314  //Release exclusive access to the CAAM module
316  }
317  }
318  else
319  {
320  //The length of the payload must be a multiple of the block size
321  status = kStatus_InvalidArgument;
322  }
323  }
324  else
325 #endif
326  //Unknown cipher algorithm?
327  {
328  //ECB mode operates in a block-by-block fashion
329  while(length >= cipher->blockSize)
330  {
331  //Encrypt current block
332  cipher->encryptBlock(context, p, c);
333 
334  //Next block
335  p += cipher->blockSize;
336  c += cipher->blockSize;
337  length -= cipher->blockSize;
338  }
339 
340  //The length of the payload must be a multiple of the block size
341  if(length != 0)
342  {
343  status = kStatus_InvalidArgument;
344  }
345  }
346 
347  //Return status code
348  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
349 }
350 
351 
352 /**
353  * @brief ECB decryption
354  * @param[in] cipher Cipher algorithm
355  * @param[in] context Cipher algorithm context
356  * @param[in] c Ciphertext to be decrypted
357  * @param[out] p Plaintext resulting from the decryption
358  * @param[in] length Total number of data bytes to be decrypted
359  * @return Error code
360  **/
361 
362 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
363  const uint8_t *c, uint8_t *p, size_t length)
364 {
365  status_t status;
366 
367  //Initialize status code
368  status = kStatus_Success;
369 
370 #if (DES_SUPPORT == ENABLED)
371  //DES cipher algorithm?
372  if(cipher == DES_CIPHER_ALGO)
373  {
374  //Check the length of the payload
375  if(length == 0)
376  {
377  //No data to process
378  }
379  else if((length % DES_BLOCK_SIZE) == 0)
380  {
381  size_t i;
382  size_t n;
383  DesContext *desContext;
384  caam_handle_t caamHandle;
385 
386  //Point to the DES context
387  desContext = (DesContext *) context;
388 
389  //Set CAAM job ring
390  caamHandle.jobRing = kCAAM_JobRing0;
391 
392  //Acquire exclusive access to the CAAM module
394 
395  //Perform DES-ECB decryption
396  for(i = 0; i < length && status == kStatus_Success; i += n)
397  {
398  //Limit the number of data to process at a time
400  //Copy the ciphertext to the buffer
401  osMemcpy(caamBufferIn, c + i, n);
402 
403  //Decrypt data
404  status = CAAM_DES_DecryptEcb(CAAM, &caamHandle, caamBufferIn,
405  caamBufferOut, n, (const uint8_t *) desContext->ks);
406 
407  //Check status code
408  if(status == kStatus_Success)
409  {
410  //Copy the resulting plaintext
411  osMemcpy(p + i, caamBufferOut, n);
412  }
413  }
414 
415  //Release exclusive access to the CAAM module
417  }
418  else
419  {
420  //The length of the payload must be a multiple of the block size
421  status = kStatus_InvalidArgument;
422  }
423  }
424  else
425 #endif
426 #if (DES3_SUPPORT == ENABLED)
427  //Triple DES cipher algorithm?
428  if(cipher == DES3_CIPHER_ALGO)
429  {
430  //Check the length of the payload
431  if(length == 0)
432  {
433  //No data to process
434  }
435  else if((length % DES3_BLOCK_SIZE) == 0)
436  {
437  size_t i;
438  size_t n;
439  Des3Context *des3Context;
440  caam_handle_t caamHandle;
441 
442  //Point to the Triple DES context
443  des3Context = (Des3Context *) context;
444 
445  //Set CAAM job ring
446  caamHandle.jobRing = kCAAM_JobRing0;
447 
448  //Acquire exclusive access to the CAAM module
450 
451  //Perform 3DES-ECB decryption
452  for(i = 0; i < length && status == kStatus_Success; i += n)
453  {
454  //Limit the number of data to process at a time
456  //Copy the ciphertext to the buffer
457  osMemcpy(caamBufferIn, c + i, n);
458 
459  //Decrypt data
460  status = CAAM_DES3_DecryptEcb(CAAM, &caamHandle, caamBufferIn,
461  caamBufferOut, n, (const uint8_t *) des3Context->k1.ks,
462  (const uint8_t *) des3Context->k2.ks,
463  (const uint8_t *) des3Context->k3.ks);
464 
465  //Check status code
466  if(status == kStatus_Success)
467  {
468  //Copy the resulting plaintext
469  osMemcpy(p + i, caamBufferOut, n);
470  }
471  }
472 
473  //Release exclusive access to the CAAM module
475  }
476  else
477  {
478  //The length of the payload must be a multiple of the block size
479  status = kStatus_InvalidArgument;
480  }
481  }
482  else
483 #endif
484 #if (AES_SUPPORT == ENABLED)
485  //AES cipher algorithm?
486  if(cipher == AES_CIPHER_ALGO)
487  {
488  //Check the length of the payload
489  if(length == 0)
490  {
491  //No data to process
492  }
493  else if((length % AES_BLOCK_SIZE) == 0)
494  {
495  size_t i;
496  size_t n;
497  size_t keySize;
498  AesContext *aesContext;
499  caam_handle_t caamHandle;
500 
501  //Point to the AES context
502  aesContext = (AesContext *) context;
503 
504  //Retrieve the length of the key
505  if(aesContext->nr == 10)
506  {
507  //10 rounds are required for 128-bit key
508  keySize = 16;
509  }
510  else if(aesContext->nr == 12)
511  {
512  //12 rounds are required for 192-bit key
513  keySize = 24;
514  }
515  else if(aesContext->nr == 14)
516  {
517  //14 rounds are required for 256-bit key
518  keySize = 32;
519  }
520  else
521  {
522  //Invalid key length
523  status = kStatus_Fail;
524  }
525 
526  //Check status code
527  if(status == kStatus_Success)
528  {
529  //Set CAAM job ring
530  caamHandle.jobRing = kCAAM_JobRing0;
531 
532  //Acquire exclusive access to the CAAM module
534 
535  //Perform AES-ECB decryption
536  for(i = 0; i < length && status == kStatus_Success; i += n)
537  {
538  //Limit the number of data to process at a time
540  //Copy the ciphertext to the buffer
541  osMemcpy(caamBufferIn, c + i, n);
542 
543  //Decrypt data
544  status = CAAM_AES_DecryptEcb(CAAM, &caamHandle, caamBufferIn,
545  caamBufferOut, n, (const uint8_t *) aesContext->ek, keySize);
546 
547  //Check status code
548  if(status == kStatus_Success)
549  {
550  //Copy the resulting plaintext
551  osMemcpy(p + i, caamBufferOut, n);
552  }
553  }
554  }
555 
556  //Release exclusive access to the CAAM module
558  }
559  else
560  {
561  //The length of the payload must be a multiple of the block size
562  status = kStatus_InvalidArgument;
563  }
564  }
565  else
566 #endif
567  //Unknown cipher algorithm?
568  {
569  //ECB mode operates in a block-by-block fashion
570  while(length >= cipher->blockSize)
571  {
572  //Decrypt current block
573  cipher->decryptBlock(context, c, p);
574 
575  //Next block
576  c += cipher->blockSize;
577  p += cipher->blockSize;
578  length -= cipher->blockSize;
579  }
580 
581  //The length of the payload must be a multiple of the block size
582  if(length != 0)
583  {
584  status = kStatus_InvalidArgument;
585  }
586  }
587 
588  //Return status code
589  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
590 }
591 
592 #endif
593 #if (CBC_SUPPORT == ENABLED)
594 
595 /**
596  * @brief CBC encryption
597  * @param[in] cipher Cipher algorithm
598  * @param[in] context Cipher algorithm context
599  * @param[in,out] iv Initialization vector
600  * @param[in] p Plaintext to be encrypted
601  * @param[out] c Ciphertext resulting from the encryption
602  * @param[in] length Total number of data bytes to be encrypted
603  * @return Error code
604  **/
605 
606 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
607  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
608 {
609  status_t status;
610 
611  //Initialize status code
612  status = kStatus_Success;
613 
614 #if (DES_SUPPORT == ENABLED)
615  //DES cipher algorithm?
616  if(cipher == DES_CIPHER_ALGO)
617  {
618  //Check the length of the payload
619  if(length == 0)
620  {
621  //No data to process
622  }
623  else if((length % DES_BLOCK_SIZE) == 0)
624  {
625  size_t i;
626  size_t n;
627  DesContext *desContext;
628  caam_handle_t caamHandle;
629 
630  //Point to the DES context
631  desContext = (DesContext *) context;
632 
633  //Set CAAM job ring
634  caamHandle.jobRing = kCAAM_JobRing0;
635 
636  //Acquire exclusive access to the CAAM module
638 
639  //Perform DES-CBC encryption
640  for(i = 0; i < length && status == kStatus_Success; i += n)
641  {
642  //Limit the number of data to process at a time
644  //Copy the plaintext to the buffer
645  osMemcpy(caamBufferIn, p + i, n);
646 
647  //Encrypt data
648  status = CAAM_DES_EncryptCbc(CAAM, &caamHandle, caamBufferIn,
649  caamBufferOut, n, iv, (const uint8_t *) desContext->ks);
650 
651  //Check status code
652  if(status == kStatus_Success)
653  {
654  //Copy the resulting ciphertext
655  osMemcpy(c + i, caamBufferOut, n);
656  //Update the value of the initialization vector
657  osMemcpy(iv, caamBufferOut + n - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
658  }
659  }
660 
661  //Release exclusive access to the CAAM module
663  }
664  else
665  {
666  //The length of the payload must be a multiple of the block size
667  status = kStatus_InvalidArgument;
668  }
669  }
670  else
671 #endif
672 #if (DES3_SUPPORT == ENABLED)
673  //Triple DES cipher algorithm?
674  if(cipher == DES3_CIPHER_ALGO)
675  {
676  //Check the length of the payload
677  if(length == 0)
678  {
679  //No data to process
680  }
681  else if((length % DES3_BLOCK_SIZE) == 0)
682  {
683  size_t i;
684  size_t n;
685  Des3Context *des3Context;
686  caam_handle_t caamHandle;
687 
688  //Point to the Triple DES context
689  des3Context = (Des3Context *) context;
690 
691  //Set CAAM job ring
692  caamHandle.jobRing = kCAAM_JobRing0;
693 
694  //Acquire exclusive access to the CAAM module
696 
697  //Perform 3DES-CBC encryption
698  for(i = 0; i < length && status == kStatus_Success; i += n)
699  {
700  //Limit the number of data to process at a time
702  //Copy the plaintext to the buffer
703  osMemcpy(caamBufferIn, p + i, n);
704 
705  //Encrypt data
706  status = CAAM_DES3_EncryptCbc(CAAM, &caamHandle, caamBufferIn,
707  caamBufferOut, n, iv, (const uint8_t *) des3Context->k1.ks,
708  (const uint8_t *) des3Context->k2.ks,
709  (const uint8_t *) des3Context->k3.ks);
710 
711  //Check status code
712  if(status == kStatus_Success)
713  {
714  //Copy the resulting ciphertext
715  osMemcpy(c + i, caamBufferOut, n);
716  //Update the value of the initialization vector
717  osMemcpy(iv, caamBufferOut + n - DES3_BLOCK_SIZE, DES3_BLOCK_SIZE);
718  }
719  }
720 
721  //Release exclusive access to the CAAM module
723  }
724  else
725  {
726  //The length of the payload must be a multiple of the block size
727  status = kStatus_InvalidArgument;
728  }
729  }
730  else
731 #endif
732 #if (AES_SUPPORT == ENABLED)
733  //AES cipher algorithm?
734  if(cipher == AES_CIPHER_ALGO)
735  {
736  //Check the length of the payload
737  if(length == 0)
738  {
739  //No data to process
740  }
741  else if((length % AES_BLOCK_SIZE) == 0)
742  {
743  size_t i;
744  size_t n;
745  size_t keySize;
746  AesContext *aesContext;
747  caam_handle_t caamHandle;
748 
749  //Point to the AES context
750  aesContext = (AesContext *) context;
751 
752  //Retrieve the length of the key
753  if(aesContext->nr == 10)
754  {
755  //10 rounds are required for 128-bit key
756  keySize = 16;
757  }
758  else if(aesContext->nr == 12)
759  {
760  //12 rounds are required for 192-bit key
761  keySize = 24;
762  }
763  else if(aesContext->nr == 14)
764  {
765  //14 rounds are required for 256-bit key
766  keySize = 32;
767  }
768  else
769  {
770  //Invalid key length
771  status = kStatus_Fail;
772  }
773 
774  //Check status code
775  if(status == kStatus_Success)
776  {
777  //Set CAAM job ring
778  caamHandle.jobRing = kCAAM_JobRing0;
779 
780  //Acquire exclusive access to the CAAM module
782 
783  //Perform AES-CBC encryption
784  for(i = 0; i < length && status == kStatus_Success; i += n)
785  {
786  //Limit the number of data to process at a time
788  //Copy the plaintext to the buffer
789  osMemcpy(caamBufferIn, p + i, n);
790 
791  //Encrypt data
792  status = CAAM_AES_EncryptCbc(CAAM, &caamHandle, caamBufferIn,
793  caamBufferOut, n, iv, (const uint8_t *) aesContext->ek, keySize);
794 
795  //Check status code
796  if(status == kStatus_Success)
797  {
798  //Copy the resulting ciphertext
799  osMemcpy(c + i, caamBufferOut, n);
800  //Update the value of the initialization vector
801  osMemcpy(iv, caamBufferOut + n - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
802  }
803  }
804  }
805 
806  //Release exclusive access to the CAAM module
808  }
809  else
810  {
811  //The length of the payload must be a multiple of the block size
812  status = kStatus_InvalidArgument;
813  }
814  }
815  else
816 #endif
817  //Unknown cipher algorithm?
818  {
819  size_t i;
820 
821  //CBC mode operates in a block-by-block fashion
822  while(length >= cipher->blockSize)
823  {
824  //XOR input block with IV contents
825  for(i = 0; i < cipher->blockSize; i++)
826  {
827  c[i] = p[i] ^ iv[i];
828  }
829 
830  //Encrypt the current block based upon the output of the previous
831  //encryption
832  cipher->encryptBlock(context, c, c);
833 
834  //Update IV with output block contents
835  osMemcpy(iv, c, cipher->blockSize);
836 
837  //Next block
838  p += cipher->blockSize;
839  c += cipher->blockSize;
840  length -= cipher->blockSize;
841  }
842 
843  //The length of the payload must be a multiple of the block size
844  if(length != 0)
845  {
846  status = kStatus_InvalidArgument;
847  }
848  }
849 
850  //Return status code
851  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
852 }
853 
854 
855 /**
856  * @brief CBC decryption
857  * @param[in] cipher Cipher algorithm
858  * @param[in] context Cipher algorithm context
859  * @param[in,out] iv Initialization vector
860  * @param[in] c Ciphertext to be decrypted
861  * @param[out] p Plaintext resulting from the decryption
862  * @param[in] length Total number of data bytes to be decrypted
863  * @return Error code
864  **/
865 
866 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
867  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
868 {
869  status_t status;
870 
871  //Initialize status code
872  status = kStatus_Success;
873 
874 #if (DES_SUPPORT == ENABLED)
875  //DES cipher algorithm?
876  if(cipher == DES_CIPHER_ALGO)
877  {
878  //Check the length of the payload
879  if(length == 0)
880  {
881  //No data to process
882  }
883  else if((length % DES_BLOCK_SIZE) == 0)
884  {
885  size_t i;
886  size_t n;
887  DesContext *desContext;
888  caam_handle_t caamHandle;
889  uint8_t block[DES_BLOCK_SIZE];
890 
891  //Point to the DES context
892  desContext = (DesContext *) context;
893 
894  //Set CAAM job ring
895  caamHandle.jobRing = kCAAM_JobRing0;
896 
897  //Acquire exclusive access to the CAAM module
899 
900  //Perform 3DES-CBC decryption
901  for(i = 0; i < length && status == kStatus_Success; i += n)
902  {
903  //Limit the number of data to process at a time
905  //Copy the ciphertext to the buffer
906  osMemcpy(caamBufferIn, c + i, n);
907  //Save the last input block
908  osMemcpy(block, caamBufferIn + n - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
909 
910  //Decrypt data
911  status = CAAM_DES_DecryptCbc(CAAM, &caamHandle, caamBufferIn,
912  caamBufferOut, n, iv, (const uint8_t *) desContext->ks);
913 
914  //Check status code
915  if(status == kStatus_Success)
916  {
917  //Copy the resulting plaintext
918  osMemcpy(p + i, caamBufferOut, n);
919  //Update the value of the initialization vector
921  }
922  }
923 
924  //Release exclusive access to the CAAM module
926  }
927  else
928  {
929  //The length of the payload must be a multiple of the block size
930  status = kStatus_InvalidArgument;
931  }
932  }
933  else
934 #endif
935 #if (DES3_SUPPORT == ENABLED)
936  //Triple DES cipher algorithm?
937  if(cipher == DES3_CIPHER_ALGO)
938  {
939  //Check the length of the payload
940  if(length == 0)
941  {
942  //No data to process
943  }
944  else if((length % DES3_BLOCK_SIZE) == 0)
945  {
946  size_t i;
947  size_t n;
948  Des3Context *des3Context;
949  caam_handle_t caamHandle;
950  uint8_t block[DES3_BLOCK_SIZE];
951 
952  //Point to the Triple DES context
953  des3Context = (Des3Context *) context;
954 
955  //Set CAAM job ring
956  caamHandle.jobRing = kCAAM_JobRing0;
957 
958  //Acquire exclusive access to the CAAM module
960 
961  //Perform 3DES-CBC decryption
962  for(i = 0; i < length && status == kStatus_Success; i += n)
963  {
964  //Limit the number of data to process at a time
966  //Copy the ciphertext to the buffer
967  osMemcpy(caamBufferIn, c + i, n);
968  //Save the last input block
969  osMemcpy(block, caamBufferIn + n - DES3_BLOCK_SIZE, DES3_BLOCK_SIZE);
970 
971  //Decrypt data
972  status = CAAM_DES3_DecryptCbc(CAAM, &caamHandle, caamBufferIn,
973  caamBufferOut, n, iv, (const uint8_t *) des3Context->k1.ks,
974  (const uint8_t *) des3Context->k2.ks,
975  (const uint8_t *) des3Context->k3.ks);
976 
977  //Check status code
978  if(status == kStatus_Success)
979  {
980  //Copy the resulting plaintext
981  osMemcpy(p + i, caamBufferOut, n);
982  //Update the value of the initialization vector
984  }
985  }
986 
987  //Release exclusive access to the CAAM module
989  }
990  else
991  {
992  //The length of the payload must be a multiple of the block size
993  status = kStatus_InvalidArgument;
994  }
995  }
996  else
997 #endif
998 #if (AES_SUPPORT == ENABLED)
999  //AES cipher algorithm?
1000  if(cipher == AES_CIPHER_ALGO)
1001  {
1002  //Check the length of the payload
1003  if(length == 0)
1004  {
1005  //No data to process
1006  }
1007  else if((length % AES_BLOCK_SIZE) == 0)
1008  {
1009  size_t i;
1010  size_t n;
1011  size_t keySize;
1012  AesContext *aesContext;
1013  caam_handle_t caamHandle;
1014  uint8_t block[AES_BLOCK_SIZE];
1015 
1016  //Point to the AES context
1017  aesContext = (AesContext *) context;
1018 
1019  //Retrieve the length of the key
1020  if(aesContext->nr == 10)
1021  {
1022  //10 rounds are required for 128-bit key
1023  keySize = 16;
1024  }
1025  else if(aesContext->nr == 12)
1026  {
1027  //12 rounds are required for 192-bit key
1028  keySize = 24;
1029  }
1030  else if(aesContext->nr == 14)
1031  {
1032  //14 rounds are required for 256-bit key
1033  keySize = 32;
1034  }
1035  else
1036  {
1037  //Invalid key length
1038  status = kStatus_Fail;
1039  }
1040 
1041  //Check status code
1042  if(status == kStatus_Success)
1043  {
1044  //Set CAAM job ring
1045  caamHandle.jobRing = kCAAM_JobRing0;
1046 
1047  //Acquire exclusive access to the CAAM module
1049 
1050  //Perform AES-CBC decryption
1051  for(i = 0; i < length && status == kStatus_Success; i += n)
1052  {
1053  //Limit the number of data to process at a time
1055  //Copy the ciphertext to the buffer
1056  osMemcpy(caamBufferIn, c + i, n);
1057  //Save the last input block
1058  osMemcpy(block, caamBufferIn + n - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
1059 
1060  //Decrypt data
1061  status = CAAM_AES_DecryptCbc(CAAM, &caamHandle, caamBufferIn,
1062  caamBufferOut, n, iv, (const uint8_t *) aesContext->ek, keySize);
1063 
1064  //Check status code
1065  if(status == kStatus_Success)
1066  {
1067  //Copy the resulting plaintext
1068  osMemcpy(p + i, caamBufferOut, n);
1069  //Update the value of the initialization vector
1071  }
1072  }
1073  }
1074 
1075  //Release exclusive access to the CAAM module
1077  }
1078  else
1079  {
1080  //The length of the payload must be a multiple of the block size
1081  status = kStatus_InvalidArgument;
1082  }
1083  }
1084  else
1085 #endif
1086  //Unknown cipher algorithm?
1087  {
1088  size_t i;
1089  uint8_t t[16];
1090 
1091  //CBC mode operates in a block-by-block fashion
1092  while(length >= cipher->blockSize)
1093  {
1094  //Save input block
1095  osMemcpy(t, c, cipher->blockSize);
1096 
1097  //Decrypt the current block
1098  cipher->decryptBlock(context, c, p);
1099 
1100  //XOR output block with IV contents
1101  for(i = 0; i < cipher->blockSize; i++)
1102  {
1103  p[i] ^= iv[i];
1104  }
1105 
1106  //Update IV with input block contents
1107  osMemcpy(iv, t, cipher->blockSize);
1108 
1109  //Next block
1110  c += cipher->blockSize;
1111  p += cipher->blockSize;
1112  length -= cipher->blockSize;
1113  }
1114 
1115  //The length of the payload must be a multiple of the block size
1116  if(length != 0)
1117  {
1118  status = kStatus_InvalidArgument;
1119  }
1120  }
1121 
1122  //Return status code
1123  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
1124 }
1125 
1126 #endif
1127 #if (CTR_SUPPORT == ENABLED)
1128 
1129 /**
1130  * @brief CTR encryption
1131  * @param[in] cipher Cipher algorithm
1132  * @param[in] context Cipher algorithm context
1133  * @param[in] m Size in bits of the specific part of the block to be incremented
1134  * @param[in,out] t Initial counter block
1135  * @param[in] p Plaintext to be encrypted
1136  * @param[out] c Ciphertext resulting from the encryption
1137  * @param[in] length Total number of data bytes to be encrypted
1138  * @return Error code
1139  **/
1140 
1141 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
1142  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
1143 {
1144  status_t status;
1145 
1146  //Initialize status code
1147  status = kStatus_Success;
1148 
1149 #if (AES_SUPPORT == ENABLED)
1150  //AES cipher algorithm?
1151  if(cipher == AES_CIPHER_ALGO)
1152  {
1153  //Check the value of the parameter
1154  if(m == (AES_BLOCK_SIZE * 8))
1155  {
1156  //Check the length of the payload
1157  if(length == 0)
1158  {
1159  //No data to process
1160  }
1161  else if((length % AES_BLOCK_SIZE) == 0)
1162  {
1163  size_t i;
1164  size_t n;
1165  size_t keySize;
1166  AesContext *aesContext;
1167  caam_handle_t caamHandle;
1168 
1169  //Point to the AES context
1170  aesContext = (AesContext *) context;
1171 
1172  //Retrieve the length of the key
1173  if(aesContext->nr == 10)
1174  {
1175  //10 rounds are required for 128-bit key
1176  keySize = 16;
1177  }
1178  else if(aesContext->nr == 12)
1179  {
1180  //12 rounds are required for 192-bit key
1181  keySize = 24;
1182  }
1183  else if(aesContext->nr == 14)
1184  {
1185  //14 rounds are required for 256-bit key
1186  keySize = 32;
1187  }
1188  else
1189  {
1190  //Invalid key length
1191  status = kStatus_Fail;
1192  }
1193 
1194  //Check status code
1195  if(status == kStatus_Success)
1196  {
1197  //Set CAAM job ring
1198  caamHandle.jobRing = kCAAM_JobRing0;
1199 
1200  //Acquire exclusive access to the CAAM module
1202 
1203  //Perform AES-CTR encryption
1204  for(i = 0; i < length && status == kStatus_Success; i += n)
1205  {
1206  //Limit the number of data to process at a time
1208  //Copy the plaintext to the buffer
1209  osMemcpy(caamBufferIn, p + i, n);
1210  //Copy the counter block
1211  osMemcpy(caamInitVector, t, AES_BLOCK_SIZE);
1212 
1213  //Encrypt data
1214  status = CAAM_AES_CryptCtr(CAAM, &caamHandle,
1215  caamBufferIn, caamBufferOut, n, caamInitVector,
1216  (const uint8_t *) aesContext->ek, keySize, NULL, NULL);
1217 
1218  //Check status code
1219  if(status == kStatus_Success)
1220  {
1221  //Copy the resulting ciphertext
1222  osMemcpy(c + i, caamBufferOut, n);
1223  //Update the value of the counter block
1224  osMemcpy(t, caamInitVector, AES_BLOCK_SIZE);
1225  }
1226  }
1227  }
1228 
1229  //Release exclusive access to the CAAM module
1231  }
1232  else
1233  {
1234  //The length of the payload must be a multiple of the block size
1235  status = kStatus_InvalidArgument;
1236  }
1237  }
1238  else
1239  {
1240  //The value of the parameter is not valid
1241  status = kStatus_InvalidArgument;
1242  }
1243  }
1244  else
1245 #endif
1246  //Unknown cipher algorithm?
1247  {
1248  //Check the value of the parameter
1249  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
1250  {
1251  size_t i;
1252  size_t n;
1253  uint16_t temp;
1254  uint8_t o[16];
1255 
1256  //Determine the size, in bytes, of the specific part of the block
1257  //to be incremented
1258  m = m / 8;
1259 
1260  //Process plaintext
1261  while(length > 0)
1262  {
1263  //CTR mode operates in a block-by-block fashion
1264  n = MIN(length, cipher->blockSize);
1265 
1266  //Compute O(j) = CIPH(T(j))
1267  cipher->encryptBlock(context, t, o);
1268 
1269  //Compute C(j) = P(j) XOR T(j)
1270  for(i = 0; i < n; i++)
1271  {
1272  c[i] = p[i] ^ o[i];
1273  }
1274 
1275  //Standard incrementing function
1276  for(temp = 1, i = 1; i <= m; i++)
1277  {
1278  //Increment the current byte and propagate the carry
1279  temp += t[cipher->blockSize - i];
1280  t[cipher->blockSize - i] = temp & 0xFF;
1281  temp >>= 8;
1282  }
1283 
1284  //Next block
1285  p += n;
1286  c += n;
1287  length -= n;
1288  }
1289  }
1290  else
1291  {
1292  //The value of the parameter is not valid
1293  status = kStatus_InvalidArgument;
1294  }
1295  }
1296 
1297  //Return status code
1298  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
1299 }
1300 
1301 #endif
1302 #if (GCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1303 
1304 /**
1305  * @brief Initialize GCM context
1306  * @param[in] context Pointer to the GCM context
1307  * @param[in] cipherAlgo Cipher algorithm
1308  * @param[in] cipherContext Pointer to the cipher algorithm context
1309  * @return Error code
1310  **/
1311 
1312 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1313  void *cipherContext)
1314 {
1315  //Check parameters
1316  if(context == NULL || cipherContext == NULL)
1317  return ERROR_INVALID_PARAMETER;
1318 
1319  //The CRYP module only supports AES cipher algorithm
1320  if(cipherAlgo != AES_CIPHER_ALGO)
1321  return ERROR_INVALID_PARAMETER;
1322 
1323  //Save cipher algorithm context
1324  context->cipherAlgo = cipherAlgo;
1325  context->cipherContext = cipherContext;
1326 
1327  //Successful initialization
1328  return NO_ERROR;
1329 }
1330 
1331 
1332 /**
1333  * @brief Authenticated encryption using GCM
1334  * @param[in] context Pointer to the GCM context
1335  * @param[in] iv Initialization vector
1336  * @param[in] ivLen Length of the initialization vector
1337  * @param[in] a Additional authenticated data
1338  * @param[in] aLen Length of the additional data
1339  * @param[in] p Plaintext to be encrypted
1340  * @param[out] c Ciphertext resulting from the encryption
1341  * @param[in] length Total number of data bytes to be encrypted
1342  * @param[out] t Authentication tag
1343  * @param[in] tLen Length of the authentication tag
1344  * @return Error code
1345  **/
1346 
1347 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1348  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1349  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1350 {
1351  status_t status;
1352  size_t keySize;
1353  caam_handle_t caamHandle;
1354  AesContext *aesContext;
1355 
1356  //Make sure the GCM context is valid
1357  if(context == NULL)
1358  return ERROR_INVALID_PARAMETER;
1359 
1360  //Check the length of the authentication tag
1361  if(tLen < 4 || tLen > 16)
1362  return ERROR_INVALID_LENGTH;
1363 
1364  //Initialize status code
1365  status = kStatus_Success;
1366 
1367  //Point to the AES context
1368  aesContext = (AesContext *) context->cipherContext;
1369 
1370  //Retrieve the length of the key
1371  if(aesContext->nr == 10)
1372  {
1373  //10 rounds are required for 128-bit key
1374  keySize = 16;
1375  }
1376  else if(aesContext->nr == 12)
1377  {
1378  //12 rounds are required for 192-bit key
1379  keySize = 24;
1380  }
1381  else if(aesContext->nr == 14)
1382  {
1383  //14 rounds are required for 256-bit key
1384  keySize = 32;
1385  }
1386  else
1387  {
1388  //Invalid key length
1389  status = kStatus_Fail;
1390  }
1391 
1392  //Check status code
1393  if(status == kStatus_Success)
1394  {
1395  //Set CAAM job ring
1396  caamHandle.jobRing = kCAAM_JobRing0;
1397 
1398  //Acquire exclusive access to the CAAM module
1400 
1401  //Perform AES-GCM encryption
1402  status = CAAM_AES_EncryptTagGcm(CAAM, &caamHandle, p, c, length, iv,
1403  ivLen, a, aLen, (const uint8_t *) aesContext->ek, keySize, t, tLen);
1404 
1405  //Release exclusive access to the CAAM module
1407  }
1408 
1409  //Return status code
1410  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
1411 }
1412 
1413 
1414 /**
1415  * @brief Authenticated decryption using GCM
1416  * @param[in] context Pointer to the GCM context
1417  * @param[in] iv Initialization vector
1418  * @param[in] ivLen Length of the initialization vector
1419  * @param[in] a Additional authenticated data
1420  * @param[in] aLen Length of the additional data
1421  * @param[in] c Ciphertext to be decrypted
1422  * @param[out] p Plaintext resulting from the decryption
1423  * @param[in] length Total number of data bytes to be decrypted
1424  * @param[in] t Authentication tag
1425  * @param[in] tLen Length of the authentication tag
1426  * @return Error code
1427  **/
1428 
1429 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1430  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1431  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1432 {
1433  status_t status;
1434  size_t keySize;
1435  caam_handle_t caamHandle;
1436  AesContext *aesContext;
1437 
1438  //Make sure the GCM context is valid
1439  if(context == NULL)
1440  return ERROR_INVALID_PARAMETER;
1441 
1442  //Check the length of the authentication tag
1443  if(tLen < 4 || tLen > 16)
1444  return ERROR_INVALID_LENGTH;
1445 
1446  //Initialize status code
1447  status = kStatus_Success;
1448 
1449  //Point to the AES context
1450  aesContext = (AesContext *) context->cipherContext;
1451 
1452  //Retrieve the length of the key
1453  if(aesContext->nr == 10)
1454  {
1455  //10 rounds are required for 128-bit key
1456  keySize = 16;
1457  }
1458  else if(aesContext->nr == 12)
1459  {
1460  //12 rounds are required for 192-bit key
1461  keySize = 24;
1462  }
1463  else if(aesContext->nr == 14)
1464  {
1465  //14 rounds are required for 256-bit key
1466  keySize = 32;
1467  }
1468  else
1469  {
1470  //Invalid key length
1471  status = kStatus_Fail;
1472  }
1473 
1474  //Check status code
1475  if(status == kStatus_Success)
1476  {
1477  //Set CAAM job ring
1478  caamHandle.jobRing = kCAAM_JobRing0;
1479 
1480  //Acquire exclusive access to the CAAM module
1482 
1483  //Perform AES-GCM decryption
1484  status = CAAM_AES_DecryptTagGcm(CAAM, &caamHandle, c, p, length, iv,
1485  ivLen, a, aLen, (const uint8_t *) aesContext->ek, keySize, t, tLen);
1486 
1487  //Release exclusive access to the CAAM module
1489  }
1490 
1491  //Return status code
1492  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
1493 }
1494 
1495 #endif
1496 #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.
#define DES3_CIPHER_ALGO
Definition: des3.h:46
#define DES3_BLOCK_SIZE
Definition: des3.h:44
#define DES_BLOCK_SIZE
Definition: des.h:43
#define DES_CIPHER_ALGO
Definition: des.h:45
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_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint8_t iv[]
Definition: ike.h:1502
uint8_t t
Definition: lldp_ext_med.h:212
OsMutex mimxrt1160CryptoMutex
i.MX RT1160 hardware cryptographic accelerator (CAAM)
#define MIMXRT1160_CAAM_BUFFER_SIZE
error_t gcmEncrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using GCM.
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.
uint8_t caamBufferIn[MIMXRT1160_CAAM_BUFFER_SIZE] __attribute__((aligned(16)))
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
error_t gcmDecrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using GCM.
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 desInit(DesContext *context, const uint8_t *key, size_t keyLen)
Initialize a DES context using the supplied key.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
i.MX RT1160 cipher hardware accelerator
uint8_t c
Definition: ndp.h:514
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
uint8_t a
Definition: ndp.h:411
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
AES algorithm context.
Definition: aes.h:58
uint_t nr
Definition: aes.h:59
uint32_t ek[60]
Definition: aes.h:60
Common interface for encryption algorithms.
Definition: crypto.h:1036
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1044
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1045
size_t blockSize
Definition: crypto.h:1040
Triple DES algorithm context.
Definition: des3.h:59
DesContext k2
Definition: des3.h:61
DesContext k3
Definition: des3.h:62
DesContext k1
Definition: des3.h:60
DES algorithm context.
Definition: des.h:58
uint32_t ks[32]
Definition: des.h:59
GCM context.
Definition: gcm.h:64
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:66
uint8_t length
Definition: tcp.h:368
uint16_t block
Definition: tftp_common.h:115