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