pic32cx_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file pic32cx_crypto_cipher.c
3  * @brief PIC32CX cipher hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2023 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.2.2
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_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 (GCM_SUPPORT == ENABLED)
873 
874 /**
875  * @brief Generate hash subkey
876  * @param[in] context AES algorithm context
877  **/
878 
880 {
881  //Perform software reset
882  AES_REGS->AES_CTRLA = AES_CTRLA_SWRST_Msk;
883  AES_REGS->AES_CTRLA = 0;
884  AES_REGS->AES_CTRLB = 0;
885 
886  //Set operation mode
887  AES_REGS->AES_CTRLA = AES_CTRLA_STARTMODE_MANUAL | AES_CTRLA_CIPHER_ENC |
888  AES_CTRLA_AESMODE_ECB | AES_CTRLA_CTYPE(15);
889 
890  //Set encryption key
891  aesLoadKey(context);
892  //Write zero to CIPLEN register
893  AES_REGS->AES_CIPLEN = 0;
894  //Enable AES module
895  AES_REGS->AES_CTRLA |= AES_CTRLA_ENABLE_Msk;
896 
897  //Write the zeros to DATA register
898  AES_REGS->AES_INDATA = 0;
899  AES_REGS->AES_INDATA = 0;
900  AES_REGS->AES_INDATA = 0;
901  AES_REGS->AES_INDATA = 0;
902 
903  //Generate the hash subkey
904  AES_REGS->AES_CTRLB |= AES_CTRLB_START_Msk;
905 
906  //The ENCCMP status flag is set when the hash subkey generation is complete
907  while((AES_REGS->AES_INTFLAG & AES_INTFLAG_ENCCMP_Msk) == 0)
908  {
909  }
910 
911  //Disable AES module
912  AES_REGS->AES_CTRLA &= ~AES_CTRLA_ENABLE_Msk;
913 }
914 
915 
916 /**
917  * @brief Set GCM operation mode
918  * @param[in] context AES algorithm context
919  * @param[in] mode Operation mode (encryption or decryption)
920  **/
921 
922 void gcmSetMode(AesContext *context, uint32_t mode)
923 {
924  //Set operation mode
925  AES_REGS->AES_CTRLA = AES_CTRLA_STARTMODE_MANUAL | mode |
926  AES_CTRLA_AESMODE_GCM | AES_CTRLA_CTYPE(15);
927 
928  //Set encryption key
929  aesLoadKey(context);
930 
931  //Enable AES module
932  AES_REGS->AES_CTRLA |= AES_CTRLA_ENABLE_Msk;
933 }
934 
935 
936 /**
937  * @brief Update GHASH value
938  * @param[in] data Input block of data
939  **/
940 
941 void gcmUpdateGhash(const uint8_t *data)
942 {
943  uint32_t *p;
944 
945  //Write data block
946  p = (uint32_t *) data;
947  AES_REGS->AES_INDATA = p[0];
948  AES_REGS->AES_INDATA = p[1];
949  AES_REGS->AES_INDATA = p[2];
950  AES_REGS->AES_INDATA = p[3];
951 
952  //Start GF multiplication
953  AES_REGS->AES_CTRLB |= AES_CTRLB_START_Msk;
954 
955  //The ENCCMP status flag is set when the GF multiplication is complete
956  while((AES_REGS->AES_INTFLAG & AES_INTFLAG_GFMCMP_Msk) == 0)
957  {
958  }
959 }
960 
961 
962 /**
963  * @brief Generate pre-counter block
964  * @param[in] iv Initialization vector
965  * @param[in] ivLen Length of the initialization vector
966  * @param[out] j Resulting value of the pre-counter block (J0)
967  **/
968 
969 void gcmGeneratePreCounterBlock(const uint8_t *iv, size_t ivLen, uint32_t *j)
970 {
971  size_t k;
972  size_t n;
973  uint8_t buffer[16];
974 
975  //Check whether the length of the IV is 96 bits
976  if(ivLen == 12)
977  {
978  //When the length of the IV is 96 bits, the padding string is appended
979  //to the IV to form the pre-counter block
980  j[0] = LOAD32LE(iv);
981  j[1] = LOAD32LE(iv + 4);
982  j[2] = LOAD32LE(iv + 8);
983  j[3] = BETOH32(1);
984  }
985  else
986  {
987  //Set GFMUL bit
988  AES_REGS->AES_CTRLB |= AES_CTRLB_GFMUL_Msk;
989 
990  //Initialize GHASH calculation
991  osMemset(buffer, 0, 16);
992 
993  //Length of the IV
994  n = ivLen;
995 
996  //Process the initialization vector
997  while(n > 0)
998  {
999  //The IV processed in a block-by-block fashion
1000  k = MIN(n, 16);
1001 
1002  //Copy current block
1003  osMemset(buffer, 0, 16);
1004  osMemcpy(buffer, iv, k);
1005 
1006  //Apply GHASH function
1007  gcmUpdateGhash(buffer);
1008 
1009  //Next block
1010  iv += k;
1011  n -= k;
1012  }
1013 
1014  //The string is appended with 64 additional 0 bits, followed by the
1015  //64-bit representation of the length of the IV
1016  osMemset(buffer, 0, 8);
1017  STORE64BE(ivLen * 8, buffer + 8);
1018 
1019  //The GHASH function is applied to the resulting string to form the
1020  //pre-counter block
1021  gcmUpdateGhash(buffer);
1022 
1023  //Retrieve the resulting value
1024  j[0] = AES_REGS->AES_GHASH[0];
1025  j[1] = AES_REGS->AES_GHASH[1];
1026  j[2] = AES_REGS->AES_GHASH[2];
1027  j[3] = AES_REGS->AES_GHASH[3];
1028 
1029  //Reset GHASH calculation
1030  AES_REGS->AES_GHASH[0] = 0;
1031  AES_REGS->AES_GHASH[1] = 0;
1032  AES_REGS->AES_GHASH[2] = 0;
1033  AES_REGS->AES_GHASH[3] = 0;
1034  }
1035 }
1036 
1037 
1038 /**
1039  * @brief Process additional authenticated data
1040  * @param[in] aad Additional authenticated data
1041  * @param[in] aadLen Length of the additional data
1042  **/
1043 
1044 void gcmProcessAuthData(const uint8_t *aad, size_t aadLen)
1045 {
1046  //Set GFMUL bit
1047  AES_REGS->AES_CTRLB |= AES_CTRLB_GFMUL_Msk;
1048 
1049  //Process additional authenticated data
1050  while(aadLen > 16)
1051  {
1052  //Additional authenticated data is written block by block
1053  gcmUpdateGhash(aad);
1054 
1055  //Next block
1056  aad += 16;
1057  aadLen -= 16;
1058  }
1059 
1060  //Process final block of additional authenticated data
1061  if(aadLen > 0)
1062  {
1063  uint8_t buffer[16];
1064 
1065  //Copy partial block
1066  osMemset(buffer, 0, 16);
1067  osMemcpy(buffer, aad, aadLen);
1068 
1069  //Write the resulting block
1070  gcmUpdateGhash(buffer);
1071  }
1072 }
1073 
1074 
1075 /**
1076  * @brief Encrypt/decrypt payload data
1077  * @param[in] j Value of the pre-counter block (J0)
1078  * @param[in] input Data to be encrypted/decrypted
1079  * @param[out] output Data resulting from the encryption/decryption process
1080  * @param[in] length Total number of data bytes to be processed
1081  **/
1082 
1083 void gcmProcessData(const uint32_t *j, const uint8_t *input, uint8_t *output,
1084  size_t length)
1085 {
1086  uint32_t buffer[4];
1087 
1088  //Clear GFMUL bit
1089  AES_REGS->AES_CTRLB &= ~AES_CTRLB_GFMUL_Msk;
1090 
1091  //Copy the left-most 96-bits of the counter block
1092  buffer[0] = j[0];
1093  buffer[1] = j[1];
1094  buffer[2] = j[2];
1095 
1096  //Increment the right-most 32 bits of the counter block
1097  buffer[3] = betoh32(j[3]) + 1;
1098  buffer[3] = htobe32(buffer[3]);
1099 
1100  //Load the resulting value in INTVECT registers
1101  AES_REGS->AES_INTVECTV[0] = buffer[0];
1102  AES_REGS->AES_INTVECTV[1] = buffer[1];
1103  AES_REGS->AES_INTVECTV[2] = buffer[2];
1104  AES_REGS->AES_INTVECTV[3] = buffer[3];
1105 
1106  //Set NEWMSG bit for the new set of plain text processing
1107  AES_REGS->AES_CTRLB |= AES_CTRLB_NEWMSG_Msk;
1108  //Load CIPLEN register
1109  AES_REGS->AES_CIPLEN = length;
1110  //Clear ENCCMP status flag
1111  AES_REGS->AES_INTFLAG = AES_INTFLAG_ENCCMP_Msk;
1112 
1113  //Process data
1114  while(length > AES_BLOCK_SIZE)
1115  {
1116  //The data is encrypted block by block
1117  aesProcessDataBlock(input, output);
1118 
1119  //Next block
1120  input += AES_BLOCK_SIZE;
1121  output += AES_BLOCK_SIZE;
1123  }
1124 
1125  //Process final block of data
1126  if(length == AES_BLOCK_SIZE)
1127  {
1128  //Set EOM bit for the last block of data
1129  AES_REGS->AES_CTRLB |= AES_CTRLB_EOM_Msk;
1130 
1131  //Encrypt the final block of data
1132  aesProcessDataBlock(input, output);
1133  }
1134  else if(length > 0)
1135  {
1136  uint8_t inputBlock[AES_BLOCK_SIZE];
1137  uint8_t outputBlock[AES_BLOCK_SIZE];
1138 
1139  //Save current GHASH value
1140  buffer[0] = AES_REGS->AES_GHASH[0];
1141  buffer[1] = AES_REGS->AES_GHASH[1];
1142  buffer[2] = AES_REGS->AES_GHASH[2];
1143  buffer[3] = AES_REGS->AES_GHASH[3];
1144 
1145  //Set EOM bit for the last block of data
1146  AES_REGS->AES_CTRLB |= AES_CTRLB_EOM_Msk;
1147 
1148  //Copy input data
1149  osMemset(inputBlock, 0, AES_BLOCK_SIZE);
1150  osMemcpy(inputBlock, input, length);
1151 
1152  //Encrypt the final block of data
1153  aesProcessDataBlock(inputBlock, outputBlock);
1154 
1155  //Copy output data
1156  osMemcpy(output, outputBlock, length);
1157 
1158  //Restore previous GHASH value (workaround)
1159  AES_REGS->AES_GHASH[0] = buffer[0];
1160  AES_REGS->AES_GHASH[1] = buffer[1];
1161  AES_REGS->AES_GHASH[2] = buffer[2];
1162  AES_REGS->AES_GHASH[3] = buffer[3];
1163 
1164  //Set GFMUL bit
1165  AES_REGS->AES_CTRLB |= AES_CTRLB_GFMUL_Msk;
1166 
1167  //Check operation mode
1168  if((AES_REGS->AES_CTRLA & AES_CTRLA_CIPHER_ENC) != 0)
1169  {
1170  osMemset(inputBlock, 0, AES_BLOCK_SIZE);
1171  osMemcpy(inputBlock, output, length);
1172  }
1173 
1174  //Recompute GHASH value (workaround)
1175  gcmUpdateGhash(inputBlock);
1176 
1177  //Clear GFMUL bit
1178  AES_REGS->AES_CTRLB &= ~AES_CTRLB_GFMUL_Msk;
1179  }
1180  else
1181  {
1182  //Just for sanity
1183  }
1184 }
1185 
1186 
1187 /**
1188  * @brief Calculate authentication tag
1189  * @param[in] context AES algorithm context
1190  * @param[in] j Value of the pre-counter block (J0)
1191  * @param[in] aadLen Length of the additional data, in bytes
1192  * @param[in] dataLen Length of the payload data, in bytes
1193  * @param[out] tag Authentication tag
1194  **/
1195 
1196 void gcmGenerateTag(AesContext *context, const uint32_t *j, size_t aadLen,
1197  size_t dataLen, uint8_t *tag)
1198 {
1199  uint32_t buffer[4];
1200  uint64_t n;
1201 
1202  //Append the 64-bit representation of the length of the AAD and the
1203  //ciphertext
1204  n = aadLen * 8;
1205  buffer[0] = htobe32(n >> 32);
1206  buffer[1] = htobe32(n);
1207  n = dataLen * 8;
1208  buffer[2] = htobe32(n >> 32);
1209  buffer[3] = htobe32(n);
1210 
1211  //Set GFMUL bit
1212  AES_REGS->AES_CTRLB |= AES_CTRLB_GFMUL_Msk;
1213 
1214  //Apply GHASH function
1215  gcmUpdateGhash((uint8_t *) buffer);
1216 
1217  //The hardware generates the final GHASH value in GHASH registers
1218  buffer[0] = AES_REGS->AES_GHASH[0];
1219  buffer[1] = AES_REGS->AES_GHASH[1];
1220  buffer[2] = AES_REGS->AES_GHASH[2];
1221  buffer[3] = AES_REGS->AES_GHASH[3];
1222 
1223  //Disable AES module
1224  AES_REGS->AES_CTRLA = 0;
1225  AES_REGS->AES_CTRLB = 0;
1226 
1227  //Set operation mode
1228  AES_REGS->AES_CTRLA = AES_CTRLA_STARTMODE_MANUAL | AES_CTRLA_CIPHER_ENC |
1229  AES_CTRLA_AESMODE_COUNTER | AES_CTRLA_CTYPE(15);
1230 
1231  //Set encryption key
1232  aesLoadKey(context);
1233  //Enable AES module
1234  AES_REGS->AES_CTRLA |= AES_CTRLA_ENABLE_Msk;
1235 
1236  //Load J0 value to INITVECTV registers
1237  AES_REGS->AES_INTVECTV[0] = j[0];
1238  AES_REGS->AES_INTVECTV[1] = j[1];
1239  AES_REGS->AES_INTVECTV[2] = j[2];
1240  AES_REGS->AES_INTVECTV[3] = j[3];
1241 
1242  //Set NEWMSG bit
1243  AES_REGS->AES_CTRLB |= AES_CTRLB_NEWMSG_Msk;
1244 
1245  //Generate the authentication tag
1246  aesProcessDataBlock((uint8_t *) buffer, (uint8_t *) buffer);
1247 
1248  //Copy the resulting value
1249  memcpy(tag, buffer, 16);
1250 
1251  //Perform software reset
1252  AES_REGS->AES_CTRLA = AES_CTRLA_SWRST_Msk;
1253 
1254  //Disable AES module
1255  AES_REGS->AES_CTRLA = 0;
1256  AES_REGS->AES_CTRLB = 0;
1257 }
1258 
1259 
1260 /**
1261  * @brief Initialize GCM context
1262  * @param[in] context Pointer to the GCM context
1263  * @param[in] cipherAlgo Cipher algorithm
1264  * @param[in] cipherContext Pointer to the cipher algorithm context
1265  * @return Error code
1266  **/
1267 
1268 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
1269  void *cipherContext)
1270 {
1271  //The CRYP module only supports AES cipher algorithm
1272  if(cipherAlgo != AES_CIPHER_ALGO)
1273  return ERROR_INVALID_PARAMETER;
1274 
1275  //Save cipher algorithm context
1276  context->cipherAlgo = cipherAlgo;
1277  context->cipherContext = cipherContext;
1278 
1279  //Successful initialization
1280  return NO_ERROR;
1281 }
1282 
1283 
1284 /**
1285  * @brief Authenticated encryption using GCM
1286  * @param[in] context Pointer to the GCM context
1287  * @param[in] iv Initialization vector
1288  * @param[in] ivLen Length of the initialization vector
1289  * @param[in] a Additional authenticated data
1290  * @param[in] aLen Length of the additional data
1291  * @param[in] p Plaintext to be encrypted
1292  * @param[out] c Ciphertext resulting from the encryption
1293  * @param[in] length Total number of data bytes to be encrypted
1294  * @param[out] t Authentication tag
1295  * @param[in] tLen Length of the authentication tag
1296  * @return Error code
1297  **/
1298 
1299 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
1300  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
1301  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
1302 {
1303  uint8_t authTag[16];
1304  uint32_t j[4];
1305 
1306  //Make sure the GCM context is valid
1307  if(context == NULL)
1308  return ERROR_INVALID_PARAMETER;
1309 
1310  //The length of the IV shall meet SP 800-38D requirements
1311  if(ivLen < 1)
1312  return ERROR_INVALID_LENGTH;
1313 
1314  //Check the length of the authentication tag
1315  if(tLen < 4 || tLen > 16)
1316  return ERROR_INVALID_LENGTH;
1317 
1318  //Acquire exclusive access to the AES module
1320 
1321  //Perform AES-GCM encryption
1323  gcmSetMode(context->cipherContext, AES_CTRLA_CIPHER_ENC);
1324  gcmGeneratePreCounterBlock(iv, ivLen, j);
1325  gcmProcessAuthData(a, aLen);
1326  gcmProcessData(j, p, c, length);
1327  gcmGenerateTag(context->cipherContext, j, aLen, length, authTag);
1328 
1329  //Release exclusive access to the AES module
1331 
1332  //Copy the resulting authentication tag
1333  osMemcpy(t, authTag, tLen);
1334 
1335  //Successful processing
1336  return NO_ERROR;
1337 }
1338 
1339 
1340 /**
1341  * @brief Authenticated decryption using GCM
1342  * @param[in] context Pointer to the GCM context
1343  * @param[in] iv Initialization vector
1344  * @param[in] ivLen Length of the initialization vector
1345  * @param[in] a Additional authenticated data
1346  * @param[in] aLen Length of the additional data
1347  * @param[in] c Ciphertext to be decrypted
1348  * @param[out] p Plaintext resulting from the decryption
1349  * @param[in] length Total number of data bytes to be decrypted
1350  * @param[in] t Authentication tag
1351  * @param[in] tLen Length of the authentication tag
1352  * @return Error code
1353  **/
1354 
1355 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
1356  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
1357  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
1358 {
1359  size_t i;
1360  uint8_t mask;
1361  uint8_t authTag[16];
1362  uint32_t j[4];
1363 
1364  //Make sure the GCM context is valid
1365  if(context == NULL)
1366  return ERROR_INVALID_PARAMETER;
1367 
1368  //The length of the IV shall meet SP 800-38D requirements
1369  if(ivLen < 1)
1370  return ERROR_INVALID_LENGTH;
1371 
1372  //Check the length of the authentication tag
1373  if(tLen < 4 || tLen > 16)
1374  return ERROR_INVALID_LENGTH;
1375 
1376  //Acquire exclusive access to the AES module
1378 
1379  //Perform AES-GCM decryption
1381  gcmSetMode(context->cipherContext, AES_CTRLA_CIPHER_DEC);
1382  gcmGeneratePreCounterBlock(iv, ivLen, j);
1383  gcmProcessAuthData(a, aLen);
1384  gcmProcessData(j, c, p, length);
1385  gcmGenerateTag(context->cipherContext, j, aLen, length, authTag);
1386 
1387  //Release exclusive access to the AES module
1389 
1390  //The calculated tag is bitwise compared to the received tag
1391  for(mask = 0, i = 0; i < tLen; i++)
1392  {
1393  mask |= authTag[i] ^ t[i];
1394  }
1395 
1396  //The message is authenticated if and only if the tags match
1397  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
1398 }
1399 
1400 #endif
1401 #endif
uint16_t block
Definition: tftp_common.h:113
uint8_t length
Definition: coap_common.h:193
#define betoh32(value)
Definition: cpu_endian.h:454
uint8_t a
Definition: ndp.h:409
uint8_t data[]
Definition: ethernet.h:220
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:968
uint8_t p
Definition: ndp.h:298
uint8_t t
Definition: lldp_ext_med.h:210
uint8_t o
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.
Collection of AEAD algorithms.
size_t blockSize
Definition: crypto.h:963
#define BETOH32(value)
Definition: cpu_endian.h:451
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
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.
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:967
AES algorithm context.
Definition: aes.h:58
OsMutex pic32cxCryptoMutex
#define AES_BLOCK_SIZE
Definition: aes.h:43
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:137
error_t
Error codes.
Definition: error.h:43
void aesLoadKey(AesContext *context)
Load AES key.
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.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
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.
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:317
Block cipher modes of operation.
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
void gcmProcessData(const uint32_t *j, const uint8_t *input, uint8_t *output, size_t length)
Encrypt/decrypt payload data.
#define MIN(a, b)
Definition: os_port.h:62
uint32_t dataLen
Definition: sftp_common.h:227
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
uint_t nr
Definition: aes.h:59
#define htobe32(value)
Definition: cpu_endian.h:446
void gcmUpdateGhash(const uint8_t *data)
Update GHASH value.
GCM context.
Definition: gcm.h:64
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
void gcmGenerateTag(AesContext *context, const uint32_t *j, size_t aadLen, size_t dataLen, uint8_t *tag)
Calculate authentication tag.
uint8_t n
void gcmGenerateHashSubKey(AesContext *context)
Generate hash subkey.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void gcmSetMode(AesContext *context, uint32_t mode)
Set GCM operation mode.
PIC32CX cipher hardware accelerator.
void aesProcessDataBlock(const uint8_t *input, uint8_t *output)
Encrypt/decrypt a 16-byte block using AES algorithm.
void gcmProcessAuthData(const uint8_t *aad, size_t aadLen)
Process additional authenticated data.
uint8_t s
Common interface for encryption algorithms.
Definition: crypto.h:959
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
#define AES_CIPHER_ALGO
Definition: aes.h:45
uint8_t mode
Definition: ntp_common.h:149
#define LOAD32LE(p)
Definition: cpu_endian.h:203
uint32_t ek[60]
Definition: aes.h:60
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.
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:131
PIC32CX hardware cryptographic accelerator.
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.
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:66
error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
void gcmGeneratePreCounterBlock(const uint8_t *iv, size_t ivLen, uint32_t *j)
Generate pre-counter block.
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:512
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:143
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.