s7g2_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file s7g2_crypto_cipher.c
3  * @brief Synergy S7G2 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 "hw_sce_private.h"
36 #include "hw_sce_tdes_private.h"
37 #include "hw_sce_aes_private.h"
38 #include "core/crypto.h"
43 #include "aead/aead_algorithms.h"
44 #include "debug.h"
45 
46 //Check crypto library configuration
47 #if (S7G2_CRYPTO_CIPHER_SUPPORT == ENABLED)
48 #if (DES3_SUPPORT == ENABLED)
49 
50 
51 /**
52  * @brief Initialize a Triple DES context using the supplied key
53  * @param[in] context Pointer to the Triple DES context to initialize
54  * @param[in] key Pointer to the key
55  * @param[in] keyLen Length of the key
56  * @return Error code
57  **/
58 
59 error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
60 {
61  //Check parameters
62  if(context == NULL || key == NULL)
64 
65  //Check key length
66  if(keyLen == 8)
67  {
68  //This option provides backward compatibility with DES, because the
69  //first and second DES operations cancel out
70  context->k1.ks[0] = LOAD32LE(key + 0);
71  context->k1.ks[1] = LOAD32LE(key + 4);
72  context->k1.ks[2] = LOAD32LE(key + 0);
73  context->k1.ks[3] = LOAD32LE(key + 4);
74  context->k1.ks[4] = LOAD32LE(key + 0);
75  context->k1.ks[5] = LOAD32LE(key + 4);
76  }
77  else if(keyLen == 16)
78  {
79  //If the key length is 128 bits including parity, the first 8 bytes of the
80  //encoding represent the key used for the two outer DES operations, and
81  //the second 8 bytes represent the key used for the inner DES operation
82  context->k1.ks[0] = LOAD32LE(key + 0);
83  context->k1.ks[1] = LOAD32LE(key + 4);
84  context->k1.ks[2] = LOAD32LE(key + 8);
85  context->k1.ks[3] = LOAD32LE(key + 12);
86  context->k1.ks[4] = LOAD32LE(key + 0);
87  context->k1.ks[5] = LOAD32LE(key + 4);
88  }
89  else if(keyLen == 24)
90  {
91  //If the key length is 192 bits including parity, then 3 independent DES
92  //keys are represented, in the order in which they are used for encryption
93  context->k1.ks[0] = LOAD32LE(key + 0);
94  context->k1.ks[1] = LOAD32LE(key + 4);
95  context->k1.ks[2] = LOAD32LE(key + 8);
96  context->k1.ks[3] = LOAD32LE(key + 12);
97  context->k1.ks[4] = LOAD32LE(key + 16);
98  context->k1.ks[5] = LOAD32LE(key + 20);
99  }
100  else
101  {
102  //The length of the key is not valid
104  }
105 
106  //No error to report
107  return NO_ERROR;
108 }
109 
110 
111 /**
112  * @brief Encrypt a 8-byte block using Triple DES algorithm
113  * @param[in] context Pointer to the Triple DES context
114  * @param[in] input Plaintext block to encrypt
115  * @param[out] output Ciphertext block resulting from encryption
116  **/
117 
118 void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
119 {
120  ssp_err_t status;
121 
122  //Acquire exclusive access to the SCE7 module
124 
125  //Perform Triple DES encryption
126  status = HW_SCE_TDES_192EcbEncrypt(context->k1.ks, DES3_BLOCK_SIZE / 4,
127  (const uint32_t *) input, (uint32_t *) output);
128 
129  //Check status code
130  if(status != SSP_SUCCESS)
131  {
132  osMemset(output, 0, DES3_BLOCK_SIZE);
133  }
134 
135  //Release exclusive access to the SCE7 module
137 }
138 
139 
140 /**
141  * @brief Decrypt a 8-byte block using Triple DES algorithm
142  * @param[in] context Pointer to the Triple DES context
143  * @param[in] input Ciphertext block to decrypt
144  * @param[out] output Plaintext block resulting from decryption
145  **/
146 
147 void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
148 {
149  ssp_err_t status;
150 
151  //Acquire exclusive access to the SCE7 module
153 
154  //Perform Triple DES decryption
155  status = HW_SCE_TDES_192EcbDecrypt(context->k1.ks, DES3_BLOCK_SIZE / 4,
156  (const uint32_t *) input, (uint32_t *) output);
157 
158  //Check status code
159  if(status != SSP_SUCCESS)
160  {
161  osMemset(output, 0, DES3_BLOCK_SIZE);
162  }
163 
164  //Release exclusive access to the SCE7 module
166 }
167 
168 #endif
169 #if (AES_SUPPORT == ENABLED)
170 
171 /**
172  * @brief Key expansion
173  * @param[in] context Pointer to the AES context to initialize
174  * @param[in] key Pointer to the key
175  * @param[in] keyLen Length of the key
176  * @return Error code
177  **/
178 
179 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
180 {
181  ssp_err_t status;
182 
183  //Check parameters
184  if(context == NULL || key == NULL)
186 
187  //Initialize status code
188  status = SSP_SUCCESS;
189 
190  //Check the length of the key
191  if(keyLen == 16)
192  {
193  //10 rounds are required for 128-bit key
194  context->nr = 10;
195  //Copy the key
196  osMemcpy(context->ek, key, keyLen);
197  }
198  else if(keyLen == 24)
199  {
200  //12 rounds are required for 192-bit key
201  context->nr = 12;
202  //Copy the key
203  osMemcpy(context->ek, key, keyLen);
204  }
205  else if(keyLen == 32)
206  {
207  //14 rounds are required for 256-bit key
208  context->nr = 14;
209  //Copy the key
210  osMemcpy(context->ek, key, keyLen);
211  }
212  else
213  {
214  //192-bit keys are not supported
215  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
216  }
217 
218  //Return status code
219  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
220 }
221 
222 
223 /**
224  * @brief Encrypt a 16-byte block using AES algorithm
225  * @param[in] context Pointer to the AES context
226  * @param[in] input Plaintext block to encrypt
227  * @param[out] output Ciphertext block resulting from encryption
228  **/
229 
230 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
231 {
232  ssp_err_t status;
233 
234  //Acquire exclusive access to the SCE7 module
236 
237  //Check the length of the key
238  if(context->nr == 10)
239  {
240  //Perform AES encryption (128-bit key)
241  status = HW_SCE_AES_128EcbEncrypt(context->ek, AES_BLOCK_SIZE / 4,
242  (const uint32_t *) input, (uint32_t *) output);
243  }
244  else if(context->nr == 12)
245  {
246  //Perform AES encryption (192-bit key)
247  status = HW_SCE_AES_192EcbEncrypt(context->ek, AES_BLOCK_SIZE / 4,
248  (const uint32_t *) input, (uint32_t *) output);
249  }
250  else if(context->nr == 14)
251  {
252  //Perform AES encryption (256-bit key)
253  status = HW_SCE_AES_256EcbEncrypt(context->ek, AES_BLOCK_SIZE / 4,
254  (const uint32_t *) input, (uint32_t *) output);
255  }
256  else
257  {
258  //Invalid key length
259  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
260  }
261 
262  //Check status code
263  if(status != SSP_SUCCESS)
264  {
265  osMemset(output, 0, AES_BLOCK_SIZE);
266  }
267 
268  //Release exclusive access to the SCE7 module
270 }
271 
272 
273 /**
274  * @brief Decrypt a 16-byte block using AES algorithm
275  * @param[in] context Pointer to the AES context
276  * @param[in] input Ciphertext block to decrypt
277  * @param[out] output Plaintext block resulting from decryption
278  **/
279 
280 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
281 {
282  ssp_err_t status;
283 
284  //Acquire exclusive access to the SCE7 module
286 
287  //Check the length of the key
288  if(context->nr == 10)
289  {
290  //Perform AES decryption (128-bit key)
291  status = HW_SCE_AES_128EcbDecrypt(context->ek, AES_BLOCK_SIZE / 4,
292  (const uint32_t *) input, (uint32_t *) output);
293  }
294  else if(context->nr == 12)
295  {
296  //Perform AES decryption (192-bit key)
297  status = HW_SCE_AES_192EcbDecrypt(context->ek, AES_BLOCK_SIZE / 4,
298  (const uint32_t *) input, (uint32_t *) output);
299  }
300  else if(context->nr == 14)
301  {
302  //Perform AES decryption (256-bit key)
303  status = HW_SCE_AES_256EcbDecrypt(context->ek, AES_BLOCK_SIZE / 4,
304  (const uint32_t *) input, (uint32_t *) output);
305  }
306  else
307  {
308  //Invalid key length
309  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
310  }
311 
312  //Check status code
313  if(status != SSP_SUCCESS)
314  {
315  osMemset(output, 0, AES_BLOCK_SIZE);
316  }
317 
318  //Release exclusive access to the SCE7 module
320 }
321 
322 #endif
323 #if (ECB_SUPPORT == ENABLED)
324 
325 /**
326  * @brief ECB encryption
327  * @param[in] cipher Cipher algorithm
328  * @param[in] context Cipher algorithm context
329  * @param[in] p Plaintext to be encrypted
330  * @param[out] c Ciphertext resulting from the encryption
331  * @param[in] length Total number of data bytes to be encrypted
332  * @return Error code
333  **/
334 
335 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
336  const uint8_t *p, uint8_t *c, size_t length)
337 {
338  ssp_err_t status;
339 
340  //Initialize status code
341  status = SSP_SUCCESS;
342 
343 #if (DES3_SUPPORT == ENABLED)
344  //Triple DES cipher algorithm?
345  if(cipher == DES3_CIPHER_ALGO)
346  {
347  //Check the length of the payload
348  if(length == 0)
349  {
350  //No data to process
351  }
352  else if((length % DES3_BLOCK_SIZE) == 0)
353  {
354  Des3Context *des3Context;
355 
356  //Point to the Triple DES context
357  des3Context = (Des3Context *) context;
358 
359  //Acquire exclusive access to the SCE7 module
361 
362  //Perform 3DES-ECB encryption
363  status = HW_SCE_TDES_192EcbEncrypt(des3Context->k1.ks, length / 4,
364  (const uint32_t *) p, (uint32_t *) c);
365 
366  //Release exclusive access to the SCE7 module
368  }
369  else
370  {
371  //The length of the payload must be a multiple of the block size
372  status = SSP_ERR_CRYPTO_INVALID_SIZE;
373  }
374  }
375  else
376 #endif
377 #if (AES_SUPPORT == ENABLED)
378  //AES cipher algorithm?
379  if(cipher == AES_CIPHER_ALGO)
380  {
381  //Check the length of the payload
382  if(length == 0)
383  {
384  //No data to process
385  }
386  else if((length % AES_BLOCK_SIZE) == 0)
387  {
388  AesContext *aesContext;
389 
390  //Point to the AES context
391  aesContext = (AesContext *) context;
392 
393  //Acquire exclusive access to the SCE7 module
395 
396  //Check the length of the key
397  if(aesContext->nr == 10)
398  {
399  //Perform AES-ECB encryption (128-bit key)
400  status = HW_SCE_AES_128EcbEncrypt(aesContext->ek, length / 4,
401  (const uint32_t *) p, (uint32_t *) c);
402  }
403  else if(aesContext->nr == 12)
404  {
405  //Perform AES-ECB encryption (192-bit key)
406  status = HW_SCE_AES_192EcbEncrypt(aesContext->ek, length / 4,
407  (const uint32_t *) p, (uint32_t *) c);
408  }
409  else if(aesContext->nr == 14)
410  {
411  //Perform AES-ECB encryption (256-bit key)
412  status = HW_SCE_AES_256EcbEncrypt(aesContext->ek, length / 4,
413  (const uint32_t *) p, (uint32_t *) c);
414  }
415  else
416  {
417  //Invalid key length
418  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
419  }
420 
421  //Release exclusive access to the SCE7 module
423  }
424  else
425  {
426  //The length of the payload must be a multiple of the block size
427  status = SSP_ERR_CRYPTO_INVALID_SIZE;
428  }
429  }
430  else
431 #endif
432  //Unknown cipher algorithm?
433  {
434  //ECB mode operates in a block-by-block fashion
435  while(length >= cipher->blockSize)
436  {
437  //Encrypt current block
438  cipher->encryptBlock(context, p, c);
439 
440  //Next block
441  p += cipher->blockSize;
442  c += cipher->blockSize;
443  length -= cipher->blockSize;
444  }
445 
446  //The length of the payload must be a multiple of the block size
447  if(length != 0)
448  {
449  status = SSP_ERR_CRYPTO_INVALID_SIZE;
450  }
451  }
452 
453  //Return status code
454  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
455 }
456 
457 
458 /**
459  * @brief ECB decryption
460  * @param[in] cipher Cipher algorithm
461  * @param[in] context Cipher algorithm context
462  * @param[in] c Ciphertext to be decrypted
463  * @param[out] p Plaintext resulting from the decryption
464  * @param[in] length Total number of data bytes to be decrypted
465  * @return Error code
466  **/
467 
468 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
469  const uint8_t *c, uint8_t *p, size_t length)
470 {
471  ssp_err_t status;
472 
473  //Initialize status code
474  status = SSP_SUCCESS;
475 
476 #if (DES3_SUPPORT == ENABLED)
477  //Triple DES cipher algorithm?
478  if(cipher == DES3_CIPHER_ALGO)
479  {
480  //Check the length of the payload
481  if(length == 0)
482  {
483  //No data to process
484  }
485  else if((length % DES3_BLOCK_SIZE) == 0)
486  {
487  Des3Context *des3Context;
488 
489  //Point to the Triple DES context
490  des3Context = (Des3Context *) context;
491 
492  //Acquire exclusive access to the SCE7 module
494 
495  //Perform 3DES-ECB decryption
496  status = HW_SCE_TDES_192EcbDecrypt(des3Context->k1.ks, length / 4,
497  (const uint32_t *) p, (uint32_t *) c);
498 
499  //Release exclusive access to the SCE7 module
501  }
502  else
503  {
504  //The length of the payload must be a multiple of the block size
505  status = SSP_ERR_CRYPTO_INVALID_SIZE;
506  }
507  }
508  else
509 #endif
510 #if (AES_SUPPORT == ENABLED)
511  //AES cipher algorithm?
512  if(cipher == AES_CIPHER_ALGO)
513  {
514  //Check the length of the payload
515  if(length == 0)
516  {
517  //No data to process
518  }
519  else if((length % AES_BLOCK_SIZE) == 0)
520  {
521  AesContext *aesContext;
522 
523  //Point to the AES context
524  aesContext = (AesContext *) context;
525 
526  //Acquire exclusive access to the SCE7 module
528 
529  //Check the length of the key
530  if(aesContext->nr == 10)
531  {
532  //Perform AES-ECB decryption (128-bit key)
533  status = HW_SCE_AES_128EcbDecrypt(aesContext->ek, length / 4,
534  (const uint32_t *) c, (uint32_t *) p);
535  }
536  else if(aesContext->nr == 12)
537  {
538  //Perform AES-ECB decryption (192-bit key)
539  status = HW_SCE_AES_192EcbDecrypt(aesContext->ek, length / 4,
540  (const uint32_t *) c, (uint32_t *) p);
541  }
542  else if(aesContext->nr == 14)
543  {
544  //Perform AES-ECB decryption (256-bit key)
545  status = HW_SCE_AES_256EcbDecrypt(aesContext->ek, length / 4,
546  (const uint32_t *) c, (uint32_t *) p);
547  }
548  else
549  {
550  //Invalid key length
551  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
552  }
553 
554  //Release exclusive access to the SCE7 module
556  }
557  else
558  {
559  //The length of the payload must be a multiple of the block size
560  status = SSP_ERR_CRYPTO_INVALID_SIZE;
561  }
562  }
563  else
564 #endif
565  //Unknown cipher algorithm?
566  {
567  //ECB mode operates in a block-by-block fashion
568  while(length >= cipher->blockSize)
569  {
570  //Decrypt current block
571  cipher->decryptBlock(context, c, p);
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  status = SSP_ERR_CRYPTO_INVALID_SIZE;
583  }
584  }
585 
586  //Return status code
587  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
588 }
589 
590 #endif
591 #if (CBC_SUPPORT == ENABLED)
592 
593 /**
594  * @brief CBC encryption
595  * @param[in] cipher Cipher algorithm
596  * @param[in] context Cipher algorithm context
597  * @param[in,out] iv Initialization vector
598  * @param[in] p Plaintext to be encrypted
599  * @param[out] c Ciphertext resulting from the encryption
600  * @param[in] length Total number of data bytes to be encrypted
601  * @return Error code
602  **/
603 
604 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
605  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
606 {
607  ssp_err_t status;
608 
609  //Initialize status code
610  status = SSP_SUCCESS;
611 
612 #if (DES3_SUPPORT == ENABLED)
613  //Triple DES cipher algorithm?
614  if(cipher == DES3_CIPHER_ALGO)
615  {
616  //Check the length of the payload
617  if(length == 0)
618  {
619  //No data to process
620  }
621  else if((length % DES3_BLOCK_SIZE) == 0)
622  {
623  Des3Context *des3Context;
624 
625  //Point to the Triple DES context
626  des3Context = (Des3Context *) context;
627 
628  //Acquire exclusive access to the SCE7 module
630 
631  //Perform 3DES-CBC encryption
632  status = HW_SCE_TDES_192CbcEncrypt(des3Context->k1.ks,
633  (const uint32_t *) iv, length / 4, (const uint32_t *) p,
634  (uint32_t *) c, (uint32_t *) iv);
635 
636  //Release exclusive access to the SCE7 module
638  }
639  else
640  {
641  //The length of the payload must be a multiple of the block size
642  status = SSP_ERR_CRYPTO_INVALID_SIZE;
643  }
644  }
645  else
646 #endif
647 #if (AES_SUPPORT == ENABLED)
648  //AES cipher algorithm?
649  if(cipher == AES_CIPHER_ALGO)
650  {
651  //Check the length of the payload
652  if(length == 0)
653  {
654  //No data to process
655  }
656  else if((length % AES_BLOCK_SIZE) == 0)
657  {
658  AesContext *aesContext;
659 
660  //Point to the AES context
661  aesContext = (AesContext *) context;
662 
663  //Acquire exclusive access to the SCE7 module
665 
666  //Check the length of the key
667  if(aesContext->nr == 10)
668  {
669  //Perform AES-CBC encryption (128-bit key)
670  status = HW_SCE_AES_128CbcEncrypt(aesContext->ek,
671  (const uint32_t *) iv, length / 4, (const uint32_t *) p,
672  (uint32_t *) c, (uint32_t *) iv);
673  }
674  else if(aesContext->nr == 12)
675  {
676  //Perform AES-CBC encryption (192-bit key)
677  status = HW_SCE_AES_192CbcEncrypt(aesContext->ek,
678  (const uint32_t *) iv, length / 4, (const uint32_t *) p,
679  (uint32_t *) c, (uint32_t *) iv);
680  }
681  else if(aesContext->nr == 14)
682  {
683  //Perform AES-CBC encryption (256-bit key)
684  status = HW_SCE_AES_256CbcEncrypt(aesContext->ek,
685  (const uint32_t *) iv, length / 4, (const uint32_t *) p,
686  (uint32_t *) c, (uint32_t *) iv);
687  }
688  else
689  {
690  //Invalid key length
691  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
692  }
693 
694  //Release exclusive access to the SCE7 module
696  }
697  else
698  {
699  //The length of the payload must be a multiple of the block size
700  status = SSP_ERR_CRYPTO_INVALID_SIZE;
701  }
702  }
703  else
704 #endif
705  //Unknown cipher algorithm?
706  {
707  size_t i;
708 
709  //CBC mode operates in a block-by-block fashion
710  while(length >= cipher->blockSize)
711  {
712  //XOR input block with IV contents
713  for(i = 0; i < cipher->blockSize; i++)
714  {
715  c[i] = p[i] ^ iv[i];
716  }
717 
718  //Encrypt the current block based upon the output of the previous
719  //encryption
720  cipher->encryptBlock(context, c, c);
721 
722  //Update IV with output block contents
723  osMemcpy(iv, c, cipher->blockSize);
724 
725  //Next block
726  p += cipher->blockSize;
727  c += cipher->blockSize;
728  length -= cipher->blockSize;
729  }
730 
731  //The length of the payload must be a multiple of the block size
732  if(length != 0)
733  {
734  status = SSP_ERR_CRYPTO_INVALID_SIZE;
735  }
736  }
737 
738  //Return status code
739  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
740 }
741 
742 
743 /**
744  * @brief CBC decryption
745  * @param[in] cipher Cipher algorithm
746  * @param[in] context Cipher algorithm context
747  * @param[in,out] iv Initialization vector
748  * @param[in] c Ciphertext to be decrypted
749  * @param[out] p Plaintext resulting from the decryption
750  * @param[in] length Total number of data bytes to be decrypted
751  * @return Error code
752  **/
753 
754 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
755  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
756 {
757  ssp_err_t status;
758 
759  //Initialize status code
760  status = SSP_SUCCESS;
761 
762 #if (DES3_SUPPORT == ENABLED)
763  //Triple DES cipher algorithm?
764  if(cipher == DES3_CIPHER_ALGO)
765  {
766  //Check the length of the payload
767  if(length == 0)
768  {
769  //No data to process
770  }
771  else if((length % DES3_BLOCK_SIZE) == 0)
772  {
773  Des3Context *des3Context;
774 
775  //Point to the Triple DES context
776  des3Context = (Des3Context *) context;
777 
778  //Acquire exclusive access to the SCE7 module
780 
781  //Perform 3DES-CBC decryption
782  status = HW_SCE_TDES_192CbcDecrypt(des3Context->k1.ks,
783  (const uint32_t *) iv, length / 4, (const uint32_t *) c,
784  (uint32_t *) p, (uint32_t *) iv);
785 
786  //Release exclusive access to the SCE7 module
788  }
789  else
790  {
791  //The length of the payload must be a multiple of the block size
792  status = SSP_ERR_CRYPTO_INVALID_SIZE;
793  }
794  }
795  else
796 #endif
797 #if (AES_SUPPORT == ENABLED)
798  //AES cipher algorithm?
799  if(cipher == AES_CIPHER_ALGO)
800  {
801  //Check the length of the payload
802  if(length == 0)
803  {
804  //No data to process
805  }
806  else if((length % AES_BLOCK_SIZE) == 0)
807  {
808  AesContext *aesContext;
809 
810  //Point to the AES context
811  aesContext = (AesContext *) context;
812 
813  //Acquire exclusive access to the SCE7 module
815 
816  //Check the length of the key
817  if(aesContext->nr == 10)
818  {
819  //Perform AES-CBC decryption (128-bit key)
820  status = HW_SCE_AES_128CbcDecrypt(aesContext->ek,
821  (const uint32_t *) iv, length / 4, (const uint32_t *) c,
822  (uint32_t *) p, (uint32_t *) iv);
823  }
824  else if(aesContext->nr == 12)
825  {
826  //Perform AES-CBC decryption (192-bit key)
827  status = HW_SCE_AES_192CbcDecrypt(aesContext->ek,
828  (const uint32_t *) iv, length / 4, (const uint32_t *) c,
829  (uint32_t *) p, (uint32_t *) iv);
830  }
831  else if(aesContext->nr == 14)
832  {
833  //Perform AES-CBC decryption (256-bit key)
834  status = HW_SCE_AES_256CbcDecrypt(aesContext->ek,
835  (const uint32_t *) iv, length / 4, (const uint32_t *) c,
836  (uint32_t *) p, (uint32_t *) iv);
837  }
838  else
839  {
840  //Invalid key length
841  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
842  }
843 
844  //Release exclusive access to the SCE7 module
846  }
847  else
848  {
849  //The length of the payload must be a multiple of the block size
850  status = SSP_ERR_CRYPTO_INVALID_SIZE;
851  }
852  }
853  else
854 #endif
855  //Unknown cipher algorithm?
856  {
857  size_t i;
858  uint8_t t[16];
859 
860  //CBC mode operates in a block-by-block fashion
861  while(length >= cipher->blockSize)
862  {
863  //Save input block
864  osMemcpy(t, c, cipher->blockSize);
865 
866  //Decrypt the current block
867  cipher->decryptBlock(context, c, p);
868 
869  //XOR output block with IV contents
870  for(i = 0; i < cipher->blockSize; i++)
871  {
872  p[i] ^= iv[i];
873  }
874 
875  //Update IV with input block contents
876  osMemcpy(iv, t, cipher->blockSize);
877 
878  //Next block
879  c += cipher->blockSize;
880  p += cipher->blockSize;
881  length -= cipher->blockSize;
882  }
883 
884  //The length of the payload must be a multiple of the block size
885  if(length != 0)
886  {
887  status = SSP_ERR_CRYPTO_INVALID_SIZE;
888  }
889  }
890 
891  //Return status code
892  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
893 }
894 
895 #endif
896 #if (CTR_SUPPORT == ENABLED)
897 
898 /**
899  * @brief CTR encryption
900  * @param[in] cipher Cipher algorithm
901  * @param[in] context Cipher algorithm context
902  * @param[in] m Size in bits of the specific part of the block to be incremented
903  * @param[in,out] t Initial counter block
904  * @param[in] p Plaintext to be encrypted
905  * @param[out] c Ciphertext resulting from the encryption
906  * @param[in] length Total number of data bytes to be encrypted
907  * @return Error code
908  **/
909 
910 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
911  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
912 {
913  ssp_err_t status;
914 
915  //Initialize status code
916  status = SSP_SUCCESS;
917 
918 #if (DES3_SUPPORT == ENABLED)
919  //Triple DES cipher algorithm?
920  if(cipher == DES3_CIPHER_ALGO)
921  {
922  //Check the value of the parameter
923  if(m == (DES3_BLOCK_SIZE * 8))
924  {
925  //Check the length of the payload
926  if(length == 0)
927  {
928  //No data to process
929  }
930  else if((length % DES3_BLOCK_SIZE) == 0)
931  {
932  Des3Context *des3Context;
933 
934  //Point to the Triple DES context
935  des3Context = (Des3Context *) context;
936 
937  //Acquire exclusive access to the SCE7 module
939 
940  //Perform 3DES-CTR encryption
941  status = HW_SCE_TDES_192CtrEncrypt(des3Context->k1.ks,
942  (const uint32_t *) t, length / 4, (const uint32_t *) p,
943  (uint32_t *) c, (uint32_t *) t);
944 
945  //Release exclusive access to the SCE7 module
947  }
948  else
949  {
950  //The length of the payload must be a multiple of the block size
951  status = SSP_ERR_CRYPTO_INVALID_SIZE;
952  }
953  }
954  else
955  {
956  //The value of the parameter is not valid
957  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
958  }
959  }
960  else
961 #endif
962 #if (AES_SUPPORT == ENABLED)
963  //AES cipher algorithm?
964  if(cipher == AES_CIPHER_ALGO)
965  {
966  //Check the value of the parameter
967  if(m == (AES_BLOCK_SIZE * 8))
968  {
969  //Check the length of the payload
970  if(length == 0)
971  {
972  //No data to process
973  }
974  else if((length % AES_BLOCK_SIZE) == 0)
975  {
976  AesContext *aesContext;
977 
978  //Point to the AES context
979  aesContext = (AesContext *) context;
980 
981  //Acquire exclusive access to the SCE7 module
983 
984  //Check the length of the key
985  if(aesContext->nr == 10)
986  {
987  //Perform AES-CTR encryption (128-bit key)
988  status = HW_SCE_AES_128CtrEncrypt(aesContext->ek,
989  (const uint32_t *) t, length / 4, (const uint32_t *) p,
990  (uint32_t *) c, (uint32_t *) t);
991  }
992  else if(aesContext->nr == 12)
993  {
994  //Perform AES-CTR encryption (192-bit key)
995  status = HW_SCE_AES_192CtrEncrypt(aesContext->ek,
996  (const uint32_t *) t, length / 4, (const uint32_t *) p,
997  (uint32_t *) c, (uint32_t *) t);
998  }
999  else if(aesContext->nr == 14)
1000  {
1001  //Perform AES-CTR encryption (256-bit key)
1002  status = HW_SCE_AES_256CtrEncrypt(aesContext->ek,
1003  (const uint32_t *) t, length / 4, (const uint32_t *) p,
1004  (uint32_t *) c, (uint32_t *) t);
1005  }
1006  else
1007  {
1008  //Invalid key length
1009  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1010  }
1011 
1012  //Release exclusive access to the SCE7 module
1014  }
1015  else
1016  {
1017  //The length of the payload must be a multiple of the block size
1018  status = SSP_ERR_CRYPTO_INVALID_SIZE;
1019  }
1020  }
1021  else
1022  {
1023  //The value of the parameter is not valid
1024  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1025  }
1026  }
1027  else
1028 #endif
1029  //Unknown cipher algorithm?
1030  {
1031  //Check the value of the parameter
1032  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
1033  {
1034  size_t i;
1035  size_t n;
1036  uint16_t temp;
1037  uint8_t o[16];
1038 
1039  //Determine the size, in bytes, of the specific part of the block
1040  //to be incremented
1041  m = m / 8;
1042 
1043  //Process plaintext
1044  while(length > 0)
1045  {
1046  //CTR mode operates in a block-by-block fashion
1047  n = MIN(length, cipher->blockSize);
1048 
1049  //Compute O(j) = CIPH(T(j))
1050  cipher->encryptBlock(context, t, o);
1051 
1052  //Compute C(j) = P(j) XOR T(j)
1053  for(i = 0; i < n; i++)
1054  {
1055  c[i] = p[i] ^ o[i];
1056  }
1057 
1058  //Standard incrementing function
1059  for(temp = 1, i = 1; i <= m; i++)
1060  {
1061  //Increment the current byte and propagate the carry
1062  temp += t[cipher->blockSize - i];
1063  t[cipher->blockSize - i] = temp & 0xFF;
1064  temp >>= 8;
1065  }
1066 
1067  //Next block
1068  p += n;
1069  c += n;
1070  length -= n;
1071  }
1072  }
1073  else
1074  {
1075  //The value of the parameter is not valid
1076  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1077  }
1078  }
1079 
1080  //Return status code
1081  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
1082 }
1083 
1084 #endif
1085 #if (GCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1086 
1087 /**
1088  * @brief Initialize GCM context
1089  * @param[in] context Pointer to the GCM context
1090  * @param[in] cipherAlgo Cipher algorithm
1091  * @param[in] cipherContext Pointer to the cipher algorithm context
1092  * @return Error code
1093  **/
1094 
1095 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1096  void *cipherContext)
1097 {
1098  uint32_t h[4];
1099 
1100  //The SCE7 module only supports AES cipher algorithm
1101  if(cipherAlgo != AES_CIPHER_ALGO)
1102  return ERROR_INVALID_PARAMETER;
1103 
1104  //Save cipher algorithm context
1105  context->cipherAlgo = cipherAlgo;
1106  context->cipherContext = cipherContext;
1107 
1108  //Let H = 0
1109  h[0] = 0;
1110  h[1] = 0;
1111  h[2] = 0;
1112  h[3] = 0;
1113 
1114  //Generate the hash subkey H
1115  aesEncryptBlock(context->cipherContext, (uint8_t *) h, (uint8_t *) h);
1116 
1117  //Save the resulting value
1118  context->m[0][0] = h[0];
1119  context->m[0][1] = h[1];
1120  context->m[0][2] = h[2];
1121  context->m[0][3] = h[3];
1122 
1123  //Successful initialization
1124  return NO_ERROR;
1125 }
1126 
1127 
1128 /**
1129  * @brief Authenticated encryption using GCM
1130  * @param[in] context Pointer to the GCM context
1131  * @param[in] iv Initialization vector
1132  * @param[in] ivLen Length of the initialization vector
1133  * @param[in] a Additional authenticated data
1134  * @param[in] aLen Length of the additional data
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  * @param[out] t Authentication tag
1139  * @param[in] tLen Length of the authentication tag
1140  * @return Error code
1141  **/
1142 
1143 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1144  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1145  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1146 {
1147  size_t k;
1148  size_t n;
1149  uint64_t m;
1150  uint32_t b[4];
1151  uint32_t j[4];
1152  uint32_t s[4];
1153  AesContext *aesContext;
1154 
1155  //Make sure the GCM context is valid
1156  if(context == NULL)
1157  return ERROR_INVALID_PARAMETER;
1158 
1159  //The length of the IV shall meet SP 800-38D requirements
1160  if(ivLen < 1)
1161  return ERROR_INVALID_LENGTH;
1162 
1163  //Check the length of the authentication tag
1164  if(tLen < 4 || tLen > 16)
1165  return ERROR_INVALID_LENGTH;
1166 
1167  //Point to the AES context
1168  aesContext = (AesContext *) context->cipherContext;
1169 
1170  //Check the length of the key
1171  if(aesContext->nr != 10 && aesContext->nr != 12 && aesContext->nr != 14)
1172  return ERROR_INVALID_PARAMETER;
1173 
1174  //Acquire exclusive access to the SCE7 module
1176 
1177  //Check whether the length of the IV is 96 bits
1178  if(ivLen == 12)
1179  {
1180  //When the length of the IV is 96 bits, the padding string is appended
1181  //to the IV to form the pre-counter block
1182  j[0] = LOAD32LE(iv);
1183  j[1] = LOAD32LE(iv + 4);
1184  j[2] = LOAD32LE(iv + 8);
1185  j[3] = BETOH32(1);
1186  }
1187  else
1188  {
1189  //Initialize GHASH calculation
1190  j[0] = 0;
1191  j[1] = 0;
1192  j[2] = 0;
1193  j[3] = 0;
1194 
1195  //Length of the IV
1196  n = ivLen;
1197 
1198  //Process the initialization vector
1199  if(n >= 16)
1200  {
1201  //Ensure the size of the incoming data to be processed is a multiple
1202  //of 16 bytes
1203  k = n & ~15UL;
1204 
1205  //Apply GHASH function
1206  HW_SCE_AES_Ghash(context->m[0], j, k / 4, (const uint32_t *) iv, j);
1207 
1208  //Advance data pointer
1209  iv += k;
1210  n -= k;
1211  }
1212 
1213  //Process the final block of the initialization vector
1214  if(n > 0)
1215  {
1216  //Copy partial block
1217  osMemset(b, 0, 16);
1218  osMemcpy(b, iv, n);
1219 
1220  //Apply GHASH function
1221  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1222  }
1223 
1224  //The string is appended with 64 additional 0 bits, followed by the
1225  //64-bit representation of the length of the IV
1226  b[0] = 0;
1227  b[1] = 0;
1228  m = ivLen * 8;
1229  b[2] = htobe32(m >> 32);
1230  b[3] = htobe32(m);
1231 
1232  //The GHASH function is applied to the resulting string to form the
1233  //pre-counter block
1234  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1235  }
1236 
1237  //Compute CIPH(J(0))
1238  if(aesContext->nr == 10)
1239  {
1240  HW_SCE_AES_128EcbEncrypt(aesContext->ek, 4, j, b);
1241  }
1242  else if(aesContext->nr == 12)
1243  {
1244  HW_SCE_AES_192EcbEncrypt(aesContext->ek, 4, j, b);
1245  }
1246  else
1247  {
1248  HW_SCE_AES_256EcbEncrypt(aesContext->ek, 4, j, b);
1249  }
1250 
1251  //Save MSB(CIPH(J(0)))
1252  osMemcpy(t, (const uint8_t *) b, tLen);
1253 
1254  //Increment the right-most 32 bits of the counter block. The remaining
1255  //left-most 96 bits remain unchanged
1256  j[3] = htobe32(betoh32(j[3]) + 1);
1257 
1258  //Initialize GHASH calculation
1259  s[0] = 0;
1260  s[1] = 0;
1261  s[2] = 0;
1262  s[3] = 0;
1263 
1264  //Length of the AAD
1265  n = aLen;
1266 
1267  //Process AAD
1268  if(n >= 16)
1269  {
1270  //Ensure the size of the incoming data to be processed is a multiple
1271  //of 16 bytes
1272  k = n & ~15UL;
1273 
1274  //Apply GHASH function
1275  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) a, s);
1276 
1277  //Advance data pointer
1278  a += k;
1279  n -= k;
1280  }
1281 
1282  //Process the final block of AAD
1283  if(n > 0)
1284  {
1285  //Copy partial block
1286  osMemset(b, 0, 16);
1287  osMemcpy(b, a, n);
1288 
1289  //Apply GHASH function
1290  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1291  }
1292 
1293  //Length of the plaintext
1294  n = length;
1295 
1296  //Process plaintext
1297  if(n >= 16)
1298  {
1299  //Ensure the size of the incoming data to be processed is a multiple
1300  //of 16 bytes
1301  k = n & ~15UL;
1302 
1303  //Encrypt plaintext
1304  if(aesContext->nr == 10)
1305  {
1306  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, k / 4,
1307  (const uint32_t *) p, (uint32_t *) c, j);
1308  }
1309  else if(aesContext->nr == 12)
1310  {
1311  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, k / 4,
1312  (const uint32_t *) p, (uint32_t *) c, j);
1313  }
1314  else
1315  {
1316  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, k / 4,
1317  (const uint32_t *) p, (uint32_t *) c, j);
1318  }
1319 
1320  //Apply GHASH function
1321  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) c, s);
1322 
1323  //Advance data pointer
1324  p += k;
1325  c += k;
1326  n -= k;
1327  }
1328 
1329  //Process the final block of plaintext
1330  if(n > 0)
1331  {
1332  //Copy partial block
1333  osMemset(b, 0, 16);
1334  osMemcpy(b, p, n);
1335 
1336  //Encrypt plaintext
1337  if(aesContext->nr == 10)
1338  {
1339  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1340  }
1341  else if(aesContext->nr == 12)
1342  {
1343  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1344  }
1345  else
1346  {
1347  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1348  }
1349 
1350  //Pad the final ciphertext block with zeroes
1351  osMemset((uint8_t *) b + n, 0, 16 - n);
1352 
1353  //Apply GHASH function
1354  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1355 
1356  //Copy partial block
1357  osMemcpy(c, b, n);
1358  }
1359 
1360  //Append the 64-bit representation of the length of the AAD and the
1361  //ciphertext
1362  m = aLen * 8;
1363  b[0] = htobe32(m >> 32);
1364  b[1] = htobe32(m);
1365  m = length * 8;
1366  b[2] = htobe32(m >> 32);
1367  b[3] = htobe32(m);
1368 
1369  //The GHASH function is applied to the result to produce a single output
1370  //block S
1371  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1372 
1373  //Let T = MSB(GCTR(J(0), S)
1374  gcmXorBlock(t, t, (const uint8_t *) s, tLen);
1375 
1376  //Release exclusive access to the SCE7 module
1378 
1379  //Successful encryption
1380  return NO_ERROR;
1381 }
1382 
1383 
1384 /**
1385  * @brief Authenticated decryption using GCM
1386  * @param[in] context Pointer to the GCM context
1387  * @param[in] iv Initialization vector
1388  * @param[in] ivLen Length of the initialization vector
1389  * @param[in] a Additional authenticated data
1390  * @param[in] aLen Length of the additional data
1391  * @param[in] c Ciphertext to be decrypted
1392  * @param[out] p Plaintext resulting from the decryption
1393  * @param[in] length Total number of data bytes to be decrypted
1394  * @param[in] t Authentication tag
1395  * @param[in] tLen Length of the authentication tag
1396  * @return Error code
1397  **/
1398 
1399 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1400  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1401  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1402 {
1403  uint8_t mask;
1404  size_t k;
1405  size_t n;
1406  uint64_t m;
1407  uint8_t r[16];
1408  uint32_t b[4];
1409  uint32_t j[4];
1410  uint32_t s[4];
1411  AesContext *aesContext;
1412 
1413  ///Make sure the GCM context is valid
1414  if(context == NULL)
1415  return ERROR_INVALID_PARAMETER;
1416 
1417  //The length of the IV shall meet SP 800-38D requirements
1418  if(ivLen < 1)
1419  return ERROR_INVALID_LENGTH;
1420 
1421  //Check the length of the authentication tag
1422  if(tLen < 4 || tLen > 16)
1423  return ERROR_INVALID_LENGTH;
1424 
1425  //Point to the AES context
1426  aesContext = (AesContext *) context->cipherContext;
1427 
1428  //Check the length of the key
1429  if(aesContext->nr != 10 && aesContext->nr != 12 && aesContext->nr != 14)
1430  return ERROR_INVALID_PARAMETER;
1431 
1432  //Acquire exclusive access to the SCE7 module
1434 
1435  //Check whether the length of the IV is 96 bits
1436  if(ivLen == 12)
1437  {
1438  //When the length of the IV is 96 bits, the padding string is appended
1439  //to the IV to form the pre-counter block
1440  j[0] = LOAD32LE(iv);
1441  j[1] = LOAD32LE(iv + 4);
1442  j[2] = LOAD32LE(iv + 8);
1443  j[3] = BETOH32(1);
1444  }
1445  else
1446  {
1447  //Initialize GHASH calculation
1448  j[0] = 0;
1449  j[1] = 0;
1450  j[2] = 0;
1451  j[3] = 0;
1452 
1453  //Length of the IV
1454  n = ivLen;
1455 
1456  //Process the initialization vector
1457  if(n >= 16)
1458  {
1459  //Ensure the size of the incoming data to be processed is a multiple
1460  //of 16 bytes
1461  k = n & ~15UL;
1462 
1463  //Apply GHASH function
1464  HW_SCE_AES_Ghash(context->m[0], j, k / 4, (const uint32_t *) iv, j);
1465 
1466  //Advance data pointer
1467  iv += k;
1468  n -= k;
1469  }
1470 
1471  //Process the final block of the initialization vector
1472  if(n > 0)
1473  {
1474  //Copy partial block
1475  osMemset(b, 0, 16);
1476  osMemcpy(b, iv, n);
1477 
1478  //Apply GHASH function
1479  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1480  }
1481 
1482  //The string is appended with 64 additional 0 bits, followed by the
1483  //64-bit representation of the length of the IV
1484  b[0] = 0;
1485  b[1] = 0;
1486  m = ivLen * 8;
1487  b[2] = htobe32(m >> 32);
1488  b[3] = htobe32(m);
1489 
1490  //The GHASH function is applied to the resulting string to form the
1491  //pre-counter block
1492  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1493  }
1494 
1495  //Compute CIPH(J(0))
1496  if(aesContext->nr == 10)
1497  {
1498  HW_SCE_AES_128EcbEncrypt(aesContext->ek, 4, j, b);
1499  }
1500  else if(aesContext->nr == 12)
1501  {
1502  HW_SCE_AES_192EcbEncrypt(aesContext->ek, 4, j, b);
1503  }
1504  else
1505  {
1506  HW_SCE_AES_256EcbEncrypt(aesContext->ek, 4, j, b);
1507  }
1508 
1509  //Save MSB(CIPH(J(0)))
1510  osMemcpy(r, (const uint8_t *) b, tLen);
1511 
1512  //Increment the right-most 32 bits of the counter block. The remaining
1513  //left-most 96 bits remain unchanged
1514  j[3] = htobe32(betoh32(j[3]) + 1);
1515 
1516  //Initialize GHASH calculation
1517  s[0] = 0;
1518  s[1] = 0;
1519  s[2] = 0;
1520  s[3] = 0;
1521 
1522  //Length of the AAD
1523  n = aLen;
1524 
1525  //Process AAD
1526  if(n >= 16)
1527  {
1528  //Ensure the size of the incoming data to be processed is a multiple
1529  //of 16 bytes
1530  k = n & ~15UL;
1531 
1532  //Apply GHASH function
1533  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) a, s);
1534 
1535  //Advance data pointer
1536  a += k;
1537  n -= k;
1538  }
1539 
1540  //Process the final block of AAD
1541  if(n > 0)
1542  {
1543  //Copy partial block
1544  osMemset(b, 0, 16);
1545  osMemcpy(b, a, n);
1546 
1547  //Apply GHASH function
1548  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1549  }
1550 
1551  //Length of the ciphertext
1552  n = length;
1553 
1554  //Process ciphertext
1555  if(n >= 16)
1556  {
1557  //Ensure the size of the incoming data to be processed is a multiple
1558  //of 16 bytes
1559  k = n & ~15UL;
1560 
1561  //Apply GHASH function
1562  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) c, s);
1563 
1564  //Decrypt ciphertext
1565  if(aesContext->nr == 10)
1566  {
1567  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, k / 4,
1568  (const uint32_t *) c, (uint32_t *) p, j);
1569  }
1570  else if(aesContext->nr == 12)
1571  {
1572  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, k / 4,
1573  (const uint32_t *) c, (uint32_t *) p, j);
1574  }
1575  else
1576  {
1577  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, k / 4,
1578  (const uint32_t *) c, (uint32_t *) p, j);
1579  }
1580 
1581  //Advance data pointer
1582  c += k;
1583  p += k;
1584  n -= k;
1585  }
1586 
1587  //Process the final block of ciphertext
1588  if(n > 0)
1589  {
1590  //Copy partial block
1591  osMemset(b, 0, 16);
1592  osMemcpy(b, c, n);
1593 
1594  //Apply GHASH function
1595  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1596 
1597  //Decrypt ciphertext
1598  if(aesContext->nr == 10)
1599  {
1600  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1601  }
1602  else if(aesContext->nr == 12)
1603  {
1604  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1605  }
1606  else
1607  {
1608  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1609  }
1610 
1611  //Copy partial block
1612  osMemcpy(p, b, n);
1613  }
1614 
1615  //Append the 64-bit representation of the length of the AAD and the
1616  //ciphertext
1617  m = aLen * 8;
1618  b[0] = htobe32(m >> 32);
1619  b[1] = htobe32(m);
1620  m = length * 8;
1621  b[2] = htobe32(m >> 32);
1622  b[3] = htobe32(m);
1623 
1624  //The GHASH function is applied to the result to produce a single output
1625  //block S
1626  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1627 
1628  //Let R = MSB(GCTR(J(0), S))
1629  gcmXorBlock(r, r, (const uint8_t *) s, tLen);
1630 
1631  //The calculated tag is bitwise compared to the received tag. The message
1632  //is authenticated if and only if the tags match
1633  for(mask = 0, n = 0; n < tLen; n++)
1634  {
1635  mask |= r[n] ^ t[n];
1636  }
1637 
1638  //Release exclusive access to the SCE7 module
1640 
1641  //Return status code
1642  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1643 }
1644 
1645 #endif
1646 #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 BETOH32(value)
Definition: cpu_endian.h:451
#define betoh32(value)
Definition: cpu_endian.h:454
#define LOAD32LE(p)
Definition: cpu_endian.h:203
#define htobe32(value)
Definition: cpu_endian.h:446
General definitions for cryptographic algorithms.
Debugging facilities.
#define DES3_CIPHER_ALGO
Definition: des3.h:46
#define DES3_BLOCK_SIZE
Definition: des3.h:44
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
void gcmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: gcm.c:597
uint8_t iv[]
Definition: ike.h:1502
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t b
Definition: nbns_common.h:104
uint8_t h
Definition: ndp.h:302
uint8_t c
Definition: ndp.h:514
uint8_t r
Definition: ndp.h:346
uint8_t s
Definition: ndp.h:345
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
uint8_t a
Definition: ndp.h:411
#define osMemset(p, value, length)
Definition: os_port.h:135
#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.
OsMutex s7g2CryptoMutex
Definition: s7g2_crypto.c:41
Synergy S7G2 hardware cryptographic accelerator (SCE7)
void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using Triple DES algorithm.
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
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.
error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
Initialize a Triple DES context using the supplied key.
void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using Triple DES algorithm.
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 aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
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 ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
Synergy S7G2 cipher hardware accelerator.
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 k1
Definition: des3.h:60
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
uint32_t m[GCM_TABLE_N][4]
Precalculated table.
Definition: gcm.h:67
uint8_t length
Definition: tcp.h:368
uint8_t mask
Definition: web_socket.h:319