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