apm32f4xx_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file apm32f4xx_crypto_cipher.c
3  * @brief APM32F4 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 "apm32f4xx.h"
36 #include "apm32f4xx_rcm.h"
37 #include "core/crypto.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (APM32F4XX_CRYPTO_CIPHER_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief CRYP module initialization
50  * @return Error code
51  **/
52 
54 {
55  //Enable CRYP peripheral clock
56  RCM_EnableAHB2PeriphClock(RCM_AHB2_PERIPH_CRYP);
57 
58  //Successful processing
59  return NO_ERROR;
60 }
61 
62 
63 #if (DES_SUPPORT == ENABLED)
64 
65 /**
66  * @brief Perform DES encryption or decryption
67  * @param[in] context DES algorithm context
68  * @param[in,out] iv Initialization vector
69  * @param[in] input Data to be encrypted/decrypted
70  * @param[out] output Data resulting from the encryption/decryption process
71  * @param[in] length Total number of data bytes to be processed
72  * @param[in] mode Operation mode
73  **/
74 
75 void desProcessData(DesContext *context, uint8_t *iv, const uint8_t *input,
76  uint8_t *output, size_t length, uint32_t mode)
77 {
78  uint32_t temp;
79 
80  //Acquire exclusive access to the CRYP module
82 
83  //Configure the data type
84  CRYP->CTRL = CRYP_CTRL_DTSEL_8B;
85  //Configure the algorithm and chaining mode
86  CRYP->CTRL |= mode;
87 
88  //Set encryption key
89  CRYP->K1L = context->ks[0];
90  CRYP->K1R = context->ks[1];
91 
92  //Valid initialization vector?
93  if(iv != NULL)
94  {
95  //Set initialization vector
96  CRYP->IV0L = LOAD32BE(iv);
97  CRYP->IV0R = LOAD32BE(iv + 4);
98  }
99 
100  //Flush the input and output FIFOs
101  CRYP->CTRL |= CRYP_CTRL_FFLUSH;
102  //Enable the cryptographic processor
103  CRYP->CTRL |= CRYP_CTRL_CRYPEN;
104 
105  //Process data
106  while(length >= DES_BLOCK_SIZE)
107  {
108  //Wait for the input FIFO to be ready to accept data
109  while((CRYP->STS & CRYP_STS_IFFULL) == 0)
110  {
111  }
112 
113  //Write the input FIFO
114  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input);
115  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input + 4);
116 
117  //Wait for the output to be ready
118  while((CRYP->STS & CRYP_STS_OFEMPT) == 0)
119  {
120  }
121 
122  //Read the output FIFO
123  temp = CRYP->DATAOUT;
124  __UNALIGNED_UINT32_WRITE(output, temp);
125  temp = CRYP->DATAOUT;
126  __UNALIGNED_UINT32_WRITE(output + 4, temp);
127 
128  //Next block
129  input += DES_BLOCK_SIZE;
130  output += DES_BLOCK_SIZE;
132  }
133 
134  //Valid initialization vector?
135  if(iv != NULL)
136  {
137  //Update the value of the initialization vector
138  temp = CRYP->IV0L;
139  STORE32BE(temp, iv);
140  temp = CRYP->IV0R;
141  STORE32BE(temp, iv + 4);
142  }
143 
144  //Disable the cryptographic processor by clearing the CRYPEN bit
145  CRYP->CTRL = 0;
146 
147  //Release exclusive access to the CRYP module
149 }
150 
151 
152 /**
153  * @brief Initialize a DES context using the supplied key
154  * @param[in] context Pointer to the DES context to initialize
155  * @param[in] key Pointer to the key
156  * @param[in] keyLen Length of the key (must be set to 8)
157  * @return Error code
158  **/
159 
160 error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
161 {
162  //Check parameters
163  if(context == NULL || key == NULL)
165 
166  //Invalid key length?
167  if(keyLen != 8)
169 
170  //Copy the 64-bit key
171  context->ks[0] = LOAD32BE(key + 0);
172  context->ks[1] = LOAD32BE(key + 4);
173 
174  //No error to report
175  return NO_ERROR;
176 }
177 
178 
179 /**
180  * @brief Encrypt a 8-byte block using DES algorithm
181  * @param[in] context Pointer to the DES context
182  * @param[in] input Plaintext block to encrypt
183  * @param[out] output Ciphertext block resulting from encryption
184  **/
185 
186 void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
187 {
188  //Perform DES encryption
189  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE,
191 }
192 
193 
194 /**
195  * @brief Decrypt a 8-byte block using DES algorithm
196  * @param[in] context Pointer to the DES context
197  * @param[in] input Ciphertext block to decrypt
198  * @param[out] output Plaintext block resulting from decryption
199  **/
200 
201 void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
202 {
203  //Perform DES decryption
204  desProcessData(context, NULL, input, output, DES_BLOCK_SIZE,
206 }
207 
208 #endif
209 #if (DES3_SUPPORT == ENABLED)
210 
211 /**
212  * @brief Perform Triple DES encryption or decryption
213  * @param[in] context Triple DES algorithm context
214  * @param[in,out] iv Initialization vector
215  * @param[in] input Data to be encrypted/decrypted
216  * @param[out] output Data resulting from the encryption/decryption process
217  * @param[in] length Total number of data bytes to be processed
218  * @param[in] mode Operation mode
219  **/
220 
221 void des3ProcessData(Des3Context *context, uint8_t *iv, const uint8_t *input,
222  uint8_t *output, size_t length, uint32_t mode)
223 {
224  uint32_t temp;
225 
226  //Acquire exclusive access to the CRYP module
228 
229  //Configure the data type
230  CRYP->CTRL = CRYP_CTRL_DTSEL_8B;
231  //Configure the algorithm and chaining mode
232  CRYP->CTRL |= mode;
233 
234  //Set encryption key
235  CRYP->K1L = context->k1.ks[0];
236  CRYP->K1R = context->k1.ks[1];
237  CRYP->K2L = context->k2.ks[0];
238  CRYP->K2R = context->k2.ks[1];
239  CRYP->K3L = context->k3.ks[0];
240  CRYP->K3R = context->k3.ks[1];
241 
242  //Valid initialization vector?
243  if(iv != NULL)
244  {
245  //Set initialization vector
246  CRYP->IV0L = LOAD32BE(iv);
247  CRYP->IV0R = LOAD32BE(iv + 4);
248  }
249 
250  //Flush the input and output FIFOs
251  CRYP->CTRL |= CRYP_CTRL_FFLUSH;
252  //Enable the cryptographic processor
253  CRYP->CTRL |= CRYP_CTRL_CRYPEN;
254 
255  //Process data
256  while(length >= DES3_BLOCK_SIZE)
257  {
258  //Wait for the input FIFO to be ready to accept data
259  while((CRYP->STS & CRYP_STS_IFFULL) == 0)
260  {
261  }
262 
263  //Write the input FIFO
264  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input);
265  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input + 4);
266 
267  //Wait for the output to be ready
268  while((CRYP->STS & CRYP_STS_OFEMPT) == 0)
269  {
270  }
271 
272  //Read the output FIFO
273  temp = CRYP->DATAOUT;
274  __UNALIGNED_UINT32_WRITE(output, temp);
275  temp = CRYP->DATAOUT;
276  __UNALIGNED_UINT32_WRITE(output + 4, temp);
277 
278  //Next block
279  input += DES3_BLOCK_SIZE;
280  output += DES3_BLOCK_SIZE;
282  }
283 
284  //Valid initialization vector?
285  if(iv != NULL)
286  {
287  //Update the value of the initialization vector
288  temp = CRYP->IV0L;
289  STORE32BE(temp, iv);
290  temp = CRYP->IV0R;
291  STORE32BE(temp, iv + 4);
292  }
293 
294  //Disable the cryptographic processor by clearing the CRYPEN bit
295  CRYP->CTRL = 0;
296 
297  //Release exclusive access to the CRYP module
299 }
300 
301 
302 /**
303  * @brief Initialize a Triple DES context using the supplied key
304  * @param[in] context Pointer to the Triple DES context to initialize
305  * @param[in] key Pointer to the key
306  * @param[in] keyLen Length of the key
307  * @return Error code
308  **/
309 
310 error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
311 {
312  //Check parameters
313  if(context == NULL || key == NULL)
315 
316  //Check key length
317  if(keyLen == 8)
318  {
319  //This option provides backward compatibility with DES, because the
320  //first and second DES operations cancel out
321  context->k1.ks[0] = LOAD32BE(key + 0);
322  context->k1.ks[1] = LOAD32BE(key + 4);
323  context->k2.ks[0] = LOAD32BE(key + 0);
324  context->k2.ks[1] = LOAD32BE(key + 4);
325  context->k3.ks[0] = LOAD32BE(key + 0);
326  context->k3.ks[1] = LOAD32BE(key + 4);
327  }
328  else if(keyLen == 16)
329  {
330  //If the key length is 128 bits including parity, the first 8 bytes of the
331  //encoding represent the key used for the two outer DES operations, and
332  //the second 8 bytes represent the key used for the inner DES operation
333  context->k1.ks[0] = LOAD32BE(key + 0);
334  context->k1.ks[1] = LOAD32BE(key + 4);
335  context->k2.ks[0] = LOAD32BE(key + 8);
336  context->k2.ks[1] = LOAD32BE(key + 12);
337  context->k3.ks[0] = LOAD32BE(key + 0);
338  context->k3.ks[1] = LOAD32BE(key + 4);
339  }
340  else if(keyLen == 24)
341  {
342  //If the key length is 192 bits including parity, then 3 independent DES
343  //keys are represented, in the order in which they are used for encryption
344  context->k1.ks[0] = LOAD32BE(key + 0);
345  context->k1.ks[1] = LOAD32BE(key + 4);
346  context->k2.ks[0] = LOAD32BE(key + 8);
347  context->k2.ks[1] = LOAD32BE(key + 12);
348  context->k3.ks[0] = LOAD32BE(key + 16);
349  context->k3.ks[1] = LOAD32BE(key + 20);
350  }
351  else
352  {
353  //The length of the key is not valid
355  }
356 
357  //No error to report
358  return NO_ERROR;
359 }
360 
361 
362 /**
363  * @brief Encrypt a 8-byte block using Triple DES algorithm
364  * @param[in] context Pointer to the Triple DES context
365  * @param[in] input Plaintext block to encrypt
366  * @param[out] output Ciphertext block resulting from encryption
367  **/
368 
369 void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
370 {
371  //Perform Triple DES encryption
372  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE,
374 }
375 
376 
377 /**
378  * @brief Decrypt a 8-byte block using Triple DES algorithm
379  * @param[in] context Pointer to the Triple DES context
380  * @param[in] input Ciphertext block to decrypt
381  * @param[out] output Plaintext block resulting from decryption
382  **/
383 
384 void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
385 {
386  //Perform Triple DES decryption
387  des3ProcessData(context, NULL, input, output, DES3_BLOCK_SIZE,
389 }
390 
391 #endif
392 #if (AES_SUPPORT == ENABLED)
393 
394 /**
395  * @brief Load AES key
396  * @param[in] context AES algorithm context
397  **/
398 
399 void aesLoadKey(AesContext *context)
400 {
401  uint32_t temp;
402 
403  //Read control register
404  temp = CRYP->CTRL & ~CRYP_CTRL_KSIZESEL;
405 
406  //Check the length of the key
407  if(context->nr == 10)
408  {
409  //10 rounds are required for 128-bit key
410  CRYP->CTRL = temp | CRYP_CTRL_KSIZESEL_128B;
411 
412  //Set the 128-bit encryption key
413  CRYP->K2L = context->ek[0];
414  CRYP->K2R = context->ek[1];
415  CRYP->K3L = context->ek[2];
416  CRYP->K3R = context->ek[3];
417  }
418  else if(context->nr == 12)
419  {
420  //12 rounds are required for 192-bit key
421  CRYP->CTRL = temp | CRYP_CTRL_KSIZESEL_192B;
422 
423  //Set the 192-bit encryption key
424  CRYP->K1L = context->ek[0];
425  CRYP->K1R = context->ek[1];
426  CRYP->K2L = context->ek[2];
427  CRYP->K2R = context->ek[3];
428  CRYP->K3L = context->ek[4];
429  CRYP->K3R = context->ek[5];
430  }
431  else
432  {
433  //14 rounds are required for 256-bit key
434  CRYP->CTRL = temp | CRYP_CTRL_KSIZESEL_256B;
435 
436  //Set the 256-bit encryption key
437  CRYP->K0L = context->ek[0];
438  CRYP->K0R = context->ek[1];
439  CRYP->K1L = context->ek[2];
440  CRYP->K1R = context->ek[3];
441  CRYP->K2L = context->ek[4];
442  CRYP->K2R = context->ek[5];
443  CRYP->K3L = context->ek[6];
444  CRYP->K3R = context->ek[7];
445  }
446 }
447 
448 
449 /**
450  * @brief Perform AES encryption or decryption
451  * @param[in] context AES algorithm context
452  * @param[in,out] iv Initialization vector
453  * @param[in] input Data to be encrypted/decrypted
454  * @param[out] output Data resulting from the encryption/decryption process
455  * @param[in] length Total number of data bytes to be processed
456  * @param[in] mode Operation mode
457  **/
458 
459 void aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input,
460  uint8_t *output, size_t length, uint32_t mode)
461 {
462  uint32_t temp;
463 
464  //Acquire exclusive access to the CRYP module
466 
467  //Configure the data type
468  CRYP->CTRL = CRYP_CTRL_DTSEL_8B;
469 
470  //AES-ECB or AES-CBC decryption?
471  if((mode & CRYP_CTRL_ALGODIRSEL) != 0)
472  {
473  //Configure the key preparation mode by setting the ALGOMODE bits to '111'
474  CRYP->CTRL |= CRYP_CTRL_ALGOMSEL_AES_KEY;
475  //Set encryption key
476  aesLoadKey(context);
477  //Write the CRYPEN bit to 1
478  CRYP->CTRL |= CRYP_CTRL_CRYPEN;
479 
480  //Wait until BUSY returns to 0
481  while((CRYP->STS & CRYP_STS_BUSY) != 0)
482  {
483  }
484 
485  //The algorithm must be configured once the key has been prepared
486  temp = CRYP->CTRL & ~CRYP_CTRL_ALGOMSEL;
487  CRYP->CTRL = temp | mode;
488  }
489  else
490  {
491  //Configure the algorithm and chaining mode
492  CRYP->CTRL |= mode;
493  //Set encryption key
494  aesLoadKey(context);
495  }
496 
497  //Valid initialization vector?
498  if(iv != NULL)
499  {
500  //Set initialization vector
501  CRYP->IV0L = LOAD32BE(iv);
502  CRYP->IV0R = LOAD32BE(iv + 4);
503  CRYP->IV1L = LOAD32BE(iv + 8);
504  CRYP->IV1R = LOAD32BE(iv + 12);
505  }
506 
507  //Flush the input and output FIFOs
508  CRYP->CTRL |= CRYP_CTRL_FFLUSH;
509  //Enable the cryptographic processor
510  CRYP->CTRL |= CRYP_CTRL_CRYPEN;
511 
512  //Process data
513  while(length >= AES_BLOCK_SIZE)
514  {
515  //Wait for the input FIFO to be ready to accept data
516  while((CRYP->STS & CRYP_STS_IFFULL) == 0)
517  {
518  }
519 
520  //Write the input FIFO
521  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input);
522  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input + 4);
523  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input + 8);
524  CRYP->DATAIN = __UNALIGNED_UINT32_READ(input + 12);
525 
526  //Wait for the output to be ready
527  while((CRYP->STS & CRYP_STS_OFEMPT) == 0)
528  {
529  }
530 
531  //Read the output FIFO
532  temp = CRYP->DATAOUT;
533  __UNALIGNED_UINT32_WRITE(output, temp);
534  temp = CRYP->DATAOUT;
535  __UNALIGNED_UINT32_WRITE(output + 4, temp);
536  temp = CRYP->DATAOUT;
537  __UNALIGNED_UINT32_WRITE(output + 8, temp);
538  temp = CRYP->DATAOUT;
539  __UNALIGNED_UINT32_WRITE(output + 12, temp);
540 
541  //Next block
542  input += AES_BLOCK_SIZE;
543  output += AES_BLOCK_SIZE;
545  }
546 
547  //Process final block of data
548  if(length > 0)
549  {
550  uint32_t buffer[4];
551 
552  //Copy partial block
553  osMemset(buffer, 0, AES_BLOCK_SIZE);
554  osMemcpy(buffer, input, length);
555 
556  //Wait for the input FIFO to be ready to accept data
557  while((CRYP->STS & CRYP_STS_IFFULL) == 0)
558  {
559  }
560 
561  //Write input block
562  CRYP->DATAIN = buffer[0];
563  CRYP->DATAIN = buffer[1];
564  CRYP->DATAIN = buffer[2];
565  CRYP->DATAIN = buffer[3];
566 
567  //Wait for the output to be ready
568  while((CRYP->STS & CRYP_STS_OFEMPT) == 0)
569  {
570  }
571 
572  //Read output block
573  buffer[0] = CRYP->DATAOUT;
574  buffer[1] = CRYP->DATAOUT;
575  buffer[2] = CRYP->DATAOUT;
576  buffer[3] = CRYP->DATAOUT;
577 
578  //Copy partial block
579  osMemcpy(output, buffer, length);
580  }
581 
582  //Valid initialization vector?
583  if(iv != NULL)
584  {
585  //Update the value of the initialization vector
586  temp = CRYP->IV0L;
587  STORE32BE(temp, iv);
588  temp = CRYP->IV0R;
589  STORE32BE(temp, iv + 4);
590  temp = CRYP->IV1L;
591  STORE32BE(temp, iv + 8);
592  temp = CRYP->IV1R;
593  STORE32BE(temp, iv + 12);
594  }
595 
596  //Disable the cryptographic processor by clearing the CRYPEN bit
597  CRYP->CTRL = 0;
598 
599  //Release exclusive access to the CRYP module
601 }
602 
603 
604 /**
605  * @brief Key expansion
606  * @param[in] context Pointer to the AES context to initialize
607  * @param[in] key Pointer to the key
608  * @param[in] keyLen Length of the key
609  * @return Error code
610  **/
611 
612 error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
613 {
614  size_t i;
615 
616  //Check parameters
617  if(context == NULL || key == NULL)
619 
620  //Check the length of the key
621  if(keyLen == 16)
622  {
623  //10 rounds are required for 128-bit key
624  context->nr = 10;
625  }
626  else if(keyLen == 24)
627  {
628  //12 rounds are required for 192-bit key
629  context->nr = 12;
630  }
631  else if(keyLen == 32)
632  {
633  //14 rounds are required for 256-bit key
634  context->nr = 14;
635  }
636  else
637  {
638  //Report an error
640  }
641 
642  //Determine the number of 32-bit words in the key
643  keyLen /= 4;
644 
645  //Copy the original key
646  for(i = 0; i < keyLen; i++)
647  {
648  context->ek[i] = LOAD32BE(key + (i * 4));
649  }
650 
651  //No error to report
652  return NO_ERROR;
653 }
654 
655 
656 /**
657  * @brief Encrypt a 16-byte block using AES algorithm
658  * @param[in] context Pointer to the AES context
659  * @param[in] input Plaintext block to encrypt
660  * @param[out] output Ciphertext block resulting from encryption
661  **/
662 
663 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
664 {
665  //Perform AES encryption
666  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
668 }
669 
670 
671 /**
672  * @brief Decrypt a 16-byte block using AES algorithm
673  * @param[in] context Pointer to the AES context
674  * @param[in] input Ciphertext block to decrypt
675  * @param[out] output Plaintext block resulting from decryption
676  **/
677 
678 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
679 {
680  //Perform AES decryption
681  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
683 }
684 
685 #endif
686 #if (ECB_SUPPORT == ENABLED)
687 
688 /**
689  * @brief ECB encryption
690  * @param[in] cipher Cipher algorithm
691  * @param[in] context Cipher algorithm context
692  * @param[in] p Plaintext to be encrypted
693  * @param[out] c Ciphertext resulting from the encryption
694  * @param[in] length Total number of data bytes to be encrypted
695  * @return Error code
696  **/
697 
698 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
699  const uint8_t *p, uint8_t *c, size_t length)
700 {
701  error_t error;
702 
703  //Initialize status code
704  error = NO_ERROR;
705 
706 #if (DES_SUPPORT == ENABLED)
707  //DES cipher algorithm?
708  if(cipher == DES_CIPHER_ALGO)
709  {
710  //Check the length of the payload
711  if(length == 0)
712  {
713  //No data to process
714  }
715  else if((length % DES_BLOCK_SIZE) == 0)
716  {
717  //Encrypt payload data
719  }
720  else
721  {
722  //The length of the payload must be a multiple of the block size
723  error = ERROR_INVALID_LENGTH;
724  }
725  }
726  else
727 #endif
728 #if (DES3_SUPPORT == ENABLED)
729  //Triple DES cipher algorithm?
730  if(cipher == DES3_CIPHER_ALGO)
731  {
732  //Check the length of the payload
733  if(length == 0)
734  {
735  //No data to process
736  }
737  else if((length % DES3_BLOCK_SIZE) == 0)
738  {
739  //Encrypt payload data
741  }
742  else
743  {
744  //The length of the payload must be a multiple of the block size
745  error = ERROR_INVALID_LENGTH;
746  }
747  }
748  else
749 #endif
750 #if (AES_SUPPORT == ENABLED)
751  //AES cipher algorithm?
752  if(cipher == AES_CIPHER_ALGO)
753  {
754  //Check the length of the payload
755  if(length == 0)
756  {
757  //No data to process
758  }
759  else if((length % AES_BLOCK_SIZE) == 0)
760  {
761  //Encrypt payload data
763  }
764  else
765  {
766  //The length of the payload must be a multiple of the block size
767  error = ERROR_INVALID_LENGTH;
768  }
769  }
770  else
771 #endif
772  //Unknown cipher algorithm?
773  {
774  //ECB mode operates in a block-by-block fashion
775  while(length >= cipher->blockSize)
776  {
777  //Encrypt current block
778  cipher->encryptBlock(context, p, c);
779 
780  //Next block
781  p += cipher->blockSize;
782  c += cipher->blockSize;
783  length -= cipher->blockSize;
784  }
785 
786  //The length of the payload must be a multiple of the block size
787  if(length != 0)
788  {
789  error = ERROR_INVALID_LENGTH;
790  }
791  }
792 
793  //Return status code
794  return error;
795 }
796 
797 
798 /**
799  * @brief ECB decryption
800  * @param[in] cipher Cipher algorithm
801  * @param[in] context Cipher algorithm context
802  * @param[in] c Ciphertext to be decrypted
803  * @param[out] p Plaintext resulting from the decryption
804  * @param[in] length Total number of data bytes to be decrypted
805  * @return Error code
806  **/
807 
808 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
809  const uint8_t *c, uint8_t *p, size_t length)
810 {
811  error_t error;
812 
813  //Initialize status code
814  error = NO_ERROR;
815 
816 #if (DES_SUPPORT == ENABLED)
817  //DES cipher algorithm?
818  if(cipher == DES_CIPHER_ALGO)
819  {
820  //Check the length of the payload
821  if(length == 0)
822  {
823  //No data to process
824  }
825  else if((length % DES_BLOCK_SIZE) == 0)
826  {
827  //Decrypt payload data
830  }
831  else
832  {
833  //The length of the payload must be a multiple of the block size
834  error = ERROR_INVALID_LENGTH;
835  }
836  }
837  else
838 #endif
839 #if (DES3_SUPPORT == ENABLED)
840  //Triple DES cipher algorithm?
841  if(cipher == DES3_CIPHER_ALGO)
842  {
843  //Check the length of the payload
844  if(length == 0)
845  {
846  //No data to process
847  }
848  else if((length % DES3_BLOCK_SIZE) == 0)
849  {
850  //Decrypt payload data
853  }
854  else
855  {
856  //The length of the payload must be a multiple of the block size
857  error = ERROR_INVALID_LENGTH;
858  }
859  }
860  else
861 #endif
862 #if (AES_SUPPORT == ENABLED)
863  //AES cipher algorithm?
864  if(cipher == AES_CIPHER_ALGO)
865  {
866  //Check the length of the payload
867  if(length == 0)
868  {
869  //No data to process
870  }
871  else if((length % AES_BLOCK_SIZE) == 0)
872  {
873  //Decrypt payload data
876  }
877  else
878  {
879  //The length of the payload must be a multiple of the block size
880  error = ERROR_INVALID_LENGTH;
881  }
882  }
883  else
884 #endif
885  //Unknown cipher algorithm?
886  {
887  //ECB mode operates in a block-by-block fashion
888  while(length >= cipher->blockSize)
889  {
890  //Decrypt current block
891  cipher->decryptBlock(context, c, p);
892 
893  //Next block
894  c += cipher->blockSize;
895  p += cipher->blockSize;
896  length -= cipher->blockSize;
897  }
898 
899  //The length of the payload must be a multiple of the block size
900  if(length != 0)
901  {
902  error = ERROR_INVALID_LENGTH;
903  }
904  }
905 
906  //Return status code
907  return error;
908 }
909 
910 #endif
911 #if (CBC_SUPPORT == ENABLED)
912 
913 /**
914  * @brief CBC encryption
915  * @param[in] cipher Cipher algorithm
916  * @param[in] context Cipher algorithm context
917  * @param[in,out] iv Initialization vector
918  * @param[in] p Plaintext to be encrypted
919  * @param[out] c Ciphertext resulting from the encryption
920  * @param[in] length Total number of data bytes to be encrypted
921  * @return Error code
922  **/
923 
924 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
925  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
926 {
927  error_t error;
928 
929  //Initialize status code
930  error = NO_ERROR;
931 
932 #if (DES_SUPPORT == ENABLED)
933  //DES cipher algorithm?
934  if(cipher == DES_CIPHER_ALGO)
935  {
936  //Check the length of the payload
937  if(length == 0)
938  {
939  //No data to process
940  }
941  else if((length % DES_BLOCK_SIZE) == 0)
942  {
943  //Encrypt payload data
945  }
946  else
947  {
948  //The length of the payload must be a multiple of the block size
949  error = ERROR_INVALID_LENGTH;
950  }
951  }
952  else
953 #endif
954 #if (DES3_SUPPORT == ENABLED)
955  //Triple DES cipher algorithm?
956  if(cipher == DES3_CIPHER_ALGO)
957  {
958  //Check the length of the payload
959  if(length == 0)
960  {
961  //No data to process
962  }
963  else if((length % DES3_BLOCK_SIZE) == 0)
964  {
965  //Encrypt payload data
967  }
968  else
969  {
970  //The length of the payload must be a multiple of the block size
971  error = ERROR_INVALID_LENGTH;
972  }
973  }
974  else
975 #endif
976 #if (AES_SUPPORT == ENABLED)
977  //AES cipher algorithm?
978  if(cipher == AES_CIPHER_ALGO)
979  {
980  //Check the length of the payload
981  if(length == 0)
982  {
983  //No data to process
984  }
985  else if((length % AES_BLOCK_SIZE) == 0)
986  {
987  //Encrypt payload data
989  }
990  else
991  {
992  //The length of the payload must be a multiple of the block size
993  error = ERROR_INVALID_LENGTH;
994  }
995  }
996  else
997 #endif
998  //Unknown cipher algorithm?
999  {
1000  size_t i;
1001 
1002  //CBC mode operates in a block-by-block fashion
1003  while(length >= cipher->blockSize)
1004  {
1005  //XOR input block with IV contents
1006  for(i = 0; i < cipher->blockSize; i++)
1007  {
1008  c[i] = p[i] ^ iv[i];
1009  }
1010 
1011  //Encrypt the current block based upon the output of the previous
1012  //encryption
1013  cipher->encryptBlock(context, c, c);
1014 
1015  //Update IV with output block contents
1016  osMemcpy(iv, c, cipher->blockSize);
1017 
1018  //Next block
1019  p += cipher->blockSize;
1020  c += cipher->blockSize;
1021  length -= cipher->blockSize;
1022  }
1023 
1024  //The length of the payload must be a multiple of the block size
1025  if(length != 0)
1026  {
1027  error = ERROR_INVALID_LENGTH;
1028  }
1029  }
1030 
1031  //Return status code
1032  return error;
1033 }
1034 
1035 
1036 /**
1037  * @brief CBC decryption
1038  * @param[in] cipher Cipher algorithm
1039  * @param[in] context Cipher algorithm context
1040  * @param[in,out] iv Initialization vector
1041  * @param[in] c Ciphertext to be decrypted
1042  * @param[out] p Plaintext resulting from the decryption
1043  * @param[in] length Total number of data bytes to be decrypted
1044  * @return Error code
1045  **/
1046 
1047 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
1048  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
1049 {
1050  error_t error;
1051 
1052  //Initialize status code
1053  error = NO_ERROR;
1054 
1055 #if (DES_SUPPORT == ENABLED)
1056  //DES cipher algorithm?
1057  if(cipher == DES_CIPHER_ALGO)
1058  {
1059  //Check the length of the payload
1060  if(length == 0)
1061  {
1062  //No data to process
1063  }
1064  else if((length % DES_BLOCK_SIZE) == 0)
1065  {
1066  //Decrypt payload data
1069  }
1070  else
1071  {
1072  //The length of the payload must be a multiple of the block size
1073  error = ERROR_INVALID_LENGTH;
1074  }
1075  }
1076  else
1077 #endif
1078 #if (DES3_SUPPORT == ENABLED)
1079  //Triple DES cipher algorithm?
1080  if(cipher == DES3_CIPHER_ALGO)
1081  {
1082  //Check the length of the payload
1083  if(length == 0)
1084  {
1085  //No data to process
1086  }
1087  else if((length % DES3_BLOCK_SIZE) == 0)
1088  {
1089  //Decrypt payload data
1092  }
1093  else
1094  {
1095  //The length of the payload must be a multiple of the block size
1096  error = ERROR_INVALID_LENGTH;
1097  }
1098  }
1099  else
1100 #endif
1101 #if (AES_SUPPORT == ENABLED)
1102  //AES cipher algorithm?
1103  if(cipher == AES_CIPHER_ALGO)
1104  {
1105  //Check the length of the payload
1106  if(length == 0)
1107  {
1108  //No data to process
1109  }
1110  else if((length % AES_BLOCK_SIZE) == 0)
1111  {
1112  //Decrypt payload data
1115  }
1116  else
1117  {
1118  //The length of the payload must be a multiple of the block size
1119  error = ERROR_INVALID_LENGTH;
1120  }
1121  }
1122  else
1123 #endif
1124  //Unknown cipher algorithm?
1125  {
1126  size_t i;
1127  uint8_t t[16];
1128 
1129  //CBC mode operates in a block-by-block fashion
1130  while(length >= cipher->blockSize)
1131  {
1132  //Save input block
1133  osMemcpy(t, c, cipher->blockSize);
1134 
1135  //Decrypt the current block
1136  cipher->decryptBlock(context, c, p);
1137 
1138  //XOR output block with IV contents
1139  for(i = 0; i < cipher->blockSize; i++)
1140  {
1141  p[i] ^= iv[i];
1142  }
1143 
1144  //Update IV with input block contents
1145  osMemcpy(iv, t, cipher->blockSize);
1146 
1147  //Next block
1148  c += cipher->blockSize;
1149  p += cipher->blockSize;
1150  length -= cipher->blockSize;
1151  }
1152 
1153  //The length of the payload must be a multiple of the block size
1154  if(length != 0)
1155  {
1156  error = ERROR_INVALID_LENGTH;
1157  }
1158  }
1159 
1160  //Return status code
1161  return error;
1162 }
1163 
1164 #endif
1165 #if (CTR_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
1166 
1167 /**
1168  * @brief CTR encryption
1169  * @param[in] cipher Cipher algorithm
1170  * @param[in] context Cipher algorithm context
1171  * @param[in] m Size in bits of the specific part of the block to be incremented
1172  * @param[in,out] t Initial counter block
1173  * @param[in] p Plaintext to be encrypted
1174  * @param[out] c Ciphertext resulting from the encryption
1175  * @param[in] length Total number of data bytes to be encrypted
1176  * @return Error code
1177  **/
1178 
1179 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
1180  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
1181 {
1182  error_t error;
1183 
1184  //Initialize status code
1185  error = NO_ERROR;
1186 
1187  //Check the value of the parameter
1188  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
1189  {
1190  //Determine the size, in bytes, of the specific part of the block to be
1191  //incremented
1192  m = m / 8;
1193 
1194  //AES cipher algorithm?
1195  if(cipher == AES_CIPHER_ALGO)
1196  {
1197  size_t k;
1198  size_t n;
1199  uint8_t iv[AES_BLOCK_SIZE];
1200 
1201  //Process plaintext
1202  while(length > 0)
1203  {
1204  //Limit the number of blocks to process at a time
1205  k = 256 - t[AES_BLOCK_SIZE - 1];
1206  n = MIN(length, k * AES_BLOCK_SIZE);
1207  k = (n + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
1208 
1209  //Copy initial counter value
1211  //Encrypt payload data
1213 
1214  //Standard incrementing function
1215  ctrIncBlock(t, k, AES_BLOCK_SIZE, m);
1216 
1217  //Next block
1218  p += n;
1219  c += n;
1220  length -= n;
1221  }
1222  }
1223  else
1224  {
1225  size_t i;
1226  size_t n;
1227  uint8_t o[16];
1228 
1229  //Process plaintext
1230  while(length > 0)
1231  {
1232  //CTR mode operates in a block-by-block fashion
1233  n = MIN(length, cipher->blockSize);
1234 
1235  //Compute O(j) = CIPH(T(j))
1236  cipher->encryptBlock(context, t, o);
1237 
1238  //Compute C(j) = P(j) XOR T(j)
1239  for(i = 0; i < n; i++)
1240  {
1241  c[i] = p[i] ^ o[i];
1242  }
1243 
1244  //Standard incrementing function
1245  ctrIncBlock(t, 1, cipher->blockSize, m);
1246 
1247  //Next block
1248  p += n;
1249  c += n;
1250  length -= n;
1251  }
1252  }
1253  }
1254  else
1255  {
1256  //The value of the parameter is not valid
1257  error = ERROR_INVALID_PARAMETER;
1258  }
1259 
1260  //Return status code
1261  return error;
1262 }
1263 
1264 #endif
1265 #endif
#define CRYP_CTRL_ALGOMSEL_AES_KEY
error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
Initialize a DES context using the supplied key.
#define CRYP_CTRL_ALGOMSEL_AES_ECB
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
#define LOAD32BE(p)
Definition: cpu_endian.h:210
error_t des3Init(Des3Context *context, const uint8_t *key, size_t keyLen)
Initialize a Triple DES context using the supplied key.
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1077
void desProcessData(DesContext *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t mode)
Perform DES encryption or decryption.
uint8_t p
Definition: ndp.h:300
#define CRYP_CTRL_ALGOMSEL_DES_CBC
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t o
Collection of AEAD algorithms.
error_t crypInit(void)
CRYP module initialization.
size_t blockSize
Definition: crypto.h:1072
void des3EncryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using Triple DES algorithm.
#define CRYP_CTRL_DTSEL_8B
DesContext k1
Definition: des3.h:60
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1076
#define DES3_BLOCK_SIZE
Definition: des3.h:44
AES algorithm context.
Definition: aes.h:58
#define AES_BLOCK_SIZE
Definition: aes.h:43
DES algorithm context.
Definition: des.h:58
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
error_t
Error codes.
Definition: error.h:43
#define CRYP_CTRL_CRYPEN
#define CRYP_STS_OFEMPT
void aesLoadKey(AesContext *context)
Load AES key.
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
#define CRYP_STS_BUSY
void des3ProcessData(Des3Context *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, uint32_t mode)
Perform Triple DES encryption or decryption.
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
#define CRYP_CTRL_ALGOMSEL_AES_CTR
APM32F4 cipher hardware accelerator.
uint8_t iv[]
Definition: ike.h:1502
Block cipher modes of operation.
#define DES_CIPHER_ALGO
Definition: des.h:45
error_t aesInit(AesContext *context, const uint8_t *key, size_t keyLen)
Key expansion.
uint8_t length
Definition: tcp.h:368
void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using DES algorithm.
#define MIN(a, b)
Definition: os_port.h:63
DesContext k3
Definition: des3.h:62
#define CRYP_CTRL_ALGODIRSEL
#define CRYP_STS_IFFULL
#define CRYP_CTRL_ALGOMSEL_TDES_CBC
uint_t nr
Definition: aes.h:59
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
#define CRYP_CTRL_ALGOMSEL_DES_ECB
#define CRYP_CTRL_KSIZESEL_192B
Triple DES algorithm context.
Definition: des3.h:59
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 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.
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.
#define DES_BLOCK_SIZE
Definition: des.h:43
#define CRYP_CTRL_ALGOMSEL_TDES_ECB
Common interface for encryption algorithms.
Definition: crypto.h:1068
DesContext k2
Definition: des3.h:61
#define AES_CIPHER_ALGO
Definition: aes.h:45
#define CRYP_CTRL_ALGOMSEL
#define CRYP_CTRL_ALGOMSEL_AES_CBC
#define CRYP_CTRL_KSIZESEL
#define DES3_CIPHER_ALGO
Definition: des3.h:46
void des3DecryptBlock(Des3Context *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using Triple DES algorithm.
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
uint32_t ek[60]
Definition: aes.h:60
unsigned int uint_t
Definition: compiler_port.h:50
OsMutex apm32f4xxCryptoMutex
#define osMemset(p, value, length)
Definition: os_port.h:135
#define CRYP_CTRL_KSIZESEL_256B
#define CRYP_CTRL_KSIZESEL_128B
void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using DES algorithm.
uint32_t ks[32]
Definition: des.h:59
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define CRYP_CTRL_FFLUSH
void ctrIncBlock(uint8_t *ctr, uint32_t inc, size_t blockSize, size_t m)
Increment counter block.
Definition: ctr.c:138
APM32F4 hardware cryptographic accelerator.
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.