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