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