ra6_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file ra6_crypto_pkc.c
3  * @brief RA6 public-key hardware accelerator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "hw_sce_private.h"
36 #include "hw_sce_ra_private.h"
37 #include "hw_sce_rsa_private.h"
38 #include "hw_sce_ecc_private.h"
39 #include "core/crypto.h"
42 #include "pkc/rsa.h"
43 #include "ecc/ec.h"
44 #include "ecc/ec_misc.h"
45 #include "ecc/ecdsa.h"
46 #include "debug.h"
47 
48 //Check crypto library configuration
49 #if (RA6_CRYPTO_PKC_SUPPORT == ENABLED)
50 
51 //Global variables
52 static Ra6RsaArgs rsaArgs;
53 static Ra6EcArgs ecArgs;
54 
55 #if (MPI_SUPPORT == ENABLED)
56 
57 /**
58  * @brief Modular exponentiation (fast calculation)
59  * @param[out] r Resulting integer R = A ^ E mod P
60  * @param[in] a Pointer to a multiple precision integer
61  * @param[in] e Exponent
62  * @param[in] p Modulus
63  * @return Error code
64  **/
65 
66 error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
67 {
68  error_t error;
69  fsp_err_t status;
70  size_t n;
71  size_t aLen;
72  size_t eLen;
73  size_t pLen;
74 
75  //Get the length of the integer, in bytes
76  aLen = mpiGetByteLength(a);
77  //Get the length of the exponent, in bytes
78  eLen = mpiGetByteLength(e);
79  //Get the length of the modulus, in bytes
80  pLen = mpiGetByteLength(p);
81 
82 #if (BSP_FEATURE_CRYPTO_HAS_SCE9 != 0)
83  //The SCE9 accelerator supports operand lengths up to 4096 bits
84  if((aLen <= 256 && eLen <= 4 && pLen <= 256) ||
85  (aLen <= 384 && eLen <= 4 && pLen <= 384) ||
86  (aLen <= 512 && eLen <= 4 && pLen <= 512))
87  {
88  sce_oem_cmd_t command;
89 
90  //Select appropriate scalar length
91  if(pLen <= 256)
92  {
93  command = SCE_OEM_CMD_RSA2048_PUBLIC;
94  n = 256;
95  }
96  else if(pLen <= 384)
97  {
98  command = SCE_OEM_CMD_RSA3072_PUBLIC;
99  n = 384;
100  }
101  else
102  {
103  command = SCE_OEM_CMD_RSA4096_PUBLIC;
104  n = 512;
105  }
106 
107  //Acquire exclusive access to the SCE module
109 
110  //Format message representative
111  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, n);
112 
113  //Format public key
114  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, n);
115  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + n, 4);
116 
117  //Install the plaintext public key and get the wrapped key
118  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
119  command, NULL, NULL, (uint8_t *) rsaArgs.key, rsaArgs.wrappedKey);
120 
121  //Check status code
122  if(status == FSP_SUCCESS)
123  {
124  //Perform RSA encryption
125  if(n == 256)
126  {
127  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.wrappedKey,
128  rsaArgs.m, rsaArgs.c);
129  }
130  else if(n == 384)
131  {
132  status = HW_SCE_Rsa3072ModularExponentEncryptSub(rsaArgs.wrappedKey,
133  rsaArgs.m, rsaArgs.c);
134  }
135  else if(n == 512)
136  {
137  status = HW_SCE_Rsa4096ModularExponentEncryptSub(rsaArgs.wrappedKey,
138  rsaArgs.m, rsaArgs.c);
139  }
140  else
141  {
142  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
143  }
144  }
145 
146  //Check status code
147  if(status == FSP_SUCCESS)
148  {
149  //Copy the ciphertext representative
150  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, n);
151  }
152  else
153  {
154  //Report an error
155  error = ERROR_FAILURE;
156  }
157 
158  //Release exclusive access to the SCE module
160  }
161 #else
162  //The SCE7 accelerator supports operand lengths up to 2048 bits
163  if(aLen <= 256 && eLen <= 4 && pLen <= 256)
164  {
165  //Acquire exclusive access to the SCE module
167 
168  //Format message representative
169  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, 256);
170 
171  //Format public key
172  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, 256);
173  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + 256, 4);
174 
175  //Install the plaintext public key and get the wrapped key
176  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
177  SCE_OEM_CMD_RSA2048_PUBLIC, NULL, NULL, (uint8_t *) rsaArgs.key,
178  rsaArgs.wrappedKey);
179 
180  //Check status code
181  if(status == FSP_SUCCESS)
182  {
183  //Perform RSA encryption
184  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.wrappedKey,
185  rsaArgs.m, rsaArgs.c);
186  }
187 
188  //Check status code
189  if(status == FSP_SUCCESS)
190  {
191  //Copy the ciphertext representative
192  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, 256);
193  }
194  else
195  {
196  //Report an error
197  error = ERROR_FAILURE;
198  }
199 
200  //Release exclusive access to the SCE module
202  }
203 #endif
204  else
205  {
206  //Perform modular exponentiation (r = a ^ e mod p)
207  error = mpiExpModRegular(r, a, e, p);
208  }
209 
210  //Return status code
211  return error;
212 }
213 
214 
215 /**
216  * @brief Modular exponentiation (regular calculation)
217  * @param[out] r Resulting integer R = A ^ E mod P
218  * @param[in] a Pointer to a multiple precision integer
219  * @param[in] e Exponent
220  * @param[in] p Modulus
221  * @return Error code
222  **/
223 
224 error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
225 {
226  error_t error;
227  fsp_err_t status;
228  size_t aLen;
229  size_t eLen;
230  size_t pLen;
231 
232  //Get the length of the integer, in bytes
233  aLen = mpiGetByteLength(a);
234  //Get the length of the exponent, in bytes
235  eLen = mpiGetByteLength(e);
236  //Get the length of the modulus, in bytes
237  pLen = mpiGetByteLength(p);
238 
239  //The accelerator supports operand lengths up to 2048 bits
240  if(aLen <= 256 && eLen <= 256 && pLen <= 256)
241  {
242  //Acquire exclusive access to the SCE module
244 
245  //Format ciphertext representative
246  mpiWriteRaw(a, (uint8_t *) rsaArgs.c, 256);
247 
248  //Format private key
249  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, 256);
250  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + 256, 256);
251 
252  //Install the plaintext private key and get the wrapped key
253  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
254  SCE_OEM_CMD_RSA2048_PRIVATE, NULL, NULL, (uint8_t *) rsaArgs.key,
255  rsaArgs.wrappedKey);
256 
257  //Check status code
258  if(status == FSP_SUCCESS)
259  {
260  //Perform RSA decryption
261  status = HW_SCE_Rsa2048ModularExponentDecryptSub(rsaArgs.wrappedKey,
262  rsaArgs.c, rsaArgs.m);
263  }
264 
265  //Check status code
266  if(status == FSP_SUCCESS)
267  {
268  //Copy the message representative
269  error = mpiReadRaw(r, (uint8_t *) rsaArgs.m, 256);
270  }
271  else
272  {
273  //Report an error
274  error = ERROR_FAILURE;
275  }
276 
277  //Release exclusive access to the SCE module
279  }
280  else
281  {
282  //Perform modular exponentiation (r = a ^ e mod p)
283  error = mpiExpMod(r, a, e, p);
284  }
285 
286  //Return status code
287  return error;
288 }
289 
290 #endif
291 #if (RSA_SUPPORT == ENABLED)
292 
293 /**
294  * @brief RSA decryption primitive
295  *
296  * The RSA decryption primitive recovers the message representative from
297  * the ciphertext representative under the control of a private key
298  *
299  * @param[in] key RSA private key
300  * @param[in] c Ciphertext representative
301  * @param[out] m Message representative
302  * @return Error code
303  **/
304 
305 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
306 {
307  error_t error;
308  size_t nLen;
309  size_t dLen;
310  size_t pLen;
311  size_t qLen;
312  size_t dpLen;
313  size_t dqLen;
314  size_t qinvLen;
315 
316  //Get the length of the private key
317  nLen = mpiGetByteLength(&key->n);
318  dLen = mpiGetByteLength(&key->d);
319  pLen = mpiGetByteLength(&key->p);
320  qLen = mpiGetByteLength(&key->q);
321  dpLen = mpiGetByteLength(&key->dp);
322  dqLen = mpiGetByteLength(&key->dq);
323  qinvLen = mpiGetByteLength(&key->qinv);
324 
325  //Sanity check
326  if(nLen == 0)
328 
329  //The ciphertext representative c shall be between 0 and n - 1
330  if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0)
331  return ERROR_OUT_OF_RANGE;
332 
333  //Check the length of the private key
334  if(nLen <= 256 && dLen <= 256)
335  {
336  //Let m = c ^ d mod n
337  error = mpiExpModRegular(m, c, &key->d, &key->n);
338  }
339  else if(nLen > 0 && pLen > 0 && qLen > 0 && dpLen > 0 && dqLen > 0 &&
340  qinvLen > 0)
341  {
342  Mpi m1;
343  Mpi m2;
344  Mpi h;
345 
346  //Initialize multiple-precision integers
347  mpiInit(&m1);
348  mpiInit(&m2);
349  mpiInit(&h);
350 
351  //Compute m1 = c ^ dP mod p
352  error = mpiMod(&m1, c, &key->p);
353 
354  if(!error)
355  {
356  error = mpiExpModRegular(&m1, &m1, &key->dp, &key->p);
357  }
358 
359  //Compute m2 = c ^ dQ mod q
360  if(!error)
361  {
362  error = mpiMod(&m2, c, &key->q);
363  }
364 
365  if(!error)
366  {
367  error = mpiExpModRegular(&m2, &m2, &key->dq, &key->q);
368  }
369 
370  //Let h = (m1 - m2) * qInv mod p
371  if(!error)
372  {
373  error = mpiSub(&h, &m1, &m2);
374  }
375 
376  if(!error)
377  {
378  error = mpiMulMod(&h, &h, &key->qinv, &key->p);
379  }
380 
381  //Let m = m2 + q * h
382  if(!error)
383  {
384  error = mpiMul(m, &key->q, &h);
385  }
386 
387  if(!error)
388  {
389  error = mpiAdd(m, m, &m2);
390  }
391 
392  //Free previously allocated memory
393  mpiFree(&m1);
394  mpiFree(&m2);
395  mpiFree(&h);
396  }
397  else if(nLen > 0 && dLen > 0)
398  {
399  //Let m = c ^ d mod n
400  error = mpiExpModRegular(m, c, &key->d, &key->n);
401  }
402  else
403  {
404  //Report an error
405  error = ERROR_INVALID_PARAMETER;
406  }
407 
408  //Return status code
409  return error;
410 }
411 
412 #endif
413 #if (EC_SUPPORT == ENABLED)
414 
415 /**
416  * @brief Scalar multiplication (fast calculation)
417  * @param[in] curve Elliptic curve parameters
418  * @param[out] r Resulting point R = d.S
419  * @param[in] d An integer d such as 0 <= d < p
420  * @param[in] s EC point
421  * @return Error code
422  **/
423 
424 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
425  const EcPoint3 *s)
426 {
427  //Compute R = d.S
428  return ecMulRegular(curve, r, d, s);
429 }
430 
431 
432 /**
433  * @brief Scalar multiplication (regular calculation)
434  * @param[in] curve Elliptic curve parameters
435  * @param[out] r Resulting point R = d.S
436  * @param[in] d An integer d such as 0 <= d < q
437  * @param[in] s EC point
438  * @return Error code
439  **/
440 
441 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
442  const EcPoint3 *s)
443 {
444  error_t error;
445  fsp_err_t status;
446  size_t n;
447  uint32_t curveType;
448  uint32_t command;
449  sce_oem_cmd_t oemCommand;
450 
451  //Check elliptic curve parameters
452  if(osStrcmp(curve->name, "secp256k1") == 0)
453  {
454  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
455  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
456  command = 0;
457  n = 32;
458  }
459  else if(osStrcmp(curve->name, "secp256r1") == 0)
460  {
461  curveType = SCE_ECC_CURVE_TYPE_NIST;
462  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
463  command = 0;
464  n = 32;
465  }
466  else if(osStrcmp(curve->name, "secp384r1") == 0)
467  {
468  curveType = SCE_ECC_CURVE_TYPE_NIST;
469  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
470  command = 0;
471  n = 48;
472  }
473  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
474  {
475  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
476  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
477  command = 0;
478  n = 32;
479  }
480  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
481  {
482  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
483  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
484  command = 0;
485  n = 48;
486  }
487  else
488  {
489  return ERROR_FAILURE;
490  }
491 
492  //Acquire exclusive access to the SCE module
494 
495  //Set scalar value
496  ecScalarExport(d, n / 4, (uint8_t *) ecArgs.d, n,
498 
499  //Set input point
500  ecScalarExport(s->x, n / 4, (uint8_t *) ecArgs.g, n,
502 
503  ecScalarExport(s->y, n / 4, (uint8_t *) ecArgs.g + n, n,
505 
506  //Install the plaintext private key and get the wrapped key
507  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
508  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
509 
510  //Check status code
511  if(status == FSP_SUCCESS)
512  {
513  //Perform scalar multiplication
514  if(curve->fieldSize == 256)
515  {
516  status = HW_SCE_Ecc256ScalarMultiplicationSub(&curveType,
517  &command, ecArgs.wrappedKey, ecArgs.g, ecArgs.q);
518  }
519  else if(curve->fieldSize == 384)
520  {
521  status = HW_SCE_Ecc384ScalarMultiplicationSub(&curveType,
522  ecArgs.wrappedKey, ecArgs.g, ecArgs.q);
523  }
524  else
525  {
526  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
527  }
528  }
529 
530  //Check status code
531  if(status == FSP_SUCCESS)
532  {
533  //Copy the x-coordinate of the result
534  error = ecScalarImport(r->x, EC_MAX_MODULUS_SIZE, (uint8_t *) ecArgs.q,
536 
537  //Check status code
538  if(!error)
539  {
540  //Copy the y-coordinate of the result
542  (uint8_t *) ecArgs.q + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
543  }
544 
545  //Check status code
546  if(!error)
547  {
548  //Set the z-coordinate of the result
550  }
551  }
552  else
553  {
554  //Report an error
555  error = ERROR_FAILURE;
556  }
557 
558  //Release exclusive access to the SCE module
560 
561  //Return status code
562  return error;
563 }
564 
565 #endif
566 #if (ECDSA_SUPPORT == ENABLED)
567 
568 /**
569  * @brief ECDSA signature generation
570  * @param[in] prngAlgo PRNG algorithm
571  * @param[in] prngContext Pointer to the PRNG context
572  * @param[in] privateKey Signer's EC private key
573  * @param[in] digest Digest of the message to be signed
574  * @param[in] digestLen Length in octets of the digest
575  * @param[out] signature (R, S) integer pair
576  * @return Error code
577  **/
578 
579 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
580  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
581  EcdsaSignature *signature)
582 {
583  error_t error;
584  fsp_err_t status;
585  size_t n;
586  size_t orderLen;
587  uint32_t curveType;
588  uint32_t command;
589  sce_oem_cmd_t oemCommand;
590  const EcCurve *curve;
591 
592  //Check parameters
593  if(privateKey == NULL || digest == NULL || signature == NULL)
595 
596  //Invalid elliptic curve?
597  if(privateKey->curve == NULL)
599 
600  //Get elliptic curve parameters
601  curve = privateKey->curve;
602 
603  //Get the length of the order, in bytes
604  orderLen = (curve->orderSize + 7) / 8;
605 
606  //Check elliptic curve parameters
607  if(osStrcmp(curve->name, "secp256k1") == 0)
608  {
609  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
610  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
611  command = 0;
612  n = 32;
613  }
614  else if(osStrcmp(curve->name, "secp256r1") == 0)
615  {
616  curveType = SCE_ECC_CURVE_TYPE_NIST;
617  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
618  command = 0;
619  n = 32;
620  }
621  else if(osStrcmp(curve->name, "secp384r1") == 0)
622  {
623  curveType = SCE_ECC_CURVE_TYPE_NIST;
624  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
625  command = 0;
626  n = 48;
627  }
628  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
629  {
630  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
631  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
632  command = 0;
633  n = 32;
634  }
635  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
636  {
637  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
638  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
639  command = 0;
640  n = 48;
641  }
642  else
643  {
644  return ERROR_FAILURE;
645  }
646 
647  //Keep the leftmost bits of the hash value
648  digestLen = MIN(digestLen, orderLen);
649 
650  //Acquire exclusive access to the SCE module
652 
653  //Pad the digest with leading zeroes if necessary
654  osMemset(ecArgs.digest, 0, n);
655  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
656 
657  //Set private key
658  ecScalarExport(privateKey->d, n / 4, (uint8_t *) ecArgs.d, n,
660 
661  //Install the plaintext private key and get the wrapped key
662  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
663  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
664 
665  //Check status code
666  if(status == FSP_SUCCESS)
667  {
668  //Generate ECDSA signature
669  if(curve->fieldSize == 256)
670  {
671  status = HW_SCE_EcdsaSignatureGenerateSub(&curveType, &command,
672  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
673  }
674  else if(curve->fieldSize == 384)
675  {
676  status = HW_SCE_EcdsaP384SignatureGenerateSub(&curveType,
677  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
678  }
679  else
680  {
681  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
682  }
683  }
684 
685  //Check status code
686  if(status == FSP_SUCCESS)
687  {
688  //Save elliptic curve parameters
689  signature->curve = curve;
690 
691  //Copy integer R
692  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE,
693  (uint8_t *) ecArgs.signature, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
694 
695  //Check status code
696  if(!error)
697  {
698  //Copy integer S
699  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE,
700  (uint8_t *) ecArgs.signature + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
701  }
702  }
703  else
704  {
705  //Report an error
706  error = ERROR_FAILURE;
707  }
708 
709  //Release exclusive access to the SCE module
711 
712  //Return status code
713  return error;
714 }
715 
716 
717 /**
718  * @brief ECDSA signature verification
719  * @param[in] publicKey Signer's EC public key
720  * @param[in] digest Digest of the message whose signature is to be verified
721  * @param[in] digestLen Length in octets of the digest
722  * @param[in] signature (R, S) integer pair
723  * @return Error code
724  **/
725 
727  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
728 {
729  fsp_err_t status;
730  size_t n;
731  size_t orderLen;
732  uint32_t curveType;
733  uint32_t command;
734  sce_oem_cmd_t oemCommand;
735  const EcCurve *curve;
736 
737  //Check parameters
738  if(publicKey == NULL || digest == NULL || signature == NULL)
740 
741  //Invalid elliptic curve?
742  if(publicKey->curve == NULL)
744 
745  //Verify that the public key is on the curve
746  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
747  {
749  }
750 
751  //The verifier shall check that 0 < r < q
752  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
753  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
754  {
755  //If the condition is violated, the signature shall be rejected as invalid
757  }
758 
759  //The verifier shall check that 0 < s < q
760  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
761  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
762  {
763  //If the condition is violated, the signature shall be rejected as invalid
765  }
766 
767  //Get elliptic curve parameters
768  curve = publicKey->curve;
769 
770  //Get the length of the order, in bytes
771  orderLen = (curve->orderSize + 7) / 8;
772 
773  //Check elliptic curve parameters
774  if(osStrcmp(curve->name, "secp256k1") == 0)
775  {
776  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
777  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PUBLIC;
778  command = 0;
779  n = 32;
780  }
781  else if(osStrcmp(curve->name, "secp256r1") == 0)
782  {
783  curveType = SCE_ECC_CURVE_TYPE_NIST;
784  oemCommand = SCE_OEM_CMD_ECC_P256_PUBLIC;
785  command = 0;
786  n = 32;
787  }
788  else if(osStrcmp(curve->name, "secp384r1") == 0)
789  {
790  curveType = SCE_ECC_CURVE_TYPE_NIST;
791  oemCommand = SCE_OEM_CMD_ECC_P384_PUBLIC;
792  command = 0;
793  n = 48;
794  }
795  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
796  {
797  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
798  oemCommand = SCE_OEM_CMD_ECC_P256R1_PUBLIC;
799  command = 0;
800  n = 32;
801  }
802  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
803  {
804  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
805  oemCommand = SCE_OEM_CMD_ECC_P384R1_PUBLIC;
806  command = 0;
807  n = 48;
808  }
809  else
810  {
811  return ERROR_FAILURE;
812  }
813 
814  //Keep the leftmost bits of the hash value
815  digestLen = MIN(digestLen, orderLen);
816 
817  //Acquire exclusive access to the SCE module
819 
820  //Pad the digest with leading zeroes if necessary
821  osMemset(ecArgs.digest, 0, n);
822  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
823 
824  //Set public key
825  ecScalarExport(publicKey->q.x, n / 4, (uint8_t *) ecArgs.q, n,
827 
828  ecScalarExport(publicKey->q.y, n / 4, (uint8_t *) ecArgs.q + n, n,
830 
831  //Set signature
832  ecScalarExport(signature->r, n / 4, (uint8_t *) ecArgs.signature, n,
834 
835  ecScalarExport(signature->s, n / 4, (uint8_t *) ecArgs.signature + n, n,
837 
838  //Install the plaintext public key and get the wrapped key
839  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
840  oemCommand, NULL, NULL, (uint8_t *) ecArgs.q, ecArgs.wrappedKey);
841 
842  //Check status code
843  if(status == FSP_SUCCESS)
844  {
845  //Verify ECDSA signature
846  if(curve->fieldSize == 256)
847  {
848  status = HW_SCE_EcdsaSignatureVerificationSub(&curveType, &command,
849  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
850  }
851  else if(curve->fieldSize == 384)
852  {
853  status = HW_SCE_EcdsaP384SignatureVerificationSub(&curveType,
854  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
855  }
856  else
857  {
858  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
859  }
860  }
861 
862  //Release exclusive access to the SCE module
864 
865  //Return status code
866  return (status == FSP_SUCCESS) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
867 }
868 
869 #endif
870 #endif
RA6 public-key hardware accelerator.
error_t ecScalarImport(uint32_t *r, uint_t n, const uint8_t *input, size_t length, EcScalarFormat format)
Octet string to integer conversion.
Definition: ec_misc.c:54
ECDSA signature.
Definition: ecdsa.h:63
error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
@ ERROR_OUT_OF_RANGE
Definition: error.h:138
uint32_t digest[12]
Mpi p
First factor.
Definition: rsa.h:72
uint8_t a
Definition: ndp.h:411
error_t ecScalarExport(const uint32_t *a, uint_t n, uint8_t *output, size_t length, EcScalarFormat format)
Integer to octet string conversion.
Definition: ec_misc.c:150
Arbitrary precision integer.
Definition: mpi.h:102
#define PrngAlgo
Definition: crypto.h:973
ECDSA (Elliptic Curve Digital Signature Algorithm)
uint8_t p
Definition: ndp.h:300
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdsa.h:64
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
Mpi n
Modulus.
Definition: rsa.h:69
#define mpiWriteRaw(a, data, length)
Definition: crypto_legacy.h:36
uint32_t wrappedKey[100]
#define osStrcmp(s1, s2)
Definition: os_port.h:174
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:48
Mpi d
Private exponent.
Definition: rsa.h:71
#define mpiReadRaw(r, data, length)
Definition: crypto_legacy.h:35
error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (fast calculation)
uint8_t r
Definition: ndp.h:346
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1587
uint32_t m[128]
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
RSA primitive arguments.
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 osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision subtraction.
Definition: mpi.c:969
error_t
Error codes.
Definition: error.h:43
error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision addition.
Definition: mpi.c:891
@ 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.
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
General definitions for cryptographic algorithms.
RSA public-key cryptography standard.
EC primitive arguments.
EC private key.
Definition: ec.h:432
uint32_t g[24]
uint32_t signature[24]
#define MIN(a, b)
Definition: os_port.h:63
uint32_t wrappedKey[300]
RA6 hardware cryptographic accelerator (SCE7 / SCE9)
uint32_t q[24]
OsMutex ra6CryptoMutex
Definition: ra6_crypto.c:41
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
EC public key.
Definition: ec.h:421
__weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:798
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
int_t ecScalarCompInt(const uint32_t *a, uint32_t b, uint_t n)
Compare integers.
Definition: ec_misc.c:374
uint8_t m
Definition: ndp.h:304
uint8_t n
RSA private key.
Definition: rsa.h:68
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
uint32_t key[256]
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
uint8_t s
Definition: igmp_common.h:234
error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
RSA decryption primitive.
#define EcCurve
Definition: ec.h:346
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:358
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
error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (regular calculation)
error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
int_t mpiCompInt(const Mpi *a, mpi_sword_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:429
uint32_t d[12]
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t mpiMulMod(Mpi *r, const Mpi *a, const Mpi *b, const Mpi *p)
Modular multiplication.
ECC (Elliptic Curve Cryptography)
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
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
uint32_t c[128]
Debugging facilities.
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:215
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64