pic32cz_ca90_crypto_cipher.c
Go to the documentation of this file.
1 /**
2  * @file pic32cz_ca90_crypto_cipher.c
3  * @brief PIC32CZ CA90 cipher hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.0
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 "hsm_sym.h"
37 #include "hsm_aead.h"
38 #include "core/crypto.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (PIC32CZ_CA90_CRYPTO_CIPHER_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Perform AES encryption or decryption
51  * @param[in] context AES algorithm context
52  * @param[in,out] iv Initialization vector
53  * @param[in] input Data to be encrypted/decrypted
54  * @param[out] output Data resulting from the encryption/decryption process
55  * @param[in] length Total number of data bytes to be processed
56  * @param[in] mode Mode type
57  * @param[in] cmd Command type
58  * @return Error code
59  **/
60 
61 error_t aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input,
62  uint8_t *output, size_t length, hsm_Aes_ModeTypes_E mode,
63  hsm_Aes_CmdTypes_E command)
64 {
65  uint8_t temp1;
66  uint8_t temp2;
67  hsm_Cmd_Status_E status;
68  hsm_Aes_KeySize_E keySize;
69  st_Hsm_Sym_Aes_Cmd aesCmd;
70 
71  //Check the length of the key
72  if(context->nr == 10)
73  {
74  keySize = HSM_SYM_AES_KEY_128;
75  }
76  else if(context->nr == 12)
77  {
78  keySize = HSM_SYM_AES_KEY_192;
79  }
80  else
81  {
82  keySize = HSM_SYM_AES_KEY_256;
83  }
84 
85  //Workaround
86  if(((uintptr_t) output % 2) != 0)
87  {
88  temp1 = output[-1];
89  temp2 = output[length];
90  }
91 
92  //Acquire exclusive access to the HSM
94 
95  //Perform AES encryption/decryption
96  status = Hsm_Sym_Aes_CipherDirect(&aesCmd, mode, command, (uint8_t *) input,
97  length, output, (uint8_t *) context->ek, keySize, iv, 0);
98 
99  //Release exclusive access to the HSM
101 
102  //Workaround
103  if(((uintptr_t) output % 2) != 0)
104  {
105  output[-1] = temp1;
106  output[length] = temp2;
107  }
108 
109  //Return status code
110  return (status == HSM_CMD_SUCCESS) ? NO_ERROR : ERROR_FAILURE;
111 }
112 
113 
114 /**
115  * @brief Encrypt a 16-byte block using AES algorithm
116  * @param[in] context Pointer to the AES context
117  * @param[in] input Plaintext block to encrypt
118  * @param[out] output Ciphertext block resulting from encryption
119  **/
120 
121 void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
122 {
123  //Perform AES encryption
124  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
125  HSM_SYM_AES_OPMODE_ECB, HSM_SYM_AES_ENCRYPT);
126 }
127 
128 
129 /**
130  * @brief Decrypt a 16-byte block using AES algorithm
131  * @param[in] context Pointer to the AES context
132  * @param[in] input Ciphertext block to decrypt
133  * @param[out] output Plaintext block resulting from decryption
134  **/
135 
136 void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
137 {
138  //Perform AES encryption
139  aesProcessData(context, NULL, input, output, AES_BLOCK_SIZE,
140  HSM_SYM_AES_OPMODE_ECB, HSM_SYM_AES_DECRYPT);
141 }
142 
143 
144 #if (ECB_SUPPORT == ENABLED)
145 
146 /**
147  * @brief ECB encryption
148  * @param[in] cipher Cipher algorithm
149  * @param[in] context Cipher algorithm context
150  * @param[in] p Plaintext to be encrypted
151  * @param[out] c Ciphertext resulting from the encryption
152  * @param[in] length Total number of data bytes to be encrypted
153  * @return Error code
154  **/
155 
156 error_t ecbEncrypt(const CipherAlgo *cipher, void *context,
157  const uint8_t *p, uint8_t *c, size_t length)
158 {
159  error_t error;
160 
161  //Initialize status code
162  error = NO_ERROR;
163 
164  //AES cipher algorithm?
165  if(cipher == AES_CIPHER_ALGO)
166  {
167  //Check the length of the payload
168  if(length == 0)
169  {
170  //No data to process
171  }
172  else if((length % AES_BLOCK_SIZE) == 0)
173  {
174  //Encrypt payload data
175  error = aesProcessData(context, NULL, p, c, length,
176  HSM_SYM_AES_OPMODE_ECB, HSM_SYM_AES_ENCRYPT);
177  }
178  else
179  {
180  //The length of the payload must be a multiple of the block size
181  error = ERROR_INVALID_LENGTH;
182  }
183  }
184  else
185  {
186  //ECB mode operates in a block-by-block fashion
187  while(length >= cipher->blockSize)
188  {
189  //Encrypt current block
190  cipher->encryptBlock(context, p, c);
191 
192  //Next block
193  p += cipher->blockSize;
194  c += cipher->blockSize;
195  length -= cipher->blockSize;
196  }
197 
198  //The length of the payload must be a multiple of the block size
199  if(length != 0)
200  {
201  error = ERROR_INVALID_LENGTH;
202  }
203  }
204 
205  //Return status code
206  return error;
207 }
208 
209 
210 /**
211  * @brief ECB decryption
212  * @param[in] cipher Cipher algorithm
213  * @param[in] context Cipher algorithm context
214  * @param[in] c Ciphertext to be decrypted
215  * @param[out] p Plaintext resulting from the decryption
216  * @param[in] length Total number of data bytes to be decrypted
217  * @return Error code
218  **/
219 
220 error_t ecbDecrypt(const CipherAlgo *cipher, void *context,
221  const uint8_t *c, uint8_t *p, size_t length)
222 {
223  error_t error;
224 
225  //Initialize status code
226  error = NO_ERROR;
227 
228  //AES cipher algorithm?
229  if(cipher == AES_CIPHER_ALGO)
230  {
231  //Check the length of the payload
232  if(length == 0)
233  {
234  //No data to process
235  }
236  else if((length % AES_BLOCK_SIZE) == 0)
237  {
238  //Decrypt payload data
239  error = aesProcessData(context, NULL, c, p, length,
240  HSM_SYM_AES_OPMODE_ECB, HSM_SYM_AES_DECRYPT);
241  }
242  else
243  {
244  //The length of the payload must be a multiple of the block size
245  error = ERROR_INVALID_LENGTH;
246  }
247  }
248  else
249  {
250  //ECB mode operates in a block-by-block fashion
251  while(length >= cipher->blockSize)
252  {
253  //Decrypt current block
254  cipher->decryptBlock(context, c, p);
255 
256  //Next block
257  c += cipher->blockSize;
258  p += cipher->blockSize;
259  length -= cipher->blockSize;
260  }
261 
262  //The length of the payload must be a multiple of the block size
263  if(length != 0)
264  {
265  error = ERROR_INVALID_LENGTH;
266  }
267  }
268 
269  //Return status code
270  return error;
271 }
272 
273 #endif
274 #if (CBC_SUPPORT == ENABLED)
275 
276 /**
277  * @brief CBC encryption
278  * @param[in] cipher Cipher algorithm
279  * @param[in] context Cipher algorithm context
280  * @param[in,out] iv Initialization vector
281  * @param[in] p Plaintext to be encrypted
282  * @param[out] c Ciphertext resulting from the encryption
283  * @param[in] length Total number of data bytes to be encrypted
284  * @return Error code
285  **/
286 
287 error_t cbcEncrypt(const CipherAlgo *cipher, void *context,
288  uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
289 {
290  error_t error;
291 
292  //Initialize status code
293  error = NO_ERROR;
294 
295  //AES cipher algorithm?
296  if(cipher == AES_CIPHER_ALGO)
297  {
298  //Check the length of the payload
299  if(length == 0)
300  {
301  //No data to process
302  }
303  else if((length % AES_BLOCK_SIZE) == 0)
304  {
305  //Encrypt payload data
306  error = aesProcessData(context, iv, p, c, length,
307  HSM_SYM_AES_OPMODE_CBC, HSM_SYM_AES_ENCRYPT);
308 
309  //Update the value of the initialization vector
311  }
312  else
313  {
314  //The length of the payload must be a multiple of the block size
315  error = ERROR_INVALID_LENGTH;
316  }
317  }
318  else
319  {
320  size_t i;
321 
322  //CBC mode operates in a block-by-block fashion
323  while(length >= cipher->blockSize)
324  {
325  //XOR input block with IV contents
326  for(i = 0; i < cipher->blockSize; i++)
327  {
328  c[i] = p[i] ^ iv[i];
329  }
330 
331  //Encrypt the current block based upon the output of the previous
332  //encryption
333  cipher->encryptBlock(context, c, c);
334 
335  //Update IV with output block contents
336  osMemcpy(iv, c, cipher->blockSize);
337 
338  //Next block
339  p += cipher->blockSize;
340  c += cipher->blockSize;
341  length -= cipher->blockSize;
342  }
343 
344  //The length of the payload must be a multiple of the block size
345  if(length != 0)
346  {
347  error = ERROR_INVALID_LENGTH;
348  }
349  }
350 
351  //Return status code
352  return error;
353 }
354 
355 
356 /**
357  * @brief CBC decryption
358  * @param[in] cipher Cipher algorithm
359  * @param[in] context Cipher algorithm context
360  * @param[in,out] iv Initialization vector
361  * @param[in] c Ciphertext to be decrypted
362  * @param[out] p Plaintext resulting from the decryption
363  * @param[in] length Total number of data bytes to be decrypted
364  * @return Error code
365  **/
366 
367 error_t cbcDecrypt(const CipherAlgo *cipher, void *context,
368  uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
369 {
370  error_t error;
371 
372  //Initialize status code
373  error = NO_ERROR;
374 
375  //AES cipher algorithm?
376  if(cipher == AES_CIPHER_ALGO)
377  {
378  //Check the length of the payload
379  if(length == 0)
380  {
381  //No data to process
382  }
383  else if((length % AES_BLOCK_SIZE) == 0)
384  {
385  uint8_t block[AES_BLOCK_SIZE];
386 
387  //Save the last input block
389 
390  //Decrypt payload data
391  error = aesProcessData(context, iv, c, p, length,
392  HSM_SYM_AES_OPMODE_CBC, HSM_SYM_AES_DECRYPT);
393 
394  //Update the value of the initialization vector
396  }
397  else
398  {
399  //The length of the payload must be a multiple of the block size
400  error = ERROR_INVALID_LENGTH;
401  }
402  }
403  else
404  {
405  size_t i;
406  uint8_t t[16];
407 
408  //CBC mode operates in a block-by-block fashion
409  while(length >= cipher->blockSize)
410  {
411  //Save input block
412  osMemcpy(t, c, cipher->blockSize);
413 
414  //Decrypt the current block
415  cipher->decryptBlock(context, c, p);
416 
417  //XOR output block with IV contents
418  for(i = 0; i < cipher->blockSize; i++)
419  {
420  p[i] ^= iv[i];
421  }
422 
423  //Update IV with input block contents
424  osMemcpy(iv, t, cipher->blockSize);
425 
426  //Next block
427  c += cipher->blockSize;
428  p += cipher->blockSize;
429  length -= cipher->blockSize;
430  }
431 
432  //The length of the payload must be a multiple of the block size
433  if(length != 0)
434  {
435  error = ERROR_INVALID_LENGTH;
436  }
437  }
438 
439  //Return status code
440  return error;
441 }
442 
443 #endif
444 #if (CTR_SUPPORT == ENABLED && AES_SUPPORT == ENABLED)
445 
446 /**
447  * @brief CTR encryption
448  * @param[in] cipher Cipher algorithm
449  * @param[in] context Cipher algorithm context
450  * @param[in] m Size in bits of the specific part of the block to be incremented
451  * @param[in,out] t Initial counter block
452  * @param[in] p Plaintext to be encrypted
453  * @param[out] c Ciphertext resulting from the encryption
454  * @param[in] length Total number of data bytes to be encrypted
455  * @return Error code
456  **/
457 
458 error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m,
459  uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
460 {
461  error_t error;
462 
463  //Initialize status code
464  error = NO_ERROR;
465 
466  //Check the value of the parameter
467  if((m % 8) == 0 && m <= (cipher->blockSize * 8))
468  {
469  //Determine the size, in bytes, of the specific part of the block
470  //to be incremented
471  m = m / 8;
472 
473  //AES cipher algorithm?
474  if(cipher == AES_CIPHER_ALGO)
475  {
476  size_t k;
477  size_t n;
478 
479  //Process plaintext
480  while(length > 0 && !error)
481  {
482  //Limit the number of blocks to process at a time
483  k = 256 - t[AES_BLOCK_SIZE - 1];
484  n = MIN(length, k * AES_BLOCK_SIZE);
485  k = (n + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE;
486 
487  //Encrypt payload data
488  error = aesProcessData(context, t, p, c, n,
489  HSM_SYM_AES_OPMODE_CTR, HSM_SYM_AES_ENCRYPT);
490 
491  //Standard incrementing function
493 
494  //Next block
495  p += n;
496  c += n;
497  length -= n;
498  }
499  }
500  else
501  {
502  size_t i;
503  size_t n;
504  uint8_t o[16];
505 
506  //Process plaintext
507  while(length > 0)
508  {
509  //CTR mode operates in a block-by-block fashion
510  n = MIN(length, cipher->blockSize);
511 
512  //Compute O(j) = CIPH(T(j))
513  cipher->encryptBlock(context, t, o);
514 
515  //Compute C(j) = P(j) XOR T(j)
516  for(i = 0; i < n; i++)
517  {
518  c[i] = p[i] ^ o[i];
519  }
520 
521  //Standard incrementing function
522  ctrIncBlock(t, 1, cipher->blockSize, m);
523 
524  //Next block
525  p += n;
526  c += n;
527  length -= n;
528  }
529  }
530  }
531  else
532  {
533  //The value of the parameter is not valid
534  error = ERROR_INVALID_PARAMETER;
535  }
536 
537  //Return status code
538  return error;
539 }
540 
541 #endif
542 #endif
uint16_t block
Definition: tftp_common.h:115
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1200
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:1195
error_t aesProcessData(AesContext *context, uint8_t *iv, const uint8_t *input, uint8_t *output, size_t length, hsm_Aes_ModeTypes_E mode, hsm_Aes_CmdTypes_E command)
Perform AES encryption or decryption.
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1199
AES algorithm context.
Definition: aes.h:58
#define AES_BLOCK_SIZE
Definition: aes.h:43
error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t ecbEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *p, uint8_t *c, size_t length)
ECB encryption.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
error_t ecbDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *c, uint8_t *p, size_t length)
ECB decryption.
uint8_t iv[]
Definition: ike.h:1659
Block cipher modes of operation.
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
uint_t nr
Definition: aes.h:59
OsMutex pic32czca90CryptoMutex
PIC32CZ CA90 cipher hardware accelerator.
void aesDecryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 16-byte block using AES algorithm.
PIC32CZ CA90 hardware cryptographic accelerator (HSM)
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.
Common interface for encryption algorithms.
Definition: crypto.h:1191
#define AES_CIPHER_ALGO
Definition: aes.h:45
uint32_t ek[60]
Definition: aes.h:60
unsigned int uint_t
Definition: compiler_port.h:57
error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
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.
void aesEncryptBlock(AesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 16-byte block using AES algorithm.