esp32_c6_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file esp32_c6_crypto_pkc.c
3  * @brief ESP32-C6 public-key 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 "esp_crypto_lock.h"
36 #include "soc/pcr_reg.h"
37 #include "soc/hwcrypto_reg.h"
38 #include "esp_private/periph_ctrl.h"
41 #include "pkc/rsa.h"
42 #include "ecc/curve25519.h"
43 #include "ecc/curve448.h"
44 #include "debug.h"
45 
46 //Check crypto library configuration
47 #if (ESP32_C6_CRYPTO_PKC_SUPPORT == ENABLED)
48 
49 
50 /**
51  * @brief RSA module initialization
52  **/
53 
54 void esp32c6RsaInit(void)
55 {
56  //Enable RSA module
57  periph_module_enable(PERIPH_RSA_MODULE);
58 
59  //Clear PCR_RSA_MEM_PD bit
60  REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
61 
62  //Software should query RSA_CLEAN_REG after being released from reset, and
63  //before writing to any RSA Accelerator memory blocks or registers for the
64  //first time
65  while(REG_READ(RSA_QUERY_CLEAN_REG) == 0)
66  {
67  }
68 }
69 
70 
71 /**
72  * @brief Multiple precision multiplication
73  * @param[out] r Resulting integer R = A * B
74  * @param[in] a First operand A
75  * @param[in] b Second operand B
76  * @return Error code
77  **/
78 
79 error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
80 {
81  error_t error;
82  size_t i;
83  size_t n;
84  size_t aLen;
85  size_t bLen;
86 
87  //Retrieve the length of the first operand, in 32-bit words
88  aLen = mpiGetLength(a);
89  //Retrieve the length of the second operand, in 32-bit words
90  bLen = mpiGetLength(b);
91 
92  //The accelerator supports large-number multiplication up to 1536 bits
93  if(aLen <= 48 && bLen <= 48)
94  {
95  //All numbers in calculation must be of the same length
96  n = 1;
97  n = MAX(n, aLen);
98  n = MAX(n, bLen);
99 
100  //Acquire exclusive access to the RSA module
101  esp_crypto_mpi_lock_acquire();
102 
103  //Clear the interrupt flag
104  REG_WRITE(RSA_INT_CLR_REG, 1);
105  //Set mode register
106  REG_WRITE(RSA_MODE_REG, (2 * n) - 1);
107 
108  //Copy the first operand to RSA_X_MEM
109  for(i = 0; i < n; i++)
110  {
111  if(i < a->size)
112  {
113  REG_WRITE(RSA_X_MEM + i * 4, a->data[i]);
114  }
115  else
116  {
117  REG_WRITE(RSA_X_MEM + i * 4, 0);
118  }
119  }
120 
121  //The second operand will not be written to the base address of the
122  //RSA_Z_MEM memory. This area must be filled with zeroes
123  for(i = 0; i < n; i++)
124  {
125  REG_WRITE(RSA_Z_MEM + i * 4, 0);
126  }
127 
128  //The second operand must be written to the base address of the
129  //RSA_Z_MEM memory plus the address offset 4 * n
130  for(i = 0; i < n; i++)
131  {
132  if(i < b->size)
133  {
134  REG_WRITE(RSA_Z_MEM + (n + i) * 4, b->data[i]);
135  }
136  else
137  {
138  REG_WRITE(RSA_Z_MEM + (n + i) * 4, 0);
139  }
140  }
141 
142  //Start large-number multiplication
143  REG_WRITE(RSA_SET_START_MULT_REG, 1);
144 
145  //Wait for the operation to complete
146  while(REG_READ(RSA_QUERY_IDLE_REG) == 0)
147  {
148  }
149 
150  //Set the sign of the result
151  r->sign = (a->sign == b->sign) ? 1 : -1;
152 
153  //The length of the result is 2 x N bits
154  error = mpiGrow(r, n * 2);
155 
156  //Check status code
157  if(!error)
158  {
159  //Read the result from RSA_Z_MEM
160  for(i = 0; i < r->size; i++)
161  {
162  if(i < (n * 2))
163  {
164  r->data[i] = REG_READ(RSA_Z_MEM + i * 4);
165  }
166  else
167  {
168  r->data[i] = 0;
169  }
170  }
171  }
172 
173  //Clear the interrupt flag
174  REG_WRITE(RSA_INT_CLR_REG, 1);
175 
176  //Release exclusive access to the RSA module
177  esp_crypto_mpi_lock_release();
178  }
179  else
180  {
181  //Report an error
182  error = ERROR_FAILURE;
183  }
184 
185  //Return status code
186  return error;
187 }
188 
189 
190 /**
191  * @brief Modular exponentiation
192  * @param[out] r Resulting integer R = A ^ E mod P
193  * @param[in] a Pointer to a multiple precision integer
194  * @param[in] e Exponent
195  * @param[in] p Modulus
196  * @return Error code
197  **/
198 
199 error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
200 {
201  error_t error;
202  size_t i;
203  size_t n;
204  size_t modLen;
205  size_t expLen;
206  uint32_t m;
207  Mpi t;
208  Mpi r2;
209 
210  //Initialize multiple precision integers
211  mpiInit(&t);
212  mpiInit(&r2);
213 
214  //Retrieve the length of the modulus, in bits
215  modLen = mpiGetBitLength(p);
216  //Retrieve the length of the exponent, in bits
217  expLen = mpiGetBitLength(e);
218 
219  //The accelerator supports operand lengths up to 3072 bits
220  if(modLen > 0 && modLen <= 3072 && expLen > 0 && expLen <= 3072)
221  {
222  //All numbers in calculation must be of the same length
223  n = MAX(modLen, expLen);
224  n = (n + 31) / 32;
225 
226  //Reduce the operand first
227  error = mpiMod(&t, a, p);
228 
229  //Let R = b^n and pre-compute the quantity R^2 mod M
230  if(!error)
231  {
232  error = mpiSetValue(&r2, 1);
233  }
234 
235  if(!error)
236  {
237  error = mpiShiftLeft(&r2, n * 2 * 32);
238  }
239 
240  if(!error)
241  {
242  error = mpiMod(&r2, &r2, p);
243  }
244 
245  //Check status code
246  if(!error)
247  {
248  //Acquire exclusive access to the RSA module
249  esp_crypto_mpi_lock_acquire();
250 
251  //Clear the interrupt flag
252  REG_WRITE(RSA_INT_CLR_REG, 1);
253  //Set mode register
254  REG_WRITE(RSA_MODE_REG, n - 1);
255 
256  //Copy the operand to RSA_X_MEM
257  for(i = 0; i < n; i++)
258  {
259  if(i < t.size)
260  {
261  REG_WRITE(RSA_X_MEM + i * 4, t.data[i]);
262  }
263  else
264  {
265  REG_WRITE(RSA_X_MEM + i * 4, 0);
266  }
267  }
268 
269  //Copy the exponent to RSA_Y_MEM
270  for(i = 0; i < n; i++)
271  {
272  if(i < e->size)
273  {
274  REG_WRITE(RSA_Y_MEM + i * 4, e->data[i]);
275  }
276  else
277  {
278  REG_WRITE(RSA_Y_MEM + i * 4, 0);
279  }
280  }
281 
282  //Copy the modulus to RSA_M_MEM
283  for(i = 0; i < n; i++)
284  {
285  if(i < p->size)
286  {
287  REG_WRITE(RSA_M_MEM + i * 4, p->data[i]);
288  }
289  else
290  {
291  REG_WRITE(RSA_M_MEM + i * 4, 0);
292  }
293  }
294 
295  //Copy the pre-calculated value of R^2 mod M to RSA_Z_MEM
296  for(i = 0; i < n; i++)
297  {
298  if(i < r2.size)
299  {
300  REG_WRITE(RSA_Z_MEM + i * 4, r2.data[i]);
301  }
302  else
303  {
304  REG_WRITE(RSA_Z_MEM + i * 4, 0);
305  }
306  }
307 
308  //Use Newton's method to compute the inverse of M[0] mod 2^32
309  for(m = 2 - p->data[0], i = 0; i < 4; i++)
310  {
311  m = m * (2 - m * p->data[0]);
312  }
313 
314  //Precompute M' = -1/M[0] mod 2^32;
315  m = ~m + 1;
316 
317  //Write the value of M' to RSA_M_PRIME_REG
318  REG_WRITE(RSA_M_PRIME_REG, m);
319 
320  //Enable search option
321  REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
322  REG_WRITE(RSA_SEARCH_POS_REG, expLen - 1);
323 
324  //Start modular exponentiation
325  REG_WRITE(RSA_SET_START_MODEXP_REG, 1);
326 
327  //Wait for the operation to complete
328  while(REG_READ(RSA_QUERY_IDLE_REG) == 0)
329  {
330  }
331 
332  //Adjust the size of the result if necessary
333  error = mpiGrow(r, n);
334 
335  //Check status code
336  if(!error)
337  {
338  //Read the result from RSA_Z_MEM
339  for(i = 0; i < r->size; i++)
340  {
341  if(i < n)
342  {
343  r->data[i] = REG_READ(RSA_Z_MEM + i * 4);
344  }
345  else
346  {
347  r->data[i] = 0;
348  }
349  }
350  }
351 
352  //Clear the interrupt flag
353  REG_WRITE(RSA_INT_CLR_REG, 1);
354 
355  //Release exclusive access to the RSA module
356  esp_crypto_mpi_lock_release();
357  }
358  }
359  else
360  {
361  //Report an error
362  error = ERROR_FAILURE;
363  }
364 
365  //Release previously allocated memory
366  mpiFree(&t);
367  mpiFree(&r2);
368 
369  //Return status code
370  return error;
371 }
372 
373 
374 #if (X25519_SUPPORT == ENABLED || ED25519_SUPPORT == ENABLED)
375 
376 /**
377  * @brief Modular multiplication
378  * @param[out] r Resulting integer R = (A * B) mod p
379  * @param[in] a An integer such as 0 <= A < p
380  * @param[in] b An integer such as 0 <= B < p
381  **/
382 
383 void curve25519Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
384 {
385  uint_t i;
386 
387  //Acquire exclusive access to the RSA module
388  esp_crypto_mpi_lock_acquire();
389 
390  //Clear the interrupt flag
391  REG_WRITE(RSA_INT_CLR_REG, 1);
392  //Set mode register
393  REG_WRITE(RSA_MODE_REG, 7);
394 
395  //Copy the first operand to RSA_X_MEM
396  for(i = 0; i < 8; i++)
397  {
398  REG_WRITE(RSA_X_MEM + i * 4, a[i]);
399  }
400 
401  //Copy the second operand to RSA_Y_MEM
402  for(i = 0; i < 8; i++)
403  {
404  REG_WRITE(RSA_Y_MEM + i * 4, b[i]);
405  }
406 
407  //Copy the modulus to RSA_M_MEM
408  REG_WRITE(RSA_M_MEM, 0xFFFFFFED);
409  REG_WRITE(RSA_M_MEM + 4, 0xFFFFFFFF);
410  REG_WRITE(RSA_M_MEM + 8, 0xFFFFFFFF);
411  REG_WRITE(RSA_M_MEM + 12, 0xFFFFFFFF);
412  REG_WRITE(RSA_M_MEM + 16, 0xFFFFFFFF);
413  REG_WRITE(RSA_M_MEM + 20, 0xFFFFFFFF);
414  REG_WRITE(RSA_M_MEM + 24, 0xFFFFFFFF);
415  REG_WRITE(RSA_M_MEM + 28, 0x7FFFFFFF);
416 
417  //Copy the pre-calculated value of R^2 mod M to RSA_Z_MEM
418  REG_WRITE(RSA_Z_MEM, 0x000005A4);
419  REG_WRITE(RSA_Z_MEM + 4, 0x00000000);
420  REG_WRITE(RSA_Z_MEM + 8, 0x00000000);
421  REG_WRITE(RSA_Z_MEM + 12, 0x00000000);
422  REG_WRITE(RSA_Z_MEM + 16, 0x00000000);
423  REG_WRITE(RSA_Z_MEM + 20, 0x00000000);
424  REG_WRITE(RSA_Z_MEM + 24, 0x00000000);
425  REG_WRITE(RSA_Z_MEM + 28, 0x00000000);
426 
427  //Write the value of M' to RSA_M_PRIME_REG
428  REG_WRITE(RSA_M_PRIME_REG, 0x286BCA1B);
429  //Start large-number modular multiplication
430  REG_WRITE(RSA_SET_START_MODMULT_REG, 1);
431 
432  //Wait for the operation to complete
433  while(REG_READ(RSA_QUERY_IDLE_REG) == 0)
434  {
435  }
436 
437  //Read the result from RSA_Z_MEM
438  for(i = 0; i < 8; i++)
439  {
440  r[i] = REG_READ(RSA_Z_MEM + i * 4);
441  }
442 
443  //Clear the interrupt flag
444  REG_WRITE(RSA_INT_CLR_REG, 1);
445 
446  //Release exclusive access to the RSA module
447  esp_crypto_mpi_lock_release();
448 }
449 
450 #endif
451 #if (X448_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
452 
453 /**
454  * @brief Modular multiplication
455  * @param[out] r Resulting integer R = (A * B) mod p
456  * @param[in] a An integer such as 0 <= A < p
457  * @param[in] b An integer such as 0 <= B < p
458  **/
459 
460 void curve448Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
461 {
462  uint_t i;
463 
464  //Acquire exclusive access to the RSA module
465  esp_crypto_mpi_lock_acquire();
466 
467  //Clear the interrupt flag
468  REG_WRITE(RSA_INT_CLR_REG, 1);
469  //Set mode register
470  REG_WRITE(RSA_MODE_REG, 13);
471 
472  //Copy the first operand to RSA_X_MEM
473  for(i = 0; i < 14; i++)
474  {
475  REG_WRITE(RSA_X_MEM + i * 4, a[i]);
476  }
477 
478  //Copy the second operand to RSA_Y_MEM
479  for(i = 0; i < 14; i++)
480  {
481  REG_WRITE(RSA_Y_MEM + i * 4, b[i]);
482  }
483 
484  //Copy the modulus to RSA_M_MEM
485  REG_WRITE(RSA_M_MEM, 0xFFFFFFFF);
486  REG_WRITE(RSA_M_MEM + 4, 0xFFFFFFFF);
487  REG_WRITE(RSA_M_MEM + 8, 0xFFFFFFFF);
488  REG_WRITE(RSA_M_MEM + 12, 0xFFFFFFFF);
489  REG_WRITE(RSA_M_MEM + 16, 0xFFFFFFFF);
490  REG_WRITE(RSA_M_MEM + 20, 0xFFFFFFFF);
491  REG_WRITE(RSA_M_MEM + 24, 0xFFFFFFFF);
492  REG_WRITE(RSA_M_MEM + 28, 0xFFFFFFFE);
493  REG_WRITE(RSA_M_MEM + 32, 0xFFFFFFFF);
494  REG_WRITE(RSA_M_MEM + 36, 0xFFFFFFFF);
495  REG_WRITE(RSA_M_MEM + 40, 0xFFFFFFFF);
496  REG_WRITE(RSA_M_MEM + 44, 0xFFFFFFFF);
497  REG_WRITE(RSA_M_MEM + 48, 0xFFFFFFFF);
498  REG_WRITE(RSA_M_MEM + 52, 0xFFFFFFFF);
499 
500  //Copy the pre-calculated value of R^2 mod M to RSA_Z_MEM
501  REG_WRITE(RSA_Z_MEM, 0x00000002);
502  REG_WRITE(RSA_Z_MEM + 4, 0x00000000);
503  REG_WRITE(RSA_Z_MEM + 8, 0x00000000);
504  REG_WRITE(RSA_Z_MEM + 12, 0x00000000);
505  REG_WRITE(RSA_Z_MEM + 16, 0x00000000);
506  REG_WRITE(RSA_Z_MEM + 20, 0x00000000);
507  REG_WRITE(RSA_Z_MEM + 24, 0x00000000);
508  REG_WRITE(RSA_Z_MEM + 28, 0x00000003);
509  REG_WRITE(RSA_Z_MEM + 32, 0x00000000);
510  REG_WRITE(RSA_Z_MEM + 36, 0x00000000);
511  REG_WRITE(RSA_Z_MEM + 40, 0x00000000);
512  REG_WRITE(RSA_Z_MEM + 44, 0x00000000);
513  REG_WRITE(RSA_Z_MEM + 48, 0x00000000);
514  REG_WRITE(RSA_Z_MEM + 52, 0x00000000);
515 
516  //Write the value of M' to RSA_M_PRIME_REG
517  REG_WRITE(RSA_M_PRIME_REG, 0x00000001);
518  //Start large-number modular multiplication
519  REG_WRITE(RSA_SET_START_MODMULT_REG, 1);
520 
521  //Wait for the operation to complete
522  while(REG_READ(RSA_QUERY_IDLE_REG) == 0)
523  {
524  }
525 
526  //Read the result from RSA_Z_MEM
527  for(i = 0; i < 14; i++)
528  {
529  r[i] = REG_READ(RSA_Z_MEM + i * 4);
530  }
531 
532  //Clear the interrupt flag
533  REG_WRITE(RSA_INT_CLR_REG, 1);
534 
535  //Release exclusive access to the RSA module
536  esp_crypto_mpi_lock_release();
537 }
538 
539 #endif
540 #endif
error_t mpiShiftLeft(Mpi *r, uint_t n)
Left shift operation.
Definition: mpi.c:1111
Curve448 elliptic curve (constant-time implementation)
uint8_t b
Definition: nbns_common.h:104
uint8_t a
Definition: ndp.h:411
Arbitrary precision integer.
Definition: mpi.h:80
uint8_t p
Definition: ndp.h:300
uint8_t t
Definition: lldp_ext_med.h:212
error_t mpiSetValue(Mpi *r, int_t a)
Set the value of a multiple precision integer.
Definition: mpi.c:484
void curve448Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
ESP32-C6 hardware cryptographic accelerator.
uint8_t r
Definition: ndp.h:346
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1444
ESP32-C6 public-key hardware accelerator.
void curve25519Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
error_t
Error codes.
Definition: error.h:43
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
RSA public-key cryptography standard.
uint_t * data
Definition: mpi.h:84
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:234
#define MAX(a, b)
Definition: os_port.h:67
uint_t mpiGetLength(const Mpi *a)
Get the actual length in words.
Definition: mpi.c:168
void esp32c6RsaInit(void)
RSA module initialization.
uint8_t m
Definition: ndp.h:304
uint8_t n
uint_t size
Definition: mpi.h:82
Curve25519 elliptic curve (constant-time implementation)
unsigned int uint_t
Definition: compiler_port.h:50
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
error_t mpiGrow(Mpi *r, uint_t size)
Adjust the size of multiple precision integer.
Definition: mpi.c:94
error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
Debugging facilities.
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64