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