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