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