MPHELL  4.0.0
mphell_tuto_ecdsa.c
Go to the documentation of this file.
1 /*
2  MPHELL-4.0
3  Author(s): The MPHELL team
4 
5  (C) Copyright 2015-2018 - Institut Fourier / Univ. Grenoble Alpes (France)
6 
7  This file is part of the MPHELL Library.
8  MPHELL is free software: you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation, version 3 of the License.
11 
12  MPHELL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with MPHELL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
42 #include <stdio.h>
43 #include "mphell/mphell.h"
44 
49 struct ecdsa_sig
50 {
51  number *r;
52  number *s;
53 };
54 
59 typedef struct ecdsa_sig ecdsa_sig_t;
60 
66 
67 #define PRECOMP_WIN_SIZE 9
68 #define PRECOMP_SIZE 256
69 
75 {
76  ec_point prec_G[2*PRECOMP_SIZE];
77  ec_point prec_K[2*PRECOMP_SIZE];
78 };
79 
85 
91 
97 void
98 ecdsa_sign_alloc(ecdsa_sig *sig, uint8_t size)
99 {
100  (*sig)->r = (number*)malloc(sizeof(number));
101  (*sig)->s = (number*)malloc(sizeof(number));
102  number_init((*sig)->r, size);
103  number_init((*sig)->s, size);
104  number_set_ui(*((*sig)->r), (block)0);
105  number_set_ui(*((*sig)->s), (block)0);
106 }
107 
114 void
116 {
117  if ((*sig)->r)
118  {
119  number_free((*sig)->r);
120  free((*sig)->r);
121  }
122  if ((*sig)->s)
123  {
124  number_free((*sig)->s);
125  free((*sig)->s);
126  }
127 }
128 
136 void
138 {
140  uint16_t i;
141  uint16_t pr = 2*PRECOMP_SIZE;
142 
143  /* Allocate */
144  for(i = 0; i < pr; i++)
145  {
146  ec_point_alloc(((*precomp)->prec_G)[i], E->k);
147  ec_point_alloc(((*precomp)->prec_K)[i], E->k);
148  ec_point_init(((*precomp)->prec_G)[i], E->k);
149  ec_point_init(((*precomp)->prec_K)[i], E->k);
150  }
151  ec_point_set_neutral(((*precomp)->prec_K)[0], E, STACK_1);
152  ec_point_set_neutral(((*precomp)->prec_G)[0], E, STACK_1);
153 
154  ec_point_copy(((*precomp)->prec_G)[1], E->G, E->k); /* G[0] = G */
155  ec_point_copy(((*precomp)->prec_K)[1], *key, E->k); /* K[0] = K */
156 
157  for(i = 2; i < pr; i++)
158  {
159  /* tab[i]=(i)* P1 */
160  ec_point_add(((*precomp)->prec_G)[i], E->G, ((*precomp)->prec_G)[i-1], E, STACK_1);
161  ec_point_add(((*precomp)->prec_K)[i], *key, ((*precomp)->prec_K)[i-1], E, STACK_1);
162  }
163 }
164 
170 void
172 {
173  uint16_t i;
174  uint16_t pr = 2*PRECOMP_SIZE;
175  for(i = 0; i < pr; i++)
176  {
177  ec_point_free(((*precomp)->prec_G)[i], E->k);
178  ec_point_free(((*precomp)->prec_K)[i], E->k);
179  }
180 }
181 
190 void
191 ecdsa_sign(unsigned char *hash, ecdsa_sig *sig, number_ptr priv_key, ec_curve *curve)
192 {
194  number *rr = (*sig)->r;
195  number *ss = (*sig)->s;
196 
197  uint8_t size = (*curve)->k->size;
198 
199  number k; number_tmp_alloc(&k, size, STACK_1);
200  number h; number_tmp_alloc(&h, (strlen((char *)hash)/(BLOCK_SIZE/4)), STACK_1);
201  number t; number_tmp_alloc(&t, size, STACK_1);
202  number tt; number_tmp_alloc(&tt, 2*size+1, STACK_1);
203 
204  number abs;
205  number_tmp_alloc(&abs, size, STACK_1);
206 
207  ec_point x;
208  ec_point_get_pool_elt(x, (*curve)->k, STACK_1);
209 
210  field_elt xx;
211  field_elt_get_pool_elt(&xx, (*curve)->k, STACK_1);
212 
213  bool newk = true;
214  number_set_str(h , (char*)hash, 16);
215 
216  while(newk)
217  {
218  /* Choose k randomly in [1, n-1] */
219  number_random1(k, (*curve)->n, STACK_1);
220 
221  /* Compute (x,y) = kG */
222  ec_point_mul_unified(x, k, (*curve)->G, *curve, STACK_1);
223  ec_point_get_x_affine(xx, x, *curve, STACK_1);
224 
225  /* r = x mod n */
226  field_elt_get_number(abs, xx, 1, (*curve)->k, STACK_1);
227  number_mod(*rr, abs, (*curve)->n);
228 
229  /* if r == 0 --> new k */
230  if(!number_iszero(*rr))
231  {
232  /* s = k^-1 (hash + r*priv_key) mod n */
233  number_mul(tt, *rr, priv_key);
234  number_add(tt, tt, h);
235  number_mod(tt, tt, (*curve)->n); /* To keep the multiplication small */
236  number_invmod(t, k, (*curve)->n);
237  number_mul(tt, tt, t);
238  number_mod(*ss, tt, (*curve)->n);
239 
240  /* if s == 0 --> new k */
241  if(!number_iszero(*ss))
242  {
243  newk = false;
244  }
245  }
246  }
247  (*sig)->r = rr;
248  (*sig)->s = ss;
249 
250  /* Free memory */
251  ec_point_relax_pool_elt(x, (*curve)->k, STACK_1);
252  field_elt_relax_pool_elt(&xx, (*curve)->k, STACK_1);
253  number_tmp_free(&tt, 2*size+1, STACK_1);
254  number_tmp_free(&t, size, STACK_1);
255  number_tmp_free(&h, (strlen((char *)hash)/(BLOCK_SIZE/4)), STACK_1);
256  number_tmp_free(&k, size, STACK_1);
257  number_tmp_free(&abs, size, STACK_1);
258 }
259 
268 int8_t
270 {
271  if(!ec_belongs(*pub_key, *curve, STACK_1))
272  {
273  /* pubkey does not belong to the curve */
274  return false;
275  }
276  if(ec_point_is_neutral(*pub_key, *curve, STACK_1))
277  {
278  /* pubkey is the neutral element */
279  return false;
280  }
281  /* We finally test the order of the curve */
282  ec_point x;
283  ec_point_get_pool_elt(x, (*curve)->k, STACK_1);
284  ec_point_mul(x, (*curve)->n, *pub_key, *curve, STACK_1);
285  if(!ec_point_is_neutral(x, *curve, STACK_1))
286  {
287  /* pubkey is the neutral element */
288  return false;
289  }
290  ec_point_relax_pool_elt(x, (*curve)->k, STACK_1);
291 
292  return true;
293 }
294 
305 int8_t
306 ecdsa_verify(unsigned char *hash, ecdsa_sig *sig, ec_point *pub_key, ec_curve *curve, ecdsa_precomp precomp)
307 {
309 
310  if( number_iszero(*((*sig)->r)) || number_cmp(*((*sig)->r),(*curve)->n)>=0 || number_iszero(*((*sig)->s)) || number_cmp(*((*sig)->s),(*curve)->n)>=0)
311  {
312  return false;
313  }
314  uint8_t size = (*curve)->k->size;
315 
316  number w; number_tmp_alloc(&w, size, STACK_1);
317  number u1; number_tmp_alloc(&u1, size, STACK_1);
318  number u2; number_tmp_alloc(&u2, size, STACK_1);
319  number tt2; number_tmp_alloc(&tt2, 2*size, STACK_1);
320 
321  number abs;
322  number_tmp_alloc(&abs, size, STACK_1);
323 
324  ec_point x;
325  ec_point_get_pool_elt(x, (*curve)->k, STACK_1);
326  number h; number_tmp_alloc(&h, (strlen((char *)hash)/(BLOCK_SIZE/4)), STACK_1);
327  number_set_str(h , (char*)hash, 16);
328 
329  field_elt xx;
330  field_elt_get_pool_elt(&xx, (*curve)->k, STACK_1);
331 
332  /* w = s^-1 mod n */
333  number_invmod(w, *((*sig)->s), (*curve)->n);
334 
335  /* u1 = hash * w mod n */
336  number_mod(u1, h, (*curve)->n);
337  number_mul(tt2, u1, w);
338  number_mod(u1, tt2, (*curve)->n);
339 
340  /* u2 = r*w mod n */
341  number_mul(tt2, *((*sig)->r), w);
342  number_mod(u2, tt2, (*curve)->n);
343 
344  /* x = u1*G + u2*Q */
345  ec_point_2mul_with_precomp(x, u1, precomp->prec_G, u2, precomp->prec_K, PRECOMP_WIN_SIZE, *curve, STACK_1);
346  ec_point_get_x_affine(xx, x, *curve, STACK_1);
347 
348  /* Get the result, by comparing x value with r */
349  field_elt_get_number(abs, xx, 1, (*curve)->k, STACK_1);
350  number_mod(w, abs, (*curve)->n);
351  bool result = number_cmp(w, *((*sig)->r)) == 0;
352 
353  /* Free memory */
354  number_tmp_free(&h, (strlen((char *)hash)/(BLOCK_SIZE/4)), STACK_1);
355  ec_point_relax_pool_elt(x, (*curve)->k, STACK_1);
356  field_elt_relax_pool_elt(&xx, (*curve)->k, STACK_1);
357  number_tmp_free(&tt2, 2*size, STACK_1);
358  number_tmp_free(&u2, size, STACK_1);
359  number_tmp_free(&u1, size, STACK_1);
360  number_tmp_free(&w, size, STACK_1);
361  number_tmp_free(&abs, size, STACK_1);
362 
363  return result;
364 }
365 
366 int main()
367 {
368  /* Initialise MPHELL with 256 bits of security strength for the entropy, RANDOM_AES256 as DRBG and DEVURANDOM as entropy source */
369 
371 
372  /* Allocate a field of size 4*block_SIZE = 4*64 = 256 on 64 bits architecture */
373 
374  field k;
375  field_alloc(k, FP, bits_to_nblock(256), NULL);
376 
377  /* Allocate a number of size 4*block_SIZE = 4*64 = 256 on 64 bits architecture */
378 
379  number p;
380  number_init(&p, bits_to_nblock(256));
381 
382  /* Set the number p from a string in base 16 */
383 
384  number_set_str(p, "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16);
385 
386  /* Create the field of characteristic p */
387 
388  field_create(k, "", STACK_1, 1, p);
389 
390  /* Allocate curve */
391 
392  ec_curve E;
393  ec_alloc (E, k);
394  ec_init(E, k);
395 
396  /* Create curve */
397 
398  field_elt a, b;
399  ec_point G;
400  number n, h;
401 
402  field_elt_alloc(&a, k);
403  field_elt_init(a, k);
404  field_elt_alloc(&b, k);
405  field_elt_init(b, k);
406  ec_point_alloc(G, k);
407  ec_point_init(G, k);
408  number_init(&n, bits_to_nblock(256));
409  number_init(&h, bits_to_nblock(256));
410 
411  field_elt_set_str(a, "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16, false, k, STACK_1);
412  field_elt_set_str(b, "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16, false, k, STACK_1);
413  ec_point_set_aff_str(G, "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", false, 16, WEIERSTRASS, k, STACK_1);
414  number_set_str(h, "1", 16);
415  number_set_str(n, "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
416 
417  ec_create(E, "Weierstrass_nist_256", k, a, b, G, h, n, WEIERSTRASS, JACOBIAN, STACK_1);
418 
419  printf("E: \n"); ec_curve_print(E, 16, STACK_1); printf("\n");
420 
421  field_elt_free(&a, k);
422  field_elt_free(&b, k);
423 
424  ec_point_free(G, k);
425  number_free(&n);
426  number_free(&h);
427 
428  /* Create public key */
429  ec_point pub_key;
430  ec_point_alloc(pub_key, E->k);
431  ec_point_init(pub_key, E->k);
432  ec_point_set_aff_str(pub_key, "CBE2BCC92CDA44BB7851833F41684935DAD703C9AFB5D209F2922F8F739BA2D7", "8B620F0C41F572563648CC9C1C782F71C952B87782B61431640505AA317FCC07", false, 16, WEIERSTRASS, k, STACK_1);
433 
434  /* Set private key */
435  number priv_key;
436  number_init(&priv_key,bits_to_nblock(256));
437  number_set_str(priv_key, "5A23E08CF6E463BFEDFBA98F0CCE0B3B0A18EFED7DD31834577721A96D10BB8B", 16);
438 
439  /* Digest to sign */
440  char * digest = "982c20c2493fc9ae405b74b65a022662c014a38ef3d707217e56e57afac05994";
441 
442  /* Allocate ecdsa_sig structure */
443  ecdsa_sig sig;
444  ecdsa_sign_alloc(&sig, bits_to_nblock(256));
445 
446  /* Sign the digest */
447  ecdsa_sign((unsigned char *)digest, &sig, priv_key, &E);
448 
449  printf("The signature is: (");
450  number_print(*(sig->r), 16);
451  printf(", ");
452  number_print(*(sig->s), 16);
453  printf(")\n");
454 
455  /* Verify the public key */
456  printf("\nThe validity of the public key is a:\n");
457  int ret = ecdsa_pub_key_validation(&pub_key, &E);
458  if( ret < 1 )
459  {
460  printf("ERROR\n");
461  }
462  else
463  {
464  printf("SUCCESS\n");
465  }
466 
467  /* Precomputation (to speed up verification) */
468  printf("-> Precomputation \n");
469  ecdsa_precomp precomp;
470  ecdsa_precal(&precomp, &pub_key, E);
471 
472  /* Verify the signature */
473  printf("-> Verify ECDSA signature \n");
474  ret = ecdsa_verify((unsigned char *)digest , &sig, &pub_key, &E, precomp);
475  if( ret < 1 )
476  {
477  printf("ERROR\n");
478  }
479  else
480  {
481  printf("SUCCESS\n");
482  }
483 
484  /* Free memory */
485  ec_point_free(pub_key, k);
486  number_free(&priv_key);
487  ecdsa_sign_free(&sig);
488  number_free(&p);
489  ecdsa_precal_free(&precomp, E);
490  field_free(k);
491  ec_free(E);
492 
493  free_mphell();
494 
495  return 0;
496 }
bool ec_belongs(ec_point_srcptr P, ec_curve_srcptr E, uint8_t stack)
Test if P belongs to E.
Definition: mphell-curve.c:865
bool number_iszero(number_srcptr src)
Test if src is zero.
fp_elt * field_elt
Generic field element.
Definition: mphell-field.h:39
void ec_point_set_neutral(ec_point_ptr dst, ec_curve_srcptr E, uint8_t stack)
Set dst to the neutral element.
Definition: mphell-curve.c:780
void free_mphell()
Free MPHELL memory, especially the big amount of temporary memory.
Definition: mphell-init.c:97
void ec_create(ec_curve_ptr E, const char *id_curve, field_srcptr k, fe_srcptr a, fe_srcptr b, ec_point_srcptr G, number_srcptr h, number_srcptr n, const ec_type type, const ec_formula f, uint8_t stack)
Create an elliptic curve E, the curve must be allocated and initialised (ec_alloc & ec_init)
Definition: mphell-curve.c:62
void field_elt_free(fe_ptr *src, field_srcptr k)
Free space used by src.
Definition: mphell-field.c:356
void ecdsa_sign(unsigned char *hash, ecdsa_sig *sig, number_ptr priv_key, ec_curve *curve)
Sign "hash" with ECDSA algorithm using the EC "curve" and the private key "key".
void number_invmod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that dst = src1^(-1) mod src2.
void init_mphell(const uint16_t security_strength, const random_type type, const entropy_type entropy)
Initialise MPHELL with security_strength bits of security (for random number only).
Definition: mphell-init.c:35
Define an elliptic curve point.
Definition: mphell-curve.h:103
void ec_point_alloc(ec_point_ptr P, field_srcptr k)
Allocate an elliptic curve point.
Definition: mphell-curve.c:673
void number_set_ui(number_ptr dst, const block src)
Set dst to src.
void ec_init(ec_curve_ptr E, field_srcptr k)
Initialise a curve.
Definition: mphell-curve.c:52
uint8_t bits_to_nblock(const uint16_t nbits)
Return the number of blocks required to store a nbits number.
Definition: mphell-util.c:29
void field_elt_alloc(fe_ptr *dst, field_srcptr k)
Allocate space for a field element.
Definition: mphell-field.c:277
void ec_point_init(ec_point_ptr P, field_srcptr k)
Initialise an elliptic curve point.
Definition: mphell-curve.c:682
field_t field[1]
Address of a field structure.
Definition: mphell-field.h:110
void ec_point_add(ec_point_ptr P3, ec_point_srcptr P1, ec_point_srcptr P2, ec_curve_srcptr E, uint8_t stack)
Set P3 to P1 + P2, using dedicated formulae (not protected against SPA, but faster)
void number_random1(number_ptr dst, number_srcptr bound, uint8_t stack)
Set dst to a random number_ptr between 0 and bound, the random process is chosen at the MPHELL initia...
void number_free(number *dst)
Free a number_ptr allocated on the RAM memory (malloc)
Definition: mphell-number.c:75
void ec_point_free(ec_point_ptr P, field_srcptr k)
Free the point P.
Definition: mphell-curve.c:700
void ec_free(ec_curve_ptr E)
Free the elliptic curve E.
Definition: mphell-curve.c:655
static void ec_point_relax_pool_elt(ec_point_ptr P, field_ptr k, uint8_t stack)
Relax an initialised point from the pool.
Definition: mphell-curve.h:218
bool ec_point_is_neutral(ec_point_srcptr P, ec_curve_srcptr E, uint8_t stack)
Test if P is the neutral element.
void field_create(field_ptr k, const char *id, uint8_t stack, const uint32_t n,...)
Initialize the different fields of the structure pointed by k.
Definition: mphell-field.c:76
void field_elt_get_number(number_ptr dst, fe_srcptr src, uint8_t pos, field_srcptr k, uint8_t stack)
If Montgomery arithmetic is used, lift src (which is into Montgomery form) to classical fp (or its co...
Definition: mphell-field.c:563
void ecdsa_sign_free(ecdsa_sig *sig)
Free a used signature structure.
void ec_point_set_aff_str(ec_point_ptr P, const char *str_x, const char *str_y, const bool is_reduced, const uint8_t base, const ec_type type, field_srcptr k, uint8_t stack)
Set a point from its affine coordinates under string format.
Definition: mphell-curve.c:759
static void ec_point_get_pool_elt(ec_point_ptr P, field_ptr k, uint8_t stack)
Get an initialised point from the pool.
Definition: mphell-curve.h:202
Precomputation structure.
void number_mul(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to src1 * src2.
void ecdsa_sign_alloc(ecdsa_sig *sig, uint8_t size)
Allocate a signature structure.
void ec_alloc(ec_curve_ptr E, field_srcptr k)
Allocate a curve.
Definition: mphell-curve.c:37
void ec_set_fast_unified_coordinates(ec_curve_ptr E)
Set the fastest unified coordinates system.
Definition: mphell-curve.c:544
void field_alloc(field_ptr k, const field_type type, const uint8_t size, field_ptr base)
Allocates space for the different fields of the structure pointed by k.
Definition: mphell-field.c:37
void number_tmp_free(number *t, const uint8_t size, uint8_t stack)
Free a temporary number.
Definition: mphell-number.c:45
void ec_point_mul(ec_point_ptr P3, number_srcptr n, ec_point_srcptr P1, ec_curve_srcptr E, uint8_t stack)
Set P3 to n * P1 using Montgomery for Weierstrass elliptic curve, and naive method for other elliptic...
ec_point G
Definition: mphell-curve.h:147
void field_elt_init(fe_ptr dst, field_srcptr k)
Initialise the field element.
Definition: mphell-field.c:299
void ec_point_copy(ec_point_ptr P3, ec_point_srcptr P, field_srcptr k)
Copy P into P3.
Definition: mphell-curve.c:709
void ec_point_2mul_with_precomp(ec_point_ptr P3, number_srcptr n1, ec_point *tab_P1, number_srcptr n2, ec_point *tab_P2, int16_t win_size, ec_curve_srcptr E, uint8_t stack)
Set P3 to n1 * P1 + n2 * P2 using 2 precomputated array.
Define an ECDSA signature.
void ec_curve_print(ec_curve_srcptr E, const uint8_t base, uint8_t stack)
Print a description of E.
void number_add(number_ptr dst, number_srcptr src1, number_srcptr src2)
Set dst to src1 + src2 if src1 + src2 fit in dst.
field_ptr k
Definition: mphell-curve.h:142
void number_set_str(number_ptr dst, const char *str, const uint8_t base)
Set dst to str.
void number_tmp_alloc(number *t, const uint8_t size, uint8_t stack)
Allocate a temporary number.
Definition: mphell-number.c:31
void number_init(number *dst, const uint8_t n)
Allocate a number_ptr on the RAM memory (malloc)
Definition: mphell-number.c:59
void ecdsa_precal(ecdsa_precomp *precomp, ec_point *key, ec_curve_ptr E)
Compute 1*G, 2*G, 3*G, 4*G, 5*G, 6*G, 7*G and 1*Q, 2*Q, 3*Q, 4*Q, 5*Q, 6*Q, 7*Q where G is the base p...
int8_t number_cmp(number_srcptr src1, number_srcptr src2)
Compare src1 and src2.
void field_free(field_ptr k)
Free the space of the field informations structure.
Definition: mphell-field.c:183
void number_print(number_srcptr src, const uint8_t base)
Print src in base "base".
ec_point prec_G[2 *PRECOMP_SIZE]
Define an elliptic curve.
Definition: mphell-curve.h:139
int8_t ecdsa_pub_key_validation(ec_point *pub_key, ec_curve *curve)
Verify that the public key is valid (id est check taht pub_key belongs to the curve,...
void number_mod(number_ptr dst, number_srcptr src1, number_srcptr src2)
Compute dst such that src1 = q * src2 + dst ; dst < src2.
void field_elt_set_str(fe_ptr dst, const char *str, const uint8_t base, const bool isreduced, field_srcptr k, uint8_t stack)
Set dst to str, if Montgomery arithmetic is used, is_reduced == false -> transform dst into its Montg...
Definition: mphell-field.c:505
void ecdsa_precal_free(ecdsa_precomp *precomp, ec_curve_ptr E)
Free memory of the ecdsa_precomp structure.
int8_t ecdsa_verify(unsigned char *hash, ecdsa_sig *sig, ec_point *pub_key, ec_curve *curve, ecdsa_precomp precomp)
Verify the signature "sig" of hash "hash" using public key "pub_key" and the EC "curve".
static void field_elt_relax_pool_elt(field_elt *dst, field_ptr k, uint8_t stack)
Relax an initialised field element from the pool.
Definition: mphell-field.h:167
void ec_set_fast_dedicated_coordinates(ec_curve_ptr E)
Set the fastest dedicated coordinates system.
Definition: mphell-curve.c:562
static void field_elt_get_pool_elt(field_elt *dst, field_ptr k, uint8_t stack)
Get an initialised field element from the pool.
Definition: mphell-field.h:134
ec_point prec_K[2 *PRECOMP_SIZE]
void ec_point_get_x_affine(field_elt x, ec_point_ptr P, ec_curve_srcptr E, uint8_t stack)
Convert P->x to its affine representation.
Definition: mphell-curve.c:818
void ec_point_mul_unified(ec_point_ptr P3, number_srcptr n, ec_point_srcptr P1, ec_curve_srcptr E, uint8_t stack)
Set P3 to n * P1 using Montgomery for Weierstrass elliptic curve, and naive method for other elliptic...