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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "ecc/ec.h"
37 #include "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 
904  //Check whether Sz == 0
905  if(mpiCompInt(&s->z, 0) == 0)
906  {
907  //Set R = T
908  MPI_CHECK(mpiCopy(&r->x, &t->x));
909  MPI_CHECK(mpiCopy(&r->y, &t->y));
910  MPI_CHECK(mpiCopy(&r->z, &t->z));
911  }
912  //Check whether Tz == 0
913  else if(mpiCompInt(&t->z, 0) == 0)
914  {
915  //Set R = S
916  MPI_CHECK(mpiCopy(&r->x, &s->x));
917  MPI_CHECK(mpiCopy(&r->y, &s->y));
918  MPI_CHECK(mpiCopy(&r->z, &s->z));
919  }
920  else
921  {
922  //Compute R = S + T
923  EC_CHECK(ecAdd(params, r, s, t));
924 
925  //Check whether R == (0, 0, 0)
926  if(mpiCompInt(&r->x, 0) == 0 &&
927  mpiCompInt(&r->y, 0) == 0 &&
928  mpiCompInt(&r->z, 0) == 0)
929  {
930  //Compute R = 2 * S
931  EC_CHECK(ecDouble(params, r, s));
932  }
933  }
934 
935 end:
936  //Return status code
937  return error;
938 }
939 
940 
941 /**
942  * @brief Point subtraction
943  * @param[in] params EC domain parameters
944  * @param[out] r Resulting point R = S - T
945  * @param[in] s First operand
946  * @param[in] t Second operand
947  * @return Error code
948  **/
949 
951  const EcPoint *s, const EcPoint *t)
952 {
953  error_t error;
954  EcPoint u;
955 
956  //Initialize EC point
957  ecInit(&u);
958 
959  //Set Ux = Tx and Uz = Tz
960  MPI_CHECK(mpiCopy(&u.x, &t->x));
961  MPI_CHECK(mpiCopy(&u.z, &t->z));
962  //Set Uy = p - Ty
963  MPI_CHECK(mpiSub(&u.y, &params->p, &t->y));
964 
965  //Compute R = S + U
966  EC_CHECK(ecFullAdd(params, r, s, &u));
967 
968 end:
969  //Release EC point
970  ecFree(&u);
971 
972  //Return status code
973  return error;
974 }
975 
976 
977 /**
978  * @brief Scalar multiplication
979  * @param[in] params EC domain parameters
980  * @param[out] r Resulting point R = d.S
981  * @param[in] d An integer d such as 0 <= d < p
982  * @param[in] s EC point
983  * @return Error code
984  **/
985 
986 __weak_func error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d,
987  const EcPoint *s)
988 {
989  error_t error;
990  uint_t i;
991  Mpi h;
992 
993  //Initialize multiple precision integer
994  mpiInit(&h);
995 
996  //Check whether d == 0
997  if(mpiCompInt(d, 0) == 0)
998  {
999  //Set R = (1, 1, 0)
1000  MPI_CHECK(mpiSetValue(&r->x, 1));
1001  MPI_CHECK(mpiSetValue(&r->y, 1));
1002  MPI_CHECK(mpiSetValue(&r->z, 0));
1003  }
1004  //Check whether d == 1
1005  else if(mpiCompInt(d, 1) == 0)
1006  {
1007  //Set R = S
1008  MPI_CHECK(mpiCopy(&r->x, &s->x));
1009  MPI_CHECK(mpiCopy(&r->y, &s->y));
1010  MPI_CHECK(mpiCopy(&r->z, &s->z));
1011  }
1012  //Check whether Sz == 0
1013  else if(mpiCompInt(&s->z, 0) == 0)
1014  {
1015  //Set R = (1, 1, 0)
1016  MPI_CHECK(mpiSetValue(&r->x, 1));
1017  MPI_CHECK(mpiSetValue(&r->y, 1));
1018  MPI_CHECK(mpiSetValue(&r->z, 0));
1019  }
1020  else
1021  {
1022  //Check whether Sz != 1
1023  if(mpiCompInt(&s->z, 1) != 0)
1024  {
1025  //Normalize S
1026  EC_CHECK(ecAffinify(params, r, s));
1027  EC_CHECK(ecProjectify(params, r, r));
1028  }
1029  else
1030  {
1031  //Set R = S
1032  MPI_CHECK(mpiCopy(&r->x, &s->x));
1033  MPI_CHECK(mpiCopy(&r->y, &s->y));
1034  MPI_CHECK(mpiCopy(&r->z, &s->z));
1035  }
1036 
1037 //Left-to-right binary method
1038 #if 0
1039  for(i = mpiGetBitLength(d) - 1; i >= 1; i--)
1040  {
1041  //Point doubling
1042  EC_CHECK(ecDouble(params, r, r));
1043 
1044  if(mpiGetBitValue(d, i - 1))
1045  {
1046  //Compute R = R + S
1047  EC_CHECK(ecFullAdd(params, r, r, s));
1048  }
1049  }
1050 //Fast left-to-right binary method
1051 #else
1052  //Precompute h = 3 * d
1053  MPI_CHECK(mpiAdd(&h, d, d));
1054  MPI_CHECK(mpiAdd(&h, &h, d));
1055 
1056  //Scalar multiplication
1057  for(i = mpiGetBitLength(&h) - 2; i >= 1; i--)
1058  {
1059  //Point doubling
1060  EC_CHECK(ecDouble(params, r, r));
1061 
1062  //Check whether h(i) == 1 and k(i) == 0
1063  if(mpiGetBitValue(&h, i) && !mpiGetBitValue(d, i))
1064  {
1065  //Compute R = R + S
1066  EC_CHECK(ecFullAdd(params, r, r, s));
1067  }
1068  //Check whether h(i) == 0 and k(i) == 1
1069  else if(!mpiGetBitValue(&h, i) && mpiGetBitValue(d, i))
1070  {
1071  //Compute R = R - S
1072  EC_CHECK(ecFullSub(params, r, r, s));
1073  }
1074  }
1075 #endif
1076  }
1077 
1078 end:
1079  //Release multiple precision integer
1080  mpiFree(&h);
1081 
1082  //Return status code
1083  return error;
1084 }
1085 
1086 
1087 /**
1088  * @brief An auxiliary function for the twin multiplication
1089  * @param[in] t An integer T such as 0 <= T <= 31
1090  * @return Output value
1091  **/
1092 
1094 {
1095  uint_t h;
1096 
1097  //Check the value of T
1098  if(18 <= t && t < 22)
1099  {
1100  h = 9;
1101  }
1102  else if(14 <= t && t < 18)
1103  {
1104  h = 10;
1105  }
1106  else if(22 <= t && t < 24)
1107  {
1108  h = 11;
1109  }
1110  else if(4 <= t && t < 12)
1111  {
1112  h = 14;
1113  }
1114  else
1115  {
1116  h = 12;
1117  }
1118 
1119  //Return value
1120  return h;
1121 }
1122 
1123 
1124 /**
1125  * @brief Twin multiplication
1126  * @param[in] params EC domain parameters
1127  * @param[out] r Resulting point R = d0.S + d1.T
1128  * @param[in] d0 An integer d such as 0 <= d0 < p
1129  * @param[in] s EC point
1130  * @param[in] d1 An integer d such as 0 <= d1 < p
1131  * @param[in] t EC point
1132  * @return Error code
1133  **/
1134 
1136  const Mpi *d0, const EcPoint *s, const Mpi *d1, const EcPoint *t)
1137 {
1138  error_t error;
1139  int_t k;
1140  uint_t m;
1141  uint_t m0;
1142  uint_t m1;
1143  uint_t c0;
1144  uint_t c1;
1145  uint_t h0;
1146  uint_t h1;
1147  int_t u0;
1148  int_t u1;
1149  EcPoint spt;
1150  EcPoint smt;
1151 
1152  //Initialize EC points
1153  ecInit(&spt);
1154  ecInit(&smt);
1155 
1156  //Precompute SpT = S + T
1157  EC_CHECK(ecFullAdd(params, &spt, s, t));
1158  //Precompute SmT = S - T
1159  EC_CHECK(ecFullSub(params, &smt, s, t));
1160 
1161  //Let m0 be the bit length of d0
1162  m0 = mpiGetBitLength(d0);
1163  //Let m1 be the bit length of d1
1164  m1 = mpiGetBitLength(d1);
1165  //Let m = MAX(m0, m1)
1166  m = MAX(m0, m1);
1167 
1168  //Let c be a 2 x 6 binary matrix
1169  c0 = mpiGetBitValue(d0, m - 4);
1170  c0 |= mpiGetBitValue(d0, m - 3) << 1;
1171  c0 |= mpiGetBitValue(d0, m - 2) << 2;
1172  c0 |= mpiGetBitValue(d0, m - 1) << 3;
1173  c1 = mpiGetBitValue(d1, m - 4);
1174  c1 |= mpiGetBitValue(d1, m - 3) << 1;
1175  c1 |= mpiGetBitValue(d1, m - 2) << 2;
1176  c1 |= mpiGetBitValue(d1, m - 1) << 3;
1177 
1178  //Set R = (1, 1, 0)
1179  MPI_CHECK(mpiSetValue(&r->x, 1));
1180  MPI_CHECK(mpiSetValue(&r->y, 1));
1181  MPI_CHECK(mpiSetValue(&r->z, 0));
1182 
1183  //Calculate both multiplications at the same time
1184  for(k = m; k >= 0; k--)
1185  {
1186  //Compute h(0) = 16 * c(0,1) + 8 * c(0,2) + 4 * c(0,3) + 2 * c(0,4) + c(0,5)
1187  h0 = c0 & 0x1F;
1188 
1189  //Check whether c(0,0) == 1
1190  if(c0 & 0x20)
1191  {
1192  h0 = 31 - h0;
1193  }
1194 
1195  //Compute h(1) = 16 * c(1,1) + 8 * c(1,2) + 4 * c(1,3) + 2 * c(1,4) + c(1,5)
1196  h1 = c1 & 0x1F;
1197 
1198  //Check whether c(1,0) == 1
1199  if(c1 & 0x20)
1200  {
1201  h1 = 31 - h1;
1202  }
1203 
1204  //Compute u(0)
1205  if(h0 < ecTwinMultF(h1))
1206  {
1207  u0 = 0;
1208  }
1209  else if(c0 & 0x20)
1210  {
1211  u0 = -1;
1212  }
1213  else
1214  {
1215  u0 = 1;
1216  }
1217 
1218  //Compute u(1)
1219  if(h1 < ecTwinMultF(h0))
1220  {
1221  u1 = 0;
1222  }
1223  else if(c1 & 0x20)
1224  {
1225  u1 = -1;
1226  }
1227  else
1228  {
1229  u1 = 1;
1230  }
1231 
1232  //Update c matrix
1233  c0 <<= 1;
1234  c0 |= mpiGetBitValue(d0, k - 5);
1235  c0 ^= u0 ? 0x20 : 0x00;
1236  c1 <<= 1;
1237  c1 |= mpiGetBitValue(d1, k - 5);
1238  c1 ^= u1 ? 0x20 : 0x00;
1239 
1240  //Point doubling
1241  EC_CHECK(ecDouble(params, r, r));
1242 
1243  //Check u(0) and u(1)
1244  if(u0 == -1 && u1 == -1)
1245  {
1246  //Compute R = R - SpT
1247  EC_CHECK(ecFullSub(params, r, r, &spt));
1248  }
1249  else if(u0 == -1 && u1 == 0)
1250  {
1251  //Compute R = R - S
1252  EC_CHECK(ecFullSub(params, r, r, s));
1253  }
1254  else if(u0 == -1 && u1 == 1)
1255  {
1256  //Compute R = R - SmT
1257  EC_CHECK(ecFullSub(params, r, r, &smt));
1258  }
1259  else if(u0 == 0 && u1 == -1)
1260  {
1261  //Compute R = R - T
1262  EC_CHECK(ecFullSub(params, r, r, t));
1263  }
1264  else if(u0 == 0 && u1 == 1)
1265  {
1266  //Compute R = R + T
1267  EC_CHECK(ecFullAdd(params, r, r, t));
1268  }
1269  else if(u0 == 1 && u1 == -1)
1270  {
1271  //Compute R = R + SmT
1272  EC_CHECK(ecFullAdd(params, r, r, &smt));
1273  }
1274  else if(u0 == 1 && u1 == 0)
1275  {
1276  //Compute R = R + S
1277  EC_CHECK(ecFullAdd(params, r, r, s));
1278  }
1279  else if(u0 == 1 && u1 == 1)
1280  {
1281  //Compute R = R + SpT
1282  EC_CHECK(ecFullAdd(params, r, r, &spt));
1283  }
1284  }
1285 
1286 end:
1287  //Release EC points
1288  ecFree(&spt);
1289  ecFree(&smt);
1290 
1291  //Return status code
1292  return error;
1293 }
1294 
1295 
1296 /**
1297  * @brief Fast modular addition
1298  * @param[in] params EC domain parameters
1299  * @param[out] r Resulting integer R = (A + B) mod p
1300  * @param[in] a An integer such as 0 <= A < p
1301  * @param[in] b An integer such as 0 <= B < p
1302  * @return Error code
1303  **/
1304 
1305 error_t ecAddMod(const EcDomainParameters *params, Mpi *r, const Mpi *a,
1306  const Mpi *b)
1307 {
1308  error_t error;
1309 
1310  //Compute R = A + B
1311  MPI_CHECK(mpiAdd(r, a, b));
1312 
1313  //Compute R = (A + B) mod p
1314  if(mpiComp(r, &params->p) >= 0)
1315  {
1316  MPI_CHECK(mpiSub(r, r, &params->p));
1317  }
1318 
1319 end:
1320  //Return status code
1321  return error;
1322 }
1323 
1324 
1325 /**
1326  * @brief Fast modular subtraction
1327  * @param[in] params EC domain parameters
1328  * @param[out] r Resulting integer R = (A - B) mod p
1329  * @param[in] a An integer such as 0 <= A < p
1330  * @param[in] b An integer such as 0 <= B < p
1331  * @return Error code
1332  **/
1333 
1334 error_t ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a,
1335  const Mpi *b)
1336 {
1337  error_t error;
1338 
1339  //Compute R = A - B
1340  MPI_CHECK(mpiSub(r, a, b));
1341 
1342  //Compute R = (A - B) mod p
1343  if(mpiCompInt(r, 0) < 0)
1344  {
1345  MPI_CHECK(mpiAdd(r, r, &params->p));
1346  }
1347 
1348 end:
1349  //Return status code
1350  return error;
1351 }
1352 
1353 
1354 /**
1355  * @brief Fast modular multiplication
1356  * @param[in] params EC domain parameters
1357  * @param[out] r Resulting integer R = (A * B) mod p
1358  * @param[in] a An integer such as 0 <= A < p
1359  * @param[in] b An integer such as 0 <= B < p
1360  * @return Error code
1361  **/
1362 
1363 __weak_func error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a,
1364  const Mpi *b)
1365 {
1366  error_t error;
1367 
1368  //Compute R = A * B
1369  MPI_CHECK(mpiMul(r, a, b));
1370 
1371  //Compute R = (A * B) mod p
1372  if(params->mod != NULL)
1373  {
1374  MPI_CHECK(params->mod(r, &params->p));
1375  }
1376  else
1377  {
1378  MPI_CHECK(mpiMod(r, r, &params->p));
1379  }
1380 
1381 end:
1382  //Return status code
1383  return error;
1384 }
1385 
1386 
1387 /**
1388  * @brief Fast modular squaring
1389  * @param[in] params EC domain parameters
1390  * @param[out] r Resulting integer R = (A ^ 2) mod p
1391  * @param[in] a An integer such as 0 <= A < p
1392  * @return Error code
1393  **/
1394 
1395 __weak_func error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
1396 {
1397  error_t error;
1398 
1399  //Compute R = A ^ 2
1400  MPI_CHECK(mpiMul(r, a, a));
1401 
1402  //Compute R = (A ^ 2) mod p
1403  if(params->mod != NULL)
1404  {
1405  MPI_CHECK(params->mod(r, &params->p));
1406  }
1407  else
1408  {
1409  MPI_CHECK(mpiMod(r, r, &params->p));
1410  }
1411 
1412 end:
1413  //Return status code
1414  return error;
1415 }
1416 
1417 #endif
signed int int_t
Definition: compiler_port.h:49
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
General definitions for cryptographic algorithms.
#define PrngAlgo
Definition: crypto.h:917
#define mpiReadRaw(r, data, length)
Definition: crypto_legacy.h:35
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_DEBUG_MPI(p, a)
Definition: debug.h:110
uint32_t t1
uint32_t t2
error_t ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular subtraction.
Definition: ec.c:1334
__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
error_t ecProjectify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:495
__weak_func error_t ecMulMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular multiplication.
Definition: ec.c:1363
void ecFreeDomainParameters(EcDomainParameters *params)
Release EC domain parameters.
Definition: ec.c:72
error_t ecFullAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point addition.
Definition: ec.c:899
__weak_func error_t ecAffinify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Recover affine representation.
Definition: ec.c:519
error_t ecGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, const EcDomainParameters *params, EcPrivateKey *privateKey)
EC private key generation.
Definition: ec.c:239
error_t ecAddMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b)
Fast modular addition.
Definition: ec.c:1305
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
void ecInitDomainParameters(EcDomainParameters *params)
Initialize EC domain parameters.
Definition: ec.c:51
error_t ecCopy(EcPoint *r, const EcPoint *s)
Copy EC point.
Definition: ec.c:337
const uint8_t EC_PUBLIC_KEY_OID[7]
Definition: ec.c:43
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:153
__weak_func error_t ecSqrMod(const EcDomainParameters *params, Mpi *r, const Mpi *a)
Fast modular squaring.
Definition: ec.c:1395
error_t ecFullSub(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point subtraction.
Definition: ec.c:950
error_t ecDouble(const EcDomainParameters *params, EcPoint *r, const EcPoint *s)
Point doubling.
Definition: ec.c:607
__weak_func error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d, const EcPoint *s)
Scalar multiplication.
Definition: ec.c:986
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:1135
uint_t ecTwinMultF(uint_t t)
An auxiliary function for the twin multiplication.
Definition: ec.c:1093
void ecFreePrivateKey(EcPrivateKey *key)
Release an EdDSA private key.
Definition: ec.c:192
__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
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:90
error_t ecAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t)
Point addition (helper routine)
Definition: ec.c:739
void ecInit(EcPoint *r)
Initialize elliptic curve point.
Definition: ec.c:307
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:165
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:177
void ecFree(EcPoint *r)
Release an elliptic curve point.
Definition: ec.c:321
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
error_t ecGeneratePublicKey(const EcDomainParameters *params, const EcPrivateKey *privateKey, EcPublicKey *publicKey)
Derive the public key from an EC private key.
Definition: ec.c:275
ECC (Elliptic Curve Cryptography)
@ EC_POINT_FORMAT_UNCOMPRESSED
Definition: ec.h:55
#define EC_CHECK(f)
Definition: ec.h:39
@ EC_CURVE_TYPE_X25519
Definition: ec_curves.h:276
@ EC_CURVE_TYPE_ED25519
Definition: ec_curves.h:278
@ EC_CURVE_TYPE_SECP_R1
Definition: ec_curves.h:273
@ EC_CURVE_TYPE_X448
Definition: ec_curves.h:277
@ EC_CURVE_TYPE_NONE
Definition: ec_curves.h:268
@ EC_CURVE_TYPE_ED448
Definition: ec_curves.h:279
@ EC_CURVE_TYPE_SECP_K1
Definition: ec_curves.h:272
error_t
Error codes.
Definition: error.h:43
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:242
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t mpiMul(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision multiplication.
uint8_t data[]
Definition: ethernet.h:222
uint8_t u
Definition: lldp_ext_med.h:213
uint8_t t
Definition: lldp_ext_med.h:212
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 mpiSetValue(Mpi *r, int_t a)
Set the value of a multiple precision integer.
Definition: mpi.c:484
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:234
error_t mpiCopy(Mpi *r, const Mpi *a)
Copy a multiple precision integer.
Definition: mpi.c:447
error_t mpiSub(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision subtraction.
Definition: mpi.c:864
int_t mpiCompInt(const Mpi *a, int_t b)
Compare a multiple precision integer with an integer.
Definition: mpi.c:382
int_t mpiComp(const Mpi *a, const Mpi *b)
Compare two multiple precision integers.
Definition: mpi.c:338
error_t mpiShiftRight(Mpi *r, uint_t n)
Right shift operation.
Definition: mpi.c:1178
void mpiInit(Mpi *r)
Initialize a multiple precision integer.
Definition: mpi.c:48
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
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
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
error_t mpiAdd(Mpi *r, const Mpi *a, const Mpi *b)
Multiple precision addition.
Definition: mpi.c:787
error_t mpiMod(Mpi *r, const Mpi *a, const Mpi *p)
Modulo operation.
Definition: mpi.c:1444
uint_t mpiGetBitValue(const Mpi *a, uint_t index)
Get the bit value at the specified index.
Definition: mpi.c:313
#define mpiIsEven(a)
Definition: mpi.h:55
#define MPI_CHECK(f)
Definition: mpi.h:52
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
@ MPI_FORMAT_LITTLE_ENDIAN
Definition: mpi.h:70
uint8_t b
Definition: nbns_common.h:104
uint8_t h
Definition: ndp.h:302
uint8_t r
Definition: ndp.h:346
uint8_t s
Definition: ndp.h:345
uint8_t m
Definition: ndp.h:304
uint8_t a
Definition: ndp.h:411
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MAX(a, b)
Definition: os_port.h:67
error_t mpiInvMod(Mpi *r, const Mpi *a, const Mpi *p)
Modular inverse.
Elliptic curve parameters.
Definition: ec_curves.h:295
const uint8_t gx[66]
x-coordinate of the base point G
Definition: ec_curves.h:306
const char_t * name
Curve name.
Definition: ec_curves.h:296
size_t pLen
Length of p.
Definition: ec_curves.h:301
size_t gxLen
Length of Gx.
Definition: ec_curves.h:307
size_t qLen
Length of q.
Definition: ec_curves.h:311
size_t bLen
Length of b.
Definition: ec_curves.h:305
size_t aLen
Length of a.
Definition: ec_curves.h:303
uint32_t h
Cofactor h.
Definition: ec_curves.h:312
size_t gyLen
Length of Gy.
Definition: ec_curves.h:309
const uint8_t q[66]
Order of the base point G.
Definition: ec_curves.h:310
const uint8_t gy[66]
y-coordinate of the base point G
Definition: ec_curves.h:308
const uint8_t p[66]
Prime modulus p.
Definition: ec_curves.h:300
EcCurveType type
Curve type.
Definition: ec_curves.h:299
const uint8_t b[66]
Curve parameter b.
Definition: ec_curves.h:304
EcFastModAlgo mod
Fast modular reduction.
Definition: ec_curves.h:313
const uint8_t a[66]
Curve parameter a.
Definition: ec_curves.h:302
EC domain parameters.
Definition: ec.h:76
Mpi p
Prime.
Definition: ec.h:79
EcPoint g
Base point G.
Definition: ec.h:82
const char_t * name
Curve name.
Definition: ec.h:77
uint32_t h
Cofactor h.
Definition: ec.h:84
Mpi q
Order of the point G.
Definition: ec.h:83
EcCurveType type
Curve type.
Definition: ec.h:78
EcFastModAlgo mod
Fast modular reduction.
Definition: ec.h:85
Mpi a
Curve parameter a.
Definition: ec.h:80
Mpi b
Curve parameter b.
Definition: ec.h:81
EC point.
Definition: ec.h:64
Mpi y
y-coordinate
Definition: ec.h:66
Mpi x
x-coordinate
Definition: ec.h:65
Mpi z
z-coordinate
Definition: ec.h:67
EC private key.
Definition: ec.h:104
int_t slot
Private key slot.
Definition: ec.h:106
Mpi d
Private key.
Definition: ec.h:105
EC public key.
Definition: ec.h:94
EcPoint q
Public key.
Definition: ec.h:95
Arbitrary precision integer.
Definition: mpi.h:80
uint8_t length
Definition: tcp.h:368