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.2
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] input 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 *input, size_t length, EcPublicKeyFormat format)
265 {
266  error_t error;
267  size_t n;
268 
269  //Check parameters
270  if(key != NULL && curve != NULL && input != 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, input, 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, input,
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,
300  input + n, n, EC_SCALAR_FORMAT_BIG_ENDIAN);
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
312  error = ecScalarImport(key->q.x, EC_MAX_MODULUS_SIZE, input,
314  }
315  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_Y)
316  {
317  //Convert the y-coordinate to an integer
318  error = ecScalarImport(key->q.y, EC_MAX_MODULUS_SIZE, input,
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
336  error = ecScalarImport(key->q.x, EC_MAX_MODULUS_SIZE, input,
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] output Pointer to the octet string
373  * @param[out] written 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 
378 error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *output,
379  size_t *written, EcPublicKeyFormat format)
380 {
381  error_t error;
382  size_t n;
383 
384  //Initialize status code
385  error = NO_ERROR;
386 
387  //Check parameters
388  if(key != NULL && written != NULL)
389  {
390  //Valid elliptic curve?
391  if(key->curve != NULL)
392  {
393  //Check curve type
394  if(key->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
395  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
396  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
397  {
398  //Get the length of the modulus, in bytes
399  n = (key->curve->fieldSize + 7) / 8;
400 
401  //Check the format of the public key
402  if(format == EC_PUBLIC_KEY_FORMAT_X963)
403  {
404  //Write the public key
405  error = ecExportPoint(key->curve, &key->q, output, &n);
406  }
407  else if(format == EC_PUBLIC_KEY_FORMAT_RAW)
408  {
409  //If the output parameter is NULL, then the function calculates
410  //the length of the octet string without copying any data
411  if(output != NULL)
412  {
413  //Convert the x-coordinate to an octet string
414  error = ecScalarExport(key->q.x, (n + 3) / 4, output, n,
416 
417  //Check status code
418  if(!error)
419  {
420  //Convert the y-coordinate to an octet string
421  error = ecScalarExport(key->q.y, (n + 3) / 4, output + n, n,
423  }
424  }
425 
426  //Check status code
427  if(!error)
428  {
429  //Length of the resulting octet string
430  n = 2 * n;
431  }
432  }
433  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_X)
434  {
435  //If the output parameter is NULL, then the function calculates
436  //the length of the octet string without copying any data
437  if(output != NULL)
438  {
439  //Convert the x-coordinate to an octet string
440  error = ecScalarExport(key->q.x, (n + 3) / 4, output, n,
442  }
443  }
444  else if(format == EC_PUBLIC_KEY_FORMAT_RAW_Y)
445  {
446  //If the output parameter is NULL, then the function calculates
447  //the length of the octet string without copying any data
448  if(output != NULL)
449  {
450  //Convert the y-coordinate to an octet string
451  error = ecScalarExport(key->q.y, (n + 3) / 4, output, n,
453  }
454  }
455  else
456  {
457  //Invalid format
458  error = ERROR_INVALID_PARAMETER;
459  }
460  }
461  else if(key->curve->type == EC_CURVE_TYPE_MONTGOMERY)
462  {
463  //Get the length of the modulus, in bytes
464  n = (key->curve->fieldSize + 7) / 8;
465 
466  //If the output parameter is NULL, then the function calculates the
467  //length of the octet string without copying any data
468  if(output != NULL)
469  {
470  //Convert the u-coordinate to an octet string
471  error = ecScalarExport(key->q.x, (n + 3) / 4, output, n,
473  }
474  }
475  else
476  {
477  //Report an error
479  }
480  }
481  else
482  {
483  //Invalid elliptic curve
485  }
486 
487  //Check status code
488  if(!error)
489  {
490  //Return the length of the octet string
491  *written = n;
492  }
493  }
494  else
495  {
496  //Report an error
497  error = ERROR_INVALID_PARAMETER;
498  }
499 
500  //Return status code
501  return error;
502 }
503 
504 
505 /**
506  * @brief Import an EC private key
507  * @param[out] key EC private key
508  * @param[in] curve Elliptic curve parameters
509  * @param[in] input Pointer to the octet string
510  * @param[in] length Length of the octet string, in bytes
511  * @return Error code
512  **/
513 
515  const uint8_t *input, size_t length)
516 {
517  error_t error;
518 
519  //Check parameters
520  if(key != NULL && curve != NULL && input != NULL)
521  {
522  //Check curve type
523  if(curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
524  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
525  curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
526  {
527  //Read the private key
528  error = ecScalarImport(key->d, EC_MAX_ORDER_SIZE, input, length,
530  }
531  else if(curve->type == EC_CURVE_TYPE_MONTGOMERY)
532  {
533  //Check the length of the octet string
534  if(length == ((curve->orderSize + 7) / 8))
535  {
536  //Read the private key
537  error = ecScalarImport(key->d, EC_MAX_ORDER_SIZE, input, length,
539  }
540  else
541  {
542  //Report an error
543  error = ERROR_INVALID_KEY_LENGTH;
544  }
545  }
546  else
547  {
548  //Report an error
550  }
551 
552  //Check status code
553  if(!error)
554  {
555  //Save elliptic curve parameters
556  key->curve = curve;
557  }
558  }
559  else
560  {
561  //Report an error
562  error = ERROR_INVALID_PARAMETER;
563  }
564 
565  //Return status code
566  return error;
567 }
568 
569 
570 /**
571  * @brief Export an EC private key
572  * @param[in] key EC private key
573  * @param[out] output Pointer to the octet string
574  * @param[out] written Length of the octet string, in bytes
575  * @return Error code
576  **/
577 
578 error_t ecExportPrivateKey(const EcPrivateKey *key, uint8_t *output,
579  size_t *written)
580 {
581  error_t error;
582  size_t n;
583 
584  //Initialize status code
585  error = NO_ERROR;
586 
587  //Check parameters
588  if(key != NULL && written != NULL)
589  {
590  //Valid elliptic curve?
591  if(key->curve != NULL)
592  {
593  //Check curve type
594  if(key->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
595  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
596  key->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
597  {
598  //Get the length of the order, in bytes
599  n = (key->curve->orderSize + 7) / 8;
600 
601  //If the output parameter is NULL, then the function calculates the
602  //length of the octet string without copying any data
603  if(output != NULL)
604  {
605  //Write the private key
606  error = ecScalarExport(key->d, (n + 3) / 4, output, n,
608  }
609  }
610  else if(key->curve->type == EC_CURVE_TYPE_MONTGOMERY)
611  {
612  //Get the length of the order, in bytes
613  n = (key->curve->orderSize + 7) / 8;
614 
615  //If the output parameter is NULL, then the function calculates the
616  //length of the octet string without copying any data
617  if(output != NULL)
618  {
619  //Write the private key
620  error = ecScalarExport(key->d, (n + 3) / 4, output, n,
622  }
623  }
624  else
625  {
626  //Report an error
628  }
629  }
630  else
631  {
632  //Invalid elliptic curve
634  }
635 
636  //Check status code
637  if(!error)
638  {
639  //Return the length of the octet string
640  *written = n;
641  }
642  }
643  else
644  {
645  //Invalid elliptic curve
646  error = ERROR_INVALID_PARAMETER;
647  }
648 
649  //Return status code
650  return error;
651 }
652 
653 
654 /**
655  * @brief Convert an octet string to an EC point
656  * @param[in] curve Elliptic curve parameters
657  * @param[out] r EC point resulting from the conversion
658  * @param[in] input Pointer to the octet string
659  * @param[in] length Length of the octet string
660  * @return Error code
661  **/
662 
663 error_t ecImportPoint(const EcCurve *curve, EcPoint *r, const uint8_t *input,
664  size_t length)
665 {
666  error_t error;
667  size_t n;
668 
669  //Check parameters
670  if(curve == NULL || r == NULL || input == NULL)
672 
673  //Get the length of the modulus, in bytes
674  n = (curve->fieldSize + 7) / 8;
675 
676  //Check the length of the octet string
677  if(length != (n * 2 + 1))
679 
680  //Compressed point representation is not supported
681  if(input[0] != EC_POINT_FORMAT_UNCOMPRESSED)
683 
684  //Convert the x-coordinate to an integer
685  error = ecScalarImport(r->x, EC_MAX_MODULUS_SIZE, input + 1, n,
687  //Any error to report?
688  if(error)
689  return error;
690 
691  //Convert the y-coordinate to an integer
692  error = ecScalarImport(r->y, EC_MAX_MODULUS_SIZE, input + n + 1, n,
694  //Any error to report?
695  if(error)
696  return error;
697 
698  //Successful processing
699  return NO_ERROR;
700 }
701 
702 
703 /**
704  * @brief Convert an EC point to an octet string
705  * @param[in] curve Elliptic curve parameters
706  * @param[in] a EC point to be converted
707  * @param[out] output Pointer to the octet string
708  * @param[out] written Length of the resulting octet string
709  * @return Error code
710  **/
711 
712 error_t ecExportPoint(const EcCurve *curve, const EcPoint *a, uint8_t *output,
713  size_t *written)
714 {
715  error_t error;
716  size_t n;
717 
718  //Check parameters
719  if(curve == NULL || a == NULL || written == NULL)
721 
722  //Get the length of the modulus, in bytes
723  n = (curve->fieldSize + 7) / 8;
724 
725  //If the output parameter is NULL, then the function calculates the length
726  //of the octet string without copying any data
727  if(output != NULL)
728  {
729  //Point compression is not used
730  output[0] = EC_POINT_FORMAT_UNCOMPRESSED;
731 
732  //Convert the x-coordinate to an octet string
733  error = ecScalarExport(a->x, (n + 3) / 4, output + 1, n,
735  //Conversion failed?
736  if(error)
737  return error;
738 
739  //Convert the y-coordinate to an octet string
740  error = ecScalarExport(a->y, (n + 3) / 4, output + n + 1, n,
742  //Conversion failed?
743  if(error)
744  return error;
745  }
746 
747  //Return the length of the octet string
748  *written = n * 2 + 1;
749 
750  //Successful processing
751  return NO_ERROR;
752 }
753 
754 
755 /**
756  * @brief Compute projective representation
757  * @param[in] curve Elliptic curve parameters
758  * @param[out] r Projective representation of the point
759  * @param[in] s Affine representation of the point
760  **/
761 
762 void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
763 {
764  uint_t i;
765  uint_t pLen;
766 
767  //Get the length of the modulus, in words
768  pLen = (curve->fieldSize + 31) / 32;
769 
770  //Copy x, y and z-coordinates
771  for(i = 0; i < pLen; i++)
772  {
773  r->x[i] = s->x[i];
774  r->y[i] = s->y[i];
775  r->z[i] = 0;
776  }
777 
778  //Map the point to projective space
779  r->z[0] = 1;
780 }
781 
782 
783 /**
784  * @brief Recover affine representation
785  * @param[in] curve Elliptic curve parameters
786  * @param[out] r Affine representation of the point
787  * @param[in] s Projective representation of the point
788  * @return Error code
789  **/
790 
791 __weak_func error_t ecAffinify(const EcCurve *curve, EcPoint3 *r,
792  const EcPoint3 *s)
793 {
794  error_t error;
795  uint_t pLen;
796  uint32_t a[EC_MAX_MODULUS_SIZE];
797  uint32_t b[EC_MAX_MODULUS_SIZE];
798 
799  //Get the length of the modulus, in words
800  pLen = (curve->fieldSize + 31) / 32;
801 
802  //Point at the infinity?
803  if(ecScalarTestEqualInt(s->z, 0, pLen))
804  {
805  //The point at the infinity has no affine representation
806  error = ERROR_INVALID_PARAMETER;
807  }
808  else
809  {
810  //Compute a = 1/Sz mod p
811  ecFieldInvMod(curve, a, s->z);
812 
813  //Set Rx = a^2 * Sx mod p
814  ecFieldSqrMod(curve, b, a);
815  ecFieldMulMod(curve, r->x, b, s->x);
816 
817  //Set Ry = a^3 * Sy mod p
818  ecFieldMulMod(curve, b, b, a);
819  ecFieldMulMod(curve, r->y, b, s->y);
820 
821  //Set Rz = 1
822  ecScalarSetInt(r->z, 1, pLen);
823 
824  //Successful processing
825  error = NO_ERROR;
826  }
827 
828  //Return status code
829  return error;
830 }
831 
832 
833 /**
834  * @brief Check whether the affine point S is on the curve
835  * @param[in] curve Elliptic curve parameters
836  * @param[in] s Affine representation of the point
837  * @return TRUE if the affine point S is on the curve, else FALSE
838  **/
839 
840 __weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
841 {
842  uint_t pLen;
843  bool_t valid;
844  uint32_t t1[EC_MAX_MODULUS_SIZE];
845  uint32_t t2[EC_MAX_MODULUS_SIZE];
846 
847  //Initialize flag
848  valid = FALSE;
849 
850  //Check parameters
851  if(curve != NULL && s != NULL)
852  {
853  //Verify that 0 <= Sx < p and 0 <= Sy < p
854  if(ecScalarComp(s->x, curve->p, EC_MAX_MODULUS_SIZE) < 0 &&
855  ecScalarComp(s->y, curve->p, EC_MAX_MODULUS_SIZE) < 0)
856  {
857  //Get the length of the modulus, in words
858  pLen = (curve->fieldSize + 31) / 32;
859 
860  //Compute t1 = (Sx^3 + a * Sx + b) mod p
861  ecFieldSqrMod(curve, t1, s->x);
862  ecFieldMulMod(curve, t1, t1, s->x);
863  ecFieldMulMod(curve, t2, curve->a, s->x);
864  ecFieldAddMod(curve, t1, t1, t2);
865  ecFieldAddMod(curve, t1, t1, curve->b);
866 
867  //Compute t2 = Sy^2
868  ecFieldSqrMod(curve, t2, s->y);
869 
870  //Check whether the point is on the elliptic curve
871  if(ecScalarComp(t1, t2, pLen) == 0)
872  {
873  valid = TRUE;
874  }
875  }
876  }
877 
878  //Return TRUE if the affine point S is on the curve
879  return valid;
880 }
881 
882 
883 /**
884  * @brief Point doubling
885  * @param[in] state Pointer to the working state
886  * @param[out] r Resulting point R = 2S
887  * @param[in] s Point S
888  **/
889 
890 void ecDouble(EcState *state, EcPoint3 *r, const EcPoint3 *s)
891 {
892  uint_t pLen;
893 
894  //Get the length of the modulus, in words
895  pLen = (state->curve->fieldSize + 31) / 32;
896 
897  //Set t1 = Sx
898  ecScalarCopy(state->t1, s->x, pLen);
899  //Set t2 = Sy
900  ecScalarCopy(state->t2, s->y, pLen);
901  //Set t3 = Sz
902  ecScalarCopy(state->t3, s->z, pLen);
903 
904  //Point at the infinity?
905  if(ecScalarTestEqualInt(state->t3, 0, pLen))
906  {
907  //Set R = (1, 1, 0)
908  ecScalarSetInt(r->x, 1, pLen);
909  ecScalarSetInt(r->y, 1, pLen);
910  ecScalarSetInt(r->z, 0, pLen);
911  }
912  else
913  {
914  //Check curve type
915  if(state->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0)
916  {
917  //Compute t5 = t1^2
918  ecFieldSqrMod(state->curve, state->t5, state->t1);
919  //Compute t4 = 3 * t5
920  ecFieldAddMod(state->curve, state->t4, state->t5, state->t5);
921  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
922  }
923  else if(state->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
924  {
925  //Compute t4 = t3^2
926  ecFieldSqrMod(state->curve, state->t4, state->t3);
927  //Compute t5 = t1 - t4
928  ecFieldSubMod(state->curve, state->t5, state->t1, state->t4);
929  //Compute t4 = t1 + t4
930  ecFieldAddMod(state->curve, state->t4, state->t1, state->t4);
931  //Compute t5 = t4 * t5
932  ecFieldMulMod(state->curve, state->t5, state->t4, state->t5);
933  //Compute t4 = 3 * t5
934  ecFieldAddMod(state->curve, state->t4, state->t5, state->t5);
935  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
936  }
937  else
938  {
939  //Compute t4 = t3^4
940  ecFieldSqrMod(state->curve, state->t4, state->t3);
941  ecFieldSqrMod(state->curve, state->t4, state->t4);
942  //Compute t4 = a * t4
943  ecFieldMulMod(state->curve, state->t4, state->t4, state->curve->a);
944  //Compute t5 = t1^2
945  ecFieldSqrMod(state->curve, state->t5, state->t1);
946  //Compute t4 = t4 + 3 * t5
947  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
948  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
949  ecFieldAddMod(state->curve, state->t4, state->t4, state->t5);
950  }
951 
952  //Compute t3 = t3 * t2
953  ecFieldMulMod(state->curve, state->t3, state->t3, state->t2);
954  //Compute t3 = 2 * t3
955  ecFieldAddMod(state->curve, state->t3, state->t3, state->t3);
956  //Compute t2 = t2^2
957  ecFieldSqrMod(state->curve, state->t2, state->t2);
958  //Compute t5 = t1 * t2
959  ecFieldMulMod(state->curve, state->t5, state->t1, state->t2);
960  //Compute t5 = 4 * t5
961  ecFieldAddMod(state->curve, state->t5, state->t5, state->t5);
962  ecFieldAddMod(state->curve, state->t5, state->t5, state->t5);
963  //Compute t1 = t4^2
964  ecFieldSqrMod(state->curve, state->t1, state->t4);
965  //Compute t1 = t1 - 2 * t5
966  ecFieldSubMod(state->curve, state->t1, state->t1, state->t5);
967  ecFieldSubMod(state->curve, state->t1, state->t1, state->t5);
968  //Compute t2 = t2^2
969  ecFieldSqrMod(state->curve, state->t2, state->t2);
970  //Compute t2 = 8 * t2
971  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
972  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
973  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
974  //Compute t5 = t5 - t1
975  ecFieldSubMod(state->curve, state->t5, state->t5, state->t1);
976  //Compute t5 = t4 * t5
977  ecFieldMulMod(state->curve, state->t5, state->t4, state->t5);
978  //Compute t2 = t5 - t2
979  ecFieldSubMod(state->curve, state->t2, state->t5, state->t2);
980 
981  //Set Rx = t1
982  ecScalarCopy(r->x, state->t1, pLen);
983  //Set Ry = t2
984  ecScalarCopy(r->y, state->t2, pLen);
985  //Set Rz = t3
986  ecScalarCopy(r->z, state->t3, pLen);
987  }
988 }
989 
990 
991 /**
992  * @brief Point addition (helper routine)
993  * @param[in] state Pointer to the working state
994  * @param[out] r Resulting point R = S + T
995  * @param[in] s First operand
996  * @param[in] t Second operand
997  **/
998 
999 void ecAdd(EcState *state, EcPoint3 *r, const EcPoint3 *s,
1000  const EcPoint3 *t)
1001 {
1002  uint_t pLen;
1003  uint32_t c;
1004 
1005  //Get the length of the modulus, in words
1006  pLen = (state->curve->fieldSize + 31) / 32;
1007 
1008  //Set t1 = Sx
1009  ecScalarCopy(state->t1, s->x, pLen);
1010  //Set t2 = Sy
1011  ecScalarCopy(state->t2, s->y, pLen);
1012  //Set t3 = Sz
1013  ecScalarCopy(state->t3, s->z, pLen);
1014  //Set t4 = Tx
1015  ecScalarCopy(state->t4, t->x, pLen);
1016  //Set t5 = Ty
1017  ecScalarCopy(state->t5, t->y, pLen);
1018 
1019  //Check whether Tz != 1
1020  if(ecScalarTestNotEqualInt(t->z, 1, pLen))
1021  {
1022  //Compute t6 = Tz
1023  ecScalarCopy(state->t6, t->z, pLen);
1024  //Compute t7 = t6^2
1025  ecFieldSqrMod(state->curve, state->t7, state->t6);
1026  //Compute t1 = t1 * t7
1027  ecFieldMulMod(state->curve, state->t1, state->t1, state->t7);
1028  //Compute t7 = t6 * t7
1029  ecFieldMulMod(state->curve, state->t7, state->t6, state->t7);
1030  //Compute t2 = t2 * t7
1031  ecFieldMulMod(state->curve, state->t2, state->t2, state->t7);
1032  }
1033 
1034  //Compute t7 = t3^2
1035  ecFieldSqrMod(state->curve, state->t7, state->t3);
1036  //Compute t4 = t4 * t7
1037  ecFieldMulMod(state->curve, state->t4, state->t4, state->t7);
1038  //Compute t7 = t3 * t7
1039  ecFieldMulMod(state->curve, state->t7, state->t3, state->t7);
1040  //Compute t5 = t5 * t7
1041  ecFieldMulMod(state->curve, state->t5, state->t5, state->t7);
1042  //Compute t4 = t1 - t4
1043  ecFieldSubMod(state->curve, state->t4, state->t1, state->t4);
1044  //Compute t5 = t2 - t5
1045  ecFieldSubMod(state->curve, state->t5, state->t2, state->t5);
1046 
1047  //Check whether t4 == 0
1048  if(ecScalarTestEqualInt(state->t4, 0, pLen))
1049  {
1050  //Check whether t5 == 0
1051  if(ecScalarTestEqualInt(state->t5, 0, pLen))
1052  {
1053  //Set R = (0, 0, 0)
1054  ecScalarSetInt(r->x, 0, pLen);
1055  ecScalarSetInt(r->y, 0, pLen);
1056  ecScalarSetInt(r->z, 0, pLen);
1057  }
1058  else
1059  {
1060  //Set R = (1, 1, 0)
1061  ecScalarSetInt(r->x, 1, pLen);
1062  ecScalarSetInt(r->y, 1, pLen);
1063  ecScalarSetInt(r->z, 0, pLen);
1064  }
1065  }
1066  else
1067  {
1068  //Compute t1 = 2 * t1 - t4
1069  ecFieldAddMod(state->curve, state->t1, state->t1, state->t1);
1070  ecFieldSubMod(state->curve, state->t1, state->t1, state->t4);
1071  //Compute t2 = 2 * t2 - t5
1072  ecFieldAddMod(state->curve, state->t2, state->t2, state->t2);
1073  ecFieldSubMod(state->curve, state->t2, state->t2, state->t5);
1074 
1075  //Check whether Tz != 1
1076  if(ecScalarTestNotEqualInt(t->z, 1, pLen))
1077  {
1078  //Compute t3 = t3 * t6
1079  ecFieldMulMod(state->curve, state->t3, state->t3, state->t6);
1080  }
1081 
1082  //Compute t3 = t3 * t4
1083  ecFieldMulMod(state->curve, state->t3, state->t3, state->t4);
1084  //Compute t7 = t4^2
1085  ecFieldSqrMod(state->curve, state->t7, state->t4);
1086  //Compute t4 = t4 * t7
1087  ecFieldMulMod(state->curve, state->t4, state->t4, state->t7);
1088  //Compute t7 = t1 * t7
1089  ecFieldMulMod(state->curve, state->t7, state->t1, state->t7);
1090  //Compute t1 = t5^2
1091  ecFieldSqrMod(state->curve, state->t1, state->t5);
1092  //Compute t1 = t1 - t7
1093  ecFieldSubMod(state->curve, state->t1, state->t1, state->t7);
1094  //Compute t7 = t7 - 2 * t1
1095  ecFieldAddMod(state->curve, state->t6, state->t1, state->t1);
1096  ecFieldSubMod(state->curve, state->t7, state->t7, state->t6);
1097  //Compute t5 = t5 * t7
1098  ecFieldMulMod(state->curve, state->t5, state->t5, state->t7);
1099  //Compute t4 = t2 * t4
1100  ecFieldMulMod(state->curve, state->t4, state->t2, state->t4);
1101  //Compute t2 = t5 - t4
1102  ecFieldSubMod(state->curve, state->t2, state->t5, state->t4);
1103 
1104  //Compute t2 = t2 / 2
1105  if(ecScalarGetBitValue(state->t2, 0) == 0)
1106  {
1107  //Perform a right shift operation
1108  ecScalarShiftRight(state->t2, state->t2, 1, pLen);
1109  }
1110  else
1111  {
1112  //First add p, then perform a right shift operation
1113  c = ecScalarAdd(state->t2, state->t2, state->curve->p, pLen);
1114  ecScalarShiftRight(state->t2, state->t2, 1, pLen);
1115  state->t2[pLen - 1] |= c << 31;
1116  }
1117 
1118  //Set Rx = t1
1119  ecScalarCopy(r->x, state->t1, pLen);
1120  //Set Ry = t2
1121  ecScalarCopy(r->y, state->t2, pLen);
1122  //Set Rz = t3
1123  ecScalarCopy(r->z, state->t3, pLen);
1124  }
1125 }
1126 
1127 
1128 /**
1129  * @brief Point addition
1130  * @param[in] state Pointer to the working state
1131  * @param[out] r Resulting point R = S + T
1132  * @param[in] s First operand
1133  * @param[in] t Second operand
1134  **/
1135 
1136 void ecFullAdd(EcState *state, EcPoint3 *r,
1137  const EcPoint3 *s, const EcPoint3 *t)
1138 {
1139  uint_t pLen;
1140  EcPoint3 u;
1141 
1142  //Get the length of the modulus, in words
1143  pLen = (state->curve->fieldSize + 31) / 32;
1144 
1145  //Check whether Sz == 0
1146  if(ecScalarTestEqualInt(s->z, 0, pLen))
1147  {
1148  //Set R = T
1149  ecScalarCopy(r->x, t->x, pLen);
1150  ecScalarCopy(r->y, t->y, pLen);
1151  ecScalarCopy(r->z, t->z, pLen);
1152  }
1153  //Check whether Tz == 0
1154  else if(ecScalarTestEqualInt(t->z, 0, pLen))
1155  {
1156  //Set R = S
1157  ecScalarCopy(r->x, s->x, pLen);
1158  ecScalarCopy(r->y, s->y, pLen);
1159  ecScalarCopy(r->z, s->z, pLen);
1160  }
1161  else
1162  {
1163  //Compute U = S + T
1164  ecAdd(state, &u, s, t);
1165 
1166  //Check whether U == (0, 0, 0)
1167  if(ecScalarTestEqualInt(u.x, 0, pLen) &&
1168  ecScalarTestEqualInt(u.y, 0, pLen) &&
1169  ecScalarTestEqualInt(u.z, 0, pLen))
1170  {
1171  //Compute R = 2 * S
1172  ecDouble(state, r, s);
1173  }
1174  else
1175  {
1176  //Set R = U
1177  ecScalarCopy(r->x, u.x, pLen);
1178  ecScalarCopy(r->y, u.y, pLen);
1179  ecScalarCopy(r->z, u.z, pLen);
1180  }
1181  }
1182 }
1183 
1184 
1185 /**
1186  * @brief Point subtraction
1187  * @param[in] state Pointer to the working state
1188  * @param[out] r Resulting point R = S - T
1189  * @param[in] s First operand
1190  * @param[in] t Second operand
1191  **/
1192 
1193 void ecFullSub(EcState *state, EcPoint3 *r, const EcPoint3 *s,
1194  const EcPoint3 *t)
1195 {
1196  uint_t pLen;
1197  EcPoint3 u;
1198 
1199  //Get the length of the modulus, in words
1200  pLen = (state->curve->fieldSize + 31) / 32;
1201 
1202  //Set Ux = Tx and Uz = Tz
1203  ecScalarCopy(u.x, t->x, pLen);
1204  ecScalarCopy(u.z, t->z, pLen);
1205 
1206  //Set Uy = p - Ty
1207  ecScalarSub(u.y, state->curve->p, t->y, pLen);
1208 
1209  //Compute R = S + U
1210  ecFullAdd(state, r, s, &u);
1211 }
1212 
1213 
1214 /**
1215  * @brief Scalar multiplication (fast calculation)
1216  * @param[in] curve Elliptic curve parameters
1217  * @param[out] r Resulting point R = d.S
1218  * @param[in] d An integer d such as 0 <= d < q
1219  * @param[in] s EC point
1220  * @return Error code
1221  **/
1222 
1223 __weak_func error_t ecMulFast(const EcCurve *curve, EcPoint3 *r,
1224  const uint32_t *d, const EcPoint3 *s)
1225 {
1226  uint_t i;
1227  uint_t pLen;
1228  uint_t qLen;
1229  uint32_t k[EC_MAX_ORDER_SIZE + 1];
1230  uint32_t h[EC_MAX_ORDER_SIZE + 1];
1231 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1232  EcMulFastState *state;
1233 #else
1234  EcMulFastState state[1];
1235 #endif
1236 
1237 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1238  //Allocate working state
1239  state = cryptoAllocMem(sizeof(EcMulFastState));
1240  //Failed to allocate memory?
1241  if(state == NULL)
1242  return ERROR_OUT_OF_MEMORY;
1243 #endif
1244 
1245  //Initialize working state
1246  osMemset(state, 0, sizeof(EcMulFastState));
1247  //Save elliptic curve parameters
1248  state->subState.curve = curve;
1249 
1250  //Get the length of the modulus, in words
1251  pLen = (curve->fieldSize + 31) / 32;
1252  //Get the length of the order, in words
1253  qLen = (curve->orderSize + 31) / 32;
1254 
1255  //Check whether d == 0
1256  if(ecScalarTestEqualInt(d, 0, pLen))
1257  {
1258  //Set R = (1, 1, 0)
1259  ecScalarSetInt(r->x, 1, pLen);
1260  ecScalarSetInt(r->y, 1, pLen);
1261  ecScalarSetInt(r->z, 0, pLen);
1262  }
1263  //Check whether d == 1
1264  else if(ecScalarTestEqualInt(d, 1, pLen))
1265  {
1266  //Set R = S
1267  ecScalarCopy(r->x, s->x, pLen);
1268  ecScalarCopy(r->y, s->y, pLen);
1269  ecScalarCopy(r->z, s->z, pLen);
1270  }
1271  //Check whether Sz == 0
1272  else if(ecScalarTestEqualInt(s->z, 0, pLen))
1273  {
1274  //Set R = (1, 1, 0)
1275  ecScalarSetInt(r->x, 1, pLen);
1276  ecScalarSetInt(r->y, 1, pLen);
1277  ecScalarSetInt(r->z, 0, pLen);
1278  }
1279  else
1280  {
1281  //Check whether Sz != 1
1282  if(ecScalarTestNotEqualInt(s->z, 1, pLen))
1283  {
1284  //Normalize S
1285  ecAffinify(curve, r, s);
1286  }
1287  else
1288  {
1289  //Set R = S
1290  ecScalarCopy(r->x, s->x, pLen);
1291  ecScalarCopy(r->y, s->y, pLen);
1292  ecScalarCopy(r->z, s->z, pLen);
1293  }
1294 
1295  //Let k = d
1296  ecScalarCopy(k, d, qLen);
1297  k[qLen] = 0;
1298 
1299  //Precompute h = 3 * d
1300  ecScalarAdd(h, k, k, qLen + 1);
1301  ecScalarAdd(h, h, k, qLen + 1);
1302 
1303  //Calculate the length of h, in bits
1304  pLen = ecScalarGetBitLength(h, qLen + 1);
1305 
1306  //Scalar multiplication
1307  for(i = pLen - 2; i >= 1; i--)
1308  {
1309  //Point doubling
1310  ecDouble(&state->subState, r, r);
1311 
1312  //Check the values of h(i) and k(i)
1313  if(ecScalarGetBitValue(h, i) != 0 &&
1314  ecScalarGetBitValue(k, i) == 0)
1315  {
1316  //If h(i) == 1 and k(i) == 0, then compute R = R + S
1317  ecFullAdd(&state->subState, r, r, s);
1318  }
1319  else if(ecScalarGetBitValue(h, i) == 0 &&
1320  ecScalarGetBitValue(k, i) != 0)
1321  {
1322  //If h(i) == 0 and k(i) == 1, then compute R = R - S
1323  ecFullSub(&state->subState, r, r, s);
1324  }
1325  else
1326  {
1327  //Just for sanity
1328  }
1329  }
1330  }
1331 
1332  //Erase working state
1333  osMemset(state, 0, sizeof(EcMulFastState));
1334 
1335 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1336  //Release working state
1337  cryptoFreeMem(state);
1338 #endif
1339 
1340  //Successful processing
1341  return NO_ERROR;
1342 }
1343 
1344 
1345 /**
1346  * @brief Scalar multiplication (regular calculation)
1347  * @param[in] curve Elliptic curve parameters
1348  * @param[out] r Resulting point R = d.S
1349  * @param[in] d An integer d such as 0 <= d < q
1350  * @param[in] s EC point
1351  * @return Error code
1352  **/
1353 
1354 __weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r,
1355  const uint32_t *d, const EcPoint3 *s)
1356 {
1357  int_t i;
1358  int_t pLen;
1359  uint32_t b;
1360 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1361  EcMulRegularState *state;
1362 #else
1363  EcMulRegularState state[1];
1364 #endif
1365 
1366 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1367  //Allocate working state
1368  state = cryptoAllocMem(sizeof(EcMulRegularState));
1369  //Failed to allocate memory?
1370  if(state == NULL)
1371  return ERROR_OUT_OF_MEMORY;
1372 #endif
1373 
1374  //Initialize working state
1375  osMemset(state, 0, sizeof(EcMulRegularState));
1376  //Save elliptic curve parameters
1377  state->subState.curve = curve;
1378 
1379  //Get the length of the modulus, in words
1380  pLen = (curve->fieldSize + 31) / 32;
1381 
1382  //Initialize the value of the flag
1383  state->init = ecScalarGetBitValue(d, curve->orderSize - 1);
1384 
1385  //Compute (P0, Q0) = DBLU(S)
1386  ecDblu(&state->subState, &state->p0, &state->q0, s);
1387 
1388  //Set P = P0
1389  ecScalarCopy(state->p.x, state->p0.x, pLen);
1390  ecScalarCopy(state->p.y, state->p0.y, pLen);
1391  ecScalarCopy(state->p.z, state->p0.z, pLen);
1392 
1393  //Set Q = Q0
1394  ecScalarCopy(state->q.x, state->q0.x, pLen);
1395  ecScalarCopy(state->q.y, state->q0.y, pLen);
1396  ecScalarCopy(state->q.z, state->q0.z, pLen);
1397 
1398  //Montgomery ladder with co-Z addition formulae
1399  for(i = curve->orderSize - 2; i >= 0; i--)
1400  {
1401  //The scalar is processed in a left-to-right fashion
1402  b = ecScalarGetBitValue(d, i);
1403 
1404  //Conditional swap
1405  ecScalarSwap(state->p.x, state->q.x, b, pLen);
1406  ecScalarSwap(state->p.y, state->q.y, b, pLen);
1407  ecScalarSwap(state->p.z, state->q.z, b, pLen);
1408 
1409  //Compute (P, Q) = ZADDC(Q, P)
1410  ecZaddc(&state->subState, &state->p, &state->q, &state->q, &state->p);
1411  //Compute (Q, P) = ZADDU(P, Q)
1412  ecZaddu(&state->subState, &state->q, &state->p, &state->p, &state->q);
1413 
1414  //Conditional swap
1415  ecScalarSwap(state->p.x, state->q.x, b, pLen);
1416  ecScalarSwap(state->p.y, state->q.y, b, pLen);
1417  ecScalarSwap(state->p.z, state->q.z, b, pLen);
1418 
1419  //The loop does not depend on the length of the secret scalar
1420  ecScalarSelect(state->p.x, state->p0.x, state->p.x, state->init, pLen);
1421  ecScalarSelect(state->p.y, state->p0.y, state->p.y, state->init, pLen);
1422  ecScalarSelect(state->p.z, state->p0.z, state->p.z, state->init, pLen);
1423  ecScalarSelect(state->q.x, state->q0.x, state->q.x, state->init, pLen);
1424  ecScalarSelect(state->q.y, state->q0.y, state->q.y, state->init, pLen);
1425  ecScalarSelect(state->q.z, state->q0.z, state->q.z, state->init, pLen);
1426 
1427  //Update the value of flag
1428  state->init |= b;
1429  }
1430 
1431  //Copy resulting point
1432  ecScalarCopy(r->x, state->q.x, pLen);
1433  ecScalarCopy(r->y, state->q.y, pLen);
1434  ecScalarCopy(r->z, state->q.z, pLen);
1435 
1436  //Erase working state
1437  osMemset(state, 0, sizeof(EcMulRegularState));
1438 
1439 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1440  //Release working state
1441  cryptoFreeMem(state);
1442 #endif
1443 
1444  //Successful processing
1445  return NO_ERROR;
1446 }
1447 
1448 
1449 /**
1450  * @brief Twin multiplication
1451  * @param[in] curve Elliptic curve parameters
1452  * @param[out] r Resulting point R = d0.S + d1.T
1453  * @param[in] d0 An integer d such as 0 <= d0 < q
1454  * @param[in] s EC point
1455  * @param[in] d1 An integer d such as 0 <= d1 < q
1456  * @param[in] t EC point
1457  * @return Error code
1458  **/
1459 
1460 __weak_func error_t ecTwinMul(const EcCurve *curve, EcPoint3 *r,
1461  const uint32_t *d0, const EcPoint3 *s, const uint32_t *d1,
1462  const EcPoint3 *t)
1463 {
1464  int_t k;
1465  uint_t pLen;
1466  uint_t m;
1467  uint_t m0;
1468  uint_t m1;
1469  uint_t c0;
1470  uint_t c1;
1471  uint_t h0;
1472  uint_t h1;
1473  int_t u0;
1474  int_t u1;
1475 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1476  EcTwinMulState *state;
1477 #else
1478  EcTwinMulState state[1];
1479 #endif
1480 
1481 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1482  //Allocate working state
1483  state = cryptoAllocMem(sizeof(EcTwinMulState));
1484  //Failed to allocate memory?
1485  if(state == NULL)
1486  return ERROR_OUT_OF_MEMORY;
1487 #endif
1488 
1489  //Initialize working state
1490  osMemset(state, 0, sizeof(EcTwinMulState));
1491  //Save elliptic curve parameters
1492  state->subState.curve = curve;
1493 
1494  //Get the length of the modulus, in words
1495  pLen = (curve->fieldSize + 31) / 32;
1496 
1497  //Precompute SpT = S + T
1498  ecFullAdd(&state->subState, &state->spt, s, t);
1499  //Precompute SmT = S - T
1500  ecFullSub(&state->subState, &state->smt, s, t);
1501 
1502  //Let m0 be the bit length of d0
1503  m0 = ecScalarGetBitLength(d0, (curve->orderSize + 31) / 32);
1504  //Let m1 be the bit length of d1
1505  m1 = ecScalarGetBitLength(d1, (curve->orderSize + 31) / 32);
1506  //Let m = MAX(m0, m1)
1507  m = MAX(m0, m1);
1508 
1509  //Let c be a 2 x 6 binary matrix
1510  c0 = ecScalarGetBitValue(d0, m - 4);
1511  c0 |= ecScalarGetBitValue(d0, m - 3) << 1;
1512  c0 |= ecScalarGetBitValue(d0, m - 2) << 2;
1513  c0 |= ecScalarGetBitValue(d0, m - 1) << 3;
1514  c1 = ecScalarGetBitValue(d1, m - 4);
1515  c1 |= ecScalarGetBitValue(d1, m - 3) << 1;
1516  c1 |= ecScalarGetBitValue(d1, m - 2) << 2;
1517  c1 |= ecScalarGetBitValue(d1, m - 1) << 3;
1518 
1519  //Set R = (1, 1, 0)
1520  ecScalarSetInt(r->x, 1, pLen);
1521  ecScalarSetInt(r->y, 1, pLen);
1522  ecScalarSetInt(r->z, 0, pLen);
1523 
1524  //Calculate both multiplications at the same time
1525  for(k = m; k >= 0; k--)
1526  {
1527  //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5)
1528  h0 = c0 & 0x1F;
1529 
1530  //Check whether c(0,0) == 1
1531  if(c0 & 0x20)
1532  {
1533  h0 = 31 - h0;
1534  }
1535 
1536  //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5)
1537  h1 = c1 & 0x1F;
1538 
1539  //Check whether c(1,0) == 1
1540  if(c1 & 0x20)
1541  {
1542  h1 = 31 - h1;
1543  }
1544 
1545  //Compute u(0)
1546  if(h0 < ecTwinMulF(h1))
1547  {
1548  u0 = 0;
1549  }
1550  else if(c0 & 0x20)
1551  {
1552  u0 = -1;
1553  }
1554  else
1555  {
1556  u0 = 1;
1557  }
1558 
1559  //Compute u(1)
1560  if(h1 < ecTwinMulF(h0))
1561  {
1562  u1 = 0;
1563  }
1564  else if(c1 & 0x20)
1565  {
1566  u1 = -1;
1567  }
1568  else
1569  {
1570  u1 = 1;
1571  }
1572 
1573  //Update c matrix
1574  c0 <<= 1;
1575  c0 |= ecScalarGetBitValue(d0, k - 5);
1576  c0 ^= u0 ? 0x20 : 0x00;
1577  c1 <<= 1;
1578  c1 |= ecScalarGetBitValue(d1, k - 5);
1579  c1 ^= u1 ? 0x20 : 0x00;
1580 
1581  //Point doubling
1582  ecDouble(&state->subState, r, r);
1583 
1584  //Check u(0) and u(1)
1585  if(u0 == -1 && u1 == -1)
1586  {
1587  //Compute R = R - SpT
1588  ecFullSub(&state->subState, r, r, &state->spt);
1589  }
1590  else if(u0 == -1 && u1 == 0)
1591  {
1592  //Compute R = R - S
1593  ecFullSub(&state->subState, r, r, s);
1594  }
1595  else if(u0 == -1 && u1 == 1)
1596  {
1597  //Compute R = R - SmT
1598  ecFullSub(&state->subState, r, r, &state->smt);
1599  }
1600  else if(u0 == 0 && u1 == -1)
1601  {
1602  //Compute R = R - T
1603  ecFullSub(&state->subState, r, r, t);
1604  }
1605  else if(u0 == 0 && u1 == 1)
1606  {
1607  //Compute R = R + T
1608  ecFullAdd(&state->subState, r, r, t);
1609  }
1610  else if(u0 == 1 && u1 == -1)
1611  {
1612  //Compute R = R + SmT
1613  ecFullAdd(&state->subState, r, r, &state->smt);
1614  }
1615  else if(u0 == 1 && u1 == 0)
1616  {
1617  //Compute R = R + S
1618  ecFullAdd(&state->subState, r, r, s);
1619  }
1620  else if(u0 == 1 && u1 == 1)
1621  {
1622  //Compute R = R + SpT
1623  ecFullAdd(&state->subState, r, r, &state->spt);
1624  }
1625  else
1626  {
1627  }
1628  }
1629 
1630  //Erase working state
1631  osMemset(state, 0, sizeof(EcTwinMulState));
1632 
1633 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
1634  //Release working state
1635  cryptoFreeMem(state);
1636 #endif
1637 
1638  //Successful processing
1639  return NO_ERROR;
1640 }
1641 
1642 #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
@ 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:791
@ 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:1223
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
error_t ecExportPoint(const EcCurve *curve, const EcPoint *a, uint8_t *output, size_t *written)
Convert an EC point to an octet string.
Definition: ec.c:712
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:980
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:244
EcPoint3 spt
Definition: ec.h:491
error_t ecImportPoint(const EcCurve *curve, EcPoint *r, const uint8_t *input, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:663
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:1136
#define TRUE
Definition: os_port.h:50
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
error_t ecImportPublicKey(EcPublicKey *key, const EcCurve *curve, const uint8_t *input, size_t length, EcPublicKeyFormat format)
Import an EC public key.
Definition: ec.c:263
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
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
void ecDouble(EcState *state, EcPoint3 *r, const EcPoint3 *s)
Point doubling.
Definition: ec.c:890
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:1460
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 *output, size_t *written)
Export an EC private key.
Definition: ec.c:578
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
@ EC_SCALAR_FORMAT_LITTLE_ENDIAN
Definition: ec_misc.h:50
error_t ecImportPrivateKey(EcPrivateKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EC private key.
Definition: ec.c:514
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:999
__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:840
const EcCurve * curve
Definition: ec.h:446
void ecFullSub(EcState *state, EcPoint3 *r, const EcPoint3 *s, const EcPoint3 *t)
Point subtraction.
Definition: ec.c:1193
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:833
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:762
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1354
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:828
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
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