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-2025 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.5.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  //Check the value of the parameter
919  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
920  {
921  //Determine the size, in bytes, of the specific part of the block to be
922  //incremented
923  m = m / 8;
924 
925 #if (DES3_SUPPORT == ENABLED)
926  //Triple DES cipher algorithm?
927  if(cipher == DES3_CIPHER_ALGO)
928  {
929  //Check the length of the payload
930  if(length == 0)
931  {
932  //No data to process
933  }
934  else if((length % DES3_BLOCK_SIZE) == 0)
935  {
936  size_t k;
937  size_t n;
938  Des3Context *des3Context;
939  uint32_t temp[DES3_BLOCK_SIZE];
940 
941  //Point to the Triple DES context
942  des3Context = (Des3Context *) context;
943 
944  //Acquire exclusive access to the SCE7 module
946 
947  //Process plaintext
948  while(length > 0 && status == SSP_SUCCESS)
949  {
950  //Limit the number of blocks to process at a time
951  k = 256 - t[DES3_BLOCK_SIZE - 1];
952  n = MIN(length, k * DES3_BLOCK_SIZE);
953  k = (n + DES3_BLOCK_SIZE - 1) / DES3_BLOCK_SIZE;
954 
955  //Perform 3DES-CTR encryption
956  status = HW_SCE_TDES_192CtrEncrypt(des3Context->k1.ks,
957  (const uint32_t *) t, n / 4, (const uint32_t *) p,
958  (uint32_t *) c, (uint32_t *) temp);
959 
960  //Standard incrementing function
962 
963  //Next block
964  p += n;
965  c += n;
966  length -= n;
967  }
968 
969  //Release exclusive access to the SCE7 module
971  }
972  else
973  {
974  //The length of the payload must be a multiple of the block size
975  status = SSP_ERR_CRYPTO_INVALID_SIZE;
976  }
977  }
978  else
979 #endif
980 #if (AES_SUPPORT == ENABLED)
981  //AES cipher algorithm?
982  if(cipher == AES_CIPHER_ALGO)
983  {
984  //Check the length of the payload
985  if(length == 0)
986  {
987  //No data to process
988  }
989  else if((length % AES_BLOCK_SIZE) == 0)
990  {
991  size_t k;
992  size_t n;
993  AesContext *aesContext;
994  uint32_t temp[AES_BLOCK_SIZE];
995 
996  //Point to the AES context
997  aesContext = (AesContext *) context;
998 
999  //Acquire exclusive access to the SCE7 module
1001 
1002  //Process plaintext
1003  while(length > 0 && status == SSP_SUCCESS)
1004  {
1005  //Limit the number of blocks to process at a time
1006  k = 256 - t[AES_BLOCK_SIZE - 1];
1007  n = MIN(length, k * AES_BLOCK_SIZE);
1008  k = (n + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
1009 
1010  //Check the length of the key
1011  if(aesContext->nr == 10)
1012  {
1013  //Perform AES-CTR encryption (128-bit key)
1014  status = HW_SCE_AES_128CtrEncrypt(aesContext->ek,
1015  (const uint32_t *) t, n / 4, (const uint32_t *) p,
1016  (uint32_t *) c, (uint32_t *) temp);
1017  }
1018  else if(aesContext->nr == 12)
1019  {
1020  //Perform AES-CTR encryption (192-bit key)
1021  status = HW_SCE_AES_192CtrEncrypt(aesContext->ek,
1022  (const uint32_t *) t, n / 4, (const uint32_t *) p,
1023  (uint32_t *) c, (uint32_t *) temp);
1024  }
1025  else if(aesContext->nr == 14)
1026  {
1027  //Perform AES-CTR encryption (256-bit key)
1028  status = HW_SCE_AES_256CtrEncrypt(aesContext->ek,
1029  (const uint32_t *) t, n / 4, (const uint32_t *) p,
1030  (uint32_t *) c, (uint32_t *) temp);
1031  }
1032  else
1033  {
1034  //Invalid key length
1035  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1036  }
1037 
1038  //Standard incrementing function
1039  ctrIncBlock(t, k, AES_BLOCK_SIZE, m);
1040 
1041  //Next block
1042  p += n;
1043  c += n;
1044  length -= n;
1045  }
1046 
1047  //Release exclusive access to the SCE7 module
1049  }
1050  else
1051  {
1052  //The length of the payload must be a multiple of the block size
1053  status = SSP_ERR_CRYPTO_INVALID_SIZE;
1054  }
1055  }
1056  else
1057 #endif
1058  //Unknown cipher algorithm?
1059  {
1060  size_t i;
1061  size_t n;
1062  uint8_t o[16];
1063 
1064  //Process plaintext
1065  while(length > 0)
1066  {
1067  //CTR mode operates in a block-by-block fashion
1068  n = MIN(length, cipher->blockSize);
1069 
1070  //Compute O(j) = CIPH(T(j))
1071  cipher->encryptBlock(context, t, o);
1072 
1073  //Compute C(j) = P(j) XOR T(j)
1074  for(i = 0; i < n; i++)
1075  {
1076  c[i] = p[i] ^ o[i];
1077  }
1078 
1079  //Standard incrementing function
1080  ctrIncBlock(t, 1, cipher->blockSize, m);
1081 
1082  //Next block
1083  p += n;
1084  c += n;
1085  length -= n;
1086  }
1087  }
1088  }
1089  else
1090  {
1091  //The value of the parameter is not valid
1092  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1093  }
1094 
1095  //Return status code
1096  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
1097 }
1098 
1099 #endif
1100 #if (GCM_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1101 
1102 /**
1103  * @brief Initialize GCM context
1104  * @param[in] context Pointer to the GCM context
1105  * @param[in] cipherAlgo Cipher algorithm
1106  * @param[in] cipherContext Pointer to the cipher algorithm context
1107  * @return Error code
1108  **/
1109 
1110 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1111  void *cipherContext)
1112 {
1113  uint32_t h[4];
1114 
1115  //The SCE7 module only supports AES cipher algorithm
1116  if(cipherAlgo != AES_CIPHER_ALGO)
1117  return ERROR_INVALID_PARAMETER;
1118 
1119  //Save cipher algorithm context
1120  context->cipherAlgo = cipherAlgo;
1121  context->cipherContext = cipherContext;
1122 
1123  //Let H = 0
1124  h[0] = 0;
1125  h[1] = 0;
1126  h[2] = 0;
1127  h[3] = 0;
1128 
1129  //Generate the hash subkey H
1130  aesEncryptBlock(context->cipherContext, (uint8_t *) h, (uint8_t *) h);
1131 
1132  //Save the resulting value
1133  context->m[0][0] = h[0];
1134  context->m[0][1] = h[1];
1135  context->m[0][2] = h[2];
1136  context->m[0][3] = h[3];
1137 
1138  //Successful initialization
1139  return NO_ERROR;
1140 }
1141 
1142 
1143 /**
1144  * @brief Authenticated encryption using GCM
1145  * @param[in] context Pointer to the GCM context
1146  * @param[in] iv Initialization vector
1147  * @param[in] ivLen Length of the initialization vector
1148  * @param[in] a Additional authenticated data
1149  * @param[in] aLen Length of the additional data
1150  * @param[in] p Plaintext to be encrypted
1151  * @param[out] c Ciphertext resulting from the encryption
1152  * @param[in] length Total number of data bytes to be encrypted
1153  * @param[out] t Authentication tag
1154  * @param[in] tLen Length of the authentication tag
1155  * @return Error code
1156  **/
1157 
1158 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1159  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1160  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1161 {
1162  size_t k;
1163  size_t n;
1164  uint64_t m;
1165  uint32_t b[4];
1166  uint32_t j[4];
1167  uint32_t s[4];
1168  AesContext *aesContext;
1169 
1170  //Make sure the GCM context is valid
1171  if(context == NULL)
1172  return ERROR_INVALID_PARAMETER;
1173 
1174  //The length of the IV shall meet SP 800-38D requirements
1175  if(ivLen < 1)
1176  return ERROR_INVALID_LENGTH;
1177 
1178  //Check the length of the authentication tag
1179  if(tLen < 4 || tLen > 16)
1180  return ERROR_INVALID_LENGTH;
1181 
1182  //Point to the AES context
1183  aesContext = (AesContext *) context->cipherContext;
1184 
1185  //Check the length of the key
1186  if(aesContext->nr != 10 && aesContext->nr != 12 && aesContext->nr != 14)
1187  return ERROR_INVALID_PARAMETER;
1188 
1189  //Acquire exclusive access to the SCE7 module
1191 
1192  //Check whether the length of the IV is 96 bits
1193  if(ivLen == 12)
1194  {
1195  //When the length of the IV is 96 bits, the padding string is appended
1196  //to the IV to form the pre-counter block
1197  j[0] = LOAD32LE(iv);
1198  j[1] = LOAD32LE(iv + 4);
1199  j[2] = LOAD32LE(iv + 8);
1200  j[3] = BETOH32(1);
1201  }
1202  else
1203  {
1204  //Initialize GHASH calculation
1205  j[0] = 0;
1206  j[1] = 0;
1207  j[2] = 0;
1208  j[3] = 0;
1209 
1210  //Length of the IV
1211  n = ivLen;
1212 
1213  //Process the initialization vector
1214  if(n >= 16)
1215  {
1216  //Ensure the size of the incoming data to be processed is a multiple
1217  //of 16 bytes
1218  k = n & ~15UL;
1219 
1220  //Apply GHASH function
1221  HW_SCE_AES_Ghash(context->m[0], j, k / 4, (const uint32_t *) iv, j);
1222 
1223  //Advance data pointer
1224  iv += k;
1225  n -= k;
1226  }
1227 
1228  //Process the final block of the initialization vector
1229  if(n > 0)
1230  {
1231  //Copy partial block
1232  osMemset(b, 0, 16);
1233  osMemcpy(b, iv, n);
1234 
1235  //Apply GHASH function
1236  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1237  }
1238 
1239  //The string is appended with 64 additional 0 bits, followed by the
1240  //64-bit representation of the length of the IV
1241  b[0] = 0;
1242  b[1] = 0;
1243  m = ivLen * 8;
1244  b[2] = htobe32(m >> 32);
1245  b[3] = htobe32(m);
1246 
1247  //The GHASH function is applied to the resulting string to form the
1248  //pre-counter block
1249  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1250  }
1251 
1252  //Compute CIPH(J(0))
1253  if(aesContext->nr == 10)
1254  {
1255  HW_SCE_AES_128EcbEncrypt(aesContext->ek, 4, j, b);
1256  }
1257  else if(aesContext->nr == 12)
1258  {
1259  HW_SCE_AES_192EcbEncrypt(aesContext->ek, 4, j, b);
1260  }
1261  else
1262  {
1263  HW_SCE_AES_256EcbEncrypt(aesContext->ek, 4, j, b);
1264  }
1265 
1266  //Save MSB(CIPH(J(0)))
1267  osMemcpy(t, (const uint8_t *) b, tLen);
1268 
1269  //Increment the right-most 32 bits of the counter block. The remaining
1270  //left-most 96 bits remain unchanged
1271  j[3] = htobe32(betoh32(j[3]) + 1);
1272 
1273  //Initialize GHASH calculation
1274  s[0] = 0;
1275  s[1] = 0;
1276  s[2] = 0;
1277  s[3] = 0;
1278 
1279  //Length of the AAD
1280  n = aLen;
1281 
1282  //Process AAD
1283  if(n >= 16)
1284  {
1285  //Ensure the size of the incoming data to be processed is a multiple
1286  //of 16 bytes
1287  k = n & ~15UL;
1288 
1289  //Apply GHASH function
1290  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) a, s);
1291 
1292  //Advance data pointer
1293  a += k;
1294  n -= k;
1295  }
1296 
1297  //Process the final block of AAD
1298  if(n > 0)
1299  {
1300  //Copy partial block
1301  osMemset(b, 0, 16);
1302  osMemcpy(b, a, n);
1303 
1304  //Apply GHASH function
1305  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1306  }
1307 
1308  //Length of the plaintext
1309  n = length;
1310 
1311  //Process plaintext
1312  if(n >= 16)
1313  {
1314  //Ensure the size of the incoming data to be processed is a multiple
1315  //of 16 bytes
1316  k = n & ~15UL;
1317 
1318  //Encrypt plaintext
1319  if(aesContext->nr == 10)
1320  {
1321  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, k / 4,
1322  (const uint32_t *) p, (uint32_t *) c, j);
1323  }
1324  else if(aesContext->nr == 12)
1325  {
1326  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, k / 4,
1327  (const uint32_t *) p, (uint32_t *) c, j);
1328  }
1329  else
1330  {
1331  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, k / 4,
1332  (const uint32_t *) p, (uint32_t *) c, j);
1333  }
1334 
1335  //Apply GHASH function
1336  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) c, s);
1337 
1338  //Advance data pointer
1339  p += k;
1340  c += k;
1341  n -= k;
1342  }
1343 
1344  //Process the final block of plaintext
1345  if(n > 0)
1346  {
1347  //Copy partial block
1348  osMemset(b, 0, 16);
1349  osMemcpy(b, p, n);
1350 
1351  //Encrypt plaintext
1352  if(aesContext->nr == 10)
1353  {
1354  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1355  }
1356  else if(aesContext->nr == 12)
1357  {
1358  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1359  }
1360  else
1361  {
1362  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1363  }
1364 
1365  //Pad the final ciphertext block with zeroes
1366  osMemset((uint8_t *) b + n, 0, 16 - n);
1367 
1368  //Apply GHASH function
1369  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1370 
1371  //Copy partial block
1372  osMemcpy(c, b, n);
1373  }
1374 
1375  //Append the 64-bit representation of the length of the AAD and the
1376  //ciphertext
1377  m = aLen * 8;
1378  b[0] = htobe32(m >> 32);
1379  b[1] = htobe32(m);
1380  m = length * 8;
1381  b[2] = htobe32(m >> 32);
1382  b[3] = htobe32(m);
1383 
1384  //The GHASH function is applied to the result to produce a single output
1385  //block S
1386  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1387 
1388  //Let T = MSB(GCTR(J(0), S)
1389  gcmXorBlock(t, t, (const uint8_t *) s, tLen);
1390 
1391  //Release exclusive access to the SCE7 module
1393 
1394  //Successful encryption
1395  return NO_ERROR;
1396 }
1397 
1398 
1399 /**
1400  * @brief Authenticated decryption using GCM
1401  * @param[in] context Pointer to the GCM context
1402  * @param[in] iv Initialization vector
1403  * @param[in] ivLen Length of the initialization vector
1404  * @param[in] a Additional authenticated data
1405  * @param[in] aLen Length of the additional data
1406  * @param[in] c Ciphertext to be decrypted
1407  * @param[out] p Plaintext resulting from the decryption
1408  * @param[in] length Total number of data bytes to be decrypted
1409  * @param[in] t Authentication tag
1410  * @param[in] tLen Length of the authentication tag
1411  * @return Error code
1412  **/
1413 
1414 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1415  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1416  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1417 {
1418  uint8_t mask;
1419  size_t k;
1420  size_t n;
1421  uint64_t m;
1422  uint8_t r[16];
1423  uint32_t b[4];
1424  uint32_t j[4];
1425  uint32_t s[4];
1426  AesContext *aesContext;
1427 
1428  ///Make sure the GCM context is valid
1429  if(context == NULL)
1430  return ERROR_INVALID_PARAMETER;
1431 
1432  //The length of the IV shall meet SP 800-38D requirements
1433  if(ivLen < 1)
1434  return ERROR_INVALID_LENGTH;
1435 
1436  //Check the length of the authentication tag
1437  if(tLen < 4 || tLen > 16)
1438  return ERROR_INVALID_LENGTH;
1439 
1440  //Point to the AES context
1441  aesContext = (AesContext *) context->cipherContext;
1442 
1443  //Check the length of the key
1444  if(aesContext->nr != 10 && aesContext->nr != 12 && aesContext->nr != 14)
1445  return ERROR_INVALID_PARAMETER;
1446 
1447  //Acquire exclusive access to the SCE7 module
1449 
1450  //Check whether the length of the IV is 96 bits
1451  if(ivLen == 12)
1452  {
1453  //When the length of the IV is 96 bits, the padding string is appended
1454  //to the IV to form the pre-counter block
1455  j[0] = LOAD32LE(iv);
1456  j[1] = LOAD32LE(iv + 4);
1457  j[2] = LOAD32LE(iv + 8);
1458  j[3] = BETOH32(1);
1459  }
1460  else
1461  {
1462  //Initialize GHASH calculation
1463  j[0] = 0;
1464  j[1] = 0;
1465  j[2] = 0;
1466  j[3] = 0;
1467 
1468  //Length of the IV
1469  n = ivLen;
1470 
1471  //Process the initialization vector
1472  if(n >= 16)
1473  {
1474  //Ensure the size of the incoming data to be processed is a multiple
1475  //of 16 bytes
1476  k = n & ~15UL;
1477 
1478  //Apply GHASH function
1479  HW_SCE_AES_Ghash(context->m[0], j, k / 4, (const uint32_t *) iv, j);
1480 
1481  //Advance data pointer
1482  iv += k;
1483  n -= k;
1484  }
1485 
1486  //Process the final block of the initialization vector
1487  if(n > 0)
1488  {
1489  //Copy partial block
1490  osMemset(b, 0, 16);
1491  osMemcpy(b, iv, n);
1492 
1493  //Apply GHASH function
1494  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1495  }
1496 
1497  //The string is appended with 64 additional 0 bits, followed by the
1498  //64-bit representation of the length of the IV
1499  b[0] = 0;
1500  b[1] = 0;
1501  m = ivLen * 8;
1502  b[2] = htobe32(m >> 32);
1503  b[3] = htobe32(m);
1504 
1505  //The GHASH function is applied to the resulting string to form the
1506  //pre-counter block
1507  HW_SCE_AES_Ghash(context->m[0], j, 4, b, j);
1508  }
1509 
1510  //Compute CIPH(J(0))
1511  if(aesContext->nr == 10)
1512  {
1513  HW_SCE_AES_128EcbEncrypt(aesContext->ek, 4, j, b);
1514  }
1515  else if(aesContext->nr == 12)
1516  {
1517  HW_SCE_AES_192EcbEncrypt(aesContext->ek, 4, j, b);
1518  }
1519  else
1520  {
1521  HW_SCE_AES_256EcbEncrypt(aesContext->ek, 4, j, b);
1522  }
1523 
1524  //Save MSB(CIPH(J(0)))
1525  osMemcpy(r, (const uint8_t *) b, tLen);
1526 
1527  //Increment the right-most 32 bits of the counter block. The remaining
1528  //left-most 96 bits remain unchanged
1529  j[3] = htobe32(betoh32(j[3]) + 1);
1530 
1531  //Initialize GHASH calculation
1532  s[0] = 0;
1533  s[1] = 0;
1534  s[2] = 0;
1535  s[3] = 0;
1536 
1537  //Length of the AAD
1538  n = aLen;
1539 
1540  //Process AAD
1541  if(n >= 16)
1542  {
1543  //Ensure the size of the incoming data to be processed is a multiple
1544  //of 16 bytes
1545  k = n & ~15UL;
1546 
1547  //Apply GHASH function
1548  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) a, s);
1549 
1550  //Advance data pointer
1551  a += k;
1552  n -= k;
1553  }
1554 
1555  //Process the final block of AAD
1556  if(n > 0)
1557  {
1558  //Copy partial block
1559  osMemset(b, 0, 16);
1560  osMemcpy(b, a, n);
1561 
1562  //Apply GHASH function
1563  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1564  }
1565 
1566  //Length of the ciphertext
1567  n = length;
1568 
1569  //Process ciphertext
1570  if(n >= 16)
1571  {
1572  //Ensure the size of the incoming data to be processed is a multiple
1573  //of 16 bytes
1574  k = n & ~15UL;
1575 
1576  //Apply GHASH function
1577  HW_SCE_AES_Ghash(context->m[0], s, k / 4, (const uint32_t *) c, s);
1578 
1579  //Decrypt ciphertext
1580  if(aesContext->nr == 10)
1581  {
1582  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, k / 4,
1583  (const uint32_t *) c, (uint32_t *) p, j);
1584  }
1585  else if(aesContext->nr == 12)
1586  {
1587  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, k / 4,
1588  (const uint32_t *) c, (uint32_t *) p, j);
1589  }
1590  else
1591  {
1592  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, k / 4,
1593  (const uint32_t *) c, (uint32_t *) p, j);
1594  }
1595 
1596  //Advance data pointer
1597  c += k;
1598  p += k;
1599  n -= k;
1600  }
1601 
1602  //Process the final block of ciphertext
1603  if(n > 0)
1604  {
1605  //Copy partial block
1606  osMemset(b, 0, 16);
1607  osMemcpy(b, c, n);
1608 
1609  //Apply GHASH function
1610  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1611 
1612  //Decrypt ciphertext
1613  if(aesContext->nr == 10)
1614  {
1615  HW_SCE_AES_128GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1616  }
1617  else if(aesContext->nr == 12)
1618  {
1619  HW_SCE_AES_192GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1620  }
1621  else
1622  {
1623  HW_SCE_AES_256GctrEncrypt(aesContext->ek, j, 4, b, b, j);
1624  }
1625 
1626  //Copy partial block
1627  osMemcpy(p, b, n);
1628  }
1629 
1630  //Append the 64-bit representation of the length of the AAD and the
1631  //ciphertext
1632  m = aLen * 8;
1633  b[0] = htobe32(m >> 32);
1634  b[1] = htobe32(m);
1635  m = length * 8;
1636  b[2] = htobe32(m >> 32);
1637  b[3] = htobe32(m);
1638 
1639  //The GHASH function is applied to the result to produce a single output
1640  //block S
1641  HW_SCE_AES_Ghash(context->m[0], s, 4, b, s);
1642 
1643  //Let R = MSB(GCTR(J(0), S))
1644  gcmXorBlock(r, r, (const uint8_t *) s, tLen);
1645 
1646  //The calculated tag is bitwise compared to the received tag. The message
1647  //is authenticated if and only if the tags match
1648  for(mask = 0, n = 0; n < tLen; n++)
1649  {
1650  mask |= r[n] ^ t[n];
1651  }
1652 
1653  //Release exclusive access to the SCE7 module
1655 
1656  //Return status code
1657  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1658 }
1659 
1660 #endif
1661 #endif
#define betoh32(value)
Definition: cpu_endian.h:454
uint8_t b
Definition: nbns_common.h:104
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
uint8_t a
Definition: ndp.h:411
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1113
uint8_t p
Definition: ndp.h:300
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t o
Collection of AEAD algorithms.
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
size_t blockSize
Definition: crypto.h:1108
#define BETOH32(value)
Definition: cpu_endian.h:451
DesContext k1
Definition: des3.h:60
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.
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1112
#define DES3_BLOCK_SIZE
Definition: des3.h:44
uint8_t r
Definition: ndp.h:346
AES algorithm context.
Definition: aes.h:58
#define AES_BLOCK_SIZE
Definition: aes.h:43
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.
uint8_t h
Definition: ndp.h:302
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
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
Error codes.
Definition: error.h:43
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t iv[]
Definition: ike.h:1626
Block cipher modes of operation.
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
uint32_t m[GCM_TABLE_N][4]
Precalculated table.
Definition: gcm.h:67
uint_t nr
Definition: aes.h:59
void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using Triple DES algorithm.
#define htobe32(value)
Definition: cpu_endian.h:446
GCM context.
Definition: gcm.h:64
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
Triple DES algorithm context.
Definition: des3.h:59
uint8_t m
Definition: ndp.h:304
uint8_t n
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
OsMutex s7g2CryptoMutex
Definition: s7g2_crypto.c:41
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void gcmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: gcm.c:592
Common interface for encryption algorithms.
Definition: crypto.h:1104
void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using Triple DES algorithm.
#define AES_CIPHER_ALGO
Definition: aes.h:45
uint8_t s
Definition: igmp_common.h:234
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
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 gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
Synergy S7G2 cipher hardware accelerator.
#define DES3_CIPHER_ALGO
Definition: des3.h:46
#define LOAD32LE(p)
Definition: cpu_endian.h:203
uint32_t ek[60]
Definition: aes.h:60
Synergy S7G2 hardware cryptographic accelerator (SCE7)
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:66
uint32_t ks[32]
Definition: des.h:59
void ctrIncBlock(uint8_t *ctr, uint32_t inc, size_t blockSize, size_t m)
Increment counter block.
Definition: ctr.c:138
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.