ra8_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file ra8_crypto_pkc.c
3  * @brief RA8 public-key hardware accelerator
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.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 (RA8_CRYPTO_PKC_SUPPORT == ENABLED)
50 
51 //Global variables
52 static Ra8RsaArgs rsaArgs;
53 static Ra8EcArgs 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  sce_oem_cmd_t command;
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  //The accelerator supports operand lengths up to 4096 bits
83  if((aLen <= 128 && eLen <= 4 && pLen == 128) ||
84  (aLen <= 256 && eLen <= 4 && pLen == 256) ||
85  (aLen <= 384 && eLen <= 4 && pLen == 384) ||
86  (aLen <= 512 && eLen <= 4 && pLen == 512))
87  {
88  //Select appropriate scalar length
89  if(pLen == 128)
90  {
91  command = SCE_OEM_CMD_RSA1024_PUBLIC;
92  }
93  else if(pLen == 256)
94  {
95  command = SCE_OEM_CMD_RSA2048_PUBLIC;
96  }
97  else if(pLen == 384)
98  {
99  command = SCE_OEM_CMD_RSA3072_PUBLIC;
100  }
101  else
102  {
103  command = SCE_OEM_CMD_RSA4096_PUBLIC;
104  }
105 
106  //Acquire exclusive access to the RSIP module
108 
109  //Format message representative
110  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, pLen);
111 
112  //Format public key
113  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, pLen);
114  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + pLen, 4);
115 
116 #if (BSP_FEATURE_RSIP_RSIP_E51A_SUPPORTED == 1)
117  //Just for sanity
118  (void) command;
119 
120  //Perform RSA encryption
121  if(pLen == 128)
122  {
123  status = HW_SCE_Rsa1024ModularExponentEncryptSub(rsaArgs.key,
124  rsaArgs.m, rsaArgs.c);
125  }
126  else if(pLen == 256)
127  {
128  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.key,
129  rsaArgs.m, rsaArgs.c);
130  }
131  else if(pLen == 384)
132  {
133  status = HW_SCE_Rsa3072ModularExponentEncryptSub(rsaArgs.key,
134  rsaArgs.m, rsaArgs.c);
135  }
136  else if(pLen == 512)
137  {
138  status = HW_SCE_Rsa4096ModularExponentEncryptSub(rsaArgs.key,
139  rsaArgs.m, rsaArgs.c);
140  }
141  else
142  {
143  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
144  }
145 #else
146  //Install the plaintext public key and get the wrapped key
147  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
148  command, NULL, NULL, (uint8_t *) rsaArgs.key, rsaArgs.wrappedKey);
149 
150  //Check status code
151  if(status == FSP_SUCCESS)
152  {
153  //Perform RSA encryption
154  if(pLen == 128)
155  {
156  status = HW_SCE_Rsa1024ModularExponentEncryptSub(rsaArgs.wrappedKey,
157  rsaArgs.m, rsaArgs.c);
158  }
159  else if(pLen == 256)
160  {
161  status = HW_SCE_Rsa2048ModularExponentEncryptSub(rsaArgs.wrappedKey,
162  rsaArgs.m, rsaArgs.c);
163  }
164  else if(pLen == 384)
165  {
166  status = HW_SCE_Rsa3072ModularExponentEncryptSub(rsaArgs.wrappedKey,
167  rsaArgs.m, rsaArgs.c);
168  }
169  else if(pLen == 512)
170  {
171  status = HW_SCE_Rsa4096ModularExponentEncryptSub(rsaArgs.wrappedKey,
172  rsaArgs.m, rsaArgs.c);
173  }
174  else
175  {
176  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
177  }
178  }
179 #endif
180 
181  //Check status code
182  if(status == FSP_SUCCESS)
183  {
184  //Copy the ciphertext representative
185  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, pLen);
186  }
187  else
188  {
189  //Report an error
190  error = ERROR_FAILURE;
191  }
192 
193  //Release exclusive access to the RSIP module
195  }
196  else
197  {
198  //Perform modular exponentiation (r = a ^ e mod p)
199  error = mpiExpModRegular(r, a, e, p);
200  }
201 
202  //Return status code
203  return error;
204 }
205 
206 
207 /**
208  * @brief Modular exponentiation (regular calculation)
209  * @param[out] r Resulting integer R = A ^ E mod P
210  * @param[in] a Pointer to a multiple precision integer
211  * @param[in] e Exponent
212  * @param[in] p Modulus
213  * @return Error code
214  **/
215 
216 error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
217 {
218  error_t error;
219  fsp_err_t status;
220  size_t aLen;
221  size_t eLen;
222  size_t pLen;
223  uint32_t keyType;
224  uint32_t dummy;
225  sce_oem_cmd_t command;
226 
227  //Get the length of the integer, in bytes
228  aLen = mpiGetByteLength(a);
229  //Get the length of the exponent, in bytes
230  eLen = mpiGetByteLength(e);
231  //Get the length of the modulus, in bytes
232  pLen = mpiGetByteLength(p);
233 
234  //The accelerator supports operand lengths up to 4096 bits
235  if((aLen <= 128 && eLen <= 128 && pLen == 128) ||
236  (aLen <= 256 && eLen <= 256 && pLen == 256) ||
237  (aLen <= 384 && eLen <= 384 && pLen == 384) ||
238  (aLen <= 512 && eLen <= 512 && pLen == 512))
239  {
240  //Select appropriate scalar length
241  if(pLen == 128)
242  {
243  command = SCE_OEM_CMD_RSA1024_PRIVATE;
244  }
245  else if(pLen == 256)
246  {
247  command = SCE_OEM_CMD_RSA2048_PRIVATE;
248  }
249  else if(pLen == 384)
250  {
251  command = SCE_OEM_CMD_RSA3072_PRIVATE;
252  }
253  else
254  {
255  command = SCE_OEM_CMD_RSA4096_PRIVATE;
256  }
257 
258  //Set key type
259  keyType = 0;
260  //Dummy parameter
261  dummy = 0;
262 
263  //Acquire exclusive access to the RSIP module
265 
266  //Format ciphertext representative
267  mpiWriteRaw(a, (uint8_t *) rsaArgs.c, pLen);
268 
269  //Format private key
270  mpiWriteRaw(p, (uint8_t *) rsaArgs.key, pLen);
271  mpiWriteRaw(e, (uint8_t *) rsaArgs.key + pLen, pLen);
272 
273  //Install the plaintext private key and get the wrapped key
274  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
275  command, NULL, NULL, (uint8_t *) rsaArgs.key, rsaArgs.wrappedKey);
276 
277  //Check status code
278  if(status == FSP_SUCCESS)
279  {
280  //Perform RSA decryption
281  if(pLen == 128)
282  {
283  status = HW_SCE_Rsa1024ModularExponentDecryptSub(&keyType,
284  rsaArgs.wrappedKey, &dummy, rsaArgs.c, rsaArgs.m);
285  }
286  else if(pLen == 256)
287  {
288  status = HW_SCE_Rsa2048ModularExponentDecryptSub(&keyType,
289  rsaArgs.wrappedKey, &dummy, rsaArgs.c, rsaArgs.m);
290  }
291  else if(pLen == 384)
292  {
293  status = HW_SCE_Rsa3072ModularExponentDecryptSub(&keyType,
294  rsaArgs.wrappedKey, &dummy, rsaArgs.c, rsaArgs.m);
295  }
296  else if(pLen == 512)
297  {
298  status = HW_SCE_Rsa4096ModularExponentDecryptSub(&keyType,
299  rsaArgs.wrappedKey, &dummy, rsaArgs.c, rsaArgs.m);
300  }
301  else
302  {
303  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
304  }
305  }
306 
307  //Check status code
308  if(status == FSP_SUCCESS)
309  {
310  //Copy the message representative
311  error = mpiReadRaw(r, (uint8_t *) rsaArgs.m, pLen);
312  }
313  else
314  {
315  //Report an error
316  error = ERROR_FAILURE;
317  }
318 
319  //Release exclusive access to the RSIP module
321  }
322  else
323  {
324  //Perform modular exponentiation (r = a ^ e mod p)
325  error = mpiExpMod(r, a, e, p);
326  }
327 
328  //Return status code
329  return error;
330 }
331 
332 #endif
333 #if (RSA_SUPPORT == ENABLED)
334 
335 /**
336  * @brief RSA decryption primitive
337  *
338  * The RSA decryption primitive recovers the message representative from
339  * the ciphertext representative under the control of a private key
340  *
341  * @param[in] key RSA private key
342  * @param[in] c Ciphertext representative
343  * @param[out] m Message representative
344  * @return Error code
345  **/
346 
347 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
348 {
349  error_t error;
350  size_t nLen;
351  size_t dLen;
352  size_t pLen;
353  size_t qLen;
354  size_t dpLen;
355  size_t dqLen;
356  size_t qinvLen;
357 
358  //Get the length of the private key
359  nLen = mpiGetByteLength(&key->n);
360  dLen = mpiGetByteLength(&key->d);
361  pLen = mpiGetByteLength(&key->p);
362  qLen = mpiGetByteLength(&key->q);
363  dpLen = mpiGetByteLength(&key->dp);
364  dqLen = mpiGetByteLength(&key->dq);
365  qinvLen = mpiGetByteLength(&key->qinv);
366 
367  //Sanity check
368  if(nLen == 0)
370 
371  //The ciphertext representative c shall be between 0 and n - 1
372  if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0)
373  return ERROR_OUT_OF_RANGE;
374 
375  //Check the length of the private key
376  if((nLen == 128 && dLen <= 128) || (nLen == 384 && dLen <= 384))
377  {
378  //Let m = c ^ d mod n
379  error = mpiExpModRegular(m, c, &key->d, &key->n);
380  }
381  else if(nLen > 0 && pLen > 0 && qLen > 0 && dpLen > 0 && dqLen > 0 &&
382  qinvLen > 0)
383  {
384  Mpi m1;
385  Mpi m2;
386  Mpi h;
387 
388  //Initialize multiple-precision integers
389  mpiInit(&m1);
390  mpiInit(&m2);
391  mpiInit(&h);
392 
393  //Compute m1 = c ^ dP mod p
394  error = mpiMod(&m1, c, &key->p);
395 
396  if(!error)
397  {
398  error = mpiExpModRegular(&m1, &m1, &key->dp, &key->p);
399  }
400 
401  //Compute m2 = c ^ dQ mod q
402  if(!error)
403  {
404  error = mpiMod(&m2, c, &key->q);
405  }
406 
407  if(!error)
408  {
409  error = mpiExpModRegular(&m2, &m2, &key->dq, &key->q);
410  }
411 
412  //Let h = (m1 - m2) * qInv mod p
413  if(!error)
414  {
415  error = mpiSub(&h, &m1, &m2);
416  }
417 
418  if(!error)
419  {
420  error = mpiMulMod(&h, &h, &key->qinv, &key->p);
421  }
422 
423  //Let m = m2 + q * h
424  if(!error)
425  {
426  error = mpiMul(m, &key->q, &h);
427  }
428 
429  if(!error)
430  {
431  error = mpiAdd(m, m, &m2);
432  }
433 
434  //Free previously allocated memory
435  mpiFree(&m1);
436  mpiFree(&m2);
437  mpiFree(&h);
438  }
439  else if(nLen > 0 && dLen > 0)
440  {
441  //Let m = c ^ d mod n
442  error = mpiExpModRegular(m, c, &key->d, &key->n);
443  }
444  else
445  {
446  //Report an error
447  error = ERROR_INVALID_PARAMETER;
448  }
449 
450  //Return status code
451  return error;
452 }
453 
454 #endif
455 #if (EC_SUPPORT == ENABLED)
456 
457 /**
458  * @brief Scalar multiplication (fast calculation)
459  * @param[in] curve Elliptic curve parameters
460  * @param[out] r Resulting point R = d.S
461  * @param[in] d An integer d such as 0 <= d < p
462  * @param[in] s EC point
463  * @return Error code
464  **/
465 
466 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
467  const EcPoint3 *s)
468 {
469  //Compute R = d.S
470  return ecMulRegular(curve, r, d, s);
471 }
472 
473 
474 /**
475  * @brief Scalar multiplication (regular calculation)
476  * @param[in] curve Elliptic curve parameters
477  * @param[out] r Resulting point R = d.S
478  * @param[in] d An integer d such as 0 <= d < q
479  * @param[in] s EC point
480  * @return Error code
481  **/
482 
483 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
484  const EcPoint3 *s)
485 {
486  error_t error;
487  fsp_err_t status;
488  size_t n;
489  size_t offset;
490  size_t modLen;
491  size_t orderLen;
492  uint32_t curveType;
493  uint32_t command;
494  uint32_t keyType;
495  uint32_t dummy;
496  sce_oem_cmd_t oemCommand;
497  const uint32_t *domainParams;
498 
499  //Get the length of the modulus, in words
500  modLen = (curve->fieldSize + 31) / 32;
501  //Get the length of the order, in words
502  orderLen = (curve->orderSize + 31) / 32;
503 
504  //Determine the length of the operands, in bytes
505  n = (curve->fieldSize + 7) / 8;
506  n = (n + 15U) & ~15U;
507 
508  //Check elliptic curve parameters
509  if(osStrcmp(curve->name, "secp256k1") == 0)
510  {
511  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
512  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
513  domainParams = DomainParam_Koblitz_secp256k1;
514  command = 0;
515  offset = 0;
516  }
517  else if(osStrcmp(curve->name, "secp256r1") == 0)
518  {
519  curveType = SCE_ECC_CURVE_TYPE_NIST;
520  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
521  domainParams = DomainParam_NIST_P256;
522  command = 0;
523  offset = 0;
524  }
525  else if(osStrcmp(curve->name, "secp384r1") == 0)
526  {
527  curveType = SCE_ECC_CURVE_TYPE_NIST;
528  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
529  domainParams = DomainParam_NIST_P384;
530  command = 0;
531  offset = 0;
532  }
533  else if(osStrcmp(curve->name, "secp521r1") == 0)
534  {
535  curveType = SCE_ECC_CURVE_TYPE_NIST;
536  oemCommand = SCE_OEM_CMD_ECC_P521_PRIVATE;
537  domainParams = DomainParam_NIST_P521;
538  command = 0;
539  offset = 12;
540  }
541  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
542  {
543  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
544  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
545  domainParams = DomainParam_Brainpool_256r1;
546  command = 0;
547  offset = 0;
548  }
549  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
550  {
551  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
552  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
553  domainParams = DomainParam_Brainpool_384r1;
554  command = 0;
555  offset = 0;
556  }
557  else if(osStrcmp(curve->name, "brainpoolP512r1") == 0)
558  {
559  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
560  oemCommand = SCE_OEM_CMD_ECC_P512R1_PRIVATE;
561  domainParams = DomainParam_Brainpool_512r1;
562  command = 0;
563  offset = 0;
564  }
565  else
566  {
567  return ERROR_FAILURE;
568  }
569 
570  //Set key type
571  keyType = 0;
572  //Dummy parameter
573  dummy = 0;
574 
575  //Acquire exclusive access to the RSIP module
577 
578  //Set scalar value
579  ecScalarExport(d, orderLen, (uint8_t *) ecArgs.d, n,
581 
582  //Set input point
583  ecScalarExport(s->x, modLen, (uint8_t *) ecArgs.g, n,
585 
586  ecScalarExport(s->y, modLen, (uint8_t *) ecArgs.g + n, n,
588 
589  //Install the plaintext private key and get the wrapped key
590  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
591  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
592 
593  //Check status code
594  if(status == FSP_SUCCESS)
595  {
596  //Perform scalar multiplication
597  if(curve->fieldSize == 256)
598  {
599  status = HW_SCE_Ecc256ScalarMultiplicationSub(&curveType, &command,
600  &keyType, ecArgs.wrappedKey, &dummy, ecArgs.g, domainParams,
601  ecArgs.q);
602  }
603  else if(curve->fieldSize == 384)
604  {
605  status = HW_SCE_Ecc384ScalarMultiplicationSub(&curveType, &keyType,
606  ecArgs.wrappedKey, &dummy, ecArgs.g, domainParams, ecArgs.q);
607  }
608  else if(curve->fieldSize == 512)
609  {
610  status = HW_SCE_Ecc512ScalarMultiplicationSub(&keyType,
611  ecArgs.wrappedKey, &dummy, ecArgs.g, domainParams, ecArgs.q);
612  }
613  else if(curve->fieldSize == 521)
614  {
615  status = HW_SCE_Ecc521ScalarMultiplicationSub(&keyType,
616  ecArgs.wrappedKey, &dummy, ecArgs.g, domainParams, ecArgs.q);
617  }
618  else
619  {
620  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
621  }
622  }
623 
624  //Check status code
625  if(status == FSP_SUCCESS)
626  {
627  //Copy the x-coordinate of the result
629  (uint8_t *) ecArgs.q + offset, modLen * 4,
631 
632  //Check status code
633  if(!error)
634  {
635  //Copy the y-coordinate of the result
637  (uint8_t *) ecArgs.q + offset + n, modLen * 4,
639  }
640 
641  //Check status code
642  if(!error)
643  {
644  //Set the z-coordinate of the result
646  }
647  }
648  else
649  {
650  //Report an error
651  error = ERROR_FAILURE;
652  }
653 
654  //Release exclusive access to the RSIP module
656 
657  //Return status code
658  return error;
659 }
660 
661 #endif
662 #if (ECDSA_SUPPORT == ENABLED)
663 
664 /**
665  * @brief ECDSA signature generation
666  * @param[in] prngAlgo PRNG algorithm
667  * @param[in] prngContext Pointer to the PRNG context
668  * @param[in] privateKey Signer's EC private key
669  * @param[in] digest Digest of the message to be signed
670  * @param[in] digestLen Length in octets of the digest
671  * @param[out] signature (R, S) integer pair
672  * @return Error code
673  **/
674 
675 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
676  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
677  EcdsaSignature *signature)
678 {
679  error_t error;
680  fsp_err_t status;
681  size_t n;
682  size_t offset;
683  size_t orderLen;
684  uint32_t curveType;
685  uint32_t command;
686  uint32_t keyType;
687  uint32_t dummy;
688  sce_oem_cmd_t oemCommand;
689  const uint32_t *domainParams;
690  const EcCurve *curve;
691 
692  //Check parameters
693  if(privateKey == NULL || digest == NULL || signature == NULL)
695 
696  //Invalid elliptic curve?
697  if(privateKey->curve == NULL)
699 
700  //Get elliptic curve parameters
701  curve = privateKey->curve;
702 
703  //Get the length of the order, in words
704  orderLen = (curve->orderSize + 31) / 32;
705 
706  //Determine the length of the operands, in bytes
707  n = (curve->fieldSize + 7) / 8;
708  n = (n + 15U) & ~15U;
709 
710  //Check elliptic curve parameters
711  if(osStrcmp(curve->name, "secp256k1") == 0)
712  {
713  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
714  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PRIVATE;
715  domainParams = DomainParam_Koblitz_secp256k1;
716  command = 0;
717  offset = 0;
718  }
719  else if(osStrcmp(curve->name, "secp256r1") == 0)
720  {
721  curveType = SCE_ECC_CURVE_TYPE_NIST;
722  oemCommand = SCE_OEM_CMD_ECC_P256_PRIVATE;
723  domainParams = DomainParam_NIST_P256;
724  command = 0;
725  offset = 0;
726  }
727  else if(osStrcmp(curve->name, "secp384r1") == 0)
728  {
729  curveType = SCE_ECC_CURVE_TYPE_NIST;
730  oemCommand = SCE_OEM_CMD_ECC_P384_PRIVATE;
731  domainParams = DomainParam_NIST_P384;
732  command = 0;
733  offset = 0;
734  }
735  else if(osStrcmp(curve->name, "secp521r1") == 0)
736  {
737  curveType = SCE_ECC_CURVE_TYPE_NIST;
738  oemCommand = SCE_OEM_CMD_ECC_P521_PRIVATE;
739  domainParams = DomainParam_NIST_P521;
740  command = 0;
741  offset = 12;
742  }
743  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
744  {
745  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
746  oemCommand = SCE_OEM_CMD_ECC_P256R1_PRIVATE;
747  domainParams = DomainParam_Brainpool_256r1;
748  command = 0;
749  offset = 0;
750  }
751  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
752  {
753  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
754  oemCommand = SCE_OEM_CMD_ECC_P384R1_PRIVATE;
755  domainParams = DomainParam_Brainpool_384r1;
756  command = 0;
757  offset = 0;
758  }
759  else if(osStrcmp(curve->name, "brainpoolP512r1") == 0)
760  {
761  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
762  oemCommand = SCE_OEM_CMD_ECC_P512R1_PRIVATE;
763  domainParams = DomainParam_Brainpool_512r1;
764  command = 0;
765  offset = 0;
766  }
767  else
768  {
769  return ERROR_FAILURE;
770  }
771 
772  //Set key type
773  keyType = 0;
774  //Dummy parameter
775  dummy = 0;
776 
777  //Keep the leftmost bits of the hash value
778  digestLen = MIN(digestLen, (curve->orderSize + 7) / 8);
779 
780  //Acquire exclusive access to the RSIP module
782 
783  //Pad the digest with leading zeroes if necessary
784  osMemset(ecArgs.digest, 0, n);
785  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
786 
787  //Set private key
788  ecScalarExport(privateKey->d, orderLen, (uint8_t *) ecArgs.d, n,
790 
791  //Install the plaintext private key and get the wrapped key
792  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
793  oemCommand, NULL, NULL, (uint8_t *) ecArgs.d, ecArgs.wrappedKey);
794 
795  //Check status code
796  if(status == FSP_SUCCESS)
797  {
798  //Generate ECDSA signature
799  if(curve->fieldSize == 256)
800  {
801  status = HW_SCE_EcdsaSignatureGenerateSub(&curveType, &command,
802  &keyType, ecArgs.wrappedKey, &dummy, ecArgs.digest, domainParams,
803  ecArgs.signature);
804  }
805  else if(curve->fieldSize == 384)
806  {
807  status = HW_SCE_EcdsaP384SignatureGenerateSub(&curveType, &keyType,
808  ecArgs.wrappedKey, &dummy, ecArgs.digest, domainParams,
809  ecArgs.signature);
810  }
811  else if(curve->fieldSize == 512)
812  {
813  status = HW_SCE_EcdsaP512SignatureGenerateSub(&keyType,
814  ecArgs.wrappedKey, &dummy, ecArgs.digest, domainParams,
815  ecArgs.signature);
816  }
817  else if(curve->fieldSize == 521)
818  {
819  status = HW_SCE_EcdsaP521SignatureGenerateSub(&keyType,
820  ecArgs.wrappedKey, &dummy, ecArgs.digest, domainParams,
821  ecArgs.signature);
822  }
823  else
824  {
825  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
826  }
827  }
828 
829  //Check status code
830  if(status == FSP_SUCCESS)
831  {
832  //Save elliptic curve parameters
833  signature->curve = curve;
834 
835  //Copy integer R
836  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE,
837  (uint8_t *) ecArgs.signature + offset, orderLen * 4,
839 
840  //Check status code
841  if(!error)
842  {
843  //Copy integer S
844  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE,
845  (uint8_t *) ecArgs.signature + offset + n, orderLen * 4,
847  }
848  }
849  else
850  {
851  //Report an error
852  error = ERROR_FAILURE;
853  }
854 
855  //Release exclusive access to the RSIP module
857 
858  //Return status code
859  return error;
860 }
861 
862 
863 /**
864  * @brief ECDSA signature verification
865  * @param[in] publicKey Signer's EC public key
866  * @param[in] digest Digest of the message whose signature is to be verified
867  * @param[in] digestLen Length in octets of the digest
868  * @param[in] signature (R, S) integer pair
869  * @return Error code
870  **/
871 
873  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
874 {
875  fsp_err_t status;
876  size_t n;
877  size_t modLen;
878  size_t orderLen;
879  uint32_t curveType;
880  uint32_t command;
881  sce_oem_cmd_t oemCommand;
882  const uint32_t *domainParams;
883  const EcCurve *curve;
884 
885  //Check parameters
886  if(publicKey == NULL || digest == NULL || signature == NULL)
888 
889  //Invalid elliptic curve?
890  if(publicKey->curve == NULL)
892 
893  //Verify that the public key is on the curve
894  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
895  {
897  }
898 
899  //The verifier shall check that 0 < r < q
900  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
901  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
902  {
903  //If the condition is violated, the signature shall be rejected as invalid
905  }
906 
907  //The verifier shall check that 0 < s < q
908  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
909  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
910  {
911  //If the condition is violated, the signature shall be rejected as invalid
913  }
914 
915  //Get elliptic curve parameters
916  curve = publicKey->curve;
917 
918  //Get the length of the modulus, in words
919  modLen = (curve->fieldSize + 31) / 32;
920  //Get the length of the order, in words
921  orderLen = (curve->orderSize + 31) / 32;
922 
923  //Determine the length of the operands, in bytes
924  n = (curve->fieldSize + 7) / 8;
925  n = (n + 15U) & ~15U;
926 
927  //Check elliptic curve parameters
928  if(osStrcmp(curve->name, "secp256k1") == 0)
929  {
930  curveType = SCE_ECC_CURVE_TYPE_KOBLITZ;
931  oemCommand = SCE_OEM_CMD_ECC_SECP256K1_PUBLIC;
932  domainParams = DomainParam_Koblitz_secp256k1;
933  command = 0;
934  }
935  else if(osStrcmp(curve->name, "secp256r1") == 0)
936  {
937  curveType = SCE_ECC_CURVE_TYPE_NIST;
938  oemCommand = SCE_OEM_CMD_ECC_P256_PUBLIC;
939  domainParams = DomainParam_NIST_P256;
940  command = 0;
941  }
942  else if(osStrcmp(curve->name, "secp384r1") == 0)
943  {
944  curveType = SCE_ECC_CURVE_TYPE_NIST;
945  oemCommand = SCE_OEM_CMD_ECC_P384_PUBLIC;
946  domainParams = DomainParam_NIST_P384;
947  command = 0;
948  }
949  else if(osStrcmp(curve->name, "secp521r1") == 0)
950  {
951  curveType = SCE_ECC_CURVE_TYPE_NIST;
952  oemCommand = SCE_OEM_CMD_ECC_P521_PUBLIC;
953  domainParams = DomainParam_NIST_P521;
954  command = 0;
955  }
956  else if(osStrcmp(curve->name, "brainpoolP256r1") == 0)
957  {
958  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
959  oemCommand = SCE_OEM_CMD_ECC_P256R1_PUBLIC;
960  domainParams = DomainParam_Brainpool_256r1;
961  command = 0;
962  }
963  else if(osStrcmp(curve->name, "brainpoolP384r1") == 0)
964  {
965  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
966  oemCommand = SCE_OEM_CMD_ECC_P384R1_PUBLIC;
967  domainParams = DomainParam_Brainpool_384r1;
968  command = 0;
969  }
970  else if(osStrcmp(curve->name, "brainpoolP512r1") == 0)
971  {
972  curveType = SCE_ECC_CURVE_TYPE_BRAINPOOL;
973  oemCommand = SCE_OEM_CMD_ECC_P512R1_PUBLIC;
974  domainParams = DomainParam_Brainpool_512r1;
975  command = 0;
976  }
977  else
978  {
979  return ERROR_FAILURE;
980  }
981 
982  //Keep the leftmost bits of the hash value
983  digestLen = MIN(digestLen, (curve->orderSize + 7) / 8);
984 
985  //Acquire exclusive access to the RSIP module
987 
988  //Pad the digest with leading zeroes if necessary
989  osMemset(ecArgs.digest, 0, n);
990  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
991 
992  //Set public key
993  ecScalarExport(publicKey->q.x, modLen, (uint8_t *) ecArgs.q, n,
995 
996  ecScalarExport(publicKey->q.y, modLen, (uint8_t *) ecArgs.q + n, n,
998 
999  //Set signature
1000  ecScalarExport(signature->r, orderLen, (uint8_t *) ecArgs.signature, n,
1002 
1003  ecScalarExport(signature->s, orderLen, (uint8_t *) ecArgs.signature + n,
1005 
1006 #if (BSP_FEATURE_RSIP_RSIP_E51A_SUPPORTED == 1)
1007  //Just for sanity
1008  (void) oemCommand;
1009 
1010  //Verify ECDSA signature
1011  if(curve->fieldSize == 256)
1012  {
1013  status = HW_SCE_EcdsaSignatureVerificationSub(&curveType, &command,
1014  ecArgs.q, ecArgs.digest, ecArgs.signature, domainParams);
1015  }
1016  else if(curve->fieldSize == 384)
1017  {
1018  status = HW_SCE_EcdsaP384SignatureVerificationSub(&curveType, ecArgs.q,
1019  ecArgs.digest, ecArgs.signature, domainParams);
1020  }
1021  else if(curve->fieldSize == 512)
1022  {
1023  status = HW_SCE_EcdsaP512SignatureVerificationSub(ecArgs.q,
1024  ecArgs.digest, ecArgs.signature, domainParams);
1025  }
1026  else if(curve->fieldSize == 521)
1027  {
1028  status = HW_SCE_EcdsaP521SignatureVerificationSub(ecArgs.q,
1029  ecArgs.digest, ecArgs.signature, domainParams);
1030  }
1031  else
1032  {
1033  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1034  }
1035 #else
1036  //Install the plaintext public key and get the wrapped key
1037  status = HW_SCE_GenerateOemKeyIndexPrivate(SCE_OEM_KEY_TYPE_PLAIN,
1038  oemCommand, NULL, NULL, (uint8_t *) ecArgs.q, ecArgs.wrappedKey);
1039 
1040  //Check status code
1041  if(status == FSP_SUCCESS)
1042  {
1043  //Verify ECDSA signature
1044  if(curve->fieldSize == 256)
1045  {
1046  status = HW_SCE_EcdsaSignatureVerificationSub(&curveType, &command,
1047  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature, domainParams);
1048  }
1049  else if(curve->fieldSize == 384)
1050  {
1051  status = HW_SCE_EcdsaP384SignatureVerificationSub(&curveType,
1052  ecArgs.wrappedKey, ecArgs.digest, ecArgs.signature, domainParams);
1053  }
1054  else if(curve->fieldSize == 512)
1055  {
1056  status = HW_SCE_EcdsaP512SignatureVerificationSub(ecArgs.wrappedKey,
1057  ecArgs.digest, ecArgs.signature, domainParams);
1058  }
1059  else if(curve->fieldSize == 521)
1060  {
1061  status = HW_SCE_EcdsaP521SignatureVerificationSub(ecArgs.wrappedKey,
1062  ecArgs.digest, ecArgs.signature, domainParams);
1063  }
1064  else
1065  {
1066  status = FSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1067  }
1068  }
1069 #endif
1070 
1071  //Release exclusive access to the RSIP module
1073 
1074  //Return status code
1075  return (status == FSP_SUCCESS) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
1076 }
1077 
1078 #endif
1079 #endif
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
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:1035
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 q[40]
OsMutex ra8CryptoMutex
Definition: ra8_crypto.c:41
#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:49
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:1589
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
uint8_t h
Definition: ndp.h:302
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
uint32_t d[20]
#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:971
error_t
Error codes.
Definition: error.h:43
uint32_t g[40]
RSA primitive arguments.
uint32_t digest[20]
error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision addition.
Definition: mpi.c:893
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
Mpi q
Second factor.
Definition: rsa.h:73
Helper routines for ECC.
uint32_t c[128]
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
uint32_t m[128]
General definitions for cryptographic algorithms.
error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
RSA public-key cryptography standard.
EC private key.
Definition: ec.h:432
EC primitive arguments.
#define MIN(a, b)
Definition: os_port.h:63
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
uint32_t key[256]
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 wrappedKey[300]
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.
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
RA8 public-key hardware accelerator.
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:359
Mpi dp
First factor's CRT exponent.
Definition: rsa.h:74
error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (regular calculation)
RA8 hardware cryptographic accelerator (RSIP)
uint32_t signature[40]
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 ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
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.
uint32_t wrappedKey[100]
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
Debugging facilities.
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:216
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:65