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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "ecc/ec.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (EC_SUPPORT == ENABLED)
41 
42 //EC Public Key OID (1.2.840.10045.2.1)
43 const uint8_t EC_PUBLIC_KEY_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
44 
45 
46 /**
47  * @brief Initialize EC domain parameters
48  * @param[in] params Pointer to the EC domain parameters to initialize
49  **/
50 
52 {
53  //Initialize structure
54  params->name = NULL;
55  params->type = EC_CURVE_TYPE_NONE;
56  params->mod = NULL;
57 
58  //Initialize EC domain parameters
59  mpiInit(&params->p);
60  mpiInit(&params->a);
61  mpiInit(&params->b);
62  ecInit(&params->g);
63  mpiInit(&params->q);
64 }
65 
66 
67 /**
68  * @brief Release EC domain parameters
69  * @param[in] params Pointer to the EC domain parameters to free
70  **/
71 
73 {
74  //Release previously allocated resources
75  mpiFree(&params->p);
76  mpiFree(&params->a);
77  mpiFree(&params->b);
78  ecFree(&params->g);
79  mpiFree(&params->q);
80 }
81 
82 
83 /**
84  * @brief Load EC domain parameters
85  * @param[out] params Pointer to the structure to be initialized
86  * @param[in] curveInfo Elliptic curve parameters
87  * @return Error code
88  **/
89 
91  const EcCurveInfo *curveInfo)
92 {
93  error_t error;
94 
95  //Check parameters
96  if(params == NULL || curveInfo == NULL)
98 
99  //Debug message
100  TRACE_DEBUG("Loading %s EC domain parameters...\r\n", curveInfo->name);
101 
102  //Curve name
103  params->name = curveInfo->name;
104  //Curve type
105  params->type = curveInfo->type;
106 
107  //Import prime modulus
108  MPI_CHECK(mpiReadRaw(&params->p, curveInfo->p, curveInfo->pLen));
109  //Import parameter a
110  MPI_CHECK(mpiReadRaw(&params->a, curveInfo->a, curveInfo->aLen));
111  //Import parameter b
112  MPI_CHECK(mpiReadRaw(&params->b, curveInfo->b, curveInfo->bLen));
113  //Import the x-coordinate of the base point G
114  MPI_CHECK(mpiReadRaw(&params->g.x, curveInfo->gx, curveInfo->gxLen));
115  //Import the y-coordinate of the base point G
116  MPI_CHECK(mpiReadRaw(&params->g.y, curveInfo->gy, curveInfo->gyLen));
117  //Import base point order q
118  MPI_CHECK(mpiReadRaw(&params->q, curveInfo->q, curveInfo->qLen));
119 
120  //Normalize base point G
121  MPI_CHECK(mpiSetValue(&params->g.z, 1));
122 
123  //Cofactor h
124  params->h = curveInfo->h;
125  //Fast modular reduction
126  params->mod = curveInfo->mod;
127 
128  //Debug message
129  TRACE_DEBUG(" p:\r\n");
130  TRACE_DEBUG_MPI(" ", &params->p);
131  TRACE_DEBUG(" a:\r\n");
132  TRACE_DEBUG_MPI(" ", &params->a);
133  TRACE_DEBUG(" b:\r\n");
134  TRACE_DEBUG_MPI(" ", &params->b);
135  TRACE_DEBUG(" Gx:\r\n");
136  TRACE_DEBUG_MPI(" ", &params->g.x);
137  TRACE_DEBUG(" Gy:\r\n");
138  TRACE_DEBUG_MPI(" ", &params->g.y);
139  TRACE_DEBUG(" q:\r\n");
140  TRACE_DEBUG_MPI(" ", &params->q);
141 
142 end:
143  //Return status code
144  return error;
145 }
146 
147 
148 /**
149  * @brief Initialize an EC public key
150  * @param[in] key Pointer to the EC public key to initialize
151  **/
152 
154 {
155  //Initialize EC point
156  ecInit(&key->q);
157 }
158 
159 
160 /**
161  * @brief Release an EC public key
162  * @param[in] key Pointer to the EC public key to free
163  **/
164 
166 {
167  //Free EC point
168  ecFree(&key->q);
169 }
170 
171 
172 /**
173  * @brief Initialize an EC private key
174  * @param[in] key Pointer to the EC private key to initialize
175  **/
176 
178 {
179  //Initialize multiple precision integer
180  mpiInit(&key->d);
181 
182  //Initialize private key slot
183  key->slot = -1;
184 }
185 
186 
187 /**
188  * @brief Release an EdDSA private key
189  * @param[in] key Pointer to the EC public key to free
190  **/
191 
193 {
194  //Free multiple precision integer
195  mpiFree(&key->d);
196 }
197 
198 
199 /**
200  * @brief EC key pair generation
201  * @param[in] prngAlgo PRNG algorithm
202  * @param[in] prngContext Pointer to the PRNG context
203  * @param[in] params EC domain parameters
204  * @param[out] privateKey EC private key
205  * @param[out] publicKey EC public key
206  * @return Error code
207  **/
208 
209 __weak_func error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext,
210  const EcDomainParameters *params, EcPrivateKey *privateKey,
211  EcPublicKey *publicKey)
212 {
213  error_t error;
214 
215  //Generate a private key
216  error = ecGeneratePrivateKey(prngAlgo, prngContext, params, privateKey);
217 
218  //Check status code
219  if(!error)
220  {
221  //Derive the public key from the private key
222  error = ecGeneratePublicKey(params, privateKey, publicKey);
223  }
224 
225  //Return status code
226  return error;
227 }
228 
229 
230 /**
231  * @brief EC private key generation
232  * @param[in] prngAlgo PRNG algorithm
233  * @param[in] prngContext Pointer to the PRNG context
234  * @param[in] params EC domain parameters
235  * @param[out] privateKey EC private key
236  * @return Error code
237  **/
238 
239 error_t ecGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
240  const EcDomainParameters *params, EcPrivateKey *privateKey)
241 {
242  error_t error;
243 
244  //Check parameters
245  if(prngAlgo == NULL || prngContext == NULL || params == NULL ||
246  privateKey == NULL)
247  {
249  }
250 
251  //Generate a random number d such as 0 < d < q - 1
252  error = mpiRandRange(&privateKey->d, &params->q, prngAlgo, prngContext);
253 
254  //Check status code
255  if(!error)
256  {
257  //Debug message
258  TRACE_DEBUG(" Private key:\r\n");
259  TRACE_DEBUG_MPI(" ", &privateKey->d);
260  }
261 
262  //Return status code
263  return error;
264 }
265 
266 
267 /**
268  * @brief Derive the public key from an EC private key
269  * @param[in] params EC domain parameters
270  * @param[in] privateKey EC private key
271  * @param[out] publicKey EC public key
272  * @return Error code
273  **/
274 
276  const EcPrivateKey *privateKey, EcPublicKey *publicKey)
277 {
278  error_t error;
279 
280  //Check parameters
281  if(params == NULL || privateKey == NULL || publicKey == NULL)
283 
284  //Compute Q = d.G
285  EC_CHECK(ecMult(params, &publicKey->q, &privateKey->d, &params->g));
286 
287  //Convert the public key to affine representation
288  EC_CHECK(ecAffinify(params, &publicKey->q, &publicKey->q));
289 
290  //Debug message
291  TRACE_DEBUG(" Public key X:\r\n");
292  TRACE_DEBUG_MPI(" ", &publicKey->q.x);
293  TRACE_DEBUG(" Public key Y:\r\n");
294  TRACE_DEBUG_MPI(" ", &publicKey->q.y);
295 
296 end:
297  //Return status code
298  return error;
299 }
300 
301 
302 /**
303  * @brief Initialize elliptic curve point
304  * @param[in,out] r Pointer to the EC point to be initialized
305  **/
306 
308 {
309  //Initialize structure
310  mpiInit(&r->x);
311  mpiInit(&r->y);
312  mpiInit(&r->z);
313 }
314 
315 
316 /**
317  * @brief Release an elliptic curve point
318  * @param[in,out] r Pointer to the EC point to initialize to free
319  **/
320 
322 {
323  //Release previously allocated resources
324  mpiFree(&r->x);
325  mpiFree(&r->y);
326  mpiFree(&r->z);
327 }
328 
329 
330 /**
331  * @brief Copy EC point
332  * @param[out] r Destination EC point
333  * @param[in] s Source EC point
334  * @return Error code
335  **/
336 
338 {
339  error_t error;
340 
341  //R and S are the same instance?
342  if(r == s)
343  return NO_ERROR;
344 
345  //Copy coordinates
346  MPI_CHECK(mpiCopy(&r->x, &s->x));
347  MPI_CHECK(mpiCopy(&r->y, &s->y));
348  MPI_CHECK(mpiCopy(&r->z, &s->z));
349 
350 end:
351  //Return status code
352  return error;
353 }
354 
355 
356 /**
357  * @brief Convert an octet string to an EC point
358  * @param[in] params EC domain parameters
359  * @param[out] r EC point resulting from the conversion
360  * @param[in] data Pointer to the octet string
361  * @param[in] length Length of the octet string
362  * @return Error code
363  **/
364 
366  const uint8_t *data, size_t length)
367 {
368  error_t error;
369 
370  //Montgomery or Edwards curve?
371  if(params->type == EC_CURVE_TYPE_X25519 ||
372  params->type == EC_CURVE_TYPE_X448 ||
373  params->type == EC_CURVE_TYPE_ED25519 ||
374  params->type == EC_CURVE_TYPE_ED448)
375  {
376  //Empty octet string?
377  if(length == 0)
379 
380  //Check the length of the octet string
381  if((params->type == EC_CURVE_TYPE_X25519 && length != 32) ||
382  (params->type == EC_CURVE_TYPE_X448 && length != 56) ||
383  (params->type == EC_CURVE_TYPE_ED25519 && length != 32) ||
384  (params->type == EC_CURVE_TYPE_ED448 && length != 57))
385  {
387  }
388 
389  //Convert the octet string to a multiple precision integer
391  //Any error to report?
392  if(error)
393  return error;
394  }
395  //Weierstrass curve?
396  else
397  {
398  size_t k;
399 
400  //Get the length in octets of the prime
401  k = mpiGetByteLength(&params->p);
402 
403  //Check the length of the octet string
404  if(length != (k * 2 + 1))
406 
407  //Compressed point representation is not supported
410 
411  //Convert the x-coordinate to a multiple precision integer
412  error = mpiImport(&r->x, data + 1, k, MPI_FORMAT_BIG_ENDIAN);
413  //Any error to report?
414  if(error)
415  return error;
416 
417  //Convert the y-coordinate to a multiple precision integer
418  error = mpiImport(&r->y, data + k + 1, k, MPI_FORMAT_BIG_ENDIAN);
419  //Any error to report?
420  if(error)
421  return error;
422  }
423 
424  //Successful processing
425  return NO_ERROR;
426 }
427 
428 
429 /**
430  * @brief Convert an EC point to an octet string
431  * @param[in] params EC domain parameters
432  * @param[in] a EC point to be converted
433  * @param[out] data Pointer to the octet string
434  * @param[out] length Length of the resulting octet string
435  * @return Error code
436  **/
437 
439  uint8_t *data, size_t *length)
440 {
441  error_t error;
442  size_t k;
443 
444  //Get the length in octets of the prime
445  k = mpiGetByteLength(&params->p);
446 
447  //Montgomery curve?
448  if(params->type == EC_CURVE_TYPE_X25519 ||
449  params->type == EC_CURVE_TYPE_X448)
450  {
451  //Convert the u-coordinate to an octet string
452  error = mpiExport(&a->x, data, k, MPI_FORMAT_LITTLE_ENDIAN);
453  //Conversion failed?
454  if(error)
455  return error;
456 
457  //Return the total number of bytes that have been written
458  *length = k;
459  }
460  //Weierstrass curve?
461  else
462  {
463  //Point compression is not used
465 
466  //Convert the x-coordinate to an octet string
467  error = mpiExport(&a->x, data + 1, k, MPI_FORMAT_BIG_ENDIAN);
468  //Conversion failed?
469  if(error)
470  return error;
471 
472  //Convert the y-coordinate to an octet string
473  error = mpiExport(&a->y, data + k + 1, k, MPI_FORMAT_BIG_ENDIAN);
474  //Conversion failed?
475  if(error)
476  return error;
477 
478  //Return the total number of bytes that have been written
479  *length = k * 2 + 1;
480  }
481 
482  //Successful processing
483  return NO_ERROR;
484 }
485 
486 
487 /**
488  * @brief Compute projective representation
489  * @param[in] params EC domain parameters
490  * @param[out] r Projective representation of the point
491  * @param[in] s Affine representation of the point
492  * @return Error code
493  **/
494 
496  const EcPoint *s)
497 {
498  error_t error;
499 
500  //Copy point
501  EC_CHECK(ecCopy(r, s));
502  //Map the point to projective space
503  MPI_CHECK(mpiSetValue(&r->z, 1));
504 
505 end:
506  //Return status code
507  return error;
508 }
509 
510 
511 /**
512  * @brief Recover affine representation
513  * @param[in] params EC domain parameters
514  * @param[out] r Affine representation of the point
515  * @param[in] s Projective representation of the point
516  * @return Error code
517  **/
518 
519 __weak_func error_t ecAffinify(const EcDomainParameters *params, EcPoint *r,
520  const EcPoint *s)
521 {
522  error_t error;
523  Mpi a;
524  Mpi b;
525 
526  //Point at the infinity?
527  if(mpiCompInt(&s->z, 0) == 0)
529 
530  //Initialize multiple precision integers
531  mpiInit(&a);
532  mpiInit(&b);
533 
534  //Compute a = 1/Sz mod p
535  MPI_CHECK(mpiInvMod(&a, &s->z, &params->p));
536 
537  //Set Rx = a^2 * Sx mod p
538  EC_CHECK(ecSqrMod(params, &b, &a));
539  EC_CHECK(ecMulMod(params, &r->x, &b, &s->x));
540 
541  //Set Ry = a^3 * Sy mod p
542  EC_CHECK(ecMulMod(params, &b, &b, &a));
543  EC_CHECK(ecMulMod(params, &r->y, &b, &s->y));
544 
545  //Set Rz = 1
546  MPI_CHECK(mpiSetValue(&r->z, 1));
547 
548 end:
549  //Release multiple precision integers
550  mpiFree(&a);
551  mpiFree(&b);
552 
553  //Return status code
554  return error;
555 }
556 
557 
558 /**
559  * @brief Check whether the affine point S is on the curve
560  * @param[in] params EC domain parameters
561  * @param[in] s Affine representation of the point
562  * @return TRUE if the affine point S is on the curve, else FALSE
563  **/
564 
565 __weak_func bool_t ecIsPointAffine(const EcDomainParameters *params, const EcPoint *s)
566 {
567  error_t error;
568  Mpi t1;
569  Mpi t2;
570 
571  //Initialize multiple precision integers
572  mpiInit(&t1);
573  mpiInit(&t2);
574 
575  //Compute t1 = (Sx^3 + a * Sx + b) mod p
576  EC_CHECK(ecSqrMod(params, &t1, &s->x));
577  EC_CHECK(ecMulMod(params, &t1, &t1, &s->x));
578  EC_CHECK(ecMulMod(params, &t2, &params->a, &s->x));
579  EC_CHECK(ecAddMod(params, &t1, &t1, &t2));
580  EC_CHECK(ecAddMod(params, &t1, &t1, &params->b));
581 
582  //Compute t2 = Sy^2
583  EC_CHECK(ecSqrMod(params, &t2, &s->y));
584 
585  //Check whether the point is on the elliptic curve
586  if(mpiComp(&t1, &t2) != 0)
587  error = ERROR_FAILURE;
588 
589 end:
590  //Release multiple precision integers
591  mpiFree(&t1);
592  mpiFree(&t2);
593 
594  //Return TRUE if the affine point S is on the curve, else FALSE
595  return error ? FALSE : TRUE;
596 }
597 
598 
599 /**
600  * @brief Point doubling
601  * @param[in] params EC domain parameters
602  * @param[out] r Resulting point R = 2S
603  * @param[in] s Point S
604  * @return Error code
605  **/
606 
608  const EcPoint *s)
609 {
610  error_t error;
611  Mpi t1;
612  Mpi t2;
613  Mpi t3;
614  Mpi t4;
615  Mpi t5;
616 
617  //Initialize multiple precision integers
618  mpiInit(&t1);
619  mpiInit(&t2);
620  mpiInit(&t3);
621  mpiInit(&t4);
622  mpiInit(&t5);
623 
624  //Set t1 = Sx
625  MPI_CHECK(mpiCopy(&t1, &s->x));
626  //Set t2 = Sy
627  MPI_CHECK(mpiCopy(&t2, &s->y));
628  //Set t3 = Sz
629  MPI_CHECK(mpiCopy(&t3, &s->z));
630 
631  //Point at the infinity?
632  if(mpiCompInt(&t3, 0) == 0)
633  {
634  //Set R = (1, 1, 0)
635  MPI_CHECK(mpiSetValue(&r->x, 1));
636  MPI_CHECK(mpiSetValue(&r->y, 1));
637  MPI_CHECK(mpiSetValue(&r->z, 0));
638  }
639  else
640  {
641  //SECP K1 elliptic curve?
642  if(params->type == EC_CURVE_TYPE_SECP_K1)
643  {
644  //Compute t5 = t1^2
645  EC_CHECK(ecSqrMod(params, &t5, &t1));
646  //Compute t4 = 3 * t5
647  EC_CHECK(ecAddMod(params, &t4, &t5, &t5));
648  EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
649  }
650  //SECP R1 elliptic curve?
651  else if(params->type == EC_CURVE_TYPE_SECP_R1)
652  {
653  //Compute t4 = t3^2
654  EC_CHECK(ecSqrMod(params, &t4, &t3));
655  //Compute t5 = t1 - t4
656  EC_CHECK(ecSubMod(params, &t5, &t1, &t4));
657  //Compute t4 = t1 + t4
658  EC_CHECK(ecAddMod(params, &t4, &t1, &t4));
659  //Compute t5 = t4 * t5
660  EC_CHECK(ecMulMod(params, &t5, &t4, &t5));
661  //Compute t4 = 3 * t5
662  EC_CHECK(ecAddMod(params, &t4, &t5, &t5));
663  EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
664  }
665  else
666  {
667  //Compute t4 = t3^4
668  EC_CHECK(ecSqrMod(params, &t4, &t3));
669  EC_CHECK(ecSqrMod(params, &t4, &t4));
670  //Compute t4 = a * t4
671  EC_CHECK(ecMulMod(params, &t4, &t4, &params->a));
672  //Compute t5 = t1^2
673  EC_CHECK(ecSqrMod(params, &t5, &t1));
674  //Compute t4 = t4 + 3 * t5
675  EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
676  EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
677  EC_CHECK(ecAddMod(params, &t4, &t4, &t5));
678  }
679 
680  //Compute t3 = t3 * t2
681  EC_CHECK(ecMulMod(params, &t3, &t3, &t2));
682  //Compute t3 = 2 * t3
683  EC_CHECK(ecAddMod(params, &t3, &t3, &t3));
684  //Compute t2 = t2^2
685  EC_CHECK(ecSqrMod(params, &t2, &t2));
686  //Compute t5 = t1 * t2
687  EC_CHECK(ecMulMod(params, &t5, &t1, &t2));
688  //Compute t5 = 4 * t5
689  EC_CHECK(ecAddMod(params, &t5, &t5, &t5));
690  EC_CHECK(ecAddMod(params, &t5, &t5, &t5));
691  //Compute t1 = t4^2
692  EC_CHECK(ecSqrMod(params, &t1, &t4));
693  //Compute t1 = t1 - 2 * t5
694  EC_CHECK(ecSubMod(params, &t1, &t1, &t5));
695  EC_CHECK(ecSubMod(params, &t1, &t1, &t5));
696  //Compute t2 = t2^2
697  EC_CHECK(ecSqrMod(params, &t2, &t2));
698  //Compute t2 = 8 * t2
699  EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
700  EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
701  EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
702  //Compute t5 = t5 - t1
703  EC_CHECK(ecSubMod(params, &t5, &t5, &t1));
704  //Compute t5 = t4 * t5
705  EC_CHECK(ecMulMod(params, &t5, &t4, &t5));
706  //Compute t2 = t5 - t2
707  EC_CHECK(ecSubMod(params, &t2, &t5, &t2));
708 
709  //Set Rx = t1
710  MPI_CHECK(mpiCopy(&r->x, &t1));
711  //Set Ry = t2
712  MPI_CHECK(mpiCopy(&r->y, &t2));
713  //Set Rz = t3
714  MPI_CHECK(mpiCopy(&r->z, &t3));
715  }
716 
717 end:
718  //Release multiple precision integers
719  mpiFree(&t1);
720  mpiFree(&t2);
721  mpiFree(&t3);
722  mpiFree(&t4);
723  mpiFree(&t5);
724 
725  //Return status code
726  return error;
727 }
728 
729 
730 /**
731  * @brief Point addition (helper routine)
732  * @param[in] params EC domain parameters
733  * @param[out] r Resulting point R = S + T
734  * @param[in] s First operand
735  * @param[in] t Second operand
736  * @return Error code
737  **/
738 
740  const EcPoint *s, const EcPoint *t)
741 {
742  error_t error;
743  Mpi t1;
744  Mpi t2;
745  Mpi t3;
746  Mpi t4;
747  Mpi t5;
748  Mpi t6;
749  Mpi t7;
750 
751  //Initialize multiple precision integers
752  mpiInit(&t1);
753  mpiInit(&t2);
754  mpiInit(&t3);
755  mpiInit(&t4);
756  mpiInit(&t5);
757  mpiInit(&t6);
758  mpiInit(&t7);
759 
760  //Set t1 = Sx
761  MPI_CHECK(mpiCopy(&t1, &s->x));
762  //Set t2 = Sy
763  MPI_CHECK(mpiCopy(&t2, &s->y));
764  //Set t3 = Sz
765  MPI_CHECK(mpiCopy(&t3, &s->z));
766  //Set t4 = Tx
767  MPI_CHECK(mpiCopy(&t4, &t->x));
768  //Set t5 = Ty
769  MPI_CHECK(mpiCopy(&t5, &t->y));
770 
771  //Check whether Tz != 1
772  if(mpiCompInt(&t->z, 1) != 0)
773  {
774  //Compute t6 = Tz
775  MPI_CHECK(mpiCopy(&t6, &t->z));
776  //Compute t7 = t6^2
777  EC_CHECK(ecSqrMod(params, &t7, &t6));
778  //Compute t1 = t1 * t7
779  EC_CHECK(ecMulMod(params, &t1, &t1, &t7));
780  //Compute t7 = t6 * t7
781  EC_CHECK(ecMulMod(params, &t7, &t6, &t7));
782  //Compute t2 = t2 * t7
783  EC_CHECK(ecMulMod(params, &t2, &t2, &t7));
784  }
785 
786  //Compute t7 = t3^2
787  EC_CHECK(ecSqrMod(params, &t7, &t3));
788  //Compute t4 = t4 * t7
789  EC_CHECK(ecMulMod(params, &t4, &t4, &t7));
790  //Compute t7 = t3 * t7
791  EC_CHECK(ecMulMod(params, &t7, &t3, &t7));
792  //Compute t5 = t5 * t7
793  EC_CHECK(ecMulMod(params, &t5, &t5, &t7));
794  //Compute t4 = t1 - t4
795  EC_CHECK(ecSubMod(params, &t4, &t1, &t4));
796  //Compute t5 = t2 - t5
797  EC_CHECK(ecSubMod(params, &t5, &t2, &t5));
798 
799  //Check whether t4 == 0
800  if(mpiCompInt(&t4, 0) == 0)
801  {
802  //Check whether t5 == 0
803  if(mpiCompInt(&t5, 0) == 0)
804  {
805  //Set R = (0, 0, 0)
806  MPI_CHECK(mpiSetValue(&r->x, 0));
807  MPI_CHECK(mpiSetValue(&r->y, 0));
808  MPI_CHECK(mpiSetValue(&r->z, 0));
809  }
810  else
811  {
812  //Set R = (1, 1, 0)
813  MPI_CHECK(mpiSetValue(&r->x, 1));
814  MPI_CHECK(mpiSetValue(&r->y, 1));
815  MPI_CHECK(mpiSetValue(&r->z, 0));
816  }
817  }
818  else
819  {
820  //Compute t1 = 2 * t1 - t4
821  EC_CHECK(ecAddMod(params, &t1, &t1, &t1));
822  EC_CHECK(ecSubMod(params, &t1, &t1, &t4));
823  //Compute t2 = 2 * t2 - t5
824  EC_CHECK(ecAddMod(params, &t2, &t2, &t2));
825  EC_CHECK(ecSubMod(params, &t2, &t2, &t5));
826 
827  //Check whether Tz != 1
828  if(mpiCompInt(&t->z, 1) != 0)
829  {
830  //Compute t3 = t3 * t6
831  EC_CHECK(ecMulMod(params, &t3, &t3, &t6));
832  }
833 
834  //Compute t3 = t3 * t4
835  EC_CHECK(ecMulMod(params, &t3, &t3, &t4));
836  //Compute t7 = t4^2
837  EC_CHECK(ecSqrMod(params, &t7, &t4));
838  //Compute t4 = t4 * t7
839  EC_CHECK(ecMulMod(params, &t4, &t4, &t7));
840  //Compute t7 = t1 * t7
841  EC_CHECK(ecMulMod(params, &t7, &t1, &t7));
842  //Compute t1 = t5^2
843  EC_CHECK(ecSqrMod(params, &t1, &t5));
844  //Compute t1 = t1 - t7
845  EC_CHECK(ecSubMod(params, &t1, &t1, &t7));
846  //Compute t7 = t7 - 2 * t1
847  EC_CHECK(ecAddMod(params, &t6, &t1, &t1));
848  EC_CHECK(ecSubMod(params, &t7, &t7, &t6));
849  //Compute t5 = t5 * t7
850  EC_CHECK(ecMulMod(params, &t5, &t5, &t7));
851  //Compute t4 = t2 * t4
852  EC_CHECK(ecMulMod(params, &t4, &t2, &t4));
853  //Compute t2 = t5 - t4
854  EC_CHECK(ecSubMod(params, &t2, &t5, &t4));
855 
856  //Compute t2 = t2 / 2
857  if(mpiIsEven(&t2))
858  {
859  MPI_CHECK(mpiShiftRight(&t2, 1));
860  }
861  else
862  {
863  MPI_CHECK(mpiAdd(&t2, &t2, &params->p));
864  MPI_CHECK(mpiShiftRight(&t2, 1));
865  }
866 
867  //Set Rx = t1
868  MPI_CHECK(mpiCopy(&r->x, &t1));
869  //Set Ry = t2
870  MPI_CHECK(mpiCopy(&r->y, &t2));
871  //Set Rz = t3
872  MPI_CHECK(mpiCopy(&r->z, &t3));
873  }
874 
875 end:
876  //Release multiple precision integers
877  mpiFree(&t1);
878  mpiFree(&t2);
879  mpiFree(&t3);
880  mpiFree(&t4);
881  mpiFree(&t5);
882  mpiFree(&t6);
883  mpiFree(&t7);
884 
885  //Return status code
886  return error;
887 }
888 
889 
890 /**
891  * @brief Point addition
892  * @param[in] params EC domain parameters
893  * @param[out] r Resulting point R = S + T
894  * @param[in] s First operand
895  * @param[in] t Second operand
896  * @return Error code
897  **/
898 
900  const EcPoint *s, const EcPoint *t)
901 {
902  error_t error;
903  EcPoint u;
904 
905  //Initialize EC point
906  ecInit(&u);
907 
908  //Check whether Sz == 0
909  if(mpiCompInt(&s->z, 0) == 0)
910  {
911  //Set R = T
912  MPI_CHECK(mpiCopy(&r->x, &t->x));
913  MPI_CHECK(mpiCopy(&r->y, &t->y));
914  MPI_CHECK(mpiCopy(&r->z, &t->z));
915  }
916  //Check whether Tz == 0
917  else if(mpiCompInt(&t->z, 0) == 0)
918  {
919  //Set R = S
920  MPI_CHECK(mpiCopy(&r->x, &s->x));
921  MPI_CHECK(mpiCopy(&r->y, &s->y));
922  MPI_CHECK(mpiCopy(&r->z, &s->z));
923  }
924  else
925  {
926  //Compute U = S + T
927  EC_CHECK(ecAdd(params, &u, s, t));
928 
929  //Check whether U == (0, 0, 0)
930  if(mpiCompInt(&u.x, 0) == 0 &&
931  mpiCompInt(&u.y, 0) == 0 &&
932  mpiCompInt(&u.z, 0) == 0)
933  {
934  //Compute R = 2 * S
935  EC_CHECK(ecDouble(params, r, s));
936  }
937  else
938  {
939  //Set R = U
940  EC_CHECK(ecCopy(r, &u));
941  }
942  }
943 
944 end:
945  //Release EC point
946  ecFree(&u);
947 
948  //Return status code
949  return error;
950 }
951 
952 
953 /**
954  * @brief Point subtraction
955  * @param[in] params EC domain parameters
956  * @param[out] r Resulting point R = S - T
957  * @param[in] s First operand
958  * @param[in] t Second operand
959  * @return Error code
960  **/
961 
963  const EcPoint *s, const EcPoint *t)
964 {
965  error_t error;
966  EcPoint u;
967 
968  //Initialize EC point
969  ecInit(&u);
970 
971  //Set Ux = Tx and Uz = Tz
972  MPI_CHECK(mpiCopy(&u.x, &t->x));
973  MPI_CHECK(mpiCopy(&u.z, &t->z));
974  //Set Uy = p - Ty
975  MPI_CHECK(mpiSub(&u.y, &params->p, &t->y));
976 
977  //Compute R = S + U
978  EC_CHECK(ecFullAdd(params, r, s, &u));
979 
980 end:
981  //Release EC point
982  ecFree(&u);
983 
984  //Return status code
985  return error;
986 }
987 
988 
989 /**
990  * @brief Scalar multiplication
991  * @param[in] params EC domain parameters
992  * @param[out] r Resulting point R = d.S
993  * @param[in] d An integer d such as 0 <= d < p
994  * @param[in] s EC point
995  * @return Error code
996  **/
997 
998 __weak_func error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d,
999  const EcPoint *s)
1000 {
1001  error_t error;
1002  uint_t i;
1003  Mpi h;
1004 
1005  //Initialize multiple precision integer
1006  mpiInit(&h);
1007 
1008  //Check whether d == 0
1009  if(mpiCompInt(d, 0) == 0)
1010  {
1011  //Set R = (1, 1, 0)
1012  MPI_CHECK(mpiSetValue(&r->x, 1));
1013  MPI_CHECK(mpiSetValue(&r->y, 1));
1014  MPI_CHECK(mpiSetValue(&r->z, 0));
1015  }
1016  //Check whether d == 1
1017  else if(mpiCompInt(d, 1) == 0)
1018  {
1019  //Set R = S
1020  MPI_CHECK(mpiCopy(&r->x, &s->x));
1021  MPI_CHECK(mpiCopy(&r->y, &s->y));
1022  MPI_CHECK(mpiCopy(&r->z, &s->z));
1023  }
1024  //Check whether Sz == 0
1025  else if(mpiCompInt(&s->z, 0) == 0)
1026  {
1027  //Set R = (1, 1, 0)
1028  MPI_CHECK(mpiSetValue(&r->x, 1));
1029  MPI_CHECK(mpiSetValue(&r->y, 1));
1030  MPI_CHECK(mpiSetValue(&r->z, 0));
1031  }
1032  else
1033  {
1034  //Check whether Sz != 1
1035  if(mpiCompInt(&s->z, 1) != 0)
1036  {
1037  //Normalize S
1038  EC_CHECK(ecAffinify(params, r, s));
1039  EC_CHECK(ecProjectify(params, r, r));
1040  }
1041  else
1042  {
1043  //Set R = S
1044  MPI_CHECK(mpiCopy(&r->x, &s->x));
1045  MPI_CHECK(mpiCopy(&r->y, &s->y));
1046  MPI_CHECK(mpiCopy(&r->z, &s->z));
1047  }
1048 
1049 //Left-to-right binary method
1050 #if 0
1051  for(i = mpiGetBitLength(d) - 1; i >= 1; i--)
1052  {
1053  //Point doubling
1054  EC_CHECK(ecDouble(params, r, r));
1055 
1056  if(mpiGetBitValue(d, i - 1))
1057  {
1058  //Compute R = R + S
1059  EC_CHECK(ecFullAdd(params, r, r, s));
1060  }
1061  }
1062 //Fast left-to-right binary method
1063 #else
1064  //Precompute h = 3 * d
1065  MPI_CHECK(mpiAdd(&h, d, d));
1066  MPI_CHECK(mpiAdd(&h, &h, d));
1067 
1068  //Scalar multiplication
1069  for(i = mpiGetBitLength(&h) - 2; i >= 1; i--)
1070  {
1071  //Point doubling
1072  EC_CHECK(ecDouble(params, r, r));
1073 
1074  //Check whether h(i) == 1 and k(i) == 0
1075  if(mpiGetBitValue(&h, i) && !mpiGetBitValue(d, i))
1076  {
1077  //Compute R = R + S
1078  EC_CHECK(ecFullAdd(params, r, r, s));
1079  }
1080  //Check whether h(i) == 0 and k(i) == 1
1081  else if(!mpiGetBitValue(&h, i) && mpiGetBitValue(d, i))
1082  {
1083  //Compute R = R - S
1084  EC_CHECK(ecFullSub(params, r, r, s));
1085  }
1086  }
1087 #endif
1088  }
1089 
1090 end:
1091  //Release multiple precision integer
1092  mpiFree(&h);
1093 
1094  //Return status code
1095  return error;
1096 }
1097 
1098 
1099 /**
1100  * @brief An auxiliary function for the twin multiplication
1101  * @param[in] t An integer T such as 0 <= T <= 31
1102  * @return Output value
1103  **/
1104 
1106 {
1107  uint_t h;
1108 
1109  //Check the value of T
1110  if(18 <= t && t < 22)
1111  {
1112  h = 9;
1113  }
1114  else if(14 <= t && t < 18)
1115  {
1116  h = 10;
1117  }
1118  else if(22 <= t && t < 24)
1119  {
1120  h = 11;
1121  }
1122  else if(4 <= t && t < 12)
1123  {
1124  h = 14;
1125  }
1126  else
1127  {
1128  h = 12;
1129  }
1130 
1131  //Return value
1132  return h;
1133 }
1134 
1135 
1136 /**
1137  * @brief Twin multiplication
1138  * @param[in] params EC domain parameters
1139  * @param[out] r Resulting point R = d0.S + d1.T
1140  * @param[in] d0 An integer d such as 0 <= d0 < p
1141  * @param[in] s EC point
1142  * @param[in] d1 An integer d such as 0 <= d1 < p
1143  * @param[in] t EC point
1144  * @return Error code
1145  **/
1146 
1147 __weak_func error_t ecTwinMult(const EcDomainParameters *params, EcPoint *r,
1148  const Mpi *d0, const EcPoint *s, const Mpi *d1, const EcPoint *t)
1149 {
1150  error_t error;
1151  int_t k;
1152  uint_t m;
1153  uint_t m0;
1154  uint_t m1;
1155  uint_t c0;
1156  uint_t c1;
1157  uint_t h0;
1158  uint_t h1;
1159  int_t u0;
1160  int_t u1;
1161  EcPoint spt;
1162  EcPoint smt;
1163 
1164  //Initialize EC points
1165  ecInit(&spt);
1166  ecInit(&smt);
1167 
1168  //Precompute SpT = S + T
1169  EC_CHECK(ecFullAdd(params, &spt, s, t));
1170  //Precompute SmT = S - T
1171  EC_CHECK(ecFullSub(params, &smt, s, t));
1172 
1173  //Let m0 be the bit length of d0
1174  m0 = mpiGetBitLength(d0);
1175  //Let m1 be the bit length of d1
1176  m1 = mpiGetBitLength(d1);
1177  //Let m = MAX(m0, m1)
1178  m = MAX(m0, m1);
1179 
1180  //Let c be a 2 x 6 binary matrix
1181  c0 = mpiGetBitValue(d0, m - 4);
1182  c0 |= mpiGetBitValue(d0, m - 3) << 1;
1183  c0 |= mpiGetBitValue(d0, m - 2) << 2;
1184  c0 |= mpiGetBitValue(d0, m - 1) << 3;
1185  c1 = mpiGetBitValue(d1, m - 4);
1186  c1 |= mpiGetBitValue(d1, m - 3) << 1;
1187  c1 |= mpiGetBitValue(d1, m - 2) << 2;
1188  c1 |= mpiGetBitValue(d1, m - 1) << 3;
1189 
1190  //Set R = (1, 1, 0)
1191  MPI_CHECK(mpiSetValue(&r->x, 1));
1192  MPI_CHECK(mpiSetValue(&r->y, 1));
1193  MPI_CHECK(mpiSetValue(&r->z, 0));
1194 
1195  //Calculate both multiplications at the same time
1196  for(k = m; k >= 0; k--)
1197  {
1198  //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5)
1199  h0 = c0 & 0x1F;
1200 
1201  //Check whether c(0,0) == 1
1202  if(c0 & 0x20)
1203  {
1204  h0 = 31 - h0;
1205  }
1206 
1207  //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5)
1208  h1 = c1 & 0x1F;
1209 
1210  //Check whether c(1,0) == 1
1211  if(c1 & 0x20)
1212  {
1213  h1 = 31 - h1;
1214  }
1215 
1216  //Compute u(0)
1217  if(h0 < ecTwinMultF(h1))
1218  {
1219  u0 = 0;
1220  }
1221  else if(c0 & 0x20)
1222  {
1223  u0 = -1;
1224  }
1225  else
1226  {
1227  u0 = 1;
1228  }
1229 
1230  //Compute u(1)
1231  if(h1 < ecTwinMultF(h0))
1232  {
1233  u1 = 0;
1234  }
1235  else if(c1 & 0x20)
1236  {
1237  u1 = -1;
1238  }
1239  else
1240  {
1241  u1 = 1;
1242  }
1243 
1244  //Update c matrix
1245  c0 <<= 1;
1246  c0 |= mpiGetBitValue(d0, k - 5);
1247  c0 ^= u0 ? 0x20 : 0x00;
1248  c1 <<= 1;
1249  c1 |= mpiGetBitValue(d1, k - 5);
1250  c1 ^= u1 ? 0x20 : 0x00;
1251 
1252  //Point doubling
1253  EC_CHECK(ecDouble(params, r, r));
1254 
1255  //Check u(0) and u(1)
1256  if(u0 == -1 && u1 == -1)
1257  {
1258  //Compute R = R - SpT
1259  EC_CHECK(ecFullSub(params, r, r, &spt));
1260  }
1261  else if(u0 == -1 && u1 == 0)
1262  {
1263  //Compute R = R - S
1264  EC_CHECK(ecFullSub(params, r, r, s));
1265  }
1266  else if(u0 == -1 && u1 == 1)
1267  {
1268  //Compute R = R - SmT
1269  EC_CHECK(ecFullSub(params, r, r, &smt));
1270  }
1271  else if(u0 == 0 && u1 == -1)
1272  {
1273  //Compute R = R - T
1274  EC_CHECK(ecFullSub(params, r, r, t));
1275  }
1276  else if(u0 == 0 && u1 == 1)
1277  {
1278  //Compute R = R + T
1279  EC_CHECK(ecFullAdd(params, r, r, t));
1280  }
1281  else if(u0 == 1 && u1 == -1)
1282  {
1283  //Compute R = R + SmT
1284  EC_CHECK(ecFullAdd(params, r, r, &smt));
1285  }
1286  else if(u0 == 1 && u1 == 0)
1287  {
1288  //Compute R = R + S
1289  EC_CHECK(ecFullAdd(params, r, r, s));
1290  }
1291  else if(u0 == 1 && u1 == 1)
1292  {
1293  //Compute R = R + SpT
1294  EC_CHECK(ecFullAdd(params, r, r, &spt));
1295  }
1296  }
1297 
1298 end:
1299  //Release EC points
1300  ecFree(&spt);
1301  ecFree(&smt);
1302 
1303  //Return status code
1304  return error;
1305 }
1306 
1307 
1308 /**
1309  * @brief Fast modular addition
1310  * @param[in] params EC domain parameters
1311  * @param[out] r Resulting integer R = (A + B) mod p
1312  * @param[in] a An integer such as 0 <= A < p
1313  * @param[in] b An integer such as 0 <= B < p
1314  * @return Error code
1315  **/
1316 
1317 __weak_func error_t ecAddMod(const EcDomainParameters *params, Mpi *r,
1318  const Mpi *a, const Mpi *b)
1319 {
1320  error_t error;
1321 
1322  //Compute R = A + B
1323  MPI_CHECK(mpiAdd(r, a, b));
1324 
1325  //Compute R = (A + B) mod p
1326  if(mpiComp(r, &params->p) >= 0)
1327  {
1328  MPI_CHECK(mpiSub(r, r, &params->p));
1329  }
1330 
1331 end:
1332  //Return status code
1333  return error;
1334 }
1335 
1336 
1337 /**
1338  * @brief Fast modular subtraction
1339  * @param[in] params EC domain parameters
1340  * @param[out] r Resulting integer R = (A - B) mod p
1341  * @param[in] a An integer such as 0 <= A < p
1342  * @param[in] b An integer such as 0 <= B < p
1343  * @return Error code
1344  **/
1345 
1346 __weak_func error_t ecSubMod(const EcDomainParameters *params, Mpi *r,
1347  const Mpi *a, const Mpi *b)
1348 {
1349  error_t error;
1350 
1351  //Compute R = A - B
1352  MPI_CHECK(mpiSub(r, a, b));
1353 
1354  //Compute R = (A - B) mod p
1355  if(mpiCompInt(r, 0) < 0)
1356  {
1357  MPI_CHECK(mpiAdd(r, r, &params->p));
1358  }
1359 
1360 end:
1361  //Return status code
1362  return error;
1363 }
1364 
1365 
1366 /**
1367  * @brief Fast modular multiplication
1368  * @param[in] params EC domain parameters
1369  * @param[out] r Resulting integer R = (A * B) mod p
1370  * @param[in] a An integer such as 0 <= A < p
1371  * @param[in] b An integer such as 0 <= B < p
1372  * @return Error code
1373  **/
1374 
1375 __weak_func error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a,
1376  const Mpi *b)
1377 {
1378  error_t error;
1379 
1380  //Compute R = A * B
1381  MPI_CHECK(mpiMul(r, a, b));
1382 
1383  //Compute R = (A * B) mod p
1384  if(params->mod != NULL)
1385  {
1386  MPI_CHECK(params->mod(r, &params->p));
1387  }
1388  else
1389  {
1390  MPI_CHECK(mpiMod(r, r, &params->p));
1391  }
1392 
1393 end:
1394  //Return status code
1395  return error;
1396 }
1397 
1398 
1399 /**
1400  * @brief Fast modular squaring
1401  * @param[in] params EC domain parameters
1402  * @param[out] r Resulting integer R = (A ^ 2) mod p
1403  * @param[in] a An integer such as 0 <= A < p
1404  * @return Error code
1405  **/
1406 
1407 __weak_func error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
1408 {
1409  error_t error;
1410 
1411  //Compute R = A ^ 2
1412  MPI_CHECK(mpiMul(r, a, a));
1413 
1414  //Compute R = (A ^ 2) mod p
1415  if(params->mod != NULL)
1416  {
1417  MPI_CHECK(params->mod(r, &params->p));
1418  }
1419  else
1420  {
1421  MPI_CHECK(mpiMod(r, r, &params->p));
1422  }
1423 
1424 end:
1425  //Return status code
1426  return error;
1427 }
1428 
1429 #endif
__weak_func bool_t ecIsPointAffine(const EcDomainParameters *params, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:565
const uint8_t b[66]
Curve parameter b.
Definition: ec_curves.h:311
int bool_t
Definition: compiler_port.h:53
uint8_t b
Definition: nbns_common.h:104
Mpi p
Prime.
Definition: ec.h:79
@ EC_POINT_FORMAT_UNCOMPRESSED
Definition: ec.h:55
uint8_t a
Definition: ndp.h:411
Arbitrary precision integer.
Definition: mpi.h:80
error_t ecFullSub(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point subtraction.
Definition: ec.c:962
signed int int_t
Definition: compiler_port.h:49
const uint8_t a[66]
Curve parameter a.
Definition: ec_curves.h:309
#define PrngAlgo
Definition: crypto.h:938
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:243
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
error_t ecImport(const EcDomainParameters *params, EcPoint *r, const uint8_t *data, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:365
size_t aLen
Length of a.
Definition: ec_curves.h:310
uint8_t t
Definition: lldp_ext_med.h:212
error_t ecDouble(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Point doubling.
Definition: ec.c:607
int_t slot
Private key slot.
Definition: ec.h:106
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
__weak_func error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular multiplication.
Definition: ec.c:1375
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:43
uint_t ecTwinMultF(uint_t t)
An auxiliary function for the twin multiplication.
Definition: ec.c:1105
Mpi d
Private key.
Definition: ec.h:105
#define mpiIsEven(a)
Definition: mpi.h:55
EcPoint g
Base point G.
Definition: ec.h:82
error_t mpiSetValue(Mpi *r, int_t a)
Set the value of a multiple precision integer.
Definition: mpi.c:484
uint32_t h
Cofactor h.
Definition: ec_curves.h:319
uint32_t h
Cofactor h.
Definition: ec.h:84
error_t mpiRandRange(Mpi *r, const Mpi *p, const PrngAlgo *prngAlgo, void *prngContext)
Generate a random value in the range 1 to p-1.
Definition: mpi.c:564
error_t mpiShiftRight(Mpi *r, uint_t n)
Right shift operation.
Definition: mpi.c:1178
@ EC_CURVE_TYPE_ED25519
Definition: ec_curves.h:285
error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
Modular inverse.
@ EC_CURVE_TYPE_SECP_K1
Definition: ec_curves.h:279
error_t ecAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point addition (helper routine)
Definition: ec.c:739
Mpi y
y-coordinate
Definition: ec.h:66
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
EC domain parameters.
Definition: ec.h:76
@ EC_CURVE_TYPE_X448
Definition: ec_curves.h:284
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
#define mpiReadRaw(r, data, length)
Definition: crypto_legacy.h:35
Mpi a
Curve parameter a.
Definition: ec.h:80
uint8_t r
Definition: ndp.h:346
__weak_func error_t ecTwinMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d0, const EcPoint *s, const Mpi *d1, const EcPoint *t)
Twin multiplication.
Definition: ec.c:1147
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1444
__weak_func error_t ecAddMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular addition.
Definition: ec.c:1317
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:90
#define FALSE
Definition: os_port.h:46
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
@ EC_CURVE_TYPE_SECP_R1
Definition: ec_curves.h:280
Elliptic curve parameters.
Definition: ec_curves.h:302
uint8_t h
Definition: ndp.h:302
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision subtraction.
Definition: mpi.c:864
size_t bLen
Length of b.
Definition: ec_curves.h:312
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:70
error_t
Error codes.
Definition: error.h:43
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:153
size_t qLen
Length of q.
Definition: ec_curves.h:318
error_t ecCopy(EcPoint *r, const EcPoint *s)
Copy EC point.
Definition: ec.c:337
#define MPI_CHECK(f)
Definition: mpi.h:52
error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision addition.
Definition: mpi.c:787
#define EC_CHECK(f)
Definition: ec.h:39
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
__weak_func error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, EcPrivateKey *privateKey, EcPublicKey *publicKey)
EC key pair generation.
Definition: ec.c:209
void ecInit(EcPoint *r)
Initialize elliptic curve point.
Definition: ec.c:307
EcFastModAlgo mod
Fast modular reduction.
Definition: ec_curves.h:320
const uint8_t q[66]
Order of the base point G.
Definition: ec_curves.h:317
General definitions for cryptographic algorithms.
Mpi x
x-coordinate
Definition: ec.h:65
EC private key.
Definition: ec.h:104
const char_t * name
Curve name.
Definition: ec.h:77
uint8_t u
Definition: lldp_ext_med.h:213
uint32_t t2
EC point.
Definition: ec.h:64
void ecFreePrivateKey(EcPrivateKey *key)
Release an EdDSA private key.
Definition: ec.c:192
uint8_t length
Definition: tcp.h:368
error_t ecProjectify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:495
size_t gyLen
Length of Gy.
Definition: ec_curves.h:316
const char_t * name
Curve name.
Definition: ec_curves.h:303
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:234
__weak_func error_t ecAffinify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Recover affine representation.
Definition: ec.c:519
error_t mpiCopy(Mpi *r, const Mpi *a)
Copy a multiple precision integer.
Definition: mpi.c:447
EC public key.
Definition: ec.h:94
@ EC_CURVE_TYPE_ED448
Definition: ec_curves.h:286
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define MAX(a, b)
Definition: os_port.h:67
const uint8_t gy[66]
y-coordinate of the base point G
Definition: ec_curves.h:315
uint32_t t1
__weak_func error_t ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular subtraction.
Definition: ec.c:1346
const uint8_t p[66]
Prime modulus p.
Definition: ec_curves.h:307
const uint8_t gx[66]
x-coordinate of the base point G
Definition: ec_curves.h:313
uint8_t m
Definition: ndp.h:304
@ EC_CURVE_TYPE_X25519
Definition: ec_curves.h:283
EcFastModAlgo mod
Fast modular reduction.
Definition: ec.h:85
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:177
EcPoint q
Public key.
Definition: ec.h:95
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
__weak_func error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
Fast modular squaring.
Definition: ec.c:1407
error_t ecExport(const EcDomainParameters *params, const EcPoint *a, uint8_t *data, size_t *length)
Convert an EC point to an octet string.
Definition: ec.c:438
uint8_t s
Definition: igmp_common.h:234
EcCurveType type
Curve type.
Definition: ec.h:78
size_t gxLen
Length of Gx.
Definition: ec_curves.h:314
error_t ecGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, EcPrivateKey *privateKey)
EC private key generation.
Definition: ec.c:239
error_t ecFullAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point addition.
Definition: ec.c:899
@ EC_CURVE_TYPE_NONE
Definition: ec_curves.h:275
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:338
__weak_func error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d, const EcPoint *s)
Scalar multiplication.
Definition: ec.c:998
Mpi b
Curve parameter b.
Definition: ec.h:81
unsigned int uint_t
Definition: compiler_port.h:50
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:110
void ecFree(EcPoint *r)
Release an elliptic curve point.
Definition: ec.c:321
uint_t mpiGetBitValue(const Mpi *a, uint_t index)
Get the bit value at the specified index.
Definition: mpi.c:313
Mpi z
z-coordinate
Definition: ec.h:67
ECC (Elliptic Curve Cryptography)
error_t ecGeneratePublicKey(const EcDomainParameters *params, const EcPrivateKey *privateKey, EcPublicKey *publicKey)
Derive the public key from an EC private key.
Definition: ec.c:275
int_t mpiCompInt(const Mpi *a, int_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:382
size_t pLen
Length of p.
Definition: ec_curves.h:308
Mpi q
Order of the point G.
Definition: ec.h:83
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:165
EcCurveType type
Curve type.
Definition: ec_curves.h:306
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:195
void mpiFree(Mpi *r)
Release a multiple precision integer.
Definition: mpi.c:64