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.2
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 aLen;
71  size_t eLen;
72  size_t pLen;
73 
74  //Get the length of the integer, in bytes
75  aLen = mpiGetByteLength(a);
76  //Get the length of the exponent, in bytes
77  eLen = mpiGetByteLength(e);
78  //Get the length of the modulus, in bytes
79  pLen = mpiGetByteLength(p);
80 
81 #if (BSP_FEATURE_RSIP_SCE9_SUPPORTED != 0)
82  //The SCE9 accelerator supports operand lengths up to 4096 bits
83  if(aLen <= 512 && eLen <= 4 && pLen <= 512)
84  {
85  size_t n;
86  sce_oem_cmd_t command;
87 
88  //Select appropriate scalar length
89  if(aLen <= 128 && pLen <= 128)
90  {
91  command = SCE_OEM_CMD_RSA1024_PUBLIC;
92  n = 128;
93  }
94  else if(aLen <= 256 && pLen <= 256)
95  {
96  command = SCE_OEM_CMD_RSA2048_PUBLIC;
97  n = 256;
98  }
99  else if(aLen <= 384 && pLen <= 384)
100  {
101  command = SCE_OEM_CMD_RSA3072_PUBLIC;
102  n = 384;
103  }
104  else
105  {
106  command = SCE_OEM_CMD_RSA4096_PUBLIC;
107  n = 512;
108  }
109 
110  //Acquire exclusive access to the SCE module
112 
113  //Format message representative
114  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, n);
115 
116  //Format public key
117  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, n);
118  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + n, 4);
119 
120  //Install the plaintext public key and get the wrapped key
121  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
122  command, NULL, NULL, (uint8_t *) rsaArgs.key, rsaArgs.wrappedKey);
123 
124  //Check status code
125  if(status == FSP_SUCCESS)
126  {
127  //Perform RSA encryption
128  if(n == 128)
129  {
130  status = HW_SCE_Rsa1024ModularExponentEncryptSub(rsaArgs.wrappedKey,
131  rsaArgs.m, rsaArgs.c);
132  }
133  else if(n == 256)
134  {
135  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.wrappedKey,
136  rsaArgs.m, rsaArgs.c);
137  }
138  else if(n == 384)
139  {
140  status = HW_SCE_Rsa3072ModularExponentEncryptSub(rsaArgs.wrappedKey,
141  rsaArgs.m, rsaArgs.c);
142  }
143  else if(n == 512)
144  {
145  status = HW_SCE_Rsa4096ModularExponentEncryptSub(rsaArgs.wrappedKey,
146  rsaArgs.m, rsaArgs.c);
147  }
148  else
149  {
150  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
151  }
152  }
153 
154  //Check status code
155  if(status == FSP_SUCCESS)
156  {
157  //Copy the ciphertext representative
158  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, n);
159  }
160  else
161  {
162  //Report an error
163  error = ERROR_FAILURE;
164  }
165 
166  //Release exclusive access to the SCE module
168  }
169 #else
170  //The SCE7 accelerator supports operand lengths up to 2048 bits
171  if(aLen <= 256 && eLen <= 4 && pLen <= 256)
172  {
173  //Acquire exclusive access to the SCE module
175 
176  //Format message representative
177  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, 256);
178 
179  //Format public key
180  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, 256);
181  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + 256, 4);
182 
183  //Install the plaintext public key and get the wrapped key
184  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
185  SCE_OEM_CMD_RSA2048_PUBLIC, NULL, NULL, (uint8_t *) rsaArgs.key,
186  rsaArgs.wrappedKey);
187 
188  //Check status code
189  if(status == FSP_SUCCESS)
190  {
191  //Perform RSA encryption
192  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.wrappedKey,
193  rsaArgs.m, rsaArgs.c);
194  }
195 
196  //Check status code
197  if(status == FSP_SUCCESS)
198  {
199  //Copy the ciphertext representative
200  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, 256);
201  }
202  else
203  {
204  //Report an error
205  error = ERROR_FAILURE;
206  }
207 
208  //Release exclusive access to the SCE module
210  }
211 #endif
212  else
213  {
214  //Perform modular exponentiation (r = a ^ e mod p)
215  error = mpiExpModRegular(r, a, e, p);
216  }
217 
218  //Return status code
219  return error;
220 }
221 
222 
223 /**
224  * @brief Modular exponentiation (regular calculation)
225  * @param[out] r Resulting integer R = A ^ E mod P
226  * @param[in] a Pointer to a multiple precision integer
227  * @param[in] e Exponent
228  * @param[in] p Modulus
229  * @return Error code
230  **/
231 
232 error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
233 {
234  error_t error;
235  fsp_err_t status;
236  size_t aLen;
237  size_t eLen;
238  size_t pLen;
239 
240  //Get the length of the integer, in bytes
241  aLen = mpiGetByteLength(a);
242  //Get the length of the exponent, in bytes
243  eLen = mpiGetByteLength(e);
244  //Get the length of the modulus, in bytes
245  pLen = mpiGetByteLength(p);
246 
247 #if (BSP_FEATURE_RSIP_SCE9_SUPPORTED != 0)
248  //The SCE9 accelerator supports operand lengths up to 2048 bits
249  if(aLen <= 256 && eLen <= 256 && pLen <= 256)
250  {
251  size_t n;
252  sce_oem_cmd_t command;
253 
254  //Select appropriate scalar length
255  if(aLen <= 128 && eLen <= 128 && pLen <= 128)
256  {
257  command = SCE_OEM_CMD_RSA1024_PRIVATE;
258  n = 128;
259  }
260  else
261  {
262  command = SCE_OEM_CMD_RSA2048_PRIVATE;
263  n = 256;
264  }
265 
266  //Acquire exclusive access to the SCE module
268 
269  //Format ciphertext representative
270  mpiWriteRaw(a, (uint8_t *) rsaArgs.c, n);
271 
272  //Format private key
273  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, n);
274  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + n, n);
275 
276  //Install the plaintext private key and get the wrapped key
277  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
278  command, NULL, NULL, (uint8_t *) rsaArgs.key, rsaArgs.wrappedKey);
279 
280  //Check status code
281  if(status == FSP_SUCCESS)
282  {
283  //Perform RSA decryption
284  if(n == 128)
285  {
286  status = HW_SCE_Rsa1024ModularExponentDecryptSub(rsaArgs.wrappedKey,
287  rsaArgs.c, rsaArgs.m);
288  }
289  else if(n == 256)
290  {
291  status = HW_SCE_Rsa2048ModularExponentDecryptSub(rsaArgs.wrappedKey,
292  rsaArgs.c, rsaArgs.m);
293  }
294  else
295  {
296  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
297  }
298  }
299 
300  //Check status code
301  if(status == FSP_SUCCESS)
302  {
303  //Copy the message representative
304  error = mpiReadRaw(r, (uint8_t *) rsaArgs.m, n);
305  }
306  else
307  {
308  //Report an error
309  error = ERROR_FAILURE;
310  }
311 
312  //Release exclusive access to the SCE module
314  }
315 #else
316  //The SCE7 accelerator supports operand lengths up to 2048 bits
317  if(aLen <= 256 && eLen <= 256 && pLen <= 256)
318  {
319  //Acquire exclusive access to the SCE module
321 
322  //Format ciphertext representative
323  mpiWriteRaw(a, (uint8_t *) rsaArgs.c, 256);
324 
325  //Format private key
326  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, 256);
327  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + 256, 256);
328 
329  //Install the plaintext private key and get the wrapped key
330  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
331  SCE_OEM_CMD_RSA2048_PRIVATE, NULL, NULL, (uint8_t *) rsaArgs.key,
332  rsaArgs.wrappedKey);
333 
334  //Check status code
335  if(status == FSP_SUCCESS)
336  {
337  //Perform RSA decryption
338  status = HW_SCE_Rsa2048ModularExponentDecryptSub(rsaArgs.wrappedKey,
339  rsaArgs.c, rsaArgs.m);
340  }
341 
342  //Check status code
343  if(status == FSP_SUCCESS)
344  {
345  //Copy the message representative
346  error = mpiReadRaw(r, (uint8_t *) rsaArgs.m, 256);
347  }
348  else
349  {
350  //Report an error
351  error = ERROR_FAILURE;
352  }
353 
354  //Release exclusive access to the SCE module
356  }
357 #endif
358  else
359  {
360  //Perform modular exponentiation (r = a ^ e mod p)
361  error = mpiExpMod(r, a, e, p);
362  }
363 
364  //Return status code
365  return error;
366 }
367 
368 #endif
369 #if (RSA_SUPPORT == ENABLED)
370 
371 /**
372  * @brief RSA decryption primitive
373  *
374  * The RSA decryption primitive recovers the message representative from
375  * the ciphertext representative under the control of a private key
376  *
377  * @param[in] key RSA private key
378  * @param[in] c Ciphertext representative
379  * @param[out] m Message representative
380  * @return Error code
381  **/
382 
383 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
384 {
385  error_t error;
386  size_t nLen;
387  size_t dLen;
388  size_t pLen;
389  size_t qLen;
390  size_t dpLen;
391  size_t dqLen;
392  size_t qinvLen;
393 
394  //Get the length of the private key
395  nLen = mpiGetByteLength(&key->n);
396  dLen = mpiGetByteLength(&key->d);
397  pLen = mpiGetByteLength(&key->p);
398  qLen = mpiGetByteLength(&key->q);
399  dpLen = mpiGetByteLength(&key->dp);
400  dqLen = mpiGetByteLength(&key->dq);
401  qinvLen = mpiGetByteLength(&key->qinv);
402 
403  //Sanity check
404  if(nLen == 0)
406 
407  //The ciphertext representative c shall be between 0 and n - 1
408  if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0)
409  return ERROR_OUT_OF_RANGE;
410 
411  //Check the length of the private key
412  if(nLen <= 256 && dLen <= 256)
413  {
414  //Let m = c ^ d mod n
415  error = mpiExpModRegular(m, c, &key->d, &key->n);
416  }
417  else if(nLen > 0 && pLen > 0 && qLen > 0 && dpLen > 0 && dqLen > 0 &&
418  qinvLen > 0)
419  {
420  Mpi m1;
421  Mpi m2;
422  Mpi h;
423 
424  //Initialize multiple-precision integers
425  mpiInit(&m1);
426  mpiInit(&m2);
427  mpiInit(&h);
428 
429  //Compute m1 = c ^ dP mod p
430  error = mpiMod(&m1, c, &key->p);
431 
432  if(!error)
433  {
434  error = mpiExpModRegular(&m1, &m1, &key->dp, &key->p);
435  }
436 
437  //Compute m2 = c ^ dQ mod q
438  if(!error)
439  {
440  error = mpiMod(&m2, c, &key->q);
441  }
442 
443  if(!error)
444  {
445  error = mpiExpModRegular(&m2, &m2, &key->dq, &key->q);
446  }
447 
448  //Let h = (m1 - m2) * qInv mod p
449  if(!error)
450  {
451  error = mpiSub(&h, &m1, &m2);
452  }
453 
454  if(!error)
455  {
456  error = mpiMulMod(&h, &h, &key->qinv, &key->p);
457  }
458 
459  //Let m = m2 + q * h
460  if(!error)
461  {
462  error = mpiMul(m, &key->q, &h);
463  }
464 
465  if(!error)
466  {
467  error = mpiAdd(m, m, &m2);
468  }
469 
470  //Free previously allocated memory
471  mpiFree(&m1);
472  mpiFree(&m2);
473  mpiFree(&h);
474  }
475  else if(nLen > 0 && dLen > 0)
476  {
477  //Let m = c ^ d mod n
478  error = mpiExpModRegular(m, c, &key->d, &key->n);
479  }
480  else
481  {
482  //Report an error
483  error = ERROR_INVALID_PARAMETER;
484  }
485 
486  //Return status code
487  return error;
488 }
489 
490 #endif
491 #if (EC_SUPPORT == ENABLED)
492 
493 /**
494  * @brief Scalar multiplication (fast calculation)
495  * @param[in] curve Elliptic curve parameters
496  * @param[out] r Resulting point R = d.S
497  * @param[in] d An integer d such as 0 <= d < p
498  * @param[in] s EC point
499  * @return Error code
500  **/
501 
502 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
503  const EcPoint3 *s)
504 {
505  //Compute R = d.S
506  return ecMulRegular(curve, r, d, s);
507 }
508 
509 
510 /**
511  * @brief Scalar multiplication (regular calculation)
512  * @param[in] curve Elliptic curve parameters
513  * @param[out] r Resulting point R = d.S
514  * @param[in] d An integer d such as 0 <= d < q
515  * @param[in] s EC point
516  * @return Error code
517  **/
518 
519 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
520  const EcPoint3 *s)
521 {
522  error_t error;
523  fsp_err_t status;
524  size_t n;
525  uint32_t curveType;
526  uint32_t command;
527  sce_oem_cmd_t oemCommand;
528 
529  //Check elliptic curve parameters
530  if(osStrcmp(curve->name, "secp256k1") == 0)
531  {
532  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
533  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
534  command = 0;
535  n = 32;
536  }
537  else if(osStrcmp(curve->name, "secp256r1") == 0)
538  {
539  curveType = SCE_ECC_CURVE_TYPE_NIST;
540  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
541  command = 0;
542  n = 32;
543  }
544  else if(osStrcmp(curve->name, "secp384r1") == 0)
545  {
546  curveType = SCE_ECC_CURVE_TYPE_NIST;
547  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
548  command = 0;
549  n = 48;
550  }
551  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
552  {
553  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
554  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
555  command = 0;
556  n = 32;
557  }
558  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
559  {
560  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
561  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
562  command = 0;
563  n = 48;
564  }
565  else
566  {
567  return ERROR_FAILURE;
568  }
569 
570  //Acquire exclusive access to the SCE module
572 
573  //Set scalar value
574  ecScalarExport(d, n / 4, (uint8_t *) ecArgs.d, n,
576 
577  //Set input point
578  ecScalarExport(s->x, n / 4, (uint8_t *) ecArgs.g, n,
580 
581  ecScalarExport(s->y, n / 4, (uint8_t *) ecArgs.g + n, n,
583 
584  //Install the plaintext private key and get the wrapped key
585  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
586  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
587 
588  //Check status code
589  if(status == FSP_SUCCESS)
590  {
591  //Perform scalar multiplication
592  if(curve->fieldSize == 256)
593  {
594  status = HW_SCE_Ecc256ScalarMultiplicationSub(&curveType,
595  &command, ecArgs.wrappedKey, ecArgs.g, ecArgs.q);
596  }
597  else if(curve->fieldSize == 384)
598  {
599  status = HW_SCE_Ecc384ScalarMultiplicationSub(&curveType,
600  ecArgs.wrappedKey, ecArgs.g, ecArgs.q);
601  }
602  else
603  {
604  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
605  }
606  }
607 
608  //Check status code
609  if(status == FSP_SUCCESS)
610  {
611  //Copy the x-coordinate of the result
612  error = ecScalarImport(r->x, EC_MAX_MODULUS_SIZE, (uint8_t *) ecArgs.q,
614 
615  //Check status code
616  if(!error)
617  {
618  //Copy the y-coordinate of the result
620  (uint8_t *) ecArgs.q + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
621  }
622 
623  //Check status code
624  if(!error)
625  {
626  //Set the z-coordinate of the result
628  }
629  }
630  else
631  {
632  //Report an error
633  error = ERROR_FAILURE;
634  }
635 
636  //Release exclusive access to the SCE module
638 
639  //Return status code
640  return error;
641 }
642 
643 #endif
644 #if (ECDSA_SUPPORT == ENABLED)
645 
646 /**
647  * @brief ECDSA signature generation
648  * @param[in] prngAlgo PRNG algorithm
649  * @param[in] prngContext Pointer to the PRNG context
650  * @param[in] privateKey Signer's EC private key
651  * @param[in] digest Digest of the message to be signed
652  * @param[in] digestLen Length in octets of the digest
653  * @param[out] signature (R, S) integer pair
654  * @return Error code
655  **/
656 
657 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
658  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
659  EcdsaSignature *signature)
660 {
661  error_t error;
662  fsp_err_t status;
663  size_t n;
664  size_t orderLen;
665  uint32_t curveType;
666  uint32_t command;
667  sce_oem_cmd_t oemCommand;
668  const EcCurve *curve;
669 
670  //Check parameters
671  if(privateKey == NULL || digest == NULL || signature == NULL)
673 
674  //Invalid elliptic curve?
675  if(privateKey->curve == NULL)
677 
678  //Get elliptic curve parameters
679  curve = privateKey->curve;
680 
681  //Get the length of the order, in bytes
682  orderLen = (curve->orderSize + 7) / 8;
683 
684  //Check elliptic curve parameters
685  if(osStrcmp(curve->name, "secp256k1") == 0)
686  {
687  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
688  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
689  command = 0;
690  n = 32;
691  }
692  else if(osStrcmp(curve->name, "secp256r1") == 0)
693  {
694  curveType = SCE_ECC_CURVE_TYPE_NIST;
695  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
696  command = 0;
697  n = 32;
698  }
699  else if(osStrcmp(curve->name, "secp384r1") == 0)
700  {
701  curveType = SCE_ECC_CURVE_TYPE_NIST;
702  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
703  command = 0;
704  n = 48;
705  }
706  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
707  {
708  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
709  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
710  command = 0;
711  n = 32;
712  }
713  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
714  {
715  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
716  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
717  command = 0;
718  n = 48;
719  }
720  else
721  {
722  return ERROR_FAILURE;
723  }
724 
725  //Keep the leftmost bits of the hash value
726  digestLen = MIN(digestLen, orderLen);
727 
728  //Acquire exclusive access to the SCE module
730 
731  //Pad the digest with leading zeroes if necessary
732  osMemset(ecArgs.digest, 0, n);
733  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
734 
735  //Set private key
736  ecScalarExport(privateKey->d, n / 4, (uint8_t *) ecArgs.d, n,
738 
739  //Install the plaintext private key and get the wrapped key
740  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
741  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
742 
743  //Check status code
744  if(status == FSP_SUCCESS)
745  {
746  //Generate ECDSA signature
747  if(curve->fieldSize == 256)
748  {
749  status = HW_SCE_EcdsaSignatureGenerateSub(&curveType, &command,
750  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
751  }
752  else if(curve->fieldSize == 384)
753  {
754  status = HW_SCE_EcdsaP384SignatureGenerateSub(&curveType,
755  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
756  }
757  else
758  {
759  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
760  }
761  }
762 
763  //Check status code
764  if(status == FSP_SUCCESS)
765  {
766  //Save elliptic curve parameters
767  signature->curve = curve;
768 
769  //Copy integer R
770  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE,
771  (uint8_t *) ecArgs.signature, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
772 
773  //Check status code
774  if(!error)
775  {
776  //Copy integer S
777  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE,
778  (uint8_t *) ecArgs.signature + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
779  }
780  }
781  else
782  {
783  //Report an error
784  error = ERROR_FAILURE;
785  }
786 
787  //Release exclusive access to the SCE module
789 
790  //Return status code
791  return error;
792 }
793 
794 
795 /**
796  * @brief ECDSA signature verification
797  * @param[in] publicKey Signer's EC public key
798  * @param[in] digest Digest of the message whose signature is to be verified
799  * @param[in] digestLen Length in octets of the digest
800  * @param[in] signature (R, S) integer pair
801  * @return Error code
802  **/
803 
805  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
806 {
807  fsp_err_t status;
808  size_t n;
809  size_t orderLen;
810  uint32_t curveType;
811  uint32_t command;
812  sce_oem_cmd_t oemCommand;
813  const EcCurve *curve;
814 
815  //Check parameters
816  if(publicKey == NULL || digest == NULL || signature == NULL)
818 
819  //Invalid elliptic curve?
820  if(publicKey->curve == NULL)
822 
823  //Verify that the public key is on the curve
824  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
825  {
827  }
828 
829  //The verifier shall check that 0 < r < q
830  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
831  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
832  {
833  //If the condition is violated, the signature shall be rejected as invalid
835  }
836 
837  //The verifier shall check that 0 < s < q
838  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
839  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
840  {
841  //If the condition is violated, the signature shall be rejected as invalid
843  }
844 
845  //Get elliptic curve parameters
846  curve = publicKey->curve;
847 
848  //Get the length of the order, in bytes
849  orderLen = (curve->orderSize + 7) / 8;
850 
851  //Check elliptic curve parameters
852  if(osStrcmp(curve->name, "secp256k1") == 0)
853  {
854  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
855  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PUBLIC;
856  command = 0;
857  n = 32;
858  }
859  else if(osStrcmp(curve->name, "secp256r1") == 0)
860  {
861  curveType = SCE_ECC_CURVE_TYPE_NIST;
862  oemCommand = SCE_OEM_CMD_ECC_P256_PUBLIC;
863  command = 0;
864  n = 32;
865  }
866  else if(osStrcmp(curve->name, "secp384r1") == 0)
867  {
868  curveType = SCE_ECC_CURVE_TYPE_NIST;
869  oemCommand = SCE_OEM_CMD_ECC_P384_PUBLIC;
870  command = 0;
871  n = 48;
872  }
873  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
874  {
875  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
876  oemCommand = SCE_OEM_CMD_ECC_P256R1_PUBLIC;
877  command = 0;
878  n = 32;
879  }
880  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
881  {
882  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
883  oemCommand = SCE_OEM_CMD_ECC_P384R1_PUBLIC;
884  command = 0;
885  n = 48;
886  }
887  else
888  {
889  return ERROR_FAILURE;
890  }
891 
892  //Keep the leftmost bits of the hash value
893  digestLen = MIN(digestLen, orderLen);
894 
895  //Acquire exclusive access to the SCE module
897 
898  //Pad the digest with leading zeroes if necessary
899  osMemset(ecArgs.digest, 0, n);
900  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
901 
902  //Set public key
903  ecScalarExport(publicKey->q.x, n / 4, (uint8_t *) ecArgs.q, n,
905 
906  ecScalarExport(publicKey->q.y, n / 4, (uint8_t *) ecArgs.q + n, n,
908 
909  //Set signature
910  ecScalarExport(signature->r, n / 4, (uint8_t *) ecArgs.signature, n,
912 
913  ecScalarExport(signature->s, n / 4, (uint8_t *) ecArgs.signature + n, n,
915 
916  //Install the plaintext public key and get the wrapped key
917  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
918  oemCommand, NULL, NULL, (uint8_t *) ecArgs.q, ecArgs.wrappedKey);
919 
920  //Check status code
921  if(status == FSP_SUCCESS)
922  {
923  //Verify ECDSA signature
924  if(curve->fieldSize == 256)
925  {
926  status = HW_SCE_EcdsaSignatureVerificationSub(&curveType, &command,
927  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
928  }
929  else if(curve->fieldSize == 384)
930  {
931  status = HW_SCE_EcdsaP384SignatureVerificationSub(&curveType,
932  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature);
933  }
934  else
935  {
936  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
937  }
938  }
939 
940  //Release exclusive access to the SCE module
942 
943  //Return status code
944  return (status == FSP_SUCCESS) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
945 }
946 
947 #endif
948 #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:980
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:840
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