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