ec.c
Go to the documentation of this file.
1 /**
2  * @file ec.c
3  * @brief ECC (Elliptic Curve Cryptography)
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 "core/crypto.h"
36 #include "ecc/ec.h"
37 #include "ecc/ec_misc.h"
38 #include "debug.h"
39 
40 //Check crypto library configuration
41 #if (EC_SUPPORT == ENABLED)
42 
43 //EC Public Key OID (1.2.840.10045.2.1)
44 const uint8_t EC_PUBLIC_KEY_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
45 
46 
47 /**
48  * @brief Initialize an EC public key
49  * @param[in] key Pointer to the EC public key to initialize
50  **/
51 
53 {
54  //Initialize elliptic curve parameters
55  key->curve = NULL;
56 
57  //Initialize public key
60 }
61 
62 
63 /**
64  * @brief Release an EC public key
65  * @param[in] key Pointer to the EC public key to free
66  **/
67 
69 {
70  //Clear public key
71  osMemset(key, 0, sizeof(EcPublicKey));
72 }
73 
74 
75 /**
76  * @brief Initialize an EC private key
77  * @param[in] key Pointer to the EC private key to initialize
78  **/
79 
81 {
82  //Initialize elliptic curve parameters
83  key->curve = NULL;
84 
85  //Initialize private key
87  //Initialize private key slot
88  key->slot = -1;
89 
90  //Initialize public key
91  ecInitPublicKey(&key->q);
92 }
93 
94 
95 /**
96  * @brief Release an EC private key
97  * @param[in] key Pointer to the EC public key to free
98  **/
99 
101 {
102  //Clear private key
103  osMemset(key, 0, sizeof(EcPrivateKey));
104 }
105 
106 
107 /**
108  * @brief EC key pair generation
109  * @param[in] prngAlgo PRNG algorithm
110  * @param[in] prngContext Pointer to the PRNG context
111  * @param[in] curve Elliptic curve parameters
112  * @param[out] privateKey EC private key
113  * @param[out] publicKey EC public key (optional parameter)
114  * @return Error code
115  **/
116 
117 __weak_func error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo,
118  void *prngContext, const EcCurve *curve, EcPrivateKey *privateKey,
119  EcPublicKey *publicKey)
120 {
121  error_t error;
122 
123  //Generate a private key
124  error = ecGeneratePrivateKey(prngAlgo, prngContext, curve, privateKey);
125 
126  //Check status code
127  if(!error)
128  {
129  //Derive the public key from the private key
130  error = ecGeneratePublicKey(privateKey, &privateKey->q);
131  }
132 
133  //Check status code
134  if(!error)
135  {
136  //The parameter is optional
137  if(publicKey != NULL)
138  {
139  //Copy the resulting public key
140  *publicKey = privateKey->q;
141  }
142  }
143 
144  //Return status code
145  return error;
146 }
147 
148 
149 /**
150  * @brief EC private key generation
151  * @param[in] prngAlgo PRNG algorithm
152  * @param[in] prngContext Pointer to the PRNG context
153  * @param[in] curve Elliptic curve parameters
154  * @param[out] privateKey EC private key
155  * @return Error code
156  **/
157 
158 error_t ecGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
159  const EcCurve *curve, EcPrivateKey *privateKey)
160 {
161  error_t error;
162 
163  //Check parameters
164  if(prngAlgo == NULL || prngContext == NULL || curve == NULL ||
165  privateKey == NULL)
166  {
168  }
169 
170  //Save elliptic curve parameters
171  privateKey->curve = curve;
172 
173  //Initialize private key
174  ecScalarSetInt(privateKey->d, 0, EC_MAX_ORDER_SIZE);
175  //Initialize public key
176  ecInitPublicKey(&privateKey->q);
177 
178  //Generate a random number d such as 0 < d < q - 1
179  error = ecScalarRand(curve, privateKey->d, prngAlgo, prngContext);
180  //Any error to report?
181  if(error)
182  return error;
183 
184  //Debug message
185  TRACE_DEBUG(" Private key:\r\n");
186  TRACE_DEBUG_EC_SCALAR(" ", privateKey->d, (curve->orderSize + 31) / 32);
187 
188  //Successful processing
189  return NO_ERROR;
190 }
191 
192 
193 /**
194  * @brief Derive the public key from an EC private key
195  * @param[in] privateKey EC private key
196  * @param[out] publicKey EC public key
197  * @return Error code
198  **/
199 
201  EcPublicKey *publicKey)
202 {
203  error_t error;
204  uint_t pLen;
205  EcPoint3 q;
206 
207  //Check parameters
208  if(privateKey == NULL || publicKey == NULL)
210 
211  //Invalid elliptic curve?
212  if(privateKey->curve == NULL)
214 
215  //Get the length of the modulus, in words
216  pLen = (privateKey->curve->fieldSize + 31) / 32;
217 
218  //Save elliptic curve parameters
219  publicKey->curve = privateKey->curve;
220 
221  //Initialize EC public key
222  ecScalarSetInt(publicKey->q.x, 0, EC_MAX_MODULUS_SIZE);
223  ecScalarSetInt(publicKey->q.y, 0, EC_MAX_MODULUS_SIZE);
224 
225  //Compute Q = d.G
226  error = ecMulRegular(publicKey->curve, &q, privateKey->d,
227  &publicKey->curve->g);
228  //Any error to report?
229  if(error)
230  return error;
231 
232  //Convert the public key to affine representation
233  error = ecAffinify(publicKey->curve, &q, &q);
234  //Any error to report?
235  if(error)
236  return error;
237 
238  //Save the resulting EC public key
239  ecScalarCopy(publicKey->q.x, q.x, pLen);
240  ecScalarCopy(publicKey->q.y, q.y, pLen);
241 
242  //Debug message
243  TRACE_DEBUG(" Public key X:\r\n");
244  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.x, pLen);
245  TRACE_DEBUG(" Public key Y:\r\n");
246  TRACE_DEBUG_EC_SCALAR(" ", publicKey->q.y, pLen);
247 
248  //Successful processing
249  return NO_ERROR;
250 }
251 
252 
253 /**
254  * @brief Import an EC public key
255  * @param[out] key EC public key
256  * @param[in] curve Elliptic curve parameters
257  * @param[in] data Pointer to the octet string
258  * @param[in] length Length of the octet string, in bytes
259  * @param[in] format EC public key format (X9.63 or raw format)
260  * @return Error code
261  **/
262 
264  const uint8_t *data, size_t length, EcPublicKeyFormat format)
265 {
266  error_t error;
267  size_t n;
268 
269  //Check parameters
270  if(key != NULL && curve != NULL && data != NULL)
271  {
272  //Check curve type
273  if(curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
274  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
275  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
276  {
277  //Get the length of the modulus, in bytes
278  n = (curve->fieldSize + 7) / 8;
279 
280  //Check the format of the public key
281  if(format == EC_PUBLIC_KEY_FORMAT_X963)
282  {
283  //Read the public key
284  error = ecImportPoint(curve, &key->q, data, length);
285  }
286  else if(format == EC_PUBLIC_KEY_FORMAT_RAW)
287  {
288  //Check the length of the octet string
289  if(length == (n * 2))
290  {
291  //Convert the x-coordinate to an integer
292  error = ecScalarImport(key->q.x, EC_MAX_MODULUS_SIZE, data, n,
294 
295  //Check status code
296  if(!error)
297  {
298  //Convert the y-coordinate to an integer
299  error = ecScalarImport(key->q.y, EC_MAX_MODULUS_SIZE,
301  }
302  }
303  else
304  {
305  //The length of the octet string is not acceptable
306  error = ERROR_INVALID_LENGTH;
307  }
308  }
309  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_X)
310  {
311  //Convert the x-coordinate to an integer
314  }
315  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_Y)
316  {
317  //Convert the y-coordinate to an integer
320  }
321  else
322  {
323  //Invalid format
324  error = ERROR_INVALID_PARAMETER;
325  }
326  }
327  else if(curve->type == EC_CURVE_TYPE_MONTGOMERY)
328  {
329  //Check the length of the octet string
330  if(length == ((curve->fieldSize + 7) / 8))
331  {
332  //Clear unused coordinate
334 
335  //Convert the u-coordinate to an integer
338  }
339  else
340  {
341  //Report an error
342  error = ERROR_ILLEGAL_PARAMETER;
343  }
344  }
345  else
346  {
347  //Report an error
349  }
350 
351  //Check status code
352  if(!error)
353  {
354  //Save elliptic curve parameters
355  key->curve = curve;
356  }
357  }
358  else
359  {
360  //Report an error
361  error = ERROR_INVALID_PARAMETER;
362  }
363 
364  //Return status code
365  return error;
366 }
367 
368 
369 /**
370  * @brief Export an EC public key
371  * @param[in] key EC public key
372  * @param[out] data Pointer to the octet string
373  * @param[out] length Length of the octet string, in bytes
374  * @param[in] format EC public key format (X9.63 or raw format)
375  * @return Error code
376  **/
377 
379  size_t *length, EcPublicKeyFormat format)
380 {
381  error_t error;
382  size_t n;
383 
384  //Check parameters
385  if(key != NULL && data != NULL && length != NULL)
386  {
387  //Valid elliptic curve?
388  if(key->curve != NULL)
389  {
390  //Check curve type
391  if(key->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
392  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
393  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
394  {
395  //Get the length of the modulus, in bytes
396  n = (key->curve->fieldSize + 7) / 8;
397 
398  //Check the format of the public key
399  if(format == EC_PUBLIC_KEY_FORMAT_X963)
400  {
401  //Write the public key
402  error = ecExportPoint(key->curve, &key->q, data, &n);
403  }
404  else if(format == EC_PUBLIC_KEY_FORMAT_RAW)
405  {
406  //Convert the x-coordinate to an octet string
407  error = ecScalarExport(key->q.x, (n + 3) / 4, data, n,
409 
410  //Check status code
411  if(!error)
412  {
413  //Convert the y-coordinate to an octet string
414  error = ecScalarExport(key->q.y, (n + 3) / 4, data + n, n,
416  }
417 
418  //Check status code
419  if(!error)
420  {
421  //Length of the resulting octet string
422  n = 2 * n;
423  }
424  }
425  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_X)
426  {
427  //Convert the x-coordinate to an octet string
428  error = ecScalarExport(key->q.x, (n + 3) / 4, data, n,
430  }
431  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_Y)
432  {
433  //Convert the y-coordinate to an octet string
434  error = ecScalarExport(key->q.y, (n + 3) / 4, data, n,
436  }
437  else
438  {
439  //Invalid format
440  error = ERROR_INVALID_PARAMETER;
441  }
442  }
443  else if(key->curve->type == EC_CURVE_TYPE_MONTGOMERY)
444  {
445  //Get the length of the modulus, in bytes
446  n = (key->curve->fieldSize + 7) / 8;
447 
448  //Convert the u-coordinate to an octet string
449  error = ecScalarExport(key->q.x, (n + 3) / 4, data, n,
451  }
452  else
453  {
454  //Report an error
456  }
457  }
458  else
459  {
460  //Invalid elliptic curve
462  }
463 
464  //Check status code
465  if(!error)
466  {
467  //Return the length of the octet string
468  *length = n;
469  }
470  }
471  else
472  {
473  //Report an error
474  error = ERROR_INVALID_PARAMETER;
475  }
476 
477  //Return status code
478  return error;
479 }
480 
481 
482 /**
483  * @brief Import an EC private key
484  * @param[out] key EC private key
485  * @param[in] data Pointer to the octet string
486  * @param[in] length Length of the octet string, in bytes
487  * @return Error code
488  **/
489 
491  const uint8_t *data, size_t length)
492 {
493  error_t error;
494 
495  //Check parameters
496  if(key != NULL && curve != NULL && data != NULL)
497  {
498  //Check curve type
499  if(curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
500  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
501  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
502  {
503  //Read the private key
504  error = ecScalarImport(key->d, EC_MAX_ORDER_SIZE, data, length,
506  }
507  else if(curve->type == EC_CURVE_TYPE_MONTGOMERY)
508  {
509  //Check the length of the octet string
510  if(length == ((curve->orderSize + 7) / 8))
511  {
512  //Read the private key
513  error = ecScalarImport(key->d, EC_MAX_ORDER_SIZE, data, length,
515  }
516  else
517  {
518  //Report an error
519  error = ERROR_INVALID_KEY_LENGTH;
520  }
521  }
522  else
523  {
524  //Report an error
526  }
527 
528  //Check status code
529  if(!error)
530  {
531  //Save elliptic curve parameters
532  key->curve = curve;
533  }
534  }
535  else
536  {
537  //Report an error
538  error = ERROR_INVALID_PARAMETER;
539  }
540 
541  //Return status code
542  return error;
543 }
544 
545 
546 /**
547  * @brief Export an EC private key
548  * @param[in] key EC private key
549  * @param[out] data Pointer to the octet string
550  * @param[out] length Length of the octet string, in bytes
551  * @return Error code
552  **/
553 
555  size_t *length)
556 {
557  error_t error;
558  size_t n;
559 
560  //Check parameters
561  if(key != NULL && data != NULL && length != NULL)
562  {
563  //Valid elliptic curve?
564  if(key->curve != NULL)
565  {
566  //Check curve type
567  if(key->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
568  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
569  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
570  {
571  //Get the length of the order, in bytes
572  n = (key->curve->orderSize + 7) / 8;
573 
574  //Write the private key
575  error = ecScalarExport(key->d, (n + 3) / 4, data, n,
577  }
578  else if(key->curve->type == EC_CURVE_TYPE_MONTGOMERY)
579  {
580  //Get the length of the order, in bytes
581  n = (key->curve->orderSize + 7) / 8;
582 
583  //Write the private key
584  error = ecScalarExport(key->d, (n + 3) / 4, data, n,
586  }
587  else
588  {
589  //Report an error
591  }
592  }
593  else
594  {
595  //Invalid elliptic curve
597  }
598 
599  //Check status code
600  if(!error)
601  {
602  //Return the length of the octet string
603  *length = n;
604  }
605  }
606  else
607  {
608  //Invalid elliptic curve
609  error = ERROR_INVALID_PARAMETER;
610  }
611 
612  //Return status code
613  return error;
614 }
615 
616 
617 /**
618  * @brief Convert an octet string to an EC point
619  * @param[in] curve Elliptic curve parameters
620  * @param[out] r EC point resulting from the conversion
621  * @param[in] data Pointer to the octet string
622  * @param[in] length Length of the octet string
623  * @return Error code
624  **/
625 
626 error_t ecImportPoint(const EcCurve *curve, EcPoint *r, const uint8_t *data,
627  size_t length)
628 {
629  error_t error;
630  size_t n;
631 
632  //Check parameters
633  if(curve == NULL || r == NULL || data == NULL)
635 
636  //Get the length of the modulus, in bytes
637  n = (curve->fieldSize + 7) / 8;
638 
639  //Check the length of the octet string
640  if(length != (n * 2 + 1))
642 
643  //Compressed point representation is not supported
646 
647  //Convert the x-coordinate to an integer
648  error = ecScalarImport(r->x, EC_MAX_MODULUS_SIZE, data + 1, n,
650  //Any error to report?
651  if(error)
652  return error;
653 
654  //Convert the y-coordinate to an integer
655  error = ecScalarImport(r->y, EC_MAX_MODULUS_SIZE, data + n + 1, n,
657  //Any error to report?
658  if(error)
659  return error;
660 
661  //Successful processing
662  return NO_ERROR;
663 }
664 
665 
666 /**
667  * @brief Convert an EC point to an octet string
668  * @param[in] curve Elliptic curve parameters
669  * @param[in] a EC point to be converted
670  * @param[out] data Pointer to the octet string
671  * @param[out] length Length of the resulting octet string
672  * @return Error code
673  **/
674 
675 error_t ecExportPoint(const EcCurve *curve, const EcPoint *a, uint8_t *data,
676  size_t *length)
677 {
678  error_t error;
679  size_t n;
680 
681  //Check parameters
682  if(curve == NULL || a == NULL || data == NULL || length == NULL)
684 
685  //Get the length of the modulus, in bytes
686  n = (curve->fieldSize + 7) / 8;
687 
688  //Point compression is not used
690 
691  //Convert the x-coordinate to an octet string
692  error = ecScalarExport(a->x, (n + 3) / 4, data + 1, n,
694  //Conversion failed?
695  if(error)
696  return error;
697 
698  //Convert the y-coordinate to an octet string
699  error = ecScalarExport(a->y, (n + 3) / 4, data + n + 1, n,
701  //Conversion failed?
702  if(error)
703  return error;
704 
705  //Return the length of the octet string
706  *length = n * 2 + 1;
707 
708  //Successful processing
709  return NO_ERROR;
710 }
711 
712 
713 /**
714  * @brief Compute projective representation
715  * @param[in] curve Elliptic curve parameters
716  * @param[out] r Projective representation of the point
717  * @param[in] s Affine representation of the point
718  **/
719 
720 void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
721 {
722  uint_t i;
723  uint_t pLen;
724 
725  //Get the length of the modulus, in words
726  pLen = (curve->fieldSize + 31) / 32;
727 
728  //Copy x, y and z-coordinates
729  for(i = 0; i < pLen; i++)
730  {
731  r->x[i] = s->x[i];
732  r->y[i] = s->y[i];
733  r->z[i] = 0;
734  }
735 
736  //Map the point to projective space
737  r->z[0] = 1;
738 }
739 
740 
741 /**
742  * @brief Recover affine representation
743  * @param[in] curve Elliptic curve parameters
744  * @param[out] r Affine representation of the point
745  * @param[in] s Projective representation of the point
746  * @return Error code
747  **/
748 
749 __weak_func error_t ecAffinify(const EcCurve *curve, EcPoint3 *r,
750  const EcPoint3 *s)
751 {
752  error_t error;
753  uint_t pLen;
754  uint32_t a[EC_MAX_MODULUS_SIZE];
755  uint32_t b[EC_MAX_MODULUS_SIZE];
756 
757  //Get the length of the modulus, in words
758  pLen = (curve->fieldSize + 31) / 32;
759 
760  //Point at the infinity?
761  if(ecScalarTestEqualInt(s->z, 0, pLen))
762  {
763  //The point at the infinity has no affine representation
764  error = ERROR_INVALID_PARAMETER;
765  }
766  else
767  {
768  //Compute a = 1/Sz mod p
769  ecFieldInvMod(curve, a, s->z);
770 
771  //Set Rx = a^2 * Sx mod p
772  ecFieldSqrMod(curve, b, a);
773  ecFieldMulMod(curve, r->x, b, s->x);
774 
775  //Set Ry = a^3 * Sy mod p
776  ecFieldMulMod(curve, b, b, a);
777  ecFieldMulMod(curve, r->y, b, s->y);
778 
779  //Set Rz = 1
780  ecScalarSetInt(r->z, 1, pLen);
781 
782  //Successful processing
783  error = NO_ERROR;
784  }
785 
786  //Return status code
787  return error;
788 }
789 
790 
791 /**
792  * @brief Check whether the affine point S is on the curve
793  * @param[in] curve Elliptic curve parameters
794  * @param[in] s Affine representation of the point
795  * @return TRUE if the affine point S is on the curve, else FALSE
796  **/
797 
798 __weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
799 {
800  uint_t pLen;
801  bool_t valid;
802  uint32_t t1[EC_MAX_MODULUS_SIZE];
803  uint32_t t2[EC_MAX_MODULUS_SIZE];
804 
805  //Initialize flag
806  valid = FALSE;
807 
808  //Check parameters
809  if(curve != NULL && s != NULL)
810  {
811  //Verify that 0 <= Sx < p and 0 <= Sy < p
812  if(ecScalarComp(s->x, curve->p, EC_MAX_MODULUS_SIZE) < 0 &&
813  ecScalarComp(s->y, curve->p, EC_MAX_MODULUS_SIZE) < 0)
814  {
815  //Get the length of the modulus, in words
816  pLen = (curve->fieldSize + 31) / 32;
817 
818  //Compute t1 = (Sx^3 + a * Sx + b) mod p
819  ecFieldSqrMod(curve, t1, s->x);
820  ecFieldMulMod(curve, t1, t1, s->x);
821  ecFieldMulMod(curve, t2, curve->a, s->x);
822  ecFieldAddMod(curve, t1, t1, t2);
823  ecFieldAddMod(curve, t1, t1, curve->b);
824 
825  //Compute t2 = Sy^2
826  ecFieldSqrMod(curve, t2, s->y);
827 
828  //Check whether the point is on the elliptic curve
829  if(ecScalarComp(t1, t2, pLen) == 0)
830  {
831  valid = TRUE;
832  }
833  }
834  }
835 
836  //Return TRUE if the affine point S is on the curve
837  return valid;
838 }
839 
840 
841 /**
842  * @brief Point doubling
843  * @param[in] state Pointer to the working state
844  * @param[out] r Resulting point R = 2S
845  * @param[in] s Point S
846  **/
847 
848 void ecDouble(EcState *state, EcPoint3 *r, const EcPoint3 *s)
849 {
850  uint_t pLen;
851 
852  //Get the length of the modulus, in words
853  pLen = (state->curve->fieldSize + 31) / 32;
854 
855  //Set t1 = Sx
856  ecScalarCopy(state->t1, s->x, pLen);
857  //Set t2 = Sy
858  ecScalarCopy(state->t2, s->y, pLen);
859  //Set t3 = Sz
860  ecScalarCopy(state->t3, s->z, pLen);
861 
862  //Point at the infinity?
863  if(ecScalarTestEqualInt(state->t3, 0, pLen))
864  {
865  //Set R = (1, 1, 0)
866  ecScalarSetInt(r->x, 1, pLen);
867  ecScalarSetInt(r->y, 1, pLen);
868  ecScalarSetInt(r->z, 0, pLen);
869  }
870  else
871  {
872  //Check curve type
873  if(state->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0)
874  {
875  //Compute t5 = t1^2
876  ecFieldSqrMod(state->curve, state->t5, state->t1);
877  //Compute t4 = 3 * t5
878  ecFieldAddMod(state->curve, state->t4, state->t5, state->t5);
879  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
880  }
881  else if(state->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
882  {
883  //Compute t4 = t3^2
884  ecFieldSqrMod(state->curve, state->t4, state->t3);
885  //Compute t5 = t1 - t4
886  ecFieldSubMod(state->curve, state->t5, state->t1, state->t4);
887  //Compute t4 = t1 + t4
888  ecFieldAddMod(state->curve, state->t4, state->t1, state->t4);
889  //Compute t5 = t4 * t5
890  ecFieldMulMod(state->curve, state->t5, state->t4, state->t5);
891  //Compute t4 = 3 * t5
892  ecFieldAddMod(state->curve, state->t4, state->t5, state->t5);
893  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
894  }
895  else
896  {
897  //Compute t4 = t3^4
898  ecFieldSqrMod(state->curve, state->t4, state->t3);
899  ecFieldSqrMod(state->curve, state->t4, state->t4);
900  //Compute t4 = a * t4
901  ecFieldMulMod(state->curve, state->t4, state->t4, state->curve->a);
902  //Compute t5 = t1^2
903  ecFieldSqrMod(state->curve, state->t5, state->t1);
904  //Compute t4 = t4 + 3 * t5
905  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
906  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
907  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
908  }
909 
910  //Compute t3 = t3 * t2
911  ecFieldMulMod(state->curve, state->t3, state->t3, state->t2);
912  //Compute t3 = 2 * t3
913  ecFieldAddMod(state->curve, state->t3, state->t3, state->t3);
914  //Compute t2 = t2^2
915  ecFieldSqrMod(state->curve, state->t2, state->t2);
916  //Compute t5 = t1 * t2
917  ecFieldMulMod(state->curve, state->t5, state->t1, state->t2);
918  //Compute t5 = 4 * t5
919  ecFieldAddMod(state->curve, state->t5, state->t5, state->t5);
920  ecFieldAddMod(state->curve, state->t5, state->t5, state->t5);
921  //Compute t1 = t4^2
922  ecFieldSqrMod(state->curve, state->t1, state->t4);
923  //Compute t1 = t1 - 2 * t5
924  ecFieldSubMod(state->curve, state->t1, state->t1, state->t5);
925  ecFieldSubMod(state->curve, state->t1, state->t1, state->t5);
926  //Compute t2 = t2^2
927  ecFieldSqrMod(state->curve, state->t2, state->t2);
928  //Compute t2 = 8 * t2
929  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
930  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
931  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
932  //Compute t5 = t5 - t1
933  ecFieldSubMod(state->curve, state->t5, state->t5, state->t1);
934  //Compute t5 = t4 * t5
935  ecFieldMulMod(state->curve, state->t5, state->t4, state->t5);
936  //Compute t2 = t5 - t2
937  ecFieldSubMod(state->curve, state->t2, state->t5, state->t2);
938 
939  //Set Rx = t1
940  ecScalarCopy(r->x, state->t1, pLen);
941  //Set Ry = t2
942  ecScalarCopy(r->y, state->t2, pLen);
943  //Set Rz = t3
944  ecScalarCopy(r->z, state->t3, pLen);
945  }
946 }
947 
948 
949 /**
950  * @brief Point addition (helper routine)
951  * @param[in] state Pointer to the working state
952  * @param[out] r Resulting point R = S + T
953  * @param[in] s First operand
954  * @param[in] t Second operand
955  **/
956 
957 void ecAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s,
958  const EcPoint3 *t)
959 {
960  uint_t pLen;
961  uint32_t c;
962 
963  //Get the length of the modulus, in words
964  pLen = (state->curve->fieldSize + 31) / 32;
965 
966  //Set t1 = Sx
967  ecScalarCopy(state->t1, s->x, pLen);
968  //Set t2 = Sy
969  ecScalarCopy(state->t2, s->y, pLen);
970  //Set t3 = Sz
971  ecScalarCopy(state->t3, s->z, pLen);
972  //Set t4 = Tx
973  ecScalarCopy(state->t4, t->x, pLen);
974  //Set t5 = Ty
975  ecScalarCopy(state->t5, t->y, pLen);
976 
977  //Check whether Tz != 1
978  if(ecScalarTestNotEqualInt(t->z, 1, pLen))
979  {
980  //Compute t6 = Tz
981  ecScalarCopy(state->t6, t->z, pLen);
982  //Compute t7 = t6^2
983  ecFieldSqrMod(state->curve, state->t7, state->t6);
984  //Compute t1 = t1 * t7
985  ecFieldMulMod(state->curve, state->t1, state->t1, state->t7);
986  //Compute t7 = t6 * t7
987  ecFieldMulMod(state->curve, state->t7, state->t6, state->t7);
988  //Compute t2 = t2 * t7
989  ecFieldMulMod(state->curve, state->t2, state->t2, state->t7);
990  }
991 
992  //Compute t7 = t3^2
993  ecFieldSqrMod(state->curve, state->t7, state->t3);
994  //Compute t4 = t4 * t7
995  ecFieldMulMod(state->curve, state->t4, state->t4, state->t7);
996  //Compute t7 = t3 * t7
997  ecFieldMulMod(state->curve, state->t7, state->t3, state->t7);
998  //Compute t5 = t5 * t7
999  ecFieldMulMod(state->curve, state->t5, state->t5, state->t7);
1000  //Compute t4 = t1 - t4
1001  ecFieldSubMod(state->curve, state->t4, state->t1, state->t4);
1002  //Compute t5 = t2 - t5
1003  ecFieldSubMod(state->curve, state->t5, state->t2, state->t5);
1004 
1005  //Check whether t4 == 0
1006  if(ecScalarTestEqualInt(state->t4, 0, pLen))
1007  {
1008  //Check whether t5 == 0
1009  if(ecScalarTestEqualInt(state->t5, 0, pLen))
1010  {
1011  //Set R = (0, 0, 0)
1012  ecScalarSetInt(r->x, 0, pLen);
1013  ecScalarSetInt(r->y, 0, pLen);
1014  ecScalarSetInt(r->z, 0, pLen);
1015  }
1016  else
1017  {
1018  //Set R = (1, 1, 0)
1019  ecScalarSetInt(r->x, 1, pLen);
1020  ecScalarSetInt(r->y, 1, pLen);
1021  ecScalarSetInt(r->z, 0, pLen);
1022  }
1023  }
1024  else
1025  {
1026  //Compute t1 = 2 * t1 - t4
1027  ecFieldAddMod(state->curve, state->t1, state->t1, state->t1);
1028  ecFieldSubMod(state->curve, state->t1, state->t1, state->t4);
1029  //Compute t2 = 2 * t2 - t5
1030  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
1031  ecFieldSubMod(state->curve, state->t2, state->t2, state->t5);
1032 
1033  //Check whether Tz != 1
1034  if(ecScalarTestNotEqualInt(t->z, 1, pLen))
1035  {
1036  //Compute t3 = t3 * t6
1037  ecFieldMulMod(state->curve, state->t3, state->t3, state->t6);
1038  }
1039 
1040  //Compute t3 = t3 * t4
1041  ecFieldMulMod(state->curve, state->t3, state->t3, state->t4);
1042  //Compute t7 = t4^2
1043  ecFieldSqrMod(state->curve, state->t7, state->t4);
1044  //Compute t4 = t4 * t7
1045  ecFieldMulMod(state->curve, state->t4, state->t4, state->t7);
1046  //Compute t7 = t1 * t7
1047  ecFieldMulMod(state->curve, state->t7, state->t1, state->t7);
1048  //Compute t1 = t5^2
1049  ecFieldSqrMod(state->curve, state->t1, state->t5);
1050  //Compute t1 = t1 - t7
1051  ecFieldSubMod(state->curve, state->t1, state->t1, state->t7);
1052  //Compute t7 = t7 - 2 * t1
1053  ecFieldAddMod(state->curve, state->t6, state->t1, state->t1);
1054  ecFieldSubMod(state->curve, state->t7, state->t7, state->t6);
1055  //Compute t5 = t5 * t7
1056  ecFieldMulMod(state->curve, state->t5, state->t5, state->t7);
1057  //Compute t4 = t2 * t4
1058  ecFieldMulMod(state->curve, state->t4, state->t2, state->t4);
1059  //Compute t2 = t5 - t4
1060  ecFieldSubMod(state->curve, state->t2, state->t5, state->t4);
1061 
1062  //Compute t2 = t2 / 2
1063  if(ecScalarGetBitValue(state->t2, 0) == 0)
1064  {
1065  //Perform a right shift operation
1066  ecScalarShiftRight(state->t2, state->t2, 1, pLen);
1067  }
1068  else
1069  {
1070  //First add p, then perform a right shift operation
1071  c = ecScalarAdd(state->t2, state->t2, state->curve->p, pLen);
1072  ecScalarShiftRight(state->t2, state->t2, 1, pLen);
1073  state->t2[pLen - 1] |= c << 31;
1074  }
1075 
1076  //Set Rx = t1
1077  ecScalarCopy(r->x, state->t1, pLen);
1078  //Set Ry = t2
1079  ecScalarCopy(r->y, state->t2, pLen);
1080  //Set Rz = t3
1081  ecScalarCopy(r->z, state->t3, pLen);
1082  }
1083 }
1084 
1085 
1086 /**
1087  * @brief Point addition
1088  * @param[in] state Pointer to the working state
1089  * @param[out] r Resulting point R = S + T
1090  * @param[in] s First operand
1091  * @param[in] t Second operand
1092  **/
1093 
1094 void ecFullAdd(EcState *state, EcPoint3 *r,
1095  const EcPoint3 *s, const EcPoint3 *t)
1096 {
1097  uint_t pLen;
1098  EcPoint3 u;
1099 
1100  //Get the length of the modulus, in words
1101  pLen = (state->curve->fieldSize + 31) / 32;
1102 
1103  //Check whether Sz == 0
1104  if(ecScalarTestEqualInt(s->z, 0, pLen))
1105  {
1106  //Set R = T
1107  ecScalarCopy(r->x, t->x, pLen);
1108  ecScalarCopy(r->y, t->y, pLen);
1109  ecScalarCopy(r->z, t->z, pLen);
1110  }
1111  //Check whether Tz == 0
1112  else if(ecScalarTestEqualInt(t->z, 0, pLen))
1113  {
1114  //Set R = S
1115  ecScalarCopy(r->x, s->x, pLen);
1116  ecScalarCopy(r->y, s->y, pLen);
1117  ecScalarCopy(r->z, s->z, pLen);
1118  }
1119  else
1120  {
1121  //Compute U = S + T
1122  ecAdd(state, &u, s, t);
1123 
1124  //Check whether U == (0, 0, 0)
1125  if(ecScalarTestEqualInt(u.x, 0, pLen) &&
1126  ecScalarTestEqualInt(u.y, 0, pLen) &&
1127  ecScalarTestEqualInt(u.z, 0, pLen))
1128  {
1129  //Compute R = 2 * S
1130  ecDouble(state, r, s);
1131  }
1132  else
1133  {
1134  //Set R = U
1135  ecScalarCopy(r->x, u.x, pLen);
1136  ecScalarCopy(r->y, u.y, pLen);
1137  ecScalarCopy(r->z, u.z, pLen);
1138  }
1139  }
1140 }
1141 
1142 
1143 /**
1144  * @brief Point subtraction
1145  * @param[in] state Pointer to the working state
1146  * @param[out] r Resulting point R = S - T
1147  * @param[in] s First operand
1148  * @param[in] t Second operand
1149  **/
1150 
1151 void ecFullSub(EcState *state, EcPoint3 *r, const EcPoint3 *s,
1152  const EcPoint3 *t)
1153 {
1154  uint_t pLen;
1155  EcPoint3 u;
1156 
1157  //Get the length of the modulus, in words
1158  pLen = (state->curve->fieldSize + 31) / 32;
1159 
1160  //Set Ux = Tx and Uz = Tz
1161  ecScalarCopy(u.x, t->x, pLen);
1162  ecScalarCopy(u.z, t->z, pLen);
1163 
1164  //Set Uy = p - Ty
1165  ecScalarSub(u.y, state->curve->p, t->y, pLen);
1166 
1167  //Compute R = S + U
1168  ecFullAdd(state, r, s, &u);
1169 }
1170 
1171 
1172 /**
1173  * @brief Scalar multiplication (fast calculation)
1174  * @param[in] curve Elliptic curve parameters
1175  * @param[out] r Resulting point R = d.S
1176  * @param[in] d An integer d such as 0 <= d < q
1177  * @param[in] s EC point
1178  * @return Error code
1179  **/
1180 
1181 __weak_func error_t ecMulFast(const EcCurve *curve, EcPoint3 *r,
1182  const uint32_t *d, const EcPoint3 *s)
1183 {
1184  uint_t i;
1185  uint_t pLen;
1186  uint_t qLen;
1187  uint32_t k[EC_MAX_ORDER_SIZE + 1];
1188  uint32_t h[EC_MAX_ORDER_SIZE + 1];
1189 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1190  EcMulFastState *state;
1191 #else
1192  EcMulFastState state[1];
1193 #endif
1194 
1195 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1196  //Allocate working state
1197  state = cryptoAllocMem(sizeof(EcMulFastState));
1198  //Failed to allocate memory?
1199  if(state == NULL)
1200  return ERROR_OUT_OF_MEMORY;
1201 #endif
1202 
1203  //Initialize working state
1204  osMemset(state, 0, sizeof(EcMulFastState));
1205  //Save elliptic curve parameters
1206  state->subState.curve = curve;
1207 
1208  //Get the length of the modulus, in words
1209  pLen = (curve->fieldSize + 31) / 32;
1210  //Get the length of the order, in words
1211  qLen = (curve->orderSize + 31) / 32;
1212 
1213  //Check whether d == 0
1214  if(ecScalarTestEqualInt(d, 0, pLen))
1215  {
1216  //Set R = (1, 1, 0)
1217  ecScalarSetInt(r->x, 1, pLen);
1218  ecScalarSetInt(r->y, 1, pLen);
1219  ecScalarSetInt(r->z, 0, pLen);
1220  }
1221  //Check whether d == 1
1222  else if(ecScalarTestEqualInt(d, 1, pLen))
1223  {
1224  //Set R = S
1225  ecScalarCopy(r->x, s->x, pLen);
1226  ecScalarCopy(r->y, s->y, pLen);
1227  ecScalarCopy(r->z, s->z, pLen);
1228  }
1229  //Check whether Sz == 0
1230  else if(ecScalarTestEqualInt(s->z, 0, pLen))
1231  {
1232  //Set R = (1, 1, 0)
1233  ecScalarSetInt(r->x, 1, pLen);
1234  ecScalarSetInt(r->y, 1, pLen);
1235  ecScalarSetInt(r->z, 0, pLen);
1236  }
1237  else
1238  {
1239  //Check whether Sz != 1
1240  if(ecScalarTestNotEqualInt(s->z, 1, pLen))
1241  {
1242  //Normalize S
1243  ecAffinify(curve, r, s);
1244  }
1245  else
1246  {
1247  //Set R = S
1248  ecScalarCopy(r->x, s->x, pLen);
1249  ecScalarCopy(r->y, s->y, pLen);
1250  ecScalarCopy(r->z, s->z, pLen);
1251  }
1252 
1253  //Let k = d
1254  ecScalarCopy(k, d, qLen);
1255  k[qLen] = 0;
1256 
1257  //Precompute h = 3 * d
1258  ecScalarAdd(h, k, k, qLen + 1);
1259  ecScalarAdd(h, h, k, qLen + 1);
1260 
1261  //Calculate the length of h, in bits
1262  pLen = ecScalarGetBitLength(h, qLen + 1);
1263 
1264  //Scalar multiplication
1265  for(i = pLen - 2; i >= 1; i--)
1266  {
1267  //Point doubling
1268  ecDouble(&state->subState, r, r);
1269 
1270  //Check the values of h(i) and k(i)
1271  if(ecScalarGetBitValue(h, i) != 0 &&
1272  ecScalarGetBitValue(k, i) == 0)
1273  {
1274  //If h(i) == 1 and k(i) == 0, then compute R = R + S
1275  ecFullAdd(&state->subState, r, r, s);
1276  }
1277  else if(ecScalarGetBitValue(h, i) == 0 &&
1278  ecScalarGetBitValue(k, i) != 0)
1279  {
1280  //If h(i) == 0 and k(i) == 1, then compute R = R - S
1281  ecFullSub(&state->subState, r, r, s);
1282  }
1283  else
1284  {
1285  //Just for sanity
1286  }
1287  }
1288  }
1289 
1290  //Erase working state
1291  osMemset(state, 0, sizeof(EcMulFastState));
1292 
1293 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1294  //Release working state
1295  cryptoFreeMem(state);
1296 #endif
1297 
1298  //Successful processing
1299  return NO_ERROR;
1300 }
1301 
1302 
1303 /**
1304  * @brief Scalar multiplication (regular calculation)
1305  * @param[in] curve Elliptic curve parameters
1306  * @param[out] r Resulting point R = d.S
1307  * @param[in] d An integer d such as 0 <= d < q
1308  * @param[in] s EC point
1309  * @return Error code
1310  **/
1311 
1312 __weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r,
1313  const uint32_t *d, const EcPoint3 *s)
1314 {
1315  int_t i;
1316  int_t pLen;
1317  uint32_t b;
1318 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1319  EcMulRegularState *state;
1320 #else
1321  EcMulRegularState state[1];
1322 #endif
1323 
1324 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1325  //Allocate working state
1326  state = cryptoAllocMem(sizeof(EcMulRegularState));
1327  //Failed to allocate memory?
1328  if(state == NULL)
1329  return ERROR_OUT_OF_MEMORY;
1330 #endif
1331 
1332  //Initialize working state
1333  osMemset(state, 0, sizeof(EcMulRegularState));
1334  //Save elliptic curve parameters
1335  state->subState.curve = curve;
1336 
1337  //Get the length of the modulus, in words
1338  pLen = (curve->fieldSize + 31) / 32;
1339 
1340  //Initialize the value of the flag
1341  state->init = ecScalarGetBitValue(d, curve->orderSize - 1);
1342 
1343  //Compute (P0, Q0) = DBLU(S)
1344  ecDblu(&state->subState, &state->p0, &state->q0, s);
1345 
1346  //Set P = P0
1347  ecScalarCopy(state->p.x, state->p0.x, pLen);
1348  ecScalarCopy(state->p.y, state->p0.y, pLen);
1349  ecScalarCopy(state->p.z, state->p0.z, pLen);
1350 
1351  //Set Q = Q0
1352  ecScalarCopy(state->q.x, state->q0.x, pLen);
1353  ecScalarCopy(state->q.y, state->q0.y, pLen);
1354  ecScalarCopy(state->q.z, state->q0.z, pLen);
1355 
1356  //Montgomery ladder with co-Z addition formulae
1357  for(i = curve->orderSize - 2; i >= 0; i--)
1358  {
1359  //The scalar is processed in a left-to-right fashion
1360  b = ecScalarGetBitValue(d, i);
1361 
1362  //Conditional swap
1363  ecScalarSwap(state->p.x, state->q.x, b, pLen);
1364  ecScalarSwap(state->p.y, state->q.y, b, pLen);
1365  ecScalarSwap(state->p.z, state->q.z, b, pLen);
1366 
1367  //Compute (P, Q) = ZADDC(Q, P)
1368  ecZaddc(&state->subState, &state->p, &state->q, &state->q, &state->p);
1369  //Compute (Q, P) = ZADDU(P, Q)
1370  ecZaddu(&state->subState, &state->q, &state->p, &state->p, &state->q);
1371 
1372  //Conditional swap
1373  ecScalarSwap(state->p.x, state->q.x, b, pLen);
1374  ecScalarSwap(state->p.y, state->q.y, b, pLen);
1375  ecScalarSwap(state->p.z, state->q.z, b, pLen);
1376 
1377  //The loop does not depend on the length of the secret scalar
1378  ecScalarSelect(state->p.x, state->p0.x, state->p.x, state->init, pLen);
1379  ecScalarSelect(state->p.y, state->p0.y, state->p.y, state->init, pLen);
1380  ecScalarSelect(state->p.z, state->p0.z, state->p.z, state->init, pLen);
1381  ecScalarSelect(state->q.x, state->q0.x, state->q.x, state->init, pLen);
1382  ecScalarSelect(state->q.y, state->q0.y, state->q.y, state->init, pLen);
1383  ecScalarSelect(state->q.z, state->q0.z, state->q.z, state->init, pLen);
1384 
1385  //Update the value of flag
1386  state->init |= b;
1387  }
1388 
1389  //Copy resulting point
1390  ecScalarCopy(r->x, state->q.x, pLen);
1391  ecScalarCopy(r->y, state->q.y, pLen);
1392  ecScalarCopy(r->z, state->q.z, pLen);
1393 
1394  //Erase working state
1395  osMemset(state, 0, sizeof(EcMulRegularState));
1396 
1397 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1398  //Release working state
1399  cryptoFreeMem(state);
1400 #endif
1401 
1402  //Successful processing
1403  return NO_ERROR;
1404 }
1405 
1406 
1407 /**
1408  * @brief Twin multiplication
1409  * @param[in] curve Elliptic curve parameters
1410  * @param[out] r Resulting point R = d0.S + d1.T
1411  * @param[in] d0 An integer d such as 0 <= d0 < q
1412  * @param[in] s EC point
1413  * @param[in] d1 An integer d such as 0 <= d1 < q
1414  * @param[in] t EC point
1415  * @return Error code
1416  **/
1417 
1418 __weak_func error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r,
1419  const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1,
1420  const EcPoint3 *t)
1421 {
1422  int_t k;
1423  uint_t pLen;
1424  uint_t m;
1425  uint_t m0;
1426  uint_t m1;
1427  uint_t c0;
1428  uint_t c1;
1429  uint_t h0;
1430  uint_t h1;
1431  int_t u0;
1432  int_t u1;
1433 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1434  EcTwinMulState *state;
1435 #else
1436  EcTwinMulState state[1];
1437 #endif
1438 
1439 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1440  //Allocate working state
1441  state = cryptoAllocMem(sizeof(EcTwinMulState));
1442  //Failed to allocate memory?
1443  if(state == NULL)
1444  return ERROR_OUT_OF_MEMORY;
1445 #endif
1446 
1447  //Initialize working state
1448  osMemset(state, 0, sizeof(EcTwinMulState));
1449  //Save elliptic curve parameters
1450  state->subState.curve = curve;
1451 
1452  //Get the length of the modulus, in words
1453  pLen = (curve->fieldSize + 31) / 32;
1454 
1455  //Precompute SpT = S + T
1456  ecFullAdd(&state->subState, &state->spt, s, t);
1457  //Precompute SmT = S - T
1458  ecFullSub(&state->subState, &state->smt, s, t);
1459 
1460  //Let m0 be the bit length of d0
1461  m0 = ecScalarGetBitLength(d0, (curve->orderSize + 31) / 32);
1462  //Let m1 be the bit length of d1
1463  m1 = ecScalarGetBitLength(d1, (curve->orderSize + 31) / 32);
1464  //Let m = MAX(m0, m1)
1465  m = MAX(m0, m1);
1466 
1467  //Let c be a 2 x 6 binary matrix
1468  c0 = ecScalarGetBitValue(d0, m - 4);
1469  c0 |= ecScalarGetBitValue(d0, m - 3) << 1;
1470  c0 |= ecScalarGetBitValue(d0, m - 2) << 2;
1471  c0 |= ecScalarGetBitValue(d0, m - 1) << 3;
1472  c1 = ecScalarGetBitValue(d1, m - 4);
1473  c1 |= ecScalarGetBitValue(d1, m - 3) << 1;
1474  c1 |= ecScalarGetBitValue(d1, m - 2) << 2;
1475  c1 |= ecScalarGetBitValue(d1, m - 1) << 3;
1476 
1477  //Set R = (1, 1, 0)
1478  ecScalarSetInt(r->x, 1, pLen);
1479  ecScalarSetInt(r->y, 1, pLen);
1480  ecScalarSetInt(r->z, 0, pLen);
1481 
1482  //Calculate both multiplications at the same time
1483  for(k = m; k >= 0; k--)
1484  {
1485  //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5)
1486  h0 = c0 & 0x1F;
1487 
1488  //Check whether c(0,0) == 1
1489  if(c0 & 0x20)
1490  {
1491  h0 = 31 - h0;
1492  }
1493 
1494  //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5)
1495  h1 = c1 & 0x1F;
1496 
1497  //Check whether c(1,0) == 1
1498  if(c1 & 0x20)
1499  {
1500  h1 = 31 - h1;
1501  }
1502 
1503  //Compute u(0)
1504  if(h0 < ecTwinMulF(h1))
1505  {
1506  u0 = 0;
1507  }
1508  else if(c0 & 0x20)
1509  {
1510  u0 = -1;
1511  }
1512  else
1513  {
1514  u0 = 1;
1515  }
1516 
1517  //Compute u(1)
1518  if(h1 < ecTwinMulF(h0))
1519  {
1520  u1 = 0;
1521  }
1522  else if(c1 & 0x20)
1523  {
1524  u1 = -1;
1525  }
1526  else
1527  {
1528  u1 = 1;
1529  }
1530 
1531  //Update c matrix
1532  c0 <<= 1;
1533  c0 |= ecScalarGetBitValue(d0, k - 5);
1534  c0 ^= u0 ? 0x20 : 0x00;
1535  c1 <<= 1;
1536  c1 |= ecScalarGetBitValue(d1, k - 5);
1537  c1 ^= u1 ? 0x20 : 0x00;
1538 
1539  //Point doubling
1540  ecDouble(&state->subState, r, r);
1541 
1542  //Check u(0) and u(1)
1543  if(u0 == -1 && u1 == -1)
1544  {
1545  //Compute R = R - SpT
1546  ecFullSub(&state->subState, r, r, &state->spt);
1547  }
1548  else if(u0 == -1 && u1 == 0)
1549  {
1550  //Compute R = R - S
1551  ecFullSub(&state->subState, r, r, s);
1552  }
1553  else if(u0 == -1 && u1 == 1)
1554  {
1555  //Compute R = R - SmT
1556  ecFullSub(&state->subState, r, r, &state->smt);
1557  }
1558  else if(u0 == 0 && u1 == -1)
1559  {
1560  //Compute R = R - T
1561  ecFullSub(&state->subState, r, r, t);
1562  }
1563  else if(u0 == 0 && u1 == 1)
1564  {
1565  //Compute R = R + T
1566  ecFullAdd(&state->subState, r, r, t);
1567  }
1568  else if(u0 == 1 && u1 == -1)
1569  {
1570  //Compute R = R + SmT
1571  ecFullAdd(&state->subState, r, r, &state->smt);
1572  }
1573  else if(u0 == 1 && u1 == 0)
1574  {
1575  //Compute R = R + S
1576  ecFullAdd(&state->subState, r, r, s);
1577  }
1578  else if(u0 == 1 && u1 == 1)
1579  {
1580  //Compute R = R + SpT
1581  ecFullAdd(&state->subState, r, r, &state->spt);
1582  }
1583  else
1584  {
1585  }
1586  }
1587 
1588  //Erase working state
1589  osMemset(state, 0, sizeof(EcTwinMulState));
1590 
1591 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1592  //Release working state
1593  cryptoFreeMem(state);
1594 #endif
1595 
1596  //Successful processing
1597  return NO_ERROR;
1598 }
1599 
1600 #endif
__weak_func error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EcPrivateKey *privateKey, EcPublicKey *publicKey)
EC key pair generation.
Definition: ec.c:117
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
error_t ecImportPoint(const EcCurve *curve, EcPoint *r, const uint8_t *data, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:626
@ EC_CURVE_TYPE_WEIERSTRASS_A3
Definition: ec.h:362
@ ERROR_UNSUPPORTED_ELLIPTIC_CURVE
Definition: error.h:133
__weak_func error_t ecAffinify(const EcCurve *curve, EcPoint3 *r, const EcPoint3 *s)
Recover affine representation.
Definition: ec.c:749
@ EC_CURVE_TYPE_MONTGOMERY
Definition: ec.h:363
int bool_t
Definition: compiler_port.h:61
uint8_t b
Definition: nbns_common.h:104
@ EC_PUBLIC_KEY_FORMAT_RAW_Y
Definition: ec.h:389
@ EC_POINT_FORMAT_UNCOMPRESSED
Definition: ec.h:376
__weak_func error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
Definition: ec.c:1181
error_t ecImportPublicKey(EcPublicKey *key, const EcCurve *curve, const uint8_t *data, size_t length, EcPublicKeyFormat format)
Import an EC public key.
Definition: ec.c:263
uint32_t t4[EC_MAX_MODULUS_SIZE]
Definition: ec.h:451
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
signed int int_t
Definition: compiler_port.h:56
void ecZaddc(EcState *state, EcPoint3 *r, EcPoint3 *s, const EcPoint3 *p, const EcPoint3 *q)
Conjugate co-Z addition.
Definition: ec_misc.c:1535
#define PrngAlgo
Definition: crypto.h:973
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:244
EcPoint3 spt
Definition: ec.h:491
uint32_t ecScalarGetBitValue(const uint32_t *a, int_t index)
Get the bit value at the specified index.
Definition: ec_misc.c:315
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:433
uint8_t t
Definition: lldp_ext_med.h:212
int_t slot
Private key slot.
Definition: ec.h:435
Working state (fast scalar multiplication)
Definition: ec.h:463
void ecFullAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point addition.
Definition: ec.c:1094
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:44
#define EC_MAX_ORDER_SIZE
Definition: ec.h:315
uint_t ecScalarGetBitLength(const uint32_t *a, uint_t n)
Get the actual length in bits.
Definition: ec_misc.c:273
uint32_t t7[EC_MAX_MODULUS_SIZE]
Definition: ec.h:454
EcPoint3 p0
Definition: ec.h:477
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define TRACE_DEBUG_EC_SCALAR(p, a, n)
Definition: debug.h:123
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
error_t ecGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EcPrivateKey *privateKey)
EC private key generation.
Definition: ec.c:158
void ecDouble(EcState *state, EcPoint3 *r, const EcPoint3 *s)
Point doubling.
Definition: ec.c:848
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
uint32_t ecScalarAdd(uint32_t *r, const uint32_t *a, const uint32_t *b, uint_t n)
Addition of two integers.
Definition: ec_misc.c:651
EcPoint3 smt
Definition: ec.h:492
uint32_t t6[EC_MAX_MODULUS_SIZE]
Definition: ec.h:453
Working state (regular scalar multiplication)
Definition: ec.h:475
Working state (twin multiplication)
Definition: ec.h:490
__weak_func void ecFieldAddMod(const EcCurve *curve, uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular addition.
Definition: ec_misc.c:1235
uint32_t z[EC_MAX_MODULUS_SIZE]
z-coordinate
Definition: ec.h:412
__weak_func error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r, const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1, const EcPoint3 *t)
Twin multiplication.
Definition: ec.c:1418
uint8_t r
Definition: ndp.h:346
EcState subState
Definition: ec.h:493
@ ERROR_INVALID_ELLIPTIC_CURVE
Definition: error.h:134
#define FALSE
Definition: os_port.h:46
uint8_t h
Definition: ndp.h:302
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
EcPoint3 p
Definition: ec.h:479
uint32_t init
Definition: ec.h:476
EcPoint3 q
Definition: ec.h:480
error_t
Error codes.
Definition: error.h:43
error_t ecExportPrivateKey(const EcPrivateKey *key, uint8_t *data, size_t *length)
Export an EC private key.
Definition: ec.c:554
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:52
uint32_t ecScalarSub(uint32_t *r, const uint32_t *a, const uint32_t *b, uint_t n)
Subtraction of two integers.
Definition: ec_misc.c:707
void ecScalarSetInt(uint32_t *a, uint32_t b, uint_t n)
Set integer value.
Definition: ec_misc.c:505
Helper routines for ECC.
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
void ecScalarCopy(uint32_t *a, const uint32_t *b, uint_t n)
Copy an integer.
Definition: ec_misc.c:527
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t ecExportPoint(const EcCurve *curve, const EcPoint *a, uint8_t *data, size_t *length)
Convert an EC point to an octet string.
Definition: ec.c:675
@ EC_SCALAR_FORMAT_LITTLE_ENDIAN
Definition: ec_misc.h:50
EcPublicKeyFormat
EC public key format.
Definition: ec.h:385
General definitions for cryptographic algorithms.
EcState subState
Definition: ec.h:481
EcPublicKey q
Public key.
Definition: ec.h:436
@ EC_PUBLIC_KEY_FORMAT_RAW
Definition: ec.h:387
EC private key.
Definition: ec.h:432
__weak_func void ecFieldSqrMod(const EcCurve *curve, uint32_t *r, const uint32_t *a)
Modular squaring.
Definition: ec_misc.c:1308
EcPoint3 q0
Definition: ec.h:478
uint8_t u
Definition: lldp_ext_med.h:213
uint32_t t2
EC point (affine coordinates)
Definition: ec.h:398
void ecFreePrivateKey(EcPrivateKey *key)
Release an EC private key.
Definition: ec.c:100
uint8_t length
Definition: tcp.h:375
void ecScalarSelect(uint32_t *r, const uint32_t *a, const uint32_t *b, uint32_t c, uint_t n)
Select an integer.
Definition: ec_misc.c:576
void ecAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point addition (helper routine)
Definition: ec.c:957
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *data, size_t *length, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
__weak_func void ecFieldMulMod(const EcCurve *curve, uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
Definition: ec_misc.c:1286
EC public key.
Definition: ec.h:421
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define MAX(a, b)
Definition: os_port.h:67
__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
const EcCurve * curve
Definition: ec.h:446
void ecFullSub(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point subtraction.
Definition: ec.c:1151
uint32_t t5[EC_MAX_MODULUS_SIZE]
Definition: ec.h:452
uint32_t ecScalarTestEqualInt(const uint32_t *a, uint32_t b, uint_t n)
Test if two integers are equal.
Definition: ec_misc.c:435
uint32_t t1
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
Working state (point addition/subtraction/doubling)
Definition: ec.h:445
uint8_t m
Definition: ndp.h:304
uint8_t n
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
EC point (projective coordinates)
Definition: ec.h:409
#define cryptoFreeMem(p)
Definition: crypto.h:826
void ecFieldInvMod(const EcCurve *curve, uint32_t *r, const uint32_t *a)
Modular inversion.
Definition: ec_misc.c:1354
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:80
@ EC_PUBLIC_KEY_FORMAT_RAW_X
Definition: ec.h:388
void ecZaddu(EcState *state, EcPoint3 *r, EcPoint3 *s, const EcPoint3 *p, const EcPoint3 *q)
Co-Z addition with update.
Definition: ec_misc.c:1466
void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:720
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1312
error_t ecGeneratePublicKey(const EcPrivateKey *privateKey, EcPublicKey *publicKey)
Derive the public key from an EC private key.
Definition: ec.c:200
EcPoint q
Public key.
Definition: ec.h:423
EcState subState
Definition: ec.h:466
uint32_t t3[EC_MAX_MODULUS_SIZE]
Definition: ec.h:450
void ecScalarShiftRight(uint32_t *r, const uint32_t *a, uint_t k, uint_t n)
Right shift operation.
Definition: ec_misc.c:940
error_t ecScalarRand(const EcCurve *curve, uint32_t *r, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value.
Definition: ec_misc.c:603
#define cryptoAllocMem(size)
Definition: crypto.h:821
uint8_t s
Definition: igmp_common.h:234
@ EC_CURVE_TYPE_WEIERSTRASS
Definition: ec.h:360
uint32_t t1[EC_MAX_MODULUS_SIZE]
Definition: ec.h:448
#define EcCurve
Definition: ec.h:346
error_t ecImportPrivateKey(EcPrivateKey *key, const EcCurve *curve, const uint8_t *data, size_t length)
Import an EC private key.
Definition: ec.c:490
void ecScalarSwap(uint32_t *a, uint32_t *b, uint32_t c, uint_t n)
Conditional swap.
Definition: ec_misc.c:547
__weak_func void ecFieldSubMod(const EcCurve *curve, uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular subtraction.
Definition: ec_misc.c:1261
int_t ecScalarComp(const uint32_t *a, const uint32_t *b, uint_t n)
Compare integers.
Definition: ec_misc.c:337
uint32_t ecScalarTestNotEqualInt(const uint32_t *a, uint32_t b, uint_t n)
Test if two integers are different.
Definition: ec_misc.c:478
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
uint32_t t2[EC_MAX_MODULUS_SIZE]
Definition: ec.h:449
#define osMemset(p, value, length)
Definition: os_port.h:138
uint_t ecTwinMulF(uint_t t)
An auxiliary function for the twin multiplication.
Definition: ec_misc.c:1426
ECC (Elliptic Curve Cryptography)
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:410
@ EC_CURVE_TYPE_WEIERSTRASS_A0
Definition: ec.h:361
#define EC_MAX_MODULUS_SIZE
Definition: ec.h:284
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
void ecDblu(EcState *state, EcPoint3 *r, EcPoint3 *s, const EcPoint3 *p)
Co-Z doubling with update.
Definition: ec_misc.c:1625
Debugging facilities.
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:68
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:411