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