s5d9_crypto_pkc.c
Go to the documentation of this file.
1 /**
2  * @file s5d9_crypto_pkc.c
3  * @brief Synergy S5D9 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_rsa_private.h"
37 #include "hw_sce_ecc_private.h"
38 #include "core/crypto.h"
41 #include "pkc/rsa.h"
42 #include "ecc/ec.h"
43 #include "ecc/ec_misc.h"
44 #include "ecc/ecdsa.h"
45 #include "debug.h"
46 
47 //Check crypto library configuration
48 #if (S5D9_CRYPTO_PKC_SUPPORT == ENABLED)
49 
50 //Global variables
51 static Ra6RsaArgs rsaArgs;
52 static Ra6EcArgs ecArgs;
53 
54 #if (MPI_SUPPORT == ENABLED)
55 
56 /**
57  * @brief Modular exponentiation (fast calculation)
58  * @param[out] r Resulting integer R = A ^ E mod P
59  * @param[in] a Pointer to a multiple precision integer
60  * @param[in] e Exponent
61  * @param[in] p Modulus
62  * @return Error code
63  **/
64 
65 error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
66 {
67  error_t error;
68  ssp_err_t status;
69  size_t n;
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  //The accelerator supports operand lengths up to 2048 bits
82  if((aLen <= 128 && eLen <= 4 && pLen <= 128) ||
83  (aLen <= 256 && eLen <= 4 && pLen <= 256))
84  {
85  //Select appropriate scalar length
86  n = (pLen <= 128) ? 128 : 256;
87 
88  //Acquire exclusive access to the SCE7 module
90 
91  //Format message representative
92  mpiWriteRaw(a, (uint8_t *) rsaArgs.m, n);
93 
94  //Format public key
95  mpiWriteRaw(p, (uint8_t *) rsaArgs.n, n);
96  mpiWriteRaw(e, (uint8_t *) rsaArgs.e, 4);
97 
98  //Perform RSA encryption
99  if(n == 128)
100  {
101  status = HW_SCE_RSA_1024PublicEncrypt(0, rsaArgs.m, rsaArgs.e,
102  rsaArgs.n, rsaArgs.c);
103  }
104  else if(n == 256)
105  {
106  status = HW_SCE_RSA_2048PublicEncrypt(0, rsaArgs.m, rsaArgs.e,
107  rsaArgs.n, rsaArgs.c);
108  }
109  else
110  {
111  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
112  }
113 
114  //Check status code
115  if(status == SSP_SUCCESS)
116  {
117  //Copy the ciphertext representative
118  error = mpiReadRaw(r, (uint8_t *) rsaArgs.c, n);
119  }
120  else
121  {
122  //Report an error
123  error = ERROR_FAILURE;
124  }
125 
126  //Release exclusive access to the SCE7 module
128  }
129  else
130  {
131  //Perform modular exponentiation (r = a ^ e mod p)
132  error = mpiExpModRegular(r, a, e, p);
133  }
134 
135  //Return status code
136  return error;
137 }
138 
139 
140 /**
141  * @brief Modular exponentiation (regular calculation)
142  * @param[out] r Resulting integer R = A ^ E mod P
143  * @param[in] a Pointer to a multiple precision integer
144  * @param[in] e Exponent
145  * @param[in] p Modulus
146  * @return Error code
147  **/
148 
149 error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
150 {
151  error_t error;
152  ssp_err_t status;
153  size_t n;
154  size_t aLen;
155  size_t eLen;
156  size_t pLen;
157 
158  //Get the length of the integer, in bytes
159  aLen = mpiGetByteLength(a);
160  //Get the length of the exponent, in bytes
161  eLen = mpiGetByteLength(e);
162  //Get the length of the modulus, in bytes
163  pLen = mpiGetByteLength(p);
164 
165  //The accelerator supports operand lengths up to 2048 bits
166  if((aLen <= 128 && eLen <= 128 && pLen <= 128) ||
167  (aLen <= 256 && eLen <= 256 && pLen <= 256))
168  {
169  //Select appropriate scalar length
170  n = (pLen <= 128) ? 128 : 256;
171 
172  //Acquire exclusive access to the SCE7 module
174 
175  //Format ciphertext representative
176  mpiWriteRaw(a, (uint8_t *) rsaArgs.c, n);
177 
178  //Format private key
179  mpiWriteRaw(p, (uint8_t *) rsaArgs.n, n);
180  mpiWriteRaw(e, (uint8_t *) rsaArgs.d, n);
181 
182  //Perform RSA decryption
183  if(n == 128)
184  {
185  status = HW_SCE_RSA_1024PrivateKeyDecrypt(0, rsaArgs.c, rsaArgs.d,
186  rsaArgs.n, rsaArgs.m);
187  }
188  else if(n == 256)
189  {
190  status = HW_SCE_RSA_2048PrivateKeyDecrypt(0, rsaArgs.c, rsaArgs.d,
191  rsaArgs.n, rsaArgs.m);
192  }
193  else
194  {
195  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
196  }
197 
198  //Check status code
199  if(status == SSP_SUCCESS)
200  {
201  //Copy the message representative
202  error = mpiReadRaw(r, (uint8_t *) rsaArgs.m, n);
203  }
204  else
205  {
206  //Report an error
207  error = ERROR_FAILURE;
208  }
209 
210  //Release exclusive access to the SCE7 module
212  }
213  else
214  {
215  //Perform modular exponentiation (r = a ^ e mod p)
216  error = mpiExpMod(r, a, e, p);
217  }
218 
219  //Return status code
220  return error;
221 }
222 
223 #endif
224 #if (RSA_SUPPORT == ENABLED)
225 
226 /**
227  * @brief RSA private key generation
228  * @param[in] prngAlgo PRNG algorithm
229  * @param[in] prngContext Pointer to the PRNG context
230  * @param[in] k Required bit length of the modulus n (must be 1024 or 2048)
231  * @param[in] e Public exponent (must be 65537)
232  * @param[out] privateKey RSA private key
233  * @return Error code
234  **/
235 
236 error_t rsaGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
237  size_t k, uint_t e, RsaPrivateKey *privateKey)
238 {
239  error_t error;
240  ssp_err_t status;
241  size_t n;
242 
243  //Check parameters
244  if(e != 65537 || privateKey == NULL)
246 
247  //Acquire exclusive access to the SCE7 module
249 
250  //Check the length of the modulus
251  if(k == 1024)
252  {
253  //Generate a 1024-bit RSA private key
254  status = HW_SCE_RSA_1024KeyGenerate(UINT32_MAX, rsaArgs.d, rsaArgs.n,
255  rsaArgs.params);
256  }
257  else if(k == 2048)
258  {
259  //Generate a 2048-bit RSA private key
260  status = HW_SCE_RSA_2048KeyGenerate(UINT32_MAX, rsaArgs.d, rsaArgs.n,
261  rsaArgs.params);
262  }
263  else
264  {
265  //Report an error
266  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
267  }
268 
269  //Check status code
270  if(status == SSP_SUCCESS)
271  {
272  //Compute the length of the modulus, in bytes
273  k = k / 8;
274  //Compute the length of the CRT factors, in bytes
275  n = k / 2;
276 
277  //The value of the public exponent is fixed to 65537
278  error = mpiSetValue(&privateKey->e, e);
279 
280  //Check status code
281  if(!error)
282  {
283  //Copy the private exponent
284  error = mpiReadRaw(&privateKey->d, (uint8_t *) rsaArgs.d, k);
285  }
286 
287  //Check status code
288  if(!error)
289  {
290  //Copy the modulus
291  error = mpiReadRaw(&privateKey->n, (uint8_t *) rsaArgs.n, k);
292  }
293 
294  //Check status code
295  if(!error)
296  {
297  //Copy the first factor
298  error = mpiReadRaw(&privateKey->p,
299  (uint8_t *) rsaArgs.params + n * 3, n);
300  }
301 
302  //Check status code
303  if(!error)
304  {
305  //Copy the second factor
306  error = mpiReadRaw(&privateKey->q,
307  (uint8_t *) rsaArgs.params + n, n);
308  }
309 
310  //Check status code
311  if(!error)
312  {
313  //Copy the first factor's CRT exponent
314  error = mpiReadRaw(&privateKey->dp,
315  (uint8_t *) rsaArgs.params + n * 2, n);
316  }
317 
318  //Check status code
319  if(!error)
320  {
321  //Copy the second factor's CRT exponent
322  error = mpiReadRaw(&privateKey->dq,
323  (uint8_t *) rsaArgs.params, n);
324  }
325 
326  //Check status code
327  if(!error)
328  {
329  //Copy the CRT coefficient
330  error = mpiReadRaw(&privateKey->qinv,
331  (uint8_t *) rsaArgs.params + n * 4, n);
332  }
333  }
334  else
335  {
336  //Report an error
337  error = ERROR_FAILURE;
338  }
339 
340  //Release exclusive access to the SCE7 module
342 
343  //Return status code
344  return error;
345 }
346 
347 
348 /**
349  * @brief RSA decryption primitive
350  *
351  * The RSA decryption primitive recovers the message representative from
352  * the ciphertext representative under the control of a private key
353  *
354  * @param[in] key RSA private key
355  * @param[in] c Ciphertext representative
356  * @param[out] m Message representative
357  * @return Error code
358  **/
359 
360 error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
361 {
362  error_t error;
363  size_t nLen;
364  size_t dLen;
365  size_t pLen;
366  size_t qLen;
367  size_t dpLen;
368  size_t dqLen;
369  size_t qinvLen;
370 
371  //Get the length of the private key
372  nLen = mpiGetByteLength(&key->n);
373  dLen = mpiGetByteLength(&key->d);
374  pLen = mpiGetByteLength(&key->p);
375  qLen = mpiGetByteLength(&key->q);
376  dpLen = mpiGetByteLength(&key->dp);
377  dqLen = mpiGetByteLength(&key->dq);
378  qinvLen = mpiGetByteLength(&key->qinv);
379 
380  //Sanity check
381  if(nLen == 0)
383 
384  //The ciphertext representative c shall be between 0 and n - 1
385  if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0)
386  return ERROR_OUT_OF_RANGE;
387 
388  //Check the length of the private key
389  if(nLen <= 128 && dLen <= 128)
390  {
391  //Let m = c ^ d mod n
392  error = mpiExpModRegular(m, c, &key->d, &key->n);
393  }
394  else if(nLen > 0 && pLen > 0 && qLen > 0 && dpLen > 0 && dqLen > 0 &&
395  qinvLen > 0)
396  {
397  Mpi m1;
398  Mpi m2;
399  Mpi h;
400 
401  //Initialize multiple-precision integers
402  mpiInit(&m1);
403  mpiInit(&m2);
404  mpiInit(&h);
405 
406  //Compute m1 = c ^ dP mod p
407  error = mpiMod(&m1, c, &key->p);
408 
409  if(!error)
410  {
411  error = mpiExpModRegular(&m1, &m1, &key->dp, &key->p);
412  }
413 
414  //Compute m2 = c ^ dQ mod q
415  if(!error)
416  {
417  error = mpiMod(&m2, c, &key->q);
418  }
419 
420  if(!error)
421  {
422  error = mpiExpModRegular(&m2, &m2, &key->dq, &key->q);
423  }
424 
425  //Let h = (m1 - m2) * qInv mod p
426  if(!error)
427  {
428  error = mpiSub(&h, &m1, &m2);
429  }
430 
431  if(!error)
432  {
433  error = mpiMulMod(&h, &h, &key->qinv, &key->p);
434  }
435 
436  //Let m = m2 + q * h
437  if(!error)
438  {
439  error = mpiMul(m, &key->q, &h);
440  }
441 
442  if(!error)
443  {
444  error = mpiAdd(m, m, &m2);
445  }
446 
447  //Free previously allocated memory
448  mpiFree(&m1);
449  mpiFree(&m2);
450  mpiFree(&h);
451  }
452  else if(nLen > 0 && dLen > 0)
453  {
454  //Let m = c ^ d mod n
455  error = mpiExpModRegular(m, c, &key->d, &key->n);
456  }
457  else
458  {
459  //Report an error
460  error = ERROR_INVALID_PARAMETER;
461  }
462 
463  //Return status code
464  return error;
465 }
466 
467 #endif
468 #if (EC_SUPPORT == ENABLED)
469 
470 /**
471  * @brief EC key pair generation
472  * @param[in] prngAlgo PRNG algorithm
473  * @param[in] prngContext Pointer to the PRNG context
474  * @param[in] curve Elliptic curve parameters
475  * @param[out] privateKey EC private key
476  * @param[out] publicKey EC public key (optional parameter)
477  * @return Error code
478  **/
479 
480 error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext,
481  const EcCurve *curve, EcPrivateKey *privateKey, EcPublicKey *publicKey)
482 {
483  error_t error;
484  ssp_err_t status;
485  size_t n;
486  size_t modLen;
487 
488  //Get the length of the modulus, in bytes
489  modLen = (curve->fieldSize + 7) / 8;
490 
491  //Compute the length of the scalar
492  if(modLen <= 24)
493  {
494  n = 24;
495  }
496  else if(modLen <= 28)
497  {
498  n = 28;
499  }
500  else if(modLen <= 32)
501  {
502  n = 32;
503  }
504  else if(modLen <= 48)
505  {
506  n = 48;
507  }
508  else
509  {
510  return ERROR_FAILURE;
511  }
512 
513  //Acquire exclusive access to the SCE7 module
515 
516  //Set domain parameters
517  ecScalarExport(curve->a, n / 4, (uint8_t *) ecArgs.params, n,
519 
520  ecScalarExport(curve->b, n / 4, (uint8_t *) ecArgs.params + n, n,
522 
523  ecScalarExport(curve->p, n / 4, (uint8_t *) ecArgs.params + n * 2, n,
525 
526  ecScalarExport(curve->q, n / 4, (uint8_t *) ecArgs.params + n * 3, n,
528 
529  //Set base point
530  ecScalarExport(curve->g.x, n / 4, (uint8_t *) ecArgs.g, n,
532 
533  ecScalarExport(curve->g.y, n / 4, (uint8_t *) ecArgs.g + n, n,
535 
536  //Generate an EC key pair
537  if(n == 24)
538  {
539  status = HW_SCE_ECC_192GenerateKey(ecArgs.params, ecArgs.g, ecArgs.d,
540  ecArgs.q);
541  }
542  else if(n == 28)
543  {
544  status = HW_SCE_ECC_224GenerateKey(ecArgs.params, ecArgs.g, ecArgs.d,
545  ecArgs.q);
546  }
547  else if(n == 32)
548  {
549  status = HW_SCE_ECC_256GenerateKey(ecArgs.params, ecArgs.g, ecArgs.d,
550  ecArgs.q);
551  }
552  else if(n == 48)
553  {
554  status = HW_SCE_ECC_384GenerateKey(ecArgs.params, ecArgs.g, ecArgs.d,
555  ecArgs.q);
556  }
557  else
558  {
559  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
560  }
561 
562  //Check status code
563  if(status == SSP_SUCCESS)
564  {
565  //Save elliptic curve parameters
566  privateKey->curve = curve;
567  privateKey->q.curve = curve;
568 
569  //Copy the private key
570  error = ecScalarImport(privateKey->d, EC_MAX_ORDER_SIZE,
571  (uint8_t *) ecArgs.d, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
572 
573  //Check status code
574  if(!error)
575  {
576  //Copy the x-coordinate of the public key
577  error = ecScalarImport(privateKey->q.q.x, EC_MAX_MODULUS_SIZE,
578  (uint8_t *) ecArgs.q, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
579  }
580 
581  //Check status code
582  if(!error)
583  {
584  //Copy the y-coordinate of the public key
585  error = ecScalarImport(privateKey->q.q.y, EC_MAX_MODULUS_SIZE,
586  (uint8_t *) ecArgs.q + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
587  }
588  }
589  else
590  {
591  //Report an error
592  error = ERROR_FAILURE;
593  }
594 
595  //Release exclusive access to the SCE7 module
597 
598  //Check status code
599  if(!error)
600  {
601  //The parameter is optional
602  if(publicKey != NULL)
603  {
604  //Copy the resulting public key
605  *publicKey = privateKey->q;
606  }
607  }
608 
609  //Return status code
610  return error;
611 }
612 
613 
614 /**
615  * @brief Scalar multiplication (fast calculation)
616  * @param[in] curve Elliptic curve parameters
617  * @param[out] r Resulting point R = d.S
618  * @param[in] d An integer d such as 0 <= d < p
619  * @param[in] s EC point
620  * @return Error code
621  **/
622 
623 error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
624  const EcPoint3 *s)
625 {
626  //Compute R = d.S
627  return ecMulRegular(curve, r, d, s);
628 }
629 
630 
631 /**
632  * @brief Scalar multiplication (regular calculation)
633  * @param[in] curve Elliptic curve parameters
634  * @param[out] r Resulting point R = d.S
635  * @param[in] d An integer d such as 0 <= d < q
636  * @param[in] s EC point
637  * @return Error code
638  **/
639 
640 error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d,
641  const EcPoint3 *s)
642 {
643  error_t error;
644  ssp_err_t status;
645  size_t n;
646  size_t modLen;
647 
648  //Get the length of the modulus, in bytes
649  modLen = (curve->fieldSize + 7) / 8;
650 
651  //Compute the length of the scalar
652  if(modLen <= 24)
653  {
654  n = 24;
655  }
656  else if(modLen <= 28)
657  {
658  n = 28;
659  }
660  else if(modLen <= 32)
661  {
662  n = 32;
663  }
664  else if(modLen <= 48)
665  {
666  n = 48;
667  }
668  else
669  {
670  return ERROR_FAILURE;
671  }
672 
673  //Acquire exclusive access to the SCE7 module
675 
676  //Set domain parameters
677  ecScalarExport(curve->a, n / 4, (uint8_t *) ecArgs.params, n,
679 
680  ecScalarExport(curve->b, n / 4, (uint8_t *) ecArgs.params + n, n,
682 
683  ecScalarExport(curve->p, n / 4, (uint8_t *) ecArgs.params + n * 2, n,
685 
686  ecScalarExport(curve->q, n / 4, (uint8_t *) ecArgs.params + n * 3, n,
688 
689  //Set scalar value
690  ecScalarExport(d, n / 4, (uint8_t *) ecArgs.d, n,
692 
693  //Set input point
694  ecScalarExport(s->x, n / 4, (uint8_t *) ecArgs.g, n,
696 
697  ecScalarExport(s->y, n / 4, (uint8_t *) ecArgs.g + n, n,
699 
700  //Perform scalar multiplication
701  if(n == 24)
702  {
703  status = HW_SCE_ECC_192ScalarMultiplication(ecArgs.params, ecArgs.d,
704  ecArgs.g, ecArgs.q);
705  }
706  else if(n == 28)
707  {
708  status = HW_SCE_ECC_224ScalarMultiplication(ecArgs.params, ecArgs.d,
709  ecArgs.g, ecArgs.q);
710  }
711  else if(n == 32)
712  {
713  status = HW_SCE_ECC_256ScalarMultiplication(ecArgs.params, ecArgs.d,
714  ecArgs.g, ecArgs.q);
715  }
716  else if(n == 48)
717  {
718  status = HW_SCE_ECC_384ScalarMultiplication(ecArgs.params, ecArgs.d,
719  ecArgs.g, ecArgs.q);
720  }
721  else
722  {
723  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
724  }
725 
726  //Check status code
727  if(status == SSP_SUCCESS)
728  {
729  //Copy the x-coordinate of the result
730  error = ecScalarImport(r->x, EC_MAX_MODULUS_SIZE, (uint8_t *) ecArgs.q,
732 
733  //Check status code
734  if(!error)
735  {
736  //Copy the y-coordinate of the result
738  (uint8_t *) ecArgs.q + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
739  }
740 
741  //Check status code
742  if(!error)
743  {
744  //Set the z-coordinate of the result
746  }
747  }
748  else
749  {
750  //Report an error
751  error = ERROR_FAILURE;
752  }
753 
754  //Release exclusive access to the SCE7 module
756 
757  //Return status code
758  return error;
759 }
760 
761 #endif
762 #if (ECDSA_SUPPORT == ENABLED)
763 
764 /**
765  * @brief ECDSA signature generation
766  * @param[in] prngAlgo PRNG algorithm
767  * @param[in] prngContext Pointer to the PRNG context
768  * @param[in] privateKey Signer's EC private key
769  * @param[in] digest Digest of the message to be signed
770  * @param[in] digestLen Length in octets of the digest
771  * @param[out] signature (R, S) integer pair
772  * @return Error code
773  **/
774 
775 error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext,
776  const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen,
777  EcdsaSignature *signature)
778 {
779  error_t error;
780  ssp_err_t status;
781  size_t n;
782  size_t orderLen;
783  size_t modLen;
784  const EcCurve *curve;
785 
786  //Check parameters
787  if(privateKey == NULL || digest == NULL || signature == NULL)
789 
790  //Invalid elliptic curve?
791  if(privateKey->curve == NULL)
793 
794  //Get elliptic curve parameters
795  curve = privateKey->curve;
796 
797  //Get the length of the modulus, in bytes
798  modLen = (curve->fieldSize + 7) / 8;
799  //Get the length of the order, in bytes
800  orderLen = (curve->orderSize + 7) / 8;
801 
802  //Check elliptic curve parameters
803  if(modLen <= 24)
804  {
805  n = 24;
806  }
807  else if(modLen <= 28)
808  {
809  n = 28;
810  }
811  else if(modLen <= 32)
812  {
813  n = 32;
814  }
815  else if(modLen <= 48)
816  {
817  n = 48;
818  }
819  else
820  {
821  return ERROR_FAILURE;
822  }
823 
824  //Keep the leftmost bits of the hash value
825  digestLen = MIN(digestLen, orderLen);
826 
827  //Acquire exclusive access to the SCE7 module
829 
830  //Pad the digest with leading zeroes if necessary
831  osMemset(ecArgs.digest, 0, n);
832  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
833 
834  //Set domain parameters
835  ecScalarExport(curve->a, n / 4, (uint8_t *) ecArgs.params, n,
837 
838  ecScalarExport(curve->b, n / 4, (uint8_t *) ecArgs.params + n, n,
840 
841  ecScalarExport(curve->p, n / 4, (uint8_t *) ecArgs.params + n * 2, n,
843 
844  ecScalarExport(curve->q, n / 4, (uint8_t *) ecArgs.params + n * 3, n,
846 
847  //Set base point
848  ecScalarExport(curve->g.x, n / 4, (uint8_t *) ecArgs.g, n,
850 
851  ecScalarExport(curve->g.y, n / 4, (uint8_t *) ecArgs.g + n, n,
853 
854  //Set private key
855  ecScalarExport(privateKey->d, n / 4, (uint8_t *) ecArgs.d, n,
857 
858  //Generate ECDSA signature
859  if(n == 24)
860  {
861  status = HW_SCE_ECC_192GenerateSign(ecArgs.params, ecArgs.g, ecArgs.d,
862  ecArgs.digest, ecArgs.r, ecArgs.s);
863  }
864  else if(n == 28)
865  {
866  status = HW_SCE_ECC_224GenerateSign(ecArgs.params, ecArgs.g, ecArgs.d,
867  ecArgs.digest, ecArgs.r, ecArgs.s);
868  }
869  else if(n == 32)
870  {
871  status = HW_SCE_ECC_256GenerateSign(ecArgs.params, ecArgs.g, ecArgs.d,
872  ecArgs.digest, ecArgs.r, ecArgs.s);
873  }
874  else if(n == 48)
875  {
876  status = HW_SCE_ECC_384GenerateSign(ecArgs.params, ecArgs.g, ecArgs.d,
877  ecArgs.digest, ecArgs.r, ecArgs.s);
878  }
879  else
880  {
881  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
882  }
883 
884  //Check status code
885  if(status == SSP_SUCCESS)
886  {
887  //Save elliptic curve parameters
888  signature->curve = curve;
889 
890  //Copy integer R
891  error = ecScalarImport(signature->r, EC_MAX_ORDER_SIZE,
892  (uint8_t *) ecArgs.r, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
893 
894  //Check status code
895  if(!error)
896  {
897  //Copy integer S
898  error = ecScalarImport(signature->s, EC_MAX_ORDER_SIZE,
899  (uint8_t *) ecArgs.s, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
900  }
901  }
902  else
903  {
904  //Report an error
905  error = ERROR_FAILURE;
906  }
907 
908  //Release exclusive access to the SCE7 module
910 
911  //Return status code
912  return error;
913 }
914 
915 
916 /**
917  * @brief ECDSA signature verification
918  * @param[in] publicKey Signer's EC public key
919  * @param[in] digest Digest of the message whose signature is to be verified
920  * @param[in] digestLen Length in octets of the digest
921  * @param[in] signature (R, S) integer pair
922  * @return Error code
923  **/
924 
926  const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
927 {
928  ssp_err_t status;
929  size_t n;
930  size_t orderLen;
931  size_t modLen;
932  const EcCurve *curve;
933 
934  //Check parameters
935  if(publicKey == NULL || digest == NULL || signature == NULL)
937 
938  //Invalid elliptic curve?
939  if(publicKey->curve == NULL)
941 
942  //Verify that the public key is on the curve
943  if(!ecIsPointAffine(publicKey->curve, &publicKey->q))
944  {
946  }
947 
948  //The verifier shall check that 0 < r < q
949  if(ecScalarCompInt(signature->r, 0, EC_MAX_ORDER_SIZE) <= 0 ||
950  ecScalarComp(signature->r, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
951  {
952  //If the condition is violated, the signature shall be rejected as invalid
954  }
955 
956  //The verifier shall check that 0 < s < q
957  if(ecScalarCompInt(signature->s, 0, EC_MAX_ORDER_SIZE) <= 0 ||
958  ecScalarComp(signature->s, publicKey->curve->q, EC_MAX_ORDER_SIZE) >= 0)
959  {
960  //If the condition is violated, the signature shall be rejected as invalid
962  }
963 
964  //Get elliptic curve parameters
965  curve = publicKey->curve;
966 
967  //Get the length of the modulus, in bytes
968  modLen = (curve->fieldSize + 7) / 8;
969  //Get the length of the order, in bytes
970  orderLen = (curve->orderSize + 7) / 8;
971 
972  //Check elliptic curve parameters
973  if(modLen <= 24)
974  {
975  n = 24;
976  }
977  else if(modLen <= 28)
978  {
979  n = 28;
980  }
981  else if(modLen <= 32)
982  {
983  n = 32;
984  }
985  else if(modLen <= 48)
986  {
987  n = 48;
988  }
989  else
990  {
991  return ERROR_FAILURE;
992  }
993 
994  //Keep the leftmost bits of the hash value
995  digestLen = MIN(digestLen, orderLen);
996 
997  //Acquire exclusive access to the SCE7 module
999 
1000  //Pad the digest with leading zeroes if necessary
1001  osMemset(ecArgs.digest, 0, n);
1002  osMemcpy((uint8_t *) ecArgs.digest + n - digestLen, digest, digestLen);
1003 
1004  //Set domain parameters
1005  ecScalarExport(curve->a, n / 4, (uint8_t *) ecArgs.params, n,
1007 
1008  ecScalarExport(curve->b, n / 4, (uint8_t *) ecArgs.params + n, n,
1010 
1011  ecScalarExport(curve->p, n / 4, (uint8_t *) ecArgs.params + n * 2, n,
1013 
1014  ecScalarExport(curve->q, n / 4, (uint8_t *) ecArgs.params + n * 3, n,
1016 
1017  //Set base point
1018  ecScalarExport(curve->g.x, n / 4, (uint8_t *) ecArgs.g, n,
1020 
1021  ecScalarExport(curve->g.y, n / 4, (uint8_t *) ecArgs.g + n, n,
1023 
1024  //Set public key
1025  ecScalarExport(publicKey->q.x, n / 4, (uint8_t *) ecArgs.q, n,
1027 
1028  ecScalarExport(publicKey->q.y, n / 4, (uint8_t *) ecArgs.q + n, n,
1030 
1031  //Set signature
1032  ecScalarExport(signature->r, n / 4, (uint8_t *) ecArgs.r, n,
1034 
1035  ecScalarExport(signature->s, n / 4, (uint8_t *) ecArgs.s, n,
1037 
1038  //Verify ECDSA signature
1039  if(n == 24)
1040  {
1041  status = HW_SCE_ECC_192VerifySign(ecArgs.params, ecArgs.g, ecArgs.q,
1042  ecArgs.digest, ecArgs.r, ecArgs.s);
1043  }
1044  else if(n == 28)
1045  {
1046  status = HW_SCE_ECC_224VerifySign(ecArgs.params, ecArgs.g, ecArgs.q,
1047  ecArgs.digest, ecArgs.r, ecArgs.s);
1048  }
1049  else if(n == 32)
1050  {
1051  status = HW_SCE_ECC_256VerifySign(ecArgs.params, ecArgs.g, ecArgs.q,
1052  ecArgs.digest, ecArgs.r, ecArgs.s);
1053  }
1054  else if(n == 48)
1055  {
1056  status = HW_SCE_ECC_384VerifySign(ecArgs.params, ecArgs.g, ecArgs.q,
1057  ecArgs.digest, ecArgs.r, ecArgs.s);
1058  }
1059  else
1060  {
1061  status = SSP_ERR_CRYPTO_NOT_IMPLEMENTED;
1062  }
1063 
1064  //Release exclusive access to the SCE7 module
1066 
1067  //Return status code
1068  return (status == SSP_SUCCESS) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
1069 }
1070 
1071 #endif
1072 #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_OUT_OF_RANGE
Definition: error.h:138
uint32_t digest[12]
uint32_t n[64]
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
uint32_t params[48]
uint32_t params[160]
error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
error_t rsaGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, size_t k, uint_t e, RsaPrivateKey *privateKey)
RSA private key generation.
Mpi n
Modulus.
Definition: rsa.h:69
error_t ecdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const EcPrivateKey *privateKey, const uint8_t *digest, size_t digestLen, EcdsaSignature *signature)
ECDSA signature generation.
#define mpiWriteRaw(a, data, length)
Definition: crypto_legacy.h:36
uint32_t d[64]
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
uint32_t e[1]
error_t mpiExpModFast(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (fast calculation)
uint32_t r[12]
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
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
uint32_t s[12]
error_t
Error codes.
Definition: error.h:43
error_t mpiSetValue(Mpi *r, mpi_sword_t a)
Set the value of a multiple precision integer.
Definition: mpi.c:562
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.
Synergy S5D9 public-key hardware accelerator.
uint32_t r[EC_MAX_ORDER_SIZE]
Integer R.
Definition: ecdsa.h:65
General definitions for cryptographic algorithms.
RSA public-key cryptography standard.
EcPublicKey q
Public key.
Definition: ec.h:436
EC primitive arguments.
EC private key.
Definition: ec.h:432
uint32_t g[24]
error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EcPrivateKey *privateKey, EcPublicKey *publicKey)
EC key pair generation.
Mpi e
Public exponent.
Definition: rsa.h:70
#define MIN(a, b)
Definition: os_port.h:63
uint32_t q[24]
Mpi qinv
CRT coefficient.
Definition: rsa.h:76
Mpi dq
Second factor's CRT exponent.
Definition: rsa.h:75
error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
EC public key.
Definition: ec.h:421
error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m)
RSA decryption primitive.
__weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:798
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
int_t ecScalarCompInt(const uint32_t *a, uint32_t b, uint_t n)
Compare integers.
Definition: ec_misc.c:374
uint8_t m
Definition: ndp.h:304
uint8_t n
RSA private key.
Definition: rsa.h:68
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
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
error_t ecdsaVerifySignature(const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, const EcdsaSignature *signature)
ECDSA signature verification.
uint8_t s
Definition: igmp_common.h:234
#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
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]
unsigned int uint_t
Definition: compiler_port.h:57
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.
OsMutex s5d9CryptoMutex
Definition: s5d9_crypto.c:41
ECC (Elliptic Curve Cryptography)
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
error_t mpiExpModRegular(Mpi *r, const Mpi *a, const Mpi *e, const Mpi *p)
Modular exponentiation (regular calculation)
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.
Synergy S5D9 hardware cryptographic accelerator (SCE7)
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