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