lpc55xx_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file lpc55xx_crypto_cipher.c
3  * @brief LPC5500 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.3.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "fsl_device_registers.h"
36 #include "fsl_hashcrypt.h"
37 #include "core/crypto.h"
40 #include "cipher/aes.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (LPC55XX_CRYPTO_CIPHER_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Load AES key
49  * @param[in] context AES algorithm context
50  * @param[in] handle AES handle
51  * @return status code
52  **/
53 
54 status_t aesLoadKey(AesContext *context, hashcrypt_handle_t *handle)
55 {
56  size_t keySize;
57  status_t status;
58 
59  //Initialize status code
60  status = kStatus_Success;
61 
62  //Retrieve the length of the key
63  if(context->nr == 10)
64  {
65  //10 rounds are required for 128-bit key
66  keySize = 16;
67  }
68  else if(context->nr == 12)
69  {
70  //12 rounds are required for 192-bit key
71  keySize = 24;
72  }
73  else if(context->nr == 14)
74  {
75  //14 rounds are required for 256-bit key
76  keySize = 32;
77  }
78  else
79  {
80  //Invalid key length
81  status = kStatus_Fail;
82  }
83 
84  //Check status code
85  if(status == kStatus_Success)
86  {
87  //Select key type
88  handle->keyType = kHASHCRYPT_UserKey;
89 
90  //Set AES key
91  status = HASHCRYPT_AES_SetKey(HASHCRYPT, handle,
92  (const uint8_t *) context->ek, keySize);
93  }
94 
95  //Return status code
96  return status;
97 }
98 
99 
100 /**
101  * @brief Encrypt a 16-byte block using AES algorithm
102  * @param[in] context Pointer to the AES context
103  * @param[in] input Plaintext block to encrypt
104  * @param[out] output Ciphertext block resulting from encryption
105  **/
106 
107 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
108 {
109  hashcrypt_handle_t handle;
110 
111  //Acquire exclusive access to the HASHCRYPT module
113 
114  //Load AES key
115  aesLoadKey(context, &handle);
116 
117  //Perform AES encryption
118  HASHCRYPT_AES_EncryptEcb(HASHCRYPT, &handle, input, output, AES_BLOCK_SIZE);
119 
120  //Release exclusive access to the HASHCRYPT module
122 }
123 
124 
125 /**
126  * @brief Decrypt a 16-byte block using AES algorithm
127  * @param[in] context Pointer to the AES context
128  * @param[in] input Ciphertext block to decrypt
129  * @param[out] output Plaintext block resulting from decryption
130  **/
131 
132 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
133 {
134  hashcrypt_handle_t handle;
135 
136  //Acquire exclusive access to the HASHCRYPT module
138 
139  //Load AES key
140  aesLoadKey(context, &handle);
141 
142  //Perform AES decryption
143  HASHCRYPT_AES_DecryptEcb(HASHCRYPT, &handle, input, output, AES_BLOCK_SIZE);
144 
145  //Release exclusive access to the HASHCRYPT module
147 }
148 
149 
150 #if (ECB_SUPPORT == ENABLED)
151 
152 /**
153  * @brief ECB encryption
154  * @param[in] cipher Cipher algorithm
155  * @param[in] context Cipher algorithm context
156  * @param[in] p Plaintext to be encrypted
157  * @param[out] c Ciphertext resulting from the encryption
158  * @param[in] length Total number of data bytes to be encrypted
159  * @return Error code
160  **/
161 
162 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
163  const uint8_t *p, uint8_t *c, size_t length)
164 {
165  status_t status;
166 
167  //Initialize status code
168  status = kStatus_Success;
169 
170  //AES cipher algorithm?
171  if(cipher == AES_CIPHER_ALGO)
172  {
173  //Check the length of the payload
174  if(length == 0)
175  {
176  //No data to process
177  }
178  else if((length % AES_BLOCK_SIZE) == 0)
179  {
180  AesContext *aesContext;
181  hashcrypt_handle_t handle;
182 
183  //Point to the AES context
184  aesContext = (AesContext *) context;
185 
186  //Acquire exclusive access to the HASHCRYPT module
188 
189  //Load AES key
190  status = aesLoadKey(context, &handle);
191 
192  //Check status code
193  if(status == kStatus_Success)
194  {
195  //Perform AES-ECB encryption
196  status = HASHCRYPT_AES_EncryptEcb(HASHCRYPT, &handle, p, c,
197  length);
198  }
199 
200  //Release exclusive access to the HASHCRYPT module
202  }
203  else
204  {
205  //The length of the payload must be a multiple of the block size
206  status = kStatus_InvalidArgument;
207  }
208  }
209  else
210  {
211  //ECB mode operates in a block-by-block fashion
212  while(length >= cipher->blockSize)
213  {
214  //Encrypt current block
215  cipher->encryptBlock(context, p, c);
216 
217  //Next block
218  p += cipher->blockSize;
219  c += cipher->blockSize;
220  length -= cipher->blockSize;
221  }
222 
223  //The length of the payload must be a multiple of the block size
224  if(length != 0)
225  {
226  status = kStatus_InvalidArgument;
227  }
228  }
229 
230  //Return status code
231  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
232 }
233 
234 
235 /**
236  * @brief ECB decryption
237  * @param[in] cipher Cipher algorithm
238  * @param[in] context Cipher algorithm context
239  * @param[in] c Ciphertext to be decrypted
240  * @param[out] p Plaintext resulting from the decryption
241  * @param[in] length Total number of data bytes to be decrypted
242  * @return Error code
243  **/
244 
245 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
246  const uint8_t *c, uint8_t *p, size_t length)
247 {
248  status_t status;
249 
250  //Initialize status code
251  status = kStatus_Success;
252 
253  //AES cipher algorithm?
254  if(cipher == AES_CIPHER_ALGO)
255  {
256  //Check the length of the payload
257  if(length == 0)
258  {
259  //No data to process
260  }
261  else if((length % AES_BLOCK_SIZE) == 0)
262  {
263  AesContext *aesContext;
264  hashcrypt_handle_t handle;
265 
266  //Point to the AES context
267  aesContext = (AesContext *) context;
268 
269  //Acquire exclusive access to the HASHCRYPT module
271 
272  //Load AES key
273  status = aesLoadKey(context, &handle);
274 
275  //Check status code
276  if(status == kStatus_Success)
277  {
278  //Perform AES-ECB decryption
279  status = HASHCRYPT_AES_DecryptEcb(HASHCRYPT, &handle, c, p,
280  length);
281  }
282 
283  //Release exclusive access to the HASHCRYPT module
285  }
286  else
287  {
288  //The length of the payload must be a multiple of the block size
289  status = kStatus_InvalidArgument;
290  }
291  }
292  else
293  {
294  //ECB mode operates in a block-by-block fashion
295  while(length >= cipher->blockSize)
296  {
297  //Decrypt current block
298  cipher->decryptBlock(context, c, p);
299 
300  //Next block
301  c += cipher->blockSize;
302  p += cipher->blockSize;
303  length -= cipher->blockSize;
304  }
305 
306  //The length of the payload must be a multiple of the block size
307  if(length != 0)
308  {
309  status = kStatus_InvalidArgument;
310  }
311  }
312 
313  //Return status code
314  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
315 }
316 
317 #endif
318 #if (CBC_SUPPORT == ENABLED)
319 
320 /**
321  * @brief CBC encryption
322  * @param[in] cipher Cipher algorithm
323  * @param[in] context Cipher algorithm context
324  * @param[in,out] iv Initialization vector
325  * @param[in] p Plaintext to be encrypted
326  * @param[out] c Ciphertext resulting from the encryption
327  * @param[in] length Total number of data bytes to be encrypted
328  * @return Error code
329  **/
330 
331 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
332  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
333 {
334  status_t status;
335 
336  //Initialize status code
337  status = kStatus_Success;
338 
339  //AES cipher algorithm?
340  if(cipher == AES_CIPHER_ALGO)
341  {
342  //Check the length of the payload
343  if(length == 0)
344  {
345  //No data to process
346  }
347  else if((length % AES_BLOCK_SIZE) == 0)
348  {
349  AesContext *aesContext;
350  hashcrypt_handle_t handle;
351 
352  //Point to the AES context
353  aesContext = (AesContext *) context;
354 
355  //Acquire exclusive access to the HASHCRYPT module
357 
358  //Load AES key
359  status = aesLoadKey(context, &handle);
360 
361  //Check status code
362  if(status == kStatus_Success)
363  {
364  //Perform AES-CBC encryption
365  status = HASHCRYPT_AES_EncryptCbc(HASHCRYPT, &handle, p, c,
366  length, iv);
367  }
368 
369  //Release exclusive access to the HASHCRYPT module
371 
372  //Check status code
373  if(status == kStatus_Success)
374  {
375  //Update the value of the initialization vector
377  }
378  }
379  else
380  {
381  //The length of the payload must be a multiple of the block size
382  status = kStatus_InvalidArgument;
383  }
384  }
385  else
386  {
387  size_t i;
388 
389  //CBC mode operates in a block-by-block fashion
390  while(length >= cipher->blockSize)
391  {
392  //XOR input block with IV contents
393  for(i = 0; i < cipher->blockSize; i++)
394  {
395  c[i] = p[i] ^ iv[i];
396  }
397 
398  //Encrypt the current block based upon the output of the previous
399  //encryption
400  cipher->encryptBlock(context, c, c);
401 
402  //Update IV with output block contents
403  osMemcpy(iv, c, cipher->blockSize);
404 
405  //Next block
406  p += cipher->blockSize;
407  c += cipher->blockSize;
408  length -= cipher->blockSize;
409  }
410 
411  //The length of the payload must be a multiple of the block size
412  if(length != 0)
413  {
414  status = kStatus_InvalidArgument;
415  }
416  }
417 
418  //Return status code
419  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
420 }
421 
422 
423 /**
424  * @brief CBC decryption
425  * @param[in] cipher Cipher algorithm
426  * @param[in] context Cipher algorithm context
427  * @param[in,out] iv Initialization vector
428  * @param[in] c Ciphertext to be decrypted
429  * @param[out] p Plaintext resulting from the decryption
430  * @param[in] length Total number of data bytes to be decrypted
431  * @return Error code
432  **/
433 
434 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
435  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
436 {
437  status_t status;
438 
439  //Initialize status code
440  status = kStatus_Success;
441 
442  //AES cipher algorithm?
443  if(cipher == AES_CIPHER_ALGO)
444  {
445  //Check the length of the payload
446  if(length == 0)
447  {
448  //No data to process
449  }
450  else if((length % AES_BLOCK_SIZE) == 0)
451  {
452  AesContext *aesContext;
453  hashcrypt_handle_t handle;
454  uint8_t block[AES_BLOCK_SIZE];
455 
456  //Point to the AES context
457  aesContext = (AesContext *) context;
458 
459  //Save the last input block
461 
462  //Acquire exclusive access to the HASHCRYPT module
464 
465  //Load AES key
466  status = aesLoadKey(context, &handle);
467 
468  //Check status code
469  if(status == kStatus_Success)
470  {
471  //Perform AES-CBC decryption
472  status = HASHCRYPT_AES_DecryptCbc(HASHCRYPT, &handle, c, p,
473  length, iv);
474  }
475 
476  //Release exclusive access to the HASHCRYPT module
478 
479  //Check status code
480  if(status == kStatus_Success)
481  {
482  //Update the value of the initialization vector
484  }
485  }
486  else
487  {
488  //The length of the payload must be a multiple of the block size
489  status = kStatus_InvalidArgument;
490  }
491  }
492  else
493  {
494  size_t i;
495  uint8_t t[16];
496 
497  //CBC mode operates in a block-by-block fashion
498  while(length >= cipher->blockSize)
499  {
500  //Save input block
501  osMemcpy(t, c, cipher->blockSize);
502 
503  //Decrypt the current block
504  cipher->decryptBlock(context, c, p);
505 
506  //XOR output block with IV contents
507  for(i = 0; i < cipher->blockSize; i++)
508  {
509  p[i] ^= iv[i];
510  }
511 
512  //Update IV with input block contents
513  osMemcpy(iv, t, cipher->blockSize);
514 
515  //Next block
516  c += cipher->blockSize;
517  p += cipher->blockSize;
518  length -= cipher->blockSize;
519  }
520 
521  //The length of the payload must be a multiple of the block size
522  if(length != 0)
523  {
524  status = kStatus_InvalidArgument;
525  }
526  }
527 
528  //Return status code
529  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
530 }
531 
532 #endif
533 #if (CTR_SUPPORT == ENABLED)
534 
535 /**
536  * @brief CTR encryption
537  * @param[in] cipher Cipher algorithm
538  * @param[in] context Cipher algorithm context
539  * @param[in] m Size in bits of the specific part of the block to be incremented
540  * @param[in,out] t Initial counter block
541  * @param[in] p Plaintext to be encrypted
542  * @param[out] c Ciphertext resulting from the encryption
543  * @param[in] length Total number of data bytes to be encrypted
544  * @return Error code
545  **/
546 
547 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
548  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
549 {
550  status_t status;
551 
552  //Initialize status code
553  status = kStatus_Success;
554 
555  //AES cipher algorithm?
556  if(cipher == AES_CIPHER_ALGO)
557  {
558  //Check the value of the parameter
559  if(m == (AES_BLOCK_SIZE * 8))
560  {
561  //Check the length of the payload
562  if(length == 0)
563  {
564  //No data to process
565  }
566  else if((length % AES_BLOCK_SIZE) == 0)
567  {
568  AesContext *aesContext;
569  hashcrypt_handle_t handle;
570 
571  //Point to the AES context
572  aesContext = (AesContext *) context;
573 
574  //Acquire exclusive access to the HASHCRYPT module
576 
577  //Load AES key
578  status = aesLoadKey(context, &handle);
579 
580  //Check status code
581  if(status == kStatus_Success)
582  {
583  //Perform AES-CTR encryption
584  status = HASHCRYPT_AES_CryptCtr(HASHCRYPT, &handle, p, c,
585  length, t, NULL, NULL);
586  }
587 
588  //Release exclusive access to the HASHCRYPT module
590  }
591  else
592  {
593  //The length of the payload must be a multiple of the block size
594  status = kStatus_InvalidArgument;
595  }
596  }
597  else
598  {
599  //The value of the parameter is not valid
600  status = kStatus_InvalidArgument;
601  }
602  }
603  else
604  {
605  //Check the value of the parameter
606  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
607  {
608  size_t i;
609  size_t n;
610  uint16_t temp;
611  uint8_t o[16];
612 
613  //Determine the size, in bytes, of the specific part of the block
614  //to be incremented
615  m = m / 8;
616 
617  //Process plaintext
618  while(length > 0)
619  {
620  //CTR mode operates in a block-by-block fashion
621  n = MIN(length, cipher->blockSize);
622 
623  //Compute O(j) = CIPH(T(j))
624  cipher->encryptBlock(context, t, o);
625 
626  //Compute C(j) = P(j) XOR T(j)
627  for(i = 0; i < n; i++)
628  {
629  c[i] = p[i] ^ o[i];
630  }
631 
632  //Standard incrementing function
633  for(temp = 1, i = 1; i <= m; i++)
634  {
635  //Increment the current byte and propagate the carry
636  temp += t[cipher->blockSize - i];
637  t[cipher->blockSize - i] = temp & 0xFF;
638  temp >>= 8;
639  }
640 
641  //Next block
642  p += n;
643  c += n;
644  length -= n;
645  }
646  }
647  else
648  {
649  //The value of the parameter is not valid
650  status = kStatus_InvalidArgument;
651  }
652  }
653 
654  //Return status code
655  return (status == kStatus_Success) ? NO_ERROR : ERROR_FAILURE;
656 }
657 
658 #endif
659 #endif
AES (Advanced Encryption Standard)
#define AES_CIPHER_ALGO
Definition: aes.h:45
#define AES_BLOCK_SIZE
Definition: aes.h:43
unsigned int uint_t
Definition: compiler_port.h:50
General definitions for cryptographic algorithms.
Debugging facilities.
uint8_t n
uint8_t o
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
uint8_t iv[]
Definition: ike.h:1502
uint8_t t
Definition: lldp_ext_med.h:212
OsMutex lpc55xxCryptoMutex
LPC5500 hardware cryptographic accelerator.
status_t aesLoadKey(AesContext *context, hashcrypt_handle_t *handle)
Load AES key.
error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
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.
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
LPC5500 cipher hardware accelerator.
uint8_t c
Definition: ndp.h:514
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
AES algorithm context.
Definition: aes.h:58
uint_t nr
Definition: aes.h:59
uint32_t ek[60]
Definition: aes.h:60
Common interface for encryption algorithms.
Definition: crypto.h:1036
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1044
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1045
size_t blockSize
Definition: crypto.h:1040
uint8_t length
Definition: tcp.h:368
uint16_t block
Definition: tftp_common.h:115