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-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.4
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->p) > 0 && mpiGetLength(&key->q) > 0 &&
469  mpiGetLength(&key->dp) > 0 && mpiGetLength(&key->dq) > 0 &&
470  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 
621 /**
622  * @brief Twin multiplication
623  * @param[in] curve Elliptic curve parameters
624  * @param[out] r Resulting point R = d0.S + d1.T
625  * @param[in] d0 An integer d such as 0 <= d0 < p
626  * @param[in] s EC point
627  * @param[in] d1 An integer d such as 0 <= d1 < p
628  * @param[in] t EC point
629  * @return Error code
630  **/
631 
632 error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0,
633  const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
634 {
635  error_t error;
636  EcPoint3 u;
637 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
638  EcState *state;
639 #else
640  EcState state[1];
641 #endif
642 
643 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
644  //Allocate working state
645  state = cryptoAllocMem(sizeof(EcState));
646  //Failed to allocate memory?
647  if(state == NULL)
648  return ERROR_OUT_OF_MEMORY;
649 #endif
650 
651  //Initialize working state
652  osMemset(state, 0, sizeof(EcState));
653  //Save elliptic curve parameters
654  state->curve = curve;
655 
656  //Compute d0.S
657  error = ecMulFast(curve, r, d0, s);
658 
659  //Check status code
660  if(!error)
661  {
662  //Compute d1.T
663  error = ecMulFast(curve, &u, d1, t);
664  }
665 
666  //Check status code
667  if(!error)
668  {
669  //Compute d0.S + d1.T
670  ecFullAdd(state, r, r, &u);
671  }
672 
673  //Return status code
674  return error;
675 }
676 
677 #endif
678 #if (ECDSA_SUPPORT == ENABLED) && defined(PKA_CR_MODE_ECDSA_SIGN)
679 
680 /**
681  * @brief ECDSA signature generation
682  * @param[in] prngAlgo PRNG algorithm
683  * @param[in] prngContext Pointer to the PRNG context
684  * @param[in] privateKey Signer's EC private key
685  * @param[in] digest Digest of the message to be signed
686  * @param[in] digestLen Length in octets of the digest
687  * @param[out] signature (R, S) integer pair
688  * @return Error code
689  **/
690 
691 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
692  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
693  EcdsaSignature *signature)
694 {
695  error_t error;
696  uint_t modLen;
697  uint_t orderLen;
698  uint32_t temp;
699  uint32_t k[EC_MAX_ORDER_SIZE];
700  const EcCurve *curve;
701 
702  //Check parameters
703  if(privateKey == NULL || digest == NULL || signature == NULL)
705 
706  //Invalid elliptic curve?
707  if(privateKey->curve == NULL)
709 
710  //Get elliptic curve parameters
711  curve = privateKey->curve;
712 
713  //Get the length of the modulus, in bits
714  modLen = curve->fieldSize;
715  //Get the length of the order, in bits
716  orderLen = curve->orderSize;
717 
718  //Check the length of the operands
719  if(modLen > PKA_MAX_EOS || orderLen > PKA_MAX_EOS)
720  return ERROR_FAILURE;
721 
722  //Generate a random number k such as 0 < k < q - 1
723  error = ecScalarRand(curve, k, prngAlgo, prngContext);
724 
725  //Check status code
726  if(!error)
727  {
728  //Acquire exclusive access to the PKA module
730 
731  //Specify the length of the modulus, in bits
732  PKA->RAM[PKA_ECDSA_SIGN_IN_MOD_NB_BITS] = modLen;
733  PKA->RAM[PKA_ECDSA_SIGN_IN_MOD_NB_BITS + 1] = 0;
734 
735  //Specify the length of the base point order, in bits
736  PKA->RAM[PKA_ECDSA_SIGN_IN_ORDER_NB_BITS] = orderLen;
737  PKA->RAM[PKA_ECDSA_SIGN_IN_ORDER_NB_BITS + 1] = 0;
738 
739  //Set the sign of the coefficient A
740  PKA->RAM[PKA_ECDSA_SIGN_IN_A_COEFF_SIGN] = 0;
741  PKA->RAM[PKA_ECDSA_SIGN_IN_A_COEFF_SIGN + 1] = 0;
742 
743  //Load input arguments into the PKA internal RAM
744  pkaImportScalar(curve->p, modLen, PKA_ECDSA_SIGN_IN_MOD_GF);
745  pkaImportScalar(curve->a, modLen, PKA_ECDSA_SIGN_IN_A_COEFF);
746  pkaImportScalar(curve->b, modLen, PKA_ECDSA_SIGN_IN_B_COEFF);
747  pkaImportScalar(curve->g.x, modLen, PKA_ECDSA_SIGN_IN_INITIAL_POINT_X);
748  pkaImportScalar(curve->g.y, modLen, PKA_ECDSA_SIGN_IN_INITIAL_POINT_Y);
749  pkaImportScalar(curve->q, orderLen, PKA_ECDSA_SIGN_IN_ORDER_N);
750  pkaImportScalar(privateKey->d, orderLen, PKA_ECDSA_SIGN_IN_PRIVATE_KEY_D);
751  pkaImportScalar(k, orderLen, PKA_ECDSA_SIGN_IN_K);
752 
753  //Keep the leftmost bits of the hash value
754  digestLen = MIN(digestLen, (orderLen + 7) / 8);
755  //Load the hash value into the PKA internal RAM
756  pkaImportArray(digest, digestLen, orderLen, PKA_ECDSA_SIGN_IN_HASH_E);
757 
758  //Clear error code
759  PKA->RAM[PKA_ECDSA_SIGN_OUT_ERROR] = PKA_STATUS_INVALID;
760 
761  //Disable interrupts
762  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
763 
764  //Write in the MODE field of PKA_CR register, specifying the operation
765  //which is to be executed
766  temp = PKA->CR & ~PKA_CR_MODE;
767  PKA->CR = temp | (PKA_CR_MODE_ECDSA_SIGN << PKA_CR_MODE_Pos);
768 
769  //Then assert the START bit in PKA_CR register
770  PKA->CR |= PKA_CR_START;
771 
772  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
773  //indicating that the computation is complete
774  while((PKA->SR & PKA_SR_PROCENDF) == 0)
775  {
776  }
777 
778  //Successful computation?
779  if(PKA->RAM[PKA_ECDSA_SIGN_OUT_ERROR] == PKA_STATUS_SUCCESS)
780  {
781  error = NO_ERROR;
782  }
783  else
784  {
785  error = ERROR_FAILURE;
786  }
787 
788  //Check status code
789  if(!error)
790  {
791  //Save elliptic curve parameters
792  signature->curve = curve;
793 
794  //Copy integer R
795  ecScalarSetInt(signature->r, 0, EC_MAX_ORDER_SIZE);
796  pkaExportScalar(signature->r, orderLen, PKA_ECDSA_SIGN_OUT_SIGNATURE_R);
797 
798  //Copy integer S
799  ecScalarSetInt(signature->s, 0, EC_MAX_ORDER_SIZE);
800  pkaExportScalar(signature->s, orderLen, PKA_ECDSA_SIGN_OUT_SIGNATURE_S);
801  }
802 
803  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
804  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
805 
806  //Release exclusive access to the PKA module
808  }
809 
810  //Return status code
811  return error;
812 }
813 
814 #endif
815 #if (ECDSA_SUPPORT == ENABLED) && defined(PKA_CR_MODE_ECDSA_VERIFY)
816 
817 /**
818  * @brief ECDSA signature verification
819  * @param[in] publicKey Signer's EC public key
820  * @param[in] digest Digest of the message whose signature is to be verified
821  * @param[in] digestLen Length in octets of the digest
822  * @param[in] signature (R, S) integer pair
823  * @return Error code
824  **/
825 
826 error_t ecdsaVerifySignature(const EcPublicKey *publicKey,
827  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
828 {
829  error_t error;
830  uint_t modLen;
831  uint_t orderLen;
832  uint32_t temp;
833  const EcCurve *curve;
834 
835  //Check parameters
836  if(publicKey == NULL || digest == NULL || signature == NULL)
838 
839  //Invalid elliptic curve?
840  if(publicKey->curve == NULL)
842 
843  //Verify that the public key is on the curve
844  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
845  {
847  }
848 
849  //The verifier shall check that 0 < r < q
850  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
851  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
852  {
853  //If the condition is violated, the signature shall be rejected as invalid
855  }
856 
857  //The verifier shall check that 0 < s < q
858  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
859  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
860  {
861  //If the condition is violated, the signature shall be rejected as invalid
863  }
864 
865  //Get elliptic curve parameters
866  curve = publicKey->curve;
867 
868  //Get the length of the modulus, in bits
869  modLen = curve->fieldSize;
870  //Get the length of the order, in bits
871  orderLen = curve->orderSize;
872 
873  //Check the length of the operands
874  if(modLen > PKA_MAX_EOS || orderLen > PKA_MAX_EOS)
875  return ERROR_FAILURE;
876 
877  //Acquire exclusive access to the PKA module
879 
880  //Specify the length of the modulus, in bits
881  PKA->RAM[PKA_ECDSA_VERIF_IN_MOD_NB_BITS] = modLen;
882  PKA->RAM[PKA_ECDSA_VERIF_IN_MOD_NB_BITS + 1] = 0;
883 
884  //Specify the length of the base point order, in bits
885  PKA->RAM[PKA_ECDSA_VERIF_IN_ORDER_NB_BITS] = orderLen;
886  PKA->RAM[PKA_ECDSA_VERIF_IN_ORDER_NB_BITS + 1] = 0;
887 
888  //Set the sign of the coefficient A
889  PKA->RAM[PKA_ECDSA_VERIF_IN_A_COEFF_SIGN] = 0;
890  PKA->RAM[PKA_ECDSA_VERIF_IN_A_COEFF_SIGN + 1] = 0;
891 
892  //Load input arguments into the PKA internal RAM
893  pkaImportScalar(curve->p, modLen, PKA_ECDSA_VERIF_IN_MOD_GF);
894  pkaImportScalar(curve->a, modLen, PKA_ECDSA_VERIF_IN_A_COEFF);
895  pkaImportScalar(curve->g.x, modLen, PKA_ECDSA_VERIF_IN_INITIAL_POINT_X);
896  pkaImportScalar(curve->g.y, modLen, PKA_ECDSA_VERIF_IN_INITIAL_POINT_Y);
897  pkaImportScalar(curve->q, orderLen, PKA_ECDSA_VERIF_IN_ORDER_N);
898  pkaImportScalar(publicKey->q.x, modLen, PKA_ECDSA_VERIF_IN_PUBLIC_KEY_POINT_X);
899  pkaImportScalar(publicKey->q.y, modLen, PKA_ECDSA_VERIF_IN_PUBLIC_KEY_POINT_Y);
900  pkaImportScalar(signature->r, orderLen, PKA_ECDSA_VERIF_IN_SIGNATURE_R);
901  pkaImportScalar(signature->s, orderLen, PKA_ECDSA_VERIF_IN_SIGNATURE_S);
902 
903  //Keep the leftmost bits of the hash value
904  digestLen = MIN(digestLen, (orderLen + 7) / 8);
905  //Load the hash value into the PKA internal RAM
906  pkaImportArray(digest, digestLen, orderLen, PKA_ECDSA_VERIF_IN_HASH_E);
907 
908  //Clear result
909  PKA->RAM[PKA_ECDSA_VERIF_OUT_RESULT] = PKA_STATUS_INVALID;
910 
911  //Disable interrupts
912  PKA->CR &= ~(PKA_CR_ADDRERRIE | PKA_CR_RAMERRIE | PKA_CR_PROCENDIE);
913 
914  //Write in the MODE field of PKA_CR register, specifying the operation
915  //which is to be executed
916  temp = PKA->CR & ~PKA_CR_MODE;
917  PKA->CR = temp | (PKA_CR_MODE_ECDSA_VERIFY << PKA_CR_MODE_Pos);
918 
919  //Then assert the START bit in PKA_CR register
920  PKA->CR |= PKA_CR_START;
921 
922  //Wait until the PROCENDF bit in the PKA_SR register is set to 1,
923  //indicating that the computation is complete
924  while((PKA->SR & PKA_SR_PROCENDF) == 0)
925  {
926  }
927 
928  //Test if the ECDSA signature is valid
929  if(PKA->RAM[PKA_ECDSA_VERIF_OUT_RESULT] == PKA_STATUS_SUCCESS)
930  {
931  error = NO_ERROR;
932  }
933  else
934  {
935  error = ERROR_INVALID_SIGNATURE;
936  }
937 
938  //Then clear PROCENDF bit by setting PROCENDFC bit in PKA_CLRFR
939  PKA->CLRFR = PKA_CLRFR_PROCENDFC;
940 
941  //Release exclusive access to the PKA module
943 
944  //Return status code
945  return error;
946 }
947 
948 #endif
949 #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:495
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:1223
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:1049
ECDSA (Elliptic Curve Digital Signature Algorithm)
uint8_t p
Definition: ndp.h:300
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdsa.h:64
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
uint8_t t
Definition: lldp_ext_med.h:212
void ecFullAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point addition.
Definition: ec.c:1136
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
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.
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define PKA_CR_MODE_RSA_CRT_EXP
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
Mpi d
Private exponent.
Definition: rsa.h:71
#define PKA_CR_MODE_ECC_MUL
__weak_func error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
Twin multiplication.
Definition: ec.c:1460
uint8_t r
Definition: ndp.h:346
#define PKA_STATUS_INVALID
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1589
OsMutex stm32h5xxCryptoMutex
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define PKA_CR_MODE_ECDSA_SIGN
#define PKA_CR_MODE_ECDSA_VERIFY
error_t
Error codes.
Definition: error.h:43
#define PKA_CR_MODE_MODULAR_EXP
error_t pkaRsaCrtExp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
Modular exponentiation with CRT.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
Mpi q
Second factor.
Definition: rsa.h:73
Helper routines for ECC.
#define PKA_MAX_ROS
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)
EC private key.
Definition: ec.h:432
uint8_t u
Definition: lldp_ext_med.h:213
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:255
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:840
uint_t mpiGetLength(const Mpi *a)
Get the actual length in words.
Definition: mpi.c:189
const EcCurve * curve
Definition: ec.h:446
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
Working state (point addition/subtraction/doubling)
Definition: ec.h:445
uint8_t m
Definition: ndp.h:304
uint8_t n
RSA private key.
Definition: rsa.h:68
#define PKA_STATUS_SUCCESS
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:951
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1354
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
#define cryptoAllocMem(size)
Definition: crypto.h:870
uint8_t s
Definition: igmp_common.h:234
#define EcCurve
Definition: ec.h:346
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:359
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:430
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
#define osMemset(p, value, length)
Definition: os_port.h:141
#define PKA_MAX_EOS
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:103
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