stm32h5xx_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file stm32h5xx_crypto_pkc.c
3  * @brief STM32H5 public-key hardware accelerator (PKA)
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 "stm32h5xx.h"
36 #include "stm32h5xx_hal.h"
37 #include "core/crypto.h"
40 #include "pkc/rsa.h"
41 #include "ecc/ec.h"
42 #include "ecc/ec_misc.h"
43 #include "ecc/ecdsa.h"
44 #include "debug.h"
45 
46 //Check crypto library configuration
47 #if (STM32H5XX_CRYPTO_PKC_SUPPORT == ENABLED)
48 
49 
50 /**
51  * @brief PKA module initialization
52  * @return Error code
53  **/
54 
56 {
57  //Enable PKA peripheral clock
58  __HAL_RCC_PKA_CLK_ENABLE();
59 
60  //Reset the PKA peripheral
61  PKA->CR = 0;
62 
63  //Enable the PKA peripheral
64  while((PKA->CR & PKA_CR_EN) == 0)
65  {
66  PKA->CR = PKA_CR_EN;
67  }
68 
69  //Clear flags
70  PKA->CLRFR = PKA_CLRFR_ADDRERRFC | PKA_CLRFR_RAMERRFC | PKA_CLRFR_PROCENDFC;
71 
72  //Successful processing
73  return NO_ERROR;
74 }
75 
76 
77 /**
78  * @brief Import byte array
79  * @param[in] src Pointer to the byte array
80  * @param[in] srcLen Length of the array to be copied, in bytes
81  * @param[in] destLen Length of the operand, in bits
82  * @param[in] offset PKA ram offset
83  **/
84 
85 void pkaImportArray(const uint8_t *src, size_t srcLen, uint_t destLen,
86  uint_t offset)
87 {
88  uint_t i;
89  uint_t j;
90  uint32_t temp;
91 
92  //Get the length of the operand, in 64-bit words
93  destLen = (destLen + 63) / 64;
94 
95  //Copy the array to the PKA RAM
96  for(i = 0, j = 0; i < srcLen; i++)
97  {
98  switch(i % 4)
99  {
100  case 0:
101  temp = src[srcLen - i - 1];
102  break;
103  case 1:
104  temp |= src[srcLen - i - 1] << 8;
105  break;
106  case 2:
107  temp |= src[srcLen - i - 1] << 16;
108  break;
109  default:
110  temp |= src[srcLen - i - 1] << 24;
111  PKA->RAM[offset + j] = temp;
112  j++;
113  break;
114  }
115  }
116 
117  //Pad the operand with zeroes
118  for(; i < (destLen * 8); i++)
119  {
120  switch(i % 4)
121  {
122  case 0:
123  temp = 0;
124  break;
125  case 3:
126  PKA->RAM[offset + j] = temp;
127  j++;
128  break;
129  default:
130  break;
131  }
132  }
133 
134  //An additional 64-bit word with all bits equal to zero must be added
135  PKA->RAM[offset + j] = 0;
136  PKA->RAM[offset + j + 1] = 0;
137 }
138 
139 
140 /**
141  * @brief Import scalar
142  * @param[in] src Pointer to the scalar
143  * @param[in] length Length of the operand, in bits
144  * @param[in] offset PKA ram offset
145  **/
146 
147 void pkaImportScalar(const uint32_t *src, uint_t length, uint_t offset)
148 {
149  uint_t i;
150 
151  //Get the length of the operand, in 32-bit words
152  length = (length + 31) / 32;
153 
154  //Copy the scalar to the PKA RAM
155  for(i = 0; i < length; i++)
156  {
157  PKA->RAM[offset + i] = src[i];
158  }
159 
160  //Pad the operand with zeroes
161  if((i % 2) != 0)
162  {
163  PKA->RAM[offset + i] = 0;
164  i++;
165  }
166 
167  //An additional 64-bit word with all bits equal to zero must be added
168  PKA->RAM[offset + i] = 0;
169  PKA->RAM[offset + i + 1] = 0;
170 }
171 
172 
173 /**
174  * @brief Import multiple-precision integer
175  * @param[in] src Pointer to the multiple-precision integer
176  * @param[in] length Length of the operand, in bits
177  * @param[in] offset PKA ram offset
178  **/
179 
180 void pkaImportMpi(const Mpi *src, uint_t length, uint_t offset)
181 {
182  uint_t i;
183  uint_t n;
184 
185  //Get the length of the operand, in 64-bit words
186  length = (length + 63) / 64;
187 
188  //Get the actual length of the multiple-precision integer, in words
189  n = mpiGetLength(src);
190 
191  //Copy the multiple-precision integer to the PKA RAM
192  for(i = 0; i < n && i < (length * 2); i++)
193  {
194  PKA->RAM[offset + i] = src->data[i];
195  }
196 
197  //Pad the operand with zeroes
198  for(; i < (length * 2); i++)
199  {
200  PKA->RAM[offset + i] = 0;
201  }
202 
203  //An additional 64-bit word with all bits equal to zero must be added
204  PKA->RAM[offset + i] = 0;
205  PKA->RAM[offset + i + 1] = 0;
206 }
207 
208 
209 /**
210  * @brief Export scalar
211  * @param[out] dest Pointer to the scalar
212  * @param[in] length Length of the operand, in bits
213  * @param[in] offset PKA ram offset
214  **/
215 
216 void pkaExportScalar(uint32_t *dest, uint_t length, uint_t offset)
217 {
218  uint_t i;
219 
220  //Get the length of the operand, in 32-bit words
221  length = (length + 31) / 32;
222 
223  //Copy the scalar from the PKA RAM
224  for(i = 0; i < length; i++)
225  {
226  dest[i] = PKA->RAM[offset + i];
227  }
228 }
229 
230 
231 /**
232  * @brief Export multiple-precision integer
233  * @param[out] dest Pointer to the multiple-precision integer
234  * @param[in] length Length of the operand, in bits
235  * @param[in] offset PKA ram offset
236  * @return Error code
237  **/
238 
240 {
241  error_t error;
242  uint_t i;
243 
244  //Get the length of the operand, in 32-bit words
245  length = (length + 31) / 32;
246 
247  //Skip trailing zeroes
248  while(length > 0 && PKA->RAM[offset + length - 1] == 0)
249  {
250  length--;
251  }
252 
253  //Ajust the size of the multiple precision integer
254  error = mpiGrow(dest, length);
255 
256  //Check status code
257  if(!error)
258  {
259  //Copy the multiple-precision integer from the PKA RAM
260  for(i = 0; i < length; i++)
261  {
262  dest->data[i] = PKA->RAM[offset + i];
263  }
264 
265  //Pad the resulting value with zeroes
266  for(; i < dest->size; i++)
267  {
268  dest->data[i] = 0;
269  }
270 
271  //Set the sign
272  dest->sign = 1;
273  }
274 
275  //Return status code
276  return error;
277 }
278 
279 
280 #if (MPI_SUPPORT == ENABLED) && defined(PKA_CR_MODE_MODULAR_EXP)
281 
282 /**
283  * @brief Modular exponentiation
284  * @param[out] r Resulting integer R = A ^ E mod P
285  * @param[in] a Pointer to a multiple precision integer
286  * @param[in] e Exponent
287  * @param[in] p Modulus
288  * @return Error code
289  **/
290 
291 error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
292 {
293  error_t error;
294  uint_t modLen;
295  uint_t expLen;
296  uint32_t temp;
297 
298  //Get the length of the modulus, in bits
299  modLen = mpiGetBitLength(p);
300  //Get the length of the exponent, in bits
301  expLen = mpiGetBitLength(e);
302 
303  //Check the length of the operands
304  if(modLen <= PKA_MAX_ROS && expLen <= PKA_MAX_ROS)
305  {
306  //Reduce the operand first
307  error = mpiMod(r, a, p);
308 
309  //Check status code
310  if(!error)
311  {
312  //Acquire exclusive access to the PKA module
314 
315  //Specify the length of the operand, in bits
316  PKA->RAM[PKA_MODULAR_EXP_IN_OP_NB_BITS] = modLen;
317  PKA->RAM[PKA_MODULAR_EXP_IN_OP_NB_BITS + 1] = 0;
318 
319  //Specify the length of the exponent, in bits
320  PKA->RAM[PKA_MODULAR_EXP_IN_EXP_NB_BITS] = expLen;
321  PKA->RAM[PKA_MODULAR_EXP_IN_EXP_NB_BITS + 1] = 0;
322 
323  //Load input arguments into the PKA internal RAM
324  pkaImportMpi(r, modLen, PKA_MODULAR_EXP_IN_EXPONENT_BASE);
325  pkaImportMpi(e, expLen, PKA_MODULAR_EXP_IN_EXPONENT);
326  pkaImportMpi(p, modLen, PKA_MODULAR_EXP_IN_MODULUS);
327 
328  //Disable interrupts
329  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
330 
331  //Write in the MODE field of PKA_CR register, specifying the operation
332  //which is to be executed
333  temp = PKA->CR & ~PKA_CR_MODE;
334  PKA->CR = temp | (PKA_CR_MODE_MODULAR_EXP << PKA_CR_MODE_Pos);
335 
336  //Then assert the START bit in PKA_CR register
337  PKA->CR |= PKA_CR_START;
338 
339  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
340  //indicating that the computation is complete
341  while((PKA->SR & PKA_SR_PROCENDF) == 0)
342  {
343  }
344 
345  //Read the result data from the PKA internal RAM
346  error = pkaExportMpi(r, modLen, PKA_MODULAR_EXP_OUT_RESULT);
347 
348  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
349  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
350 
351  //Release exclusive access to the PKA module
353  }
354  }
355  else
356  {
357  //Report an error
358  error = ERROR_FAILURE;
359  }
360 
361  //Return status code
362  return error;
363 }
364 
365 #endif
366 #if (RSA_SUPPORT == ENABLED) && defined(PKA_CR_MODE_RSA_CRT_EXP)
367 
368 /**
369  * @brief Modular exponentiation with CRT
370  * @param[in] key RSA public key
371  * @param[in] m Message representative
372  * @param[out] c Ciphertext representative
373  * @return Error code
374  **/
375 
376 error_t pkaRsaCrtExp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
377 {
378  error_t error;
379  uint_t nLen;
380  uint_t pLen;
381  uint_t qLen;
382  uint_t dpLen;
383  uint_t dqLen;
384  uint_t qinvLen;
385  uint32_t temp;
386 
387  //Get the length of the private key
388  nLen = mpiGetBitLength(&key->n);
389  pLen = mpiGetBitLength(&key->p);
390  qLen = mpiGetBitLength(&key->q);
391  dpLen = mpiGetBitLength(&key->dp);
392  dqLen = mpiGetBitLength(&key->dq);
393  qinvLen = mpiGetBitLength(&key->qinv);
394 
395  //Check the length of the operands
396  if(nLen <= PKA_MAX_ROS && pLen <= (nLen / 2) && qLen <= (nLen / 2) &&
397  dpLen <= (nLen / 2) && dqLen <= (nLen / 2) && qinvLen <= (nLen / 2))
398  {
399  //Acquire exclusive access to the PKA module
401 
402  //Specify the length of the operand, in bits
403  PKA->RAM[PKA_RSA_CRT_EXP_IN_MOD_NB_BITS] = nLen;
404  PKA->RAM[PKA_RSA_CRT_EXP_IN_MOD_NB_BITS + 1] = 0;
405 
406  //Load input arguments into the PKA internal RAM
407  pkaImportMpi(&key->p, nLen / 2, PKA_RSA_CRT_EXP_IN_PRIME_P);
408  pkaImportMpi(&key->q, nLen / 2, PKA_RSA_CRT_EXP_IN_PRIME_Q);
409  pkaImportMpi(&key->dp, nLen / 2, PKA_RSA_CRT_EXP_IN_DP_CRT);
410  pkaImportMpi(&key->dq, nLen / 2, PKA_RSA_CRT_EXP_IN_DQ_CRT);
411  pkaImportMpi(&key->qinv, nLen / 2, PKA_RSA_CRT_EXP_IN_QINV_CRT);
412  pkaImportMpi(c, nLen, PKA_RSA_CRT_EXP_IN_EXPONENT_BASE);
413 
414  //Disable interrupts
415  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
416 
417  //Write in the MODE field of PKA_CR register, specifying the operation
418  //which is to be executed
419  temp = PKA->CR & ~PKA_CR_MODE;
420  PKA->CR = temp | (PKA_CR_MODE_RSA_CRT_EXP << PKA_CR_MODE_Pos);
421 
422  //Then assert the START bit in PKA_CR register
423  PKA->CR |= PKA_CR_START;
424 
425  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
426  //indicating that the computation is complete
427  while((PKA->SR & PKA_SR_PROCENDF) == 0)
428  {
429  }
430 
431  //Read the result data from the PKA internal RAM
432  error = pkaExportMpi(m, nLen, PKA_RSA_CRT_EXP_OUT_RESULT);
433 
434  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
435  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
436 
437  //Release exclusive access to the PKA module
439  }
440  else
441  {
442  //Report an error
443  error = ERROR_FAILURE;
444  }
445 
446  //Return status code
447  return error;
448 }
449 
450 
451 /**
452  * @brief RSA decryption primitive
453  * @param[in] key RSA private key
454  * @param[in] c Ciphertext representative
455  * @param[out] m Message representative
456  * @return Error code
457  **/
458 
459 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
460 {
461  error_t error;
462 
463  //The ciphertext representative c shall be between 0 and n - 1
464  if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0)
465  return ERROR_OUT_OF_RANGE;
466 
467  //Use the Chinese remainder algorithm?
468  if(mpiGetLength(&key->n) > 0 && mpiGetLength(&key->p) > 0 &&
469  mpiGetLength(&key->q) > 0 && mpiGetLength(&key->dp) > 0 &&
470  mpiGetLength(&key->dq) > 0 && mpiGetLength(&key->qinv) > 0)
471  {
472  //Perform modular exponentiation (with CRT)
473  error = pkaRsaCrtExp(key, c, m);
474  }
475  else if(mpiGetLength(&key->n) > 0 && mpiGetLength(&key->d) > 0)
476  {
477  //Perform modular exponentiation (without CRT)
478  error = mpiExpMod(m, c, &key->d, &key->n);
479  }
480  else
481  {
482  //Invalid parameters
483  error = ERROR_INVALID_PARAMETER;
484  }
485 
486  //Return status code
487  return error;
488 }
489 
490 #endif
491 #if (EC_SUPPORT == ENABLED) && defined(PKA_CR_MODE_ECC_MUL)
492 
493 /**
494  * @brief Scalar multiplication (fast calculation)
495  * @param[in] curve Elliptic curve parameters
496  * @param[out] r Resulting point R = d.S
497  * @param[in] d An integer d such as 0 <= d < p
498  * @param[in] s EC point
499  * @return Error code
500  **/
501 
502 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
503  const EcPoint3 *s)
504 {
505  //Compute R = d.S
506  return ecMulRegular(curve, r, d, s);
507 }
508 
509 
510 /**
511  * @brief Scalar multiplication (regular calculation)
512  * @param[in] curve Elliptic curve parameters
513  * @param[out] r Resulting point R = d.S
514  * @param[in] d An integer d such as 0 <= d < q
515  * @param[in] s EC point
516  * @return Error code
517  **/
518 
519 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
520  const EcPoint3 *s)
521 {
522  error_t error;
523  uint_t modLen;
524  uint_t orderLen;
525  uint32_t temp;
526 
527  //Get the length of the modulus, in bits
528  modLen = curve->fieldSize;
529  //Get the length of the order, in bits
530  orderLen = curve->orderSize;
531 
532  //Check the length of the operands
533  if(modLen <= PKA_MAX_EOS && orderLen <= PKA_MAX_EOS)
534  {
535  //Acquire exclusive access to the PKA module
537 
538  //Specify the length of the modulus, in bits
539  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS] = modLen;
540  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS + 1] = 0;
541 
542  //Specify the length of the scalar, in bits
543  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_EXP_NB_BITS] = orderLen;
544  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_EXP_NB_BITS + 1] = 0;
545 
546  //Set the sign of the coefficient A
547  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_A_COEFF_SIGN] = 0;
548  PKA->RAM[PKA_ECC_SCALAR_MUL_IN_A_COEFF_SIGN + 1] = 0;
549 
550  //Load input arguments into the PKA internal RAM
551  pkaImportScalar(curve->p, modLen, PKA_ECC_SCALAR_MUL_IN_MOD_GF);
552  pkaImportScalar(curve->a, modLen, PKA_ECC_SCALAR_MUL_IN_A_COEFF);
553  pkaImportScalar(curve->b, modLen, PKA_ECC_SCALAR_MUL_IN_B_COEFF);
554  pkaImportScalar(curve->q, orderLen, PKA_ECC_SCALAR_MUL_IN_N_PRIME_ORDER);
555  pkaImportScalar(d, orderLen, PKA_ECC_SCALAR_MUL_IN_K);
556  pkaImportScalar(s->x, modLen, PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_X);
557  pkaImportScalar(s->y, modLen, PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_Y);
558 
559  //Clear error code
560  PKA->RAM[PKA_ECC_SCALAR_MUL_OUT_ERROR] = PKA_STATUS_INVALID;
561 
562  //Disable interrupts
563  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
564 
565  //Write in the MODE field of PKA_CR register, specifying the operation
566  //which is to be executed
567  temp = PKA->CR & ~PKA_CR_MODE;
568  PKA->CR = temp | (PKA_CR_MODE_ECC_MUL << PKA_CR_MODE_Pos);
569 
570  //Then assert the START bit in PKA_CR register
571  PKA->CR |= PKA_CR_START;
572 
573  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
574  //indicating that the computation is complete
575  while((PKA->SR & PKA_SR_PROCENDF) == 0)
576  {
577  }
578 
579  //Successful computation?
580  if(PKA->RAM[PKA_ECC_SCALAR_MUL_OUT_ERROR] == PKA_STATUS_SUCCESS)
581  {
582  error = NO_ERROR;
583  }
584  else
585  {
586  error = ERROR_FAILURE;
587  }
588 
589  //Check status code
590  if(!error)
591  {
592  //Copy the x-coordinate of the result
594  pkaExportScalar(r->x, modLen, PKA_ECC_SCALAR_MUL_OUT_RESULT_X);
595 
596  //Copy the y-coordinate of the result
598  pkaExportScalar(r->y, modLen, PKA_ECC_SCALAR_MUL_OUT_RESULT_Y);
599 
600  //Set the z-coordinate of the result
602  }
603 
604  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
605  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
606 
607  //Release exclusive access to the PKA module
609  }
610  else
611  {
612  //Report an error
613  error = ERROR_FAILURE;
614  }
615 
616  //Return status code
617  return error;
618 }
619 
620 #endif
621 #if (ECDSA_SUPPORT == ENABLED) && defined(PKA_CR_MODE_ECDSA_SIGN)
622 
623 /**
624  * @brief ECDSA signature generation
625  * @param[in] prngAlgo PRNG algorithm
626  * @param[in] prngContext Pointer to the PRNG context
627  * @param[in] privateKey Signer's EC private key
628  * @param[in] digest Digest of the message to be signed
629  * @param[in] digestLen Length in octets of the digest
630  * @param[out] signature (R, S) integer pair
631  * @return Error code
632  **/
633 
634 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
635  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
636  EcdsaSignature *signature)
637 {
638  error_t error;
639  uint_t modLen;
640  uint_t orderLen;
641  uint32_t temp;
642  uint32_t k[EC_MAX_ORDER_SIZE];
643  const EcCurve *curve;
644 
645  //Check parameters
646  if(privateKey == NULL || digest == NULL || signature == NULL)
648 
649  //Invalid elliptic curve?
650  if(privateKey->curve == NULL)
652 
653  //Get elliptic curve parameters
654  curve = privateKey->curve;
655 
656  //Get the length of the modulus, in bits
657  modLen = curve->fieldSize;
658  //Get the length of the order, in bits
659  orderLen = curve->orderSize;
660 
661  //Check the length of the operands
662  if(modLen > PKA_MAX_EOS || orderLen > PKA_MAX_EOS)
663  return ERROR_FAILURE;
664 
665  //Generate a random number k such as 0 < k < q - 1
666  error = ecScalarRand(curve, k, prngAlgo, prngContext);
667 
668  //Check status code
669  if(!error)
670  {
671  //Acquire exclusive access to the PKA module
673 
674  //Specify the length of the modulus, in bits
675  PKA->RAM[PKA_ECDSA_SIGN_IN_MOD_NB_BITS] = modLen;
676  PKA->RAM[PKA_ECDSA_SIGN_IN_MOD_NB_BITS + 1] = 0;
677 
678  //Specify the length of the base point order, in bits
679  PKA->RAM[PKA_ECDSA_SIGN_IN_ORDER_NB_BITS] = orderLen;
680  PKA->RAM[PKA_ECDSA_SIGN_IN_ORDER_NB_BITS + 1] = 0;
681 
682  //Set the sign of the coefficient A
683  PKA->RAM[PKA_ECDSA_SIGN_IN_A_COEFF_SIGN] = 0;
684  PKA->RAM[PKA_ECDSA_SIGN_IN_A_COEFF_SIGN + 1] = 0;
685 
686  //Load input arguments into the PKA internal RAM
687  pkaImportScalar(curve->p, modLen, PKA_ECDSA_SIGN_IN_MOD_GF);
688  pkaImportScalar(curve->a, modLen, PKA_ECDSA_SIGN_IN_A_COEFF);
689  pkaImportScalar(curve->b, modLen, PKA_ECDSA_SIGN_IN_B_COEFF);
690  pkaImportScalar(curve->g.x, modLen, PKA_ECDSA_SIGN_IN_INITIAL_POINT_X);
691  pkaImportScalar(curve->g.y, modLen, PKA_ECDSA_SIGN_IN_INITIAL_POINT_Y);
692  pkaImportScalar(curve->q, orderLen, PKA_ECDSA_SIGN_IN_ORDER_N);
693  pkaImportScalar(privateKey->d, orderLen, PKA_ECDSA_SIGN_IN_PRIVATE_KEY_D);
694  pkaImportScalar(k, orderLen, PKA_ECDSA_SIGN_IN_K);
695 
696  //Keep the leftmost bits of the hash value
697  digestLen = MIN(digestLen, (orderLen + 7) / 8);
698  //Load the hash value into the PKA internal RAM
699  pkaImportArray(digest, digestLen, orderLen, PKA_ECDSA_SIGN_IN_HASH_E);
700 
701  //Clear error code
702  PKA->RAM[PKA_ECDSA_SIGN_OUT_ERROR] = PKA_STATUS_INVALID;
703 
704  //Disable interrupts
705  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
706 
707  //Write in the MODE field of PKA_CR register, specifying the operation
708  //which is to be executed
709  temp = PKA->CR & ~PKA_CR_MODE;
710  PKA->CR = temp | (PKA_CR_MODE_ECDSA_SIGN << PKA_CR_MODE_Pos);
711 
712  //Then assert the START bit in PKA_CR register
713  PKA->CR |= PKA_CR_START;
714 
715  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
716  //indicating that the computation is complete
717  while((PKA->SR & PKA_SR_PROCENDF) == 0)
718  {
719  }
720 
721  //Successful computation?
722  if(PKA->RAM[PKA_ECDSA_SIGN_OUT_ERROR] == PKA_STATUS_SUCCESS)
723  {
724  error = NO_ERROR;
725  }
726  else
727  {
728  error = ERROR_FAILURE;
729  }
730 
731  //Check status code
732  if(!error)
733  {
734  //Save elliptic curve parameters
735  signature->curve = curve;
736 
737  //Copy integer R
738  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
739  pkaExportScalar(signature->r, orderLen, PKA_ECDSA_SIGN_OUT_SIGNATURE_R);
740 
741  //Copy integer S
742  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
743  pkaExportScalar(signature->s, orderLen, PKA_ECDSA_SIGN_OUT_SIGNATURE_S);
744  }
745 
746  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
747  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
748 
749  //Release exclusive access to the PKA module
751  }
752 
753  //Return status code
754  return error;
755 }
756 
757 #endif
758 #if (ECDSA_SUPPORT == ENABLED) && defined(PKA_CR_MODE_ECDSA_VERIFY)
759 
760 /**
761  * @brief ECDSA signature verification
762  * @param[in] publicKey Signer's EC public key
763  * @param[in] digest Digest of the message whose signature is to be verified
764  * @param[in] digestLen Length in octets of the digest
765  * @param[in] signature (R, S) integer pair
766  * @return Error code
767  **/
768 
769 error_t ecdsaVerifySignature(const EcPublicKey *publicKey,
770  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
771 {
772  error_t error;
773  uint_t modLen;
774  uint_t orderLen;
775  uint32_t temp;
776  const EcCurve *curve;
777 
778  //Check parameters
779  if(publicKey == NULL || digest == NULL || signature == NULL)
781 
782  //Invalid elliptic curve?
783  if(publicKey->curve == NULL)
785 
786  //Verify that the public key is on the curve
787  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
788  {
790  }
791 
792  //The verifier shall check that 0 < r < q
793  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
794  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
795  {
796  //If the condition is violated, the signature shall be rejected as invalid
798  }
799 
800  //The verifier shall check that 0 < s < q
801  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
802  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
803  {
804  //If the condition is violated, the signature shall be rejected as invalid
806  }
807 
808  //Get elliptic curve parameters
809  curve = publicKey->curve;
810 
811  //Get the length of the modulus, in bits
812  modLen = curve->fieldSize;
813  //Get the length of the order, in bits
814  orderLen = curve->orderSize;
815 
816  //Check the length of the operands
817  if(modLen > PKA_MAX_EOS || orderLen > PKA_MAX_EOS)
818  return ERROR_FAILURE;
819 
820  //Acquire exclusive access to the PKA module
822 
823  //Specify the length of the modulus, in bits
824  PKA->RAM[PKA_ECDSA_VERIF_IN_MOD_NB_BITS] = modLen;
825  PKA->RAM[PKA_ECDSA_VERIF_IN_MOD_NB_BITS + 1] = 0;
826 
827  //Specify the length of the base point order, in bits
828  PKA->RAM[PKA_ECDSA_VERIF_IN_ORDER_NB_BITS] = orderLen;
829  PKA->RAM[PKA_ECDSA_VERIF_IN_ORDER_NB_BITS + 1] = 0;
830 
831  //Set the sign of the coefficient A
832  PKA->RAM[PKA_ECDSA_VERIF_IN_A_COEFF_SIGN] = 0;
833  PKA->RAM[PKA_ECDSA_VERIF_IN_A_COEFF_SIGN + 1] = 0;
834 
835  //Load input arguments into the PKA internal RAM
836  pkaImportScalar(curve->p, modLen, PKA_ECDSA_VERIF_IN_MOD_GF);
837  pkaImportScalar(curve->a, modLen, PKA_ECDSA_VERIF_IN_A_COEFF);
838  pkaImportScalar(curve->g.x, modLen, PKA_ECDSA_VERIF_IN_INITIAL_POINT_X);
839  pkaImportScalar(curve->g.y, modLen, PKA_ECDSA_VERIF_IN_INITIAL_POINT_Y);
840  pkaImportScalar(curve->q, orderLen, PKA_ECDSA_VERIF_IN_ORDER_N);
841  pkaImportScalar(publicKey->q.x, modLen, PKA_ECDSA_VERIF_IN_PUBLIC_KEY_POINT_X);
842  pkaImportScalar(publicKey->q.y, modLen, PKA_ECDSA_VERIF_IN_PUBLIC_KEY_POINT_Y);
843  pkaImportScalar(signature->r, orderLen, PKA_ECDSA_VERIF_IN_SIGNATURE_R);
844  pkaImportScalar(signature->s, orderLen, PKA_ECDSA_VERIF_IN_SIGNATURE_S);
845 
846  //Keep the leftmost bits of the hash value
847  digestLen = MIN(digestLen, (orderLen + 7) / 8);
848  //Load the hash value into the PKA internal RAM
849  pkaImportArray(digest, digestLen, orderLen, PKA_ECDSA_VERIF_IN_HASH_E);
850 
851  //Clear result
852  PKA->RAM[PKA_ECDSA_VERIF_OUT_RESULT] = PKA_STATUS_INVALID;
853 
854  //Disable interrupts
855  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
856 
857  //Write in the MODE field of PKA_CR register, specifying the operation
858  //which is to be executed
859  temp = PKA->CR & ~PKA_CR_MODE;
860  PKA->CR = temp | (PKA_CR_MODE_ECDSA_VERIFY << PKA_CR_MODE_Pos);
861 
862  //Then assert the START bit in PKA_CR register
863  PKA->CR |= PKA_CR_START;
864 
865  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
866  //indicating that the computation is complete
867  while((PKA->SR & PKA_SR_PROCENDF) == 0)
868  {
869  }
870 
871  //Test if the ECDSA signature is valid
872  if(PKA->RAM[PKA_ECDSA_VERIF_OUT_RESULT] == PKA_STATUS_SUCCESS)
873  {
874  error = NO_ERROR;
875  }
876  else
877  {
878  error = ERROR_INVALID_SIGNATURE;
879  }
880 
881  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
882  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
883 
884  //Release exclusive access to the PKA module
886 
887  //Return status code
888  return error;
889 }
890 
891 #endif
892 #endif
__weak_func error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
Definition: ecdsa.c:509
ECDSA signature.
Definition: ecdsa.h:63
STM32H5 hardware cryptographic accelerator.
@ ERROR_OUT_OF_RANGE
Definition: error.h:138
__weak_func error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
Definition: ec.c:1181
#define PKA_MAX_EOS
Mpi p
First factor.
Definition: rsa.h:72
error_t pkaInit(void)
PKA module initialization.
uint8_t a
Definition: ndp.h:411
Arbitrary precision integer.
Definition: mpi.h:102
#define PrngAlgo
Definition: crypto.h:973
ECDSA (Elliptic Curve Digital Signature Algorithm)
uint8_t p
Definition: ndp.h:300
#define PKA_CR_MODE_ECDSA_VERIFY
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdsa.h:64
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
#define PKA_CR_MODE_RSA_CRT_EXP
Mpi n
Modulus.
Definition: rsa.h:69
void pkaImportScalar(const uint32_t *src, uint_t length, uint_t offset)
Import scalar.
void pkaExportScalar(uint32_t *dest, uint_t length, uint_t offset)
Export scalar.
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
Mpi d
Private exponent.
Definition: rsa.h:71
uint8_t r
Definition: ndp.h:346
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1587
OsMutex stm32h5xxCryptoMutex
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
error_t pkaRsaCrtExp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
Modular exponentiation with CRT.
#define PKA_CR_MODE_MODULAR_EXP
#define PKA_CR_MODE_ECDSA_SIGN
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define PKA_CR_MODE_ECC_MUL
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
#define PKA_STATUS_INVALID
Mpi q
Second factor.
Definition: rsa.h:73
Helper routines for ECC.
error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
RSA decryption primitive.
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
General definitions for cryptographic algorithms.
RSA public-key cryptography standard.
STM32H5 public-key hardware accelerator (PKA)
#define PKA_MAX_ROS
EC private key.
Definition: ec.h:432
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:254
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
EC public key.
Definition: ec.h:421
__weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:798
uint_t mpiGetLength(const Mpi *a)
Get the actual length in words.
Definition: mpi.c:188
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
int_t ecScalarCompInt(const uint32_t *a, uint32_t b, uint_t n)
Compare integers.
Definition: ec_misc.c:374
uint8_t m
Definition: ndp.h:304
uint8_t n
RSA private key.
Definition: rsa.h:68
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
uint_t size
Definition: mpi.h:104
EC point (projective coordinates)
Definition: ec.h:409
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void pkaImportMpi(const Mpi *src, uint_t length, uint_t offset)
Import multiple-precision integer.
__weak_func error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
Definition: ecdsa.c:655
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1312
EcPoint q
Public key.
Definition: ec.h:423
uint32_t s[EC_MAX_ORDER_SIZE]
Integer S.
Definition: ecdsa.h:66
error_t ecScalarRand(const EcCurve *curve, uint32_t *r, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: ec_misc.c:603
uint8_t s
Definition: igmp_common.h:234
#define PKA_STATUS_SUCCESS
#define EcCurve
Definition: ec.h:346
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:358
Mpi dp
First factor's CRT exponent.
Definition: rsa.h:74
int_t ecScalarComp(const uint32_t *a, const uint32_t *b, uint_t n)
Compare integers.
Definition: ec_misc.c:337
int_t mpiCompInt(const Mpi *a, mpi_sword_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:429
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
ECC (Elliptic Curve Cryptography)
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
error_t pkaExportMpi(Mpi *dest, uint_t length, uint_t offset)
Export multiple-precision integer.
mpi_word_t * data
Definition: mpi.h:106
error_t mpiGrow(Mpi *r, uint_t size)
Adjust the size of multiple precision integer.
Definition: mpi.c:102
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
error_t mpiExpMod(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation.
#define EC_MAX_MODULUS_SIZE
Definition: ec.h:284
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
void pkaImportArray(const uint8_t *src, size_t srcLen, uint_t destLen, uint_t offset)
Import byte array.
int_t sign
Definition: mpi.h:103