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