Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/mpi/ec.c
Line
Count
Source (jump to first uncovered line)
1
/* ec.c -  Elliptic Curve functions
2
 * Copyright (C) 2007 Free Software Foundation, Inc.
3
 * Copyright (C) 2013 g10 Code GmbH
4
 *
5
 * This file is part of Libgcrypt.
6
 *
7
 * Libgcrypt is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation; either version 2.1 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * Libgcrypt 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
18
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <errno.h>
25
26
#include "mpi-internal.h"
27
#include "longlong.h"
28
#include "g10lib.h"
29
#include "context.h"
30
#include "ec-context.h"
31
#include "ec-internal.h"
32
33
extern void reverse_buffer (unsigned char *buffer, unsigned int length);
34
35
7.78k
#define point_init(a)  _gcry_mpi_point_init ((a))
36
11.6k
#define point_free(a)  _gcry_mpi_point_free_parts ((a))
37
38
39
/* Print a point using the log functions.  If CTX is not NULL affine
40
   coordinates will be printed.  */
41
void
42
_gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx)
43
0
{
44
0
  gcry_mpi_t x, y;
45
0
  char buf[100];
46
47
0
  if (!point)
48
0
    {
49
0
      snprintf (buf, sizeof buf - 1, "%s.*", name);
50
0
      log_mpidump (buf, NULL);
51
0
      return;
52
0
    }
53
0
  snprintf (buf, sizeof buf - 1, "%s.X", name);
54
55
0
  if (ctx)
56
0
    {
57
0
      x = mpi_new (0);
58
0
      y = mpi_new (0);
59
0
    }
60
0
  if (!ctx || _gcry_mpi_ec_get_affine (x, y, point, ctx))
61
0
    {
62
0
      log_mpidump (buf, point->x);
63
0
      buf[strlen(buf)-1] = 'Y';
64
0
      log_mpidump (buf, point->y);
65
0
      buf[strlen(buf)-1] = 'Z';
66
0
      log_mpidump (buf, point->z);
67
0
    }
68
0
  else
69
0
    {
70
0
      buf[strlen(buf)-1] = 'x';
71
0
      log_mpidump (buf, x);
72
0
      buf[strlen(buf)-1] = 'y';
73
0
      log_mpidump (buf, y);
74
75
0
    }
76
0
  if (ctx)
77
0
    {
78
0
      _gcry_mpi_release (x);
79
0
      _gcry_mpi_release (y);
80
0
    }
81
0
}
82
83
84
/* Create a new point option.  NBITS gives the size in bits of one
85
   coordinate; it is only used to pre-allocate some resources and
86
   might also be passed as 0 to use a default value.  */
87
mpi_point_t
88
_gcry_mpi_point_new (unsigned int nbits)
89
14.6k
{
90
14.6k
  mpi_point_t p;
91
92
14.6k
  (void)nbits;  /* Currently not used.  */
93
94
14.6k
  p = xmalloc (sizeof *p);
95
14.6k
  _gcry_mpi_point_init (p);
96
14.6k
  return p;
97
14.6k
}
98
99
100
/* Release the point object P.  P may be NULL. */
101
void
102
_gcry_mpi_point_release (mpi_point_t p)
103
14.6k
{
104
14.6k
  if (p)
105
14.6k
    {
106
14.6k
      _gcry_mpi_point_free_parts (p);
107
14.6k
      xfree (p);
108
14.6k
    }
109
14.6k
}
110
111
112
/* Initialize the fields of a point object.  gcry_mpi_point_free_parts
113
   may be used to release the fields.  */
114
void
115
_gcry_mpi_point_init (mpi_point_t p)
116
37.4k
{
117
37.4k
  p->x = mpi_new (0);
118
37.4k
  p->y = mpi_new (0);
119
37.4k
  p->z = mpi_new (0);
120
37.4k
}
121
122
123
/* Release the parts of a point object. */
124
void
125
_gcry_mpi_point_free_parts (mpi_point_t p)
126
48.6k
{
127
48.6k
  mpi_free (p->x); p->x = NULL;
128
48.6k
  mpi_free (p->y); p->y = NULL;
129
48.6k
  mpi_free (p->z); p->z = NULL;
130
48.6k
}
131
132
133
/* Set the value from S into D.  */
134
static void
135
point_set (mpi_point_t d, mpi_point_t s)
136
351k
{
137
351k
  mpi_set (d->x, s->x);
138
351k
  mpi_set (d->y, s->y);
139
351k
  mpi_set (d->z, s->z);
140
351k
}
141
142
143
/* Return a copy of POINT. */
144
gcry_mpi_point_t
145
_gcry_mpi_point_copy (gcry_mpi_point_t point)
146
0
{
147
0
  mpi_point_t newpoint;
148
149
0
  newpoint = _gcry_mpi_point_new (0);
150
0
  if (point)
151
0
    point_set (newpoint, point);
152
153
0
  return newpoint;
154
0
}
155
156
157
void
158
_gcry_mpi_ec_point_resize (mpi_point_t p, mpi_ec_t ctx)
159
1.44M
{
160
1.44M
  size_t nlimbs = ctx->p->nlimbs;
161
162
1.44M
  mpi_resize (p->x, nlimbs);
163
1.44M
  p->x->nlimbs = nlimbs;
164
1.44M
  mpi_resize (p->z, nlimbs);
165
1.44M
  p->z->nlimbs = nlimbs;
166
167
1.44M
  if (ctx->model != MPI_EC_MONTGOMERY)
168
1.44M
    {
169
1.44M
      mpi_resize (p->y, nlimbs);
170
1.44M
      p->y->nlimbs = nlimbs;
171
1.44M
    }
172
1.44M
}
173
174
175
static void
176
point_swap_cond (mpi_point_t d, mpi_point_t s, unsigned long swap,
177
                 mpi_ec_t ctx)
178
0
{
179
0
  mpi_swap_cond (d->x, s->x, swap);
180
0
  if (ctx->model != MPI_EC_MONTGOMERY)
181
0
    mpi_swap_cond (d->y, s->y, swap);
182
0
  mpi_swap_cond (d->z, s->z, swap);
183
0
}
184
185
186
/* Set the projective coordinates from POINT into X, Y, and Z.  If a
187
   coordinate is not required, X, Y, or Z may be passed as NULL.  */
188
void
189
_gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
190
                     mpi_point_t point)
191
0
{
192
0
  if (x)
193
0
    mpi_set (x, point->x);
194
0
  if (y)
195
0
    mpi_set (y, point->y);
196
0
  if (z)
197
0
    mpi_set (z, point->z);
198
0
}
199
200
201
/* Set the projective coordinates from POINT into X, Y, and Z and
202
   release POINT.  If a coordinate is not required, X, Y, or Z may be
203
   passed as NULL.  */
204
void
205
_gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
206
                            mpi_point_t point)
207
0
{
208
0
  mpi_snatch (x, point->x);
209
0
  mpi_snatch (y, point->y);
210
0
  mpi_snatch (z, point->z);
211
0
  xfree (point);
212
0
}
213
214
215
/* Set the projective coordinates from X, Y, and Z into POINT.  If a
216
   coordinate is given as NULL, the value 0 is stored into point.  If
217
   POINT is given as NULL a new point object is allocated.  Returns
218
   POINT or the newly allocated point object. */
219
mpi_point_t
220
_gcry_mpi_point_set (mpi_point_t point,
221
                     gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
222
0
{
223
0
  if (!point)
224
0
    point = mpi_point_new (0);
225
226
0
  if (x)
227
0
    mpi_set (point->x, x);
228
0
  else
229
0
    mpi_clear (point->x);
230
0
  if (y)
231
0
    mpi_set (point->y, y);
232
0
  else
233
0
    mpi_clear (point->y);
234
0
  if (z)
235
0
    mpi_set (point->z, z);
236
0
  else
237
0
    mpi_clear (point->z);
238
239
0
  return point;
240
0
}
241
242
243
/* Set the projective coordinates from X, Y, and Z into POINT.  If a
244
   coordinate is given as NULL, the value 0 is stored into point.  If
245
   POINT is given as NULL a new point object is allocated.  The
246
   coordinates X, Y, and Z are released.  Returns POINT or the newly
247
   allocated point object. */
248
mpi_point_t
249
_gcry_mpi_point_snatch_set (mpi_point_t point,
250
                            gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
251
7.31k
{
252
7.31k
  if (!point)
253
7.31k
    point = mpi_point_new (0);
254
255
7.31k
  if (x)
256
7.31k
    mpi_snatch (point->x, x);
257
0
  else
258
0
    mpi_clear (point->x);
259
7.31k
  if (y)
260
7.31k
    mpi_snatch (point->y, y);
261
0
  else
262
0
    mpi_clear (point->y);
263
7.31k
  if (z)
264
7.31k
    mpi_snatch (point->z, z);
265
0
  else
266
0
    mpi_clear (point->z);
267
268
7.31k
  return point;
269
7.31k
}
270
271
272
/* W = W mod P.  */
273
static void
274
ec_mod (gcry_mpi_t w, mpi_ec_t ec)
275
164k
{
276
164k
  if (0 && ec->dialect == ECC_DIALECT_ED25519)
277
0
    _gcry_mpi_ec_ed25519_mod (w);
278
164k
  else if (ec->t.p_barrett)
279
0
    _gcry_mpi_mod_barrett (w, w, ec->t.p_barrett);
280
164k
  else
281
164k
    _gcry_mpi_mod (w, w, ec->p);
282
164k
}
283
284
static void
285
ec_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
286
1.75M
{
287
1.75M
  mpi_add (w, u, v);
288
1.75M
  ctx->mod (w, ctx);
289
1.75M
}
290
291
static void
292
ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ec)
293
5.64M
{
294
5.64M
  mpi_sub (w, u, v);
295
8.46M
  while (w->sign)
296
2.81M
    mpi_add (w, w, ec->p);
297
  /*ctx->mod (w, ec);*/
298
5.64M
}
299
300
static void
301
ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
302
15.7M
{
303
15.7M
  mpi_mul (w, u, v);
304
15.7M
  ctx->mod (w, ctx);
305
15.7M
}
306
307
/* W = 2 * U mod P.  */
308
static void
309
ec_mul2 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
310
2.45M
{
311
2.45M
  mpi_lshift (w, u, 1);
312
2.45M
  ctx->mod (w, ctx);
313
2.45M
}
314
315
static void
316
ec_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e,
317
         mpi_ec_t ctx)
318
1.36M
{
319
1.36M
  mpi_powm (w, b, e, ctx->p);
320
  /* _gcry_mpi_abs (w); */
321
1.36M
}
322
323
324
/* Shortcut for
325
     ec_powm (B, B, mpi_const (MPI_C_TWO), ctx);
326
   for easier optimization.  */
327
static void
328
ec_pow2 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
329
5.25M
{
330
  /* Using mpi_mul is slightly faster (at least on amd64).  */
331
  /* mpi_powm (w, b, mpi_const (MPI_C_TWO), ctx->p); */
332
5.25M
  ec_mulm (w, b, b, ctx);
333
5.25M
}
334
335
336
/* Shortcut for
337
     ec_powm (B, B, mpi_const (MPI_C_THREE), ctx);
338
   for easier optimization.  */
339
static void
340
ec_pow3 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
341
2.72k
{
342
2.72k
  mpi_powm (w, b, mpi_const (MPI_C_THREE), ctx->p);
343
2.72k
}
344
345
346
static void
347
ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
348
8.48k
{
349
8.48k
  if (!mpi_invm (x, a, ctx->p))
350
0
    {
351
0
      log_error ("ec_invm: inverse does not exist:\n");
352
0
      log_mpidump ("  a", a);
353
0
      log_mpidump ("  p", ctx->p);
354
0
    }
355
8.48k
}
356

357
/* Routines for 2^255 - 19.  */
358
359
325M
#define LIMB_SIZE_25519 ((256+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
360
361
static void
362
ec_addm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
363
16.2M
{
364
16.2M
  mpi_ptr_t wp, up, vp;
365
16.2M
  mpi_size_t wsize = LIMB_SIZE_25519;
366
16.2M
  mpi_limb_t n[LIMB_SIZE_25519];
367
16.2M
  mpi_limb_t borrow;
368
369
16.2M
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
370
0
    log_bug ("addm_25519: different sizes\n");
371
372
16.2M
  up = u->d;
373
16.2M
  vp = v->d;
374
16.2M
  wp = w->d;
375
376
16.2M
  _gcry_mpih_add_n (wp, up, vp, wsize);
377
16.2M
  borrow = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
378
16.2M
  mpih_set_cond (wp, n, wsize, (borrow == 0UL));
379
16.2M
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
380
16.2M
}
381
382
static void
383
ec_subm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
384
21.8M
{
385
21.8M
  mpi_ptr_t wp, up, vp;
386
21.8M
  mpi_size_t wsize = LIMB_SIZE_25519;
387
21.8M
  mpi_limb_t n[LIMB_SIZE_25519];
388
21.8M
  mpi_limb_t borrow;
389
390
21.8M
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
391
0
    log_bug ("subm_25519: different sizes\n");
392
393
21.8M
  up = u->d;
394
21.8M
  vp = v->d;
395
21.8M
  wp = w->d;
396
397
21.8M
  borrow = _gcry_mpih_sub_n (wp, up, vp, wsize);
398
21.8M
  _gcry_mpih_add_n (n, wp, ctx->p->d, wsize);
399
21.8M
  mpih_set_cond (wp, n, wsize, (borrow != 0UL));
400
21.8M
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
401
21.8M
}
402
403
static void
404
ec_mulm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
405
41.6M
{
406
41.6M
  mpi_ptr_t wp, up, vp;
407
41.6M
  mpi_size_t wsize = LIMB_SIZE_25519;
408
41.6M
  mpi_limb_t n[LIMB_SIZE_25519*2];
409
41.6M
  mpi_limb_t cy;
410
41.6M
  int msb;
411
412
41.6M
  (void)ctx;
413
41.6M
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
414
0
    log_bug ("mulm_25519: different sizes\n");
415
416
41.6M
  up = u->d;
417
41.6M
  vp = v->d;
418
41.6M
  wp = w->d;
419
420
41.6M
  _gcry_mpih_mul_n (n, up, vp, wsize);
421
41.6M
  memcpy (wp, n, wsize * BYTES_PER_MPI_LIMB);
422
41.6M
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
423
424
41.6M
  _gcry_mpih_rshift (n, n+LIMB_SIZE_25519-1, LIMB_SIZE_25519+1,
425
41.6M
         (255 % BITS_PER_MPI_LIMB));
426
427
41.6M
  cy = _gcry_mpih_addmul_1 (wp, n, wsize, 19);
428
429
41.6M
  memset (n, 0, wsize * BYTES_PER_MPI_LIMB);
430
41.6M
  msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
431
41.6M
  n[0] = (cy * 2 + msb) * 19;
432
41.6M
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
433
41.6M
  _gcry_mpih_add_n (wp, wp, n, wsize);
434
435
41.6M
  cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
436
41.6M
  mpih_set_cond (wp, n, wsize, (cy == 0UL));
437
41.6M
}
438
439
static void
440
ec_mul2_25519 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
441
3.51M
{
442
3.51M
  ec_addm_25519 (w, u, u, ctx);
443
3.51M
}
444
445
static void
446
ec_pow2_25519 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
447
15.4M
{
448
15.4M
  ec_mulm_25519 (w, b, b, ctx);
449
15.4M
}
450

451
/* Routines for 2^448 - 2^224 - 1.  */
452
453
0
#define LIMB_SIZE_448 ((448+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
454
0
#define LIMB_SIZE_HALF_448 ((LIMB_SIZE_448+1)/2)
455
456
static void
457
ec_addm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
458
0
{
459
0
  mpi_ptr_t wp, up, vp;
460
0
  mpi_size_t wsize = LIMB_SIZE_448;
461
0
  mpi_limb_t n[LIMB_SIZE_448];
462
0
  mpi_limb_t cy;
463
464
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
465
0
    log_bug ("addm_448: different sizes\n");
466
467
0
  up = u->d;
468
0
  vp = v->d;
469
0
  wp = w->d;
470
471
0
  cy = _gcry_mpih_add_n (wp, up, vp, wsize);
472
0
  _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
473
0
  mpih_set_cond (wp, n, wsize, (cy != 0UL));
474
0
}
475
476
static void
477
ec_subm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
478
0
{
479
0
  mpi_ptr_t wp, up, vp;
480
0
  mpi_size_t wsize = LIMB_SIZE_448;
481
0
  mpi_limb_t n[LIMB_SIZE_448];
482
0
  mpi_limb_t borrow;
483
484
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
485
0
    log_bug ("subm_448: different sizes\n");
486
487
0
  up = u->d;
488
0
  vp = v->d;
489
0
  wp = w->d;
490
491
0
  borrow = _gcry_mpih_sub_n (wp, up, vp, wsize);
492
0
  _gcry_mpih_add_n (n, wp, ctx->p->d, wsize);
493
0
  mpih_set_cond (wp, n, wsize, (borrow != 0UL));
494
0
}
495
496
static void
497
ec_mulm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
498
0
{
499
0
  mpi_ptr_t wp, up, vp;
500
0
  mpi_size_t wsize = LIMB_SIZE_448;
501
0
  mpi_limb_t n[LIMB_SIZE_448*2];
502
0
  mpi_limb_t a2[LIMB_SIZE_HALF_448];
503
0
  mpi_limb_t a3[LIMB_SIZE_HALF_448];
504
0
  mpi_limb_t b0[LIMB_SIZE_HALF_448];
505
0
  mpi_limb_t b1[LIMB_SIZE_HALF_448];
506
0
  mpi_limb_t cy;
507
508
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
509
0
    log_bug ("mulm_448: different sizes\n");
510
511
0
  up = u->d;
512
0
  vp = v->d;
513
0
  wp = w->d;
514
515
0
  _gcry_mpih_mul_n (n, up, vp, wsize);
516
517
0
  memcpy (b0, n, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB);
518
0
  memcpy (a2, n + wsize, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB);
519
520
0
#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
521
0
  b0[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL<<32)-1;
522
0
  a2[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL<<32)-1;
523
0
  _gcry_mpih_rshift (b1, n + wsize/2, LIMB_SIZE_HALF_448, 32);
524
0
  _gcry_mpih_rshift (a3, n + wsize + wsize/2, LIMB_SIZE_HALF_448, 32);
525
#else
526
  memcpy (b1, n + wsize/2, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB);
527
  memcpy (a3, n + wsize + wsize/2, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB);
528
#endif
529
530
0
  cy = _gcry_mpih_add_n (b0, b0, a2, LIMB_SIZE_HALF_448);
531
0
  cy += _gcry_mpih_add_n (wp, b0, a3, LIMB_SIZE_HALF_448);
532
0
#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
533
0
  cy = wp[LIMB_SIZE_HALF_448-1] >> 32;
534
0
  wp[LIMB_SIZE_HALF_448-1] &= (((mpi_limb_t)1UL <<32)-1);
535
0
#endif
536
0
  memset (b0, 0, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB);
537
0
  b0[0] = cy;
538
539
0
  cy = _gcry_mpih_add_n (b1, b1, b0, LIMB_SIZE_HALF_448);
540
0
  cy += _gcry_mpih_lshift (a3, a3, LIMB_SIZE_HALF_448, 1);
541
0
  cy += _gcry_mpih_add_n (b1, b1, a2, LIMB_SIZE_HALF_448);
542
0
  cy += _gcry_mpih_add_n (b1, b1, a3, LIMB_SIZE_HALF_448);
543
0
#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
544
0
  cy = _gcry_mpih_rshift (b1, b1, LIMB_SIZE_HALF_448, 32);
545
0
  wp[LIMB_SIZE_HALF_448-1] |= cy;
546
0
#endif
547
0
  memcpy (wp + LIMB_SIZE_HALF_448, b1, (wsize / 2) * BYTES_PER_MPI_LIMB);
548
549
0
#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
550
0
  cy = b1[LIMB_SIZE_HALF_448-1];
551
0
#endif
552
553
0
  memset (n, 0, wsize * BYTES_PER_MPI_LIMB);
554
555
0
#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
556
0
  n[LIMB_SIZE_HALF_448-1] = cy << 32;
557
#else
558
  n[LIMB_SIZE_HALF_448] = cy;
559
#endif
560
0
  n[0] = cy;
561
0
  _gcry_mpih_add_n (wp, wp, n, wsize);
562
563
0
  cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
564
0
  mpih_set_cond (wp, n, wsize, (cy == 0UL));
565
0
}
566
567
static void
568
ec_mul2_448 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
569
0
{
570
0
  ec_addm_448 (w, u, u, ctx);
571
0
}
572
573
static void
574
ec_pow2_448 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
575
0
{
576
0
  ec_mulm_448 (w, b, b, ctx);
577
0
}
578

579
580
/* Fast reduction for secp256k1 */
581
static void
582
ec_secp256k1_mod (gcry_mpi_t w, mpi_ec_t ctx)
583
5.77M
{
584
5.77M
  mpi_limb_t s[(256 + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB + 1];
585
5.77M
  mpi_limb_t n[DIM(s)];
586
5.77M
  const mpi_size_t wsize = DIM(s) - 1;
587
5.77M
  mpi_limb_t cy, borrow;
588
5.77M
  mpi_ptr_t wp;
589
590
5.77M
  MPN_NORMALIZE (w->d, w->nlimbs);
591
5.77M
  if (w->nlimbs > 2 * 256 / BITS_PER_MPI_LIMB)
592
0
    log_bug ("W must be less than m^2\n");
593
594
5.77M
  RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2);
595
596
5.77M
  wp = w->d;
597
598
  /* mod P (2^256 - 2^32 - 977) */
599
600
  /* first pass of reduction */
601
5.77M
  memcpy (n, wp + wsize, wsize * BYTES_PER_MPI_LIMB);
602
5.77M
#if BITS_PER_MPI_LIMB == 64
603
5.77M
  s[wsize] = _gcry_mpih_lshift (s, wp + wsize, wsize, 32);
604
#else
605
  s[0] = 0;
606
  memcpy (s + 1, wp + wsize, wsize * BYTES_PER_MPI_LIMB);
607
#endif
608
5.77M
  wp[wsize] = _gcry_mpih_addmul_1 (wp, n, wsize, 977);
609
5.77M
  cy = _gcry_mpih_add_n (wp, wp, s, wsize + 1);
610
611
  /* second pass of reduction */
612
5.77M
#if BITS_PER_MPI_LIMB == 64
613
  /* cy == 0 */
614
5.77M
  memset (n + 1, 0, (wsize - 1) * BYTES_PER_MPI_LIMB);
615
5.77M
  umul_ppmm(n[1], n[0], wp[wsize], ((mpi_limb_t)1 << 32) + 977);
616
#else
617
  memset (n + 2, 0, (wsize - 2) * BYTES_PER_MPI_LIMB);
618
  umul_ppmm(n[1], n[0], wp[wsize], 977);
619
  add_ssaaaa(n[2], n[1], 0, n[1], 0, cy * 977);
620
  add_ssaaaa(n[2], n[1], n[2], n[1], cy, wp[wsize]);
621
#endif
622
5.77M
  cy = _gcry_mpih_add_n (wp, wp, n, wsize);
623
624
5.77M
  borrow = _gcry_mpih_sub_n (s, wp, ctx->p->d, wsize);
625
5.77M
  mpih_set_cond (wp, s, wsize, (cy != 0UL) | (borrow == 0UL));
626
627
5.77M
  w->nlimbs = wsize;
628
5.77M
  MPN_NORMALIZE (wp, w->nlimbs);
629
5.77M
}
630
631
632
struct field_table {
633
  const char *p;
634
635
  /* computation routines for the field.  */
636
  void (* addm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
637
  void (* subm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
638
  void (* mulm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
639
  void (* mul2) (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx);
640
  void (* pow2) (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx);
641
  void (* mod) (gcry_mpi_t w, mpi_ec_t ctx);
642
};
643
644
static const struct field_table field_table[] = {
645
  {
646
    "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
647
    ec_addm_25519,
648
    ec_subm_25519,
649
    ec_mulm_25519,
650
    ec_mul2_25519,
651
    ec_pow2_25519,
652
    NULL
653
  },
654
  {
655
   "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
656
   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
657
    ec_addm_448,
658
    ec_subm_448,
659
    ec_mulm_448,
660
    ec_mul2_448,
661
    ec_pow2_448,
662
    NULL
663
  },
664
  {
665
    "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
666
    NULL,
667
    NULL,
668
    NULL,
669
    NULL,
670
    NULL,
671
    _gcry_mpi_ec_nist192_mod
672
  },
673
  {
674
    "0xffffffffffffffffffffffffffffffff000000000000000000000001",
675
    NULL,
676
    NULL,
677
    NULL,
678
    NULL,
679
    NULL,
680
    _gcry_mpi_ec_nist224_mod
681
  },
682
  {
683
    "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
684
    NULL,
685
    NULL,
686
    NULL,
687
    NULL,
688
    NULL,
689
    _gcry_mpi_ec_nist256_mod
690
  },
691
  {
692
    "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
693
    "ffffffff0000000000000000ffffffff",
694
    NULL,
695
    NULL,
696
    NULL,
697
    NULL,
698
    NULL,
699
    _gcry_mpi_ec_nist384_mod
700
  },
701
  {
702
    "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
703
    "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
704
    NULL,
705
    NULL,
706
    NULL,
707
    NULL,
708
    NULL,
709
    _gcry_mpi_ec_nist521_mod
710
  },
711
  {
712
    "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
713
    NULL,
714
    NULL,
715
    NULL,
716
    NULL,
717
    NULL,
718
    ec_secp256k1_mod
719
  },
720
  { NULL, NULL, NULL, NULL, NULL, NULL },
721
};
722
723
static gcry_mpi_t field_table_mpis[DIM(field_table)];
724

725
726
/* Force recomputation of all helper variables.  */
727
void
728
_gcry_mpi_ec_get_reset (mpi_ec_t ec)
729
7.31k
{
730
7.31k
  ec->t.valid.a_is_pminus3 = 0;
731
7.31k
  ec->t.valid.two_inv_p = 0;
732
7.31k
}
733
734
735
/* Accessor for helper variable.  */
736
static int
737
ec_get_a_is_pminus3 (mpi_ec_t ec)
738
1.05M
{
739
1.05M
  gcry_mpi_t tmp;
740
741
1.05M
  if (!ec->t.valid.a_is_pminus3)
742
1.94k
    {
743
1.94k
      ec->t.valid.a_is_pminus3 = 1;
744
1.94k
      tmp = mpi_alloc_like (ec->p);
745
1.94k
      mpi_sub_ui (tmp, ec->p, 3);
746
1.94k
      ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
747
1.94k
      mpi_free (tmp);
748
1.94k
    }
749
750
1.05M
  return ec->t.a_is_pminus3;
751
1.05M
}
752
753
754
/* Accessor for helper variable.  */
755
static gcry_mpi_t
756
ec_get_two_inv_p (mpi_ec_t ec)
757
349k
{
758
349k
  if (!ec->t.valid.two_inv_p)
759
1.94k
    {
760
1.94k
      ec->t.valid.two_inv_p = 1;
761
1.94k
      if (!ec->t.two_inv_p)
762
1.94k
        ec->t.two_inv_p = mpi_alloc (0);
763
1.94k
      ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
764
1.94k
    }
765
349k
  return ec->t.two_inv_p;
766
349k
}
767
768
769
static const char *const curve25519_bad_points[] = {
770
  "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
771
  "0x0000000000000000000000000000000000000000000000000000000000000000",
772
  "0x0000000000000000000000000000000000000000000000000000000000000001",
773
  "0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
774
  "0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
775
  "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
776
  "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
777
  NULL
778
};
779
780
781
static const char *const curve448_bad_points[] = {
782
  "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
783
  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
784
  "0x00000000000000000000000000000000000000000000000000000000"
785
  "00000000000000000000000000000000000000000000000000000000",
786
  "0x00000000000000000000000000000000000000000000000000000000"
787
  "00000000000000000000000000000000000000000000000000000001",
788
  "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
789
  "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
790
  "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
791
  "00000000000000000000000000000000000000000000000000000000",
792
  NULL
793
};
794
795
static const char *const *bad_points_table[] = {
796
  curve25519_bad_points,
797
  curve448_bad_points,
798
};
799
800
static gcry_mpi_t
801
scanval (const char *string)
802
0
{
803
0
  gpg_err_code_t rc;
804
0
  gcry_mpi_t val;
805
806
0
  rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
807
0
  if (rc)
808
0
    log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
809
0
  return val;
810
0
}
811
812
813
/* This function initialized a context for elliptic curve based on the
814
   field GF(p).  P is the prime specifying this field, A is the first
815
   coefficient.  CTX is expected to be zeroized.  */
816
static void
817
ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
818
           enum ecc_dialects dialect,
819
           int flags,
820
           gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
821
7.31k
{
822
7.31k
  int i;
823
7.31k
  static int use_barrett;
824
825
7.31k
  if (!use_barrett)
826
2
    {
827
2
      if (getenv ("GCRYPT_BARRETT"))
828
0
        use_barrett = 1;
829
2
      else
830
2
        use_barrett = -1;
831
2
    }
832
833
  /* Fixme: Do we want to check some constraints? e.g.  a < p  */
834
835
7.31k
  ctx->model = model;
836
7.31k
  ctx->dialect = dialect;
837
7.31k
  ctx->flags = flags;
838
7.31k
  ctx->nbits = mpi_get_nbits (p);
839
7.31k
  ctx->p = mpi_copy (p);
840
7.31k
  ctx->a = mpi_copy (a);
841
7.31k
  ctx->b = mpi_copy (b);
842
843
7.31k
  ctx->t.p_barrett = use_barrett > 0? _gcry_mpi_barrett_init (ctx->p, 0):NULL;
844
845
7.31k
  _gcry_mpi_ec_get_reset (ctx);
846
847
7.31k
  if (model == MPI_EC_MONTGOMERY)
848
0
    {
849
0
      for (i=0; i< DIM(bad_points_table); i++)
850
0
        {
851
0
          gcry_mpi_t p_candidate = scanval (bad_points_table[i][0]);
852
0
          int match_p = !mpi_cmp (ctx->p, p_candidate);
853
0
          int j;
854
855
0
          mpi_free (p_candidate);
856
0
          if (!match_p)
857
0
            continue;
858
859
0
          for (j=0; i< DIM(ctx->t.scratch) && bad_points_table[i][j]; j++)
860
0
            ctx->t.scratch[j] = scanval (bad_points_table[i][j]);
861
0
        }
862
0
    }
863
7.31k
  else
864
7.31k
    {
865
      /* Allocate scratch variables.  */
866
87.7k
      for (i=0; i< DIM(ctx->t.scratch); i++)
867
80.4k
        ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
868
7.31k
    }
869
870
7.31k
  ctx->addm = ec_addm;
871
7.31k
  ctx->subm = ec_subm;
872
7.31k
  ctx->mulm = ec_mulm;
873
7.31k
  ctx->mul2 = ec_mul2;
874
7.31k
  ctx->pow2 = ec_pow2;
875
7.31k
  ctx->mod = ec_mod;
876
877
21.0k
  for (i=0; field_table[i].p; i++)
878
21.0k
    {
879
21.0k
      gcry_mpi_t f_p;
880
21.0k
      gpg_err_code_t rc;
881
882
21.0k
      if (field_table_mpis[i] == NULL)
883
13
  {
884
13
    rc = _gcry_mpi_scan (&f_p, GCRYMPI_FMT_HEX, field_table[i].p, 0,
885
13
             NULL);
886
13
    if (rc)
887
0
      log_fatal ("scanning ECC parameter failed: %s\n",
888
0
           gpg_strerror (rc));
889
13
    field_table_mpis[i] = f_p; /* cache */
890
13
  }
891
21.0k
      else
892
21.0k
  {
893
21.0k
    f_p = field_table_mpis[i];
894
21.0k
  }
895
896
21.0k
      if (!mpi_cmp (p, f_p))
897
7.29k
        {
898
7.29k
          ctx->addm = field_table[i].addm ? field_table[i].addm : ctx->addm;
899
7.29k
          ctx->subm = field_table[i].subm ? field_table[i].subm : ctx->subm;
900
7.29k
          ctx->mulm = field_table[i].mulm ? field_table[i].mulm : ctx->mulm;
901
7.29k
          ctx->mul2 = field_table[i].mul2 ? field_table[i].mul2 : ctx->mul2;
902
7.29k
          ctx->pow2 = field_table[i].pow2 ? field_table[i].pow2 : ctx->pow2;
903
7.29k
          ctx->mod = field_table[i].mod ? field_table[i].mod : ctx->mod;
904
905
7.29k
    if (ctx->a)
906
7.29k
      {
907
7.29k
        mpi_resize (ctx->a, ctx->p->nlimbs);
908
7.29k
        ctx->a->nlimbs = ctx->p->nlimbs;
909
7.29k
      }
910
911
7.29k
    if (ctx->b)
912
7.29k
      {
913
7.29k
        mpi_resize (ctx->b, ctx->p->nlimbs);
914
7.29k
        ctx->b->nlimbs = ctx->p->nlimbs;
915
7.29k
      }
916
917
87.5k
          for (i=0; i< DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++)
918
80.2k
            ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs;
919
920
7.29k
          break;
921
7.29k
        }
922
21.0k
    }
923
924
  /* Prepare for fast reduction.  */
925
  /* FIXME: need a test for NIST values.  However it does not gain us
926
     any real advantage, for 384 bits it is actually slower than using
927
     mpi_mulm.  */
928
/*   ctx->nist_nbits = mpi_get_nbits (ctx->p); */
929
/*   if (ctx->nist_nbits == 192) */
930
/*     { */
931
/*       for (i=0; i < 4; i++) */
932
/*         ctx->s[i] = mpi_new (192); */
933
/*       ctx->c    = mpi_new (192*2); */
934
/*     } */
935
/*   else if (ctx->nist_nbits == 384) */
936
/*     { */
937
/*       for (i=0; i < 10; i++) */
938
/*         ctx->s[i] = mpi_new (384); */
939
/*       ctx->c    = mpi_new (384*2); */
940
/*     } */
941
7.31k
}
942
943
944
static void
945
ec_deinit (void *opaque)
946
7.31k
{
947
7.31k
  mpi_ec_t ctx = opaque;
948
7.31k
  int i;
949
950
7.31k
  _gcry_mpi_barrett_free (ctx->t.p_barrett);
951
952
  /* Domain parameter.  */
953
7.31k
  mpi_free (ctx->p);
954
7.31k
  mpi_free (ctx->a);
955
7.31k
  mpi_free (ctx->b);
956
7.31k
  _gcry_mpi_point_release (ctx->G);
957
7.31k
  mpi_free (ctx->n);
958
959
  /* The key.  */
960
7.31k
  _gcry_mpi_point_release (ctx->Q);
961
7.31k
  mpi_free (ctx->d);
962
963
  /* Private data of ec.c.  */
964
7.31k
  mpi_free (ctx->t.two_inv_p);
965
966
87.7k
  for (i=0; i< DIM(ctx->t.scratch); i++)
967
80.4k
    mpi_free (ctx->t.scratch[i]);
968
969
/*   if (ctx->nist_nbits == 192) */
970
/*     { */
971
/*       for (i=0; i < 4; i++) */
972
/*         mpi_free (ctx->s[i]); */
973
/*       mpi_free (ctx->c); */
974
/*     } */
975
/*   else if (ctx->nist_nbits == 384) */
976
/*     { */
977
/*       for (i=0; i < 10; i++) */
978
/*         mpi_free (ctx->s[i]); */
979
/*       mpi_free (ctx->c); */
980
/*     } */
981
7.31k
}
982
983
984
/* This function returns a new context for elliptic curve based on the
985
   field GF(p).  P is the prime specifying this field, A is the first
986
   coefficient, B is the second coefficient, and MODEL is the model
987
   for the curve.  This function is only used within Libgcrypt and not
988
   part of the public API.
989
990
   This context needs to be released using _gcry_mpi_ec_free.  */
991
mpi_ec_t
992
_gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
993
                             enum ecc_dialects dialect,
994
                             int flags,
995
                             gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
996
7.31k
{
997
7.31k
  mpi_ec_t ctx;
998
999
7.31k
  ctx = xcalloc (1, sizeof *ctx);
1000
7.31k
  ec_p_init (ctx, model, dialect, flags, p, a, b);
1001
1002
7.31k
  return ctx;
1003
7.31k
}
1004
1005
1006
/* This is a variant of _gcry_mpi_ec_p_internal_new which returns an
1007
   public context and does some error checking on the supplied
1008
   arguments.  On success the new context is stored at R_CTX and 0 is
1009
   returned; on error NULL is stored at R_CTX and an error code is
1010
   returned.
1011
1012
   The context needs to be released using gcry_ctx_release.  */
1013
gpg_err_code_t
1014
_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
1015
                    enum gcry_mpi_ec_models model,
1016
                    enum ecc_dialects dialect,
1017
                    int flags,
1018
                    gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
1019
0
{
1020
0
  gcry_ctx_t ctx;
1021
0
  mpi_ec_t ec;
1022
1023
0
  *r_ctx = NULL;
1024
0
  if (!p || !a)
1025
0
    return GPG_ERR_EINVAL;
1026
1027
0
  ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit);
1028
0
  if (!ctx)
1029
0
    return gpg_err_code_from_syserror ();
1030
0
  ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1031
0
  ec_p_init (ec, model, dialect, flags, p, a, b);
1032
1033
0
  *r_ctx = ctx;
1034
0
  return 0;
1035
0
}
1036
1037
1038
void
1039
_gcry_mpi_ec_free (mpi_ec_t ctx)
1040
7.34k
{
1041
7.34k
  if (ctx)
1042
7.31k
    {
1043
7.31k
      ec_deinit (ctx);
1044
7.31k
      xfree (ctx);
1045
7.31k
    }
1046
7.34k
}
1047
1048
1049
gcry_mpi_t
1050
_gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
1051
0
{
1052
0
  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1053
1054
0
  return _gcry_ecc_get_mpi (name, ec, copy);
1055
0
}
1056
1057
1058
gcry_mpi_point_t
1059
_gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
1060
0
{
1061
0
  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1062
1063
0
  (void)copy;  /* Not used.  */
1064
1065
0
  return _gcry_ecc_get_point (name, ec);
1066
0
}
1067
1068
1069
gpg_err_code_t
1070
_gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
1071
                      gcry_ctx_t ctx)
1072
0
{
1073
0
  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1074
1075
0
  return _gcry_ecc_set_mpi (name, newvalue, ec);
1076
0
}
1077
1078
1079
gpg_err_code_t
1080
_gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
1081
                        gcry_ctx_t ctx)
1082
0
{
1083
0
  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
1084
1085
0
  return _gcry_ecc_set_point (name, newvalue, ec);
1086
0
}
1087
1088
1089
/* Given an encoded point in the MPI VALUE and a context EC, decode
1090
 * the point according to the context and store it in RESULT.  On
1091
 * error an error code is return but RESULT might have been changed.
1092
 * If no context is given the function tries to decode VALUE by
1093
 * assuming a 0x04 prefixed uncompressed encoding.  */
1094
gpg_err_code_t
1095
_gcry_mpi_ec_decode_point (mpi_point_t result, gcry_mpi_t value, mpi_ec_t ec)
1096
7.31k
{
1097
7.31k
  gpg_err_code_t rc;
1098
1099
7.31k
  if (ec
1100
7.31k
      && (ec->dialect == ECC_DIALECT_ED25519
1101
7.31k
          || (ec->model == MPI_EC_EDWARDS
1102
2.72k
              && ec->dialect == ECC_DIALECT_SAFECURVE)))
1103
4.59k
    rc = _gcry_ecc_eddsa_decodepoint (value, ec, result, NULL, NULL);
1104
2.72k
  else if (ec && ec->model == MPI_EC_MONTGOMERY)
1105
0
    rc = _gcry_ecc_mont_decodepoint (value, ec, result);
1106
2.72k
  else
1107
2.72k
    rc = _gcry_ecc_sec_decodepoint (value, ec, result);
1108
1109
7.31k
  return rc;
1110
7.31k
}
1111
1112
1113
/* Compute the affine coordinates from the projective coordinates in
1114
   POINT.  Set them into X and Y.  If one coordinate is not required,
1115
   X or Y may be passed as NULL.  CTX is the usual context. Returns: 0
1116
   on success or !0 if POINT is at infinity.  */
1117
int
1118
_gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
1119
                         mpi_ec_t ctx)
1120
18.4k
{
1121
18.4k
  if (!mpi_cmp_ui (point->z, 0))
1122
0
    return -1;
1123
1124
18.4k
  switch (ctx->model)
1125
18.4k
    {
1126
4.66k
    case MPI_EC_WEIERSTRASS: /* Using Jacobian coordinates.  */
1127
4.66k
      {
1128
4.66k
        gcry_mpi_t z1, z2, z3;
1129
1130
4.66k
  if (!mpi_cmp_ui (point->z, 1))
1131
2.72k
    {
1132
2.72k
      if (x)
1133
2.72k
        mpi_set (x, point->x);
1134
2.72k
      if (y)
1135
2.72k
        mpi_set (y, point->y);
1136
2.72k
      return 0;
1137
2.72k
    }
1138
1139
1.94k
        z1 = mpi_new (0);
1140
1.94k
        z2 = mpi_new (0);
1141
1.94k
        ec_invm (z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
1142
1.94k
        ec_mulm (z2, z1, z1, ctx);    /* z2 = z^(-2) mod p  */
1143
1144
1.94k
        if (x)
1145
1.94k
          ec_mulm (x, point->x, z2, ctx);
1146
1147
1.94k
        if (y)
1148
0
          {
1149
0
            z3 = mpi_new (0);
1150
0
            ec_mulm (z3, z2, z1, ctx);      /* z3 = z^(-3) mod p  */
1151
0
            ec_mulm (y, point->y, z3, ctx);
1152
0
            mpi_free (z3);
1153
0
          }
1154
1155
1.94k
        mpi_free (z2);
1156
1.94k
        mpi_free (z1);
1157
1.94k
      }
1158
0
      return 0;
1159
1160
0
    case MPI_EC_MONTGOMERY:
1161
0
      {
1162
0
        if (x)
1163
0
          mpi_set (x, point->x);
1164
1165
0
        if (y)
1166
0
          {
1167
0
            log_fatal ("%s: Getting Y-coordinate on %s is not supported\n",
1168
0
                       "_gcry_mpi_ec_get_affine", "Montgomery");
1169
0
            return -1;
1170
0
          }
1171
0
      }
1172
0
      return 0;
1173
1174
13.7k
    case MPI_EC_EDWARDS:
1175
13.7k
      {
1176
13.7k
        gcry_mpi_t z;
1177
1178
13.7k
  if (!mpi_cmp_ui (point->z, 1))
1179
9.18k
    {
1180
9.18k
      if (x)
1181
9.18k
        mpi_set (x, point->x);
1182
9.18k
      if (y)
1183
9.18k
        mpi_set (y, point->y);
1184
9.18k
      return 0;
1185
9.18k
    }
1186
1187
4.59k
        z = mpi_new (0);
1188
4.59k
        ec_invm (z, point->z, ctx);
1189
1190
4.59k
        mpi_resize (z, ctx->p->nlimbs);
1191
4.59k
        z->nlimbs = ctx->p->nlimbs;
1192
1193
4.59k
        if (x)
1194
4.59k
          {
1195
4.59k
            mpi_resize (x, ctx->p->nlimbs);
1196
4.59k
            x->nlimbs = ctx->p->nlimbs;
1197
4.59k
            ctx->mulm (x, point->x, z, ctx);
1198
4.59k
          }
1199
4.59k
        if (y)
1200
4.59k
          {
1201
4.59k
            mpi_resize (y, ctx->p->nlimbs);
1202
4.59k
            y->nlimbs = ctx->p->nlimbs;
1203
4.59k
            ctx->mulm (y, point->y, z, ctx);
1204
4.59k
          }
1205
1206
4.59k
        _gcry_mpi_release (z);
1207
4.59k
      }
1208
0
      return 0;
1209
1210
0
    default:
1211
0
      return -1;
1212
18.4k
    }
1213
18.4k
}
1214
1215
1216

1217
/*  RESULT = 2 * POINT  (Weierstrass version). */
1218
static void
1219
dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
1220
1.05M
{
1221
4.20M
#define x3 (result->x)
1222
5.25M
#define y3 (result->y)
1223
3.15M
#define z3 (result->z)
1224
5.56M
#define t1 (ctx->t.scratch[0])
1225
6.73M
#define t2 (ctx->t.scratch[1])
1226
1.05M
#define t3 (ctx->t.scratch[2])
1227
7.35M
#define l1 (ctx->t.scratch[3])
1228
5.25M
#define l2 (ctx->t.scratch[4])
1229
2.10M
#define l3 (ctx->t.scratch[5])
1230
1231
1.05M
  if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0))
1232
0
    {
1233
      /* P_y == 0 || P_z == 0 => [1:1:0] */
1234
0
      mpi_set_ui (x3, 1);
1235
0
      mpi_set_ui (y3, 1);
1236
0
      mpi_set_ui (z3, 0);
1237
0
    }
1238
1.05M
  else
1239
1.05M
    {
1240
1.05M
      if (ec_get_a_is_pminus3 (ctx))  /* Use the faster case.  */
1241
738k
        {
1242
          /* L1 = 3(X - Z^2)(X + Z^2) */
1243
          /*                          T1: used for Z^2. */
1244
          /*                          T2: used for the right term.  */
1245
738k
          ec_pow2 (t1, point->z, ctx);
1246
738k
          ec_subm (l1, point->x, t1, ctx);
1247
738k
          ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
1248
738k
          ec_addm (t2, point->x, t1, ctx);
1249
738k
          ec_mulm (l1, l1, t2, ctx);
1250
738k
        }
1251
312k
      else /* Standard case. */
1252
312k
        {
1253
          /* L1 = 3X^2 + aZ^4 */
1254
          /*                          T1: used for aZ^4. */
1255
312k
          ec_pow2 (l1, point->x, ctx);
1256
312k
          ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
1257
312k
          ec_powm (t1, point->z, mpi_const (MPI_C_FOUR), ctx);
1258
312k
          ec_mulm (t1, t1, ctx->a, ctx);
1259
312k
          ec_addm (l1, l1, t1, ctx);
1260
312k
        }
1261
      /* Z3 = 2YZ */
1262
1.05M
      ec_mulm (z3, point->y, point->z, ctx);
1263
1.05M
      ec_mul2 (z3, z3, ctx);
1264
1265
      /* L2 = 4XY^2 */
1266
      /*                              T2: used for Y2; required later. */
1267
1.05M
      ec_pow2 (t2, point->y, ctx);
1268
1.05M
      ec_mulm (l2, t2, point->x, ctx);
1269
1.05M
      ec_mulm (l2, l2, mpi_const (MPI_C_FOUR), ctx);
1270
1271
      /* X3 = L1^2 - 2L2 */
1272
      /*                              T1: used for L2^2. */
1273
1.05M
      ec_pow2 (x3, l1, ctx);
1274
1.05M
      ec_mul2 (t1, l2, ctx);
1275
1.05M
      ec_subm (x3, x3, t1, ctx);
1276
1277
      /* L3 = 8Y^4 */
1278
      /*                              T2: taken from above. */
1279
1.05M
      ec_pow2 (t2, t2, ctx);
1280
1.05M
      ec_mulm (l3, t2, mpi_const (MPI_C_EIGHT), ctx);
1281
1282
      /* Y3 = L1(L2 - X3) - L3 */
1283
1.05M
      ec_subm (y3, l2, x3, ctx);
1284
1.05M
      ec_mulm (y3, y3, l1, ctx);
1285
1.05M
      ec_subm (y3, y3, l3, ctx);
1286
1.05M
    }
1287
1288
1.05M
#undef x3
1289
1.05M
#undef y3
1290
1.05M
#undef z3
1291
1.05M
#undef t1
1292
1.05M
#undef t2
1293
1.05M
#undef t3
1294
1.05M
#undef l1
1295
1.05M
#undef l2
1296
1.05M
#undef l3
1297
1.05M
}
1298
1299
1300
/*  RESULT = 2 * POINT  (Montgomery version). */
1301
static void
1302
dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
1303
0
{
1304
0
  (void)result;
1305
0
  (void)point;
1306
0
  (void)ctx;
1307
0
  log_fatal ("%s: %s not yet supported\n",
1308
0
             "_gcry_mpi_ec_dup_point", "Montgomery");
1309
0
}
1310
1311
1312
/*  RESULT = 2 * POINT  (Twisted Edwards version). */
1313
static void
1314
dup_point_edwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
1315
3.51M
{
1316
7.03M
#define X1 (point->x)
1317
7.03M
#define Y1 (point->y)
1318
3.51M
#define Z1 (point->z)
1319
17.5M
#define X3 (result->x)
1320
10.5M
#define Y3 (result->y)
1321
3.51M
#define Z3 (result->z)
1322
14.0M
#define B (ctx->t.scratch[0])
1323
10.5M
#define C (ctx->t.scratch[1])
1324
14.0M
#define D (ctx->t.scratch[2])
1325
10.5M
#define E (ctx->t.scratch[3])
1326
14.0M
#define F (ctx->t.scratch[4])
1327
7.03M
#define H (ctx->t.scratch[5])
1328
17.5M
#define J (ctx->t.scratch[6])
1329
1330
  /* Compute: (X_3 : Y_3 : Z_3) = 2( X_1 : Y_1 : Z_1 ) */
1331
1332
  /* B = (X_1 + Y_1)^2  */
1333
3.51M
  ctx->addm (B, X1, Y1, ctx);
1334
3.51M
  ctx->pow2 (B, B, ctx);
1335
1336
  /* C = X_1^2 */
1337
  /* D = Y_1^2 */
1338
3.51M
  ctx->pow2 (C, X1, ctx);
1339
3.51M
  ctx->pow2 (D, Y1, ctx);
1340
1341
  /* E = aC */
1342
3.51M
  if (ctx->dialect == ECC_DIALECT_ED25519)
1343
3.51M
    ctx->subm (E, ctx->p, C, ctx);
1344
0
  else
1345
0
    ctx->mulm (E, ctx->a, C, ctx);
1346
1347
  /* F = E + D */
1348
3.51M
  ctx->addm (F, E, D, ctx);
1349
1350
  /* H = Z_1^2 */
1351
3.51M
  ctx->pow2 (H, Z1, ctx);
1352
1353
  /* J = F - 2H */
1354
3.51M
  ctx->mul2 (J, H, ctx);
1355
3.51M
  ctx->subm (J, F, J, ctx);
1356
1357
  /* X_3 = (B - C - D) · J */
1358
3.51M
  ctx->subm (X3, B, C, ctx);
1359
3.51M
  ctx->subm (X3, X3, D, ctx);
1360
3.51M
  ctx->mulm (X3, X3, J, ctx);
1361
1362
  /* Y_3 = F · (E - D) */
1363
3.51M
  ctx->subm (Y3, E, D, ctx);
1364
3.51M
  ctx->mulm (Y3, Y3, F, ctx);
1365
1366
  /* Z_3 = F · J */
1367
3.51M
  ctx->mulm (Z3, F, J, ctx);
1368
1369
3.51M
#undef X1
1370
3.51M
#undef Y1
1371
3.51M
#undef Z1
1372
3.51M
#undef X3
1373
3.51M
#undef Y3
1374
3.51M
#undef Z3
1375
3.51M
#undef B
1376
3.51M
#undef C
1377
3.51M
#undef D
1378
3.51M
#undef E
1379
3.51M
#undef F
1380
3.51M
#undef H
1381
3.51M
#undef J
1382
3.51M
}
1383
1384
1385
/*  RESULT = 2 * POINT  */
1386
void
1387
_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
1388
4.56M
{
1389
4.56M
  switch (ctx->model)
1390
4.56M
    {
1391
1.05M
    case MPI_EC_WEIERSTRASS:
1392
1.05M
      dup_point_weierstrass (result, point, ctx);
1393
1.05M
      break;
1394
0
    case MPI_EC_MONTGOMERY:
1395
0
      dup_point_montgomery (result, point, ctx);
1396
0
      break;
1397
3.51M
    case MPI_EC_EDWARDS:
1398
3.51M
      dup_point_edwards (result, point, ctx);
1399
3.51M
      break;
1400
4.56M
    }
1401
4.56M
}
1402
1403
1404
/* RESULT = P1 + P2  (Weierstrass version).*/
1405
static void
1406
add_points_weierstrass (mpi_point_t result,
1407
                        mpi_point_t p1, mpi_point_t p2,
1408
                        mpi_ec_t ctx)
1409
349k
{
1410
349k
#define x1 (p1->x    )
1411
349k
#define y1 (p1->y    )
1412
1.04M
#define z1 (p1->z    )
1413
349k
#define x2 (p2->x    )
1414
349k
#define y2 (p2->y    )
1415
700k
#define z2 (p2->z    )
1416
698k
#define x3 (result->x)
1417
1.04M
#define y3 (result->y)
1418
1.04M
#define z3 (result->z)
1419
703k
#define l1 (ctx->t.scratch[0])
1420
1.74M
#define l2 (ctx->t.scratch[1])
1421
1.39M
#define l3 (ctx->t.scratch[2])
1422
1.74M
#define l4 (ctx->t.scratch[3])
1423
1.74M
#define l5 (ctx->t.scratch[4])
1424
1.04M
#define l6 (ctx->t.scratch[5])
1425
698k
#define l7 (ctx->t.scratch[6])
1426
698k
#define l8 (ctx->t.scratch[7])
1427
1.39M
#define l9 (ctx->t.scratch[8])
1428
2.79M
#define t1 (ctx->t.scratch[9])
1429
1.74M
#define t2 (ctx->t.scratch[10])
1430
1431
349k
  if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) )
1432
0
    {
1433
      /* Same point; need to call the duplicate function.  */
1434
0
      _gcry_mpi_ec_dup_point (result, p1, ctx);
1435
0
    }
1436
349k
  else if (!mpi_cmp_ui (z1, 0))
1437
0
    {
1438
      /* P1 is at infinity.  */
1439
0
      mpi_set (x3, p2->x);
1440
0
      mpi_set (y3, p2->y);
1441
0
      mpi_set (z3, p2->z);
1442
0
    }
1443
349k
  else if (!mpi_cmp_ui (z2, 0))
1444
0
    {
1445
      /* P2 is at infinity.  */
1446
0
      mpi_set (x3, p1->x);
1447
0
      mpi_set (y3, p1->y);
1448
0
      mpi_set (z3, p1->z);
1449
0
    }
1450
349k
  else
1451
349k
    {
1452
349k
      int z1_is_one = !mpi_cmp_ui (z1, 1);
1453
349k
      int z2_is_one = !mpi_cmp_ui (z2, 1);
1454
1455
      /* l1 = x1 z2^2  */
1456
      /* l2 = x2 z1^2  */
1457
349k
      if (z2_is_one)
1458
347k
        mpi_set (l1, x1);
1459
1.79k
      else
1460
1.79k
        {
1461
1.79k
          ec_pow2 (l1, z2, ctx);
1462
1.79k
          ec_mulm (l1, l1, x1, ctx);
1463
1.79k
        }
1464
349k
      if (z1_is_one)
1465
0
        mpi_set (l2, x2);
1466
349k
      else
1467
349k
        {
1468
349k
          ec_pow2 (l2, z1, ctx);
1469
349k
          ec_mulm (l2, l2, x2, ctx);
1470
349k
        }
1471
      /* l3 = l1 - l2 */
1472
349k
      ec_subm (l3, l1, l2, ctx);
1473
      /* l4 = y1 z2^3  */
1474
349k
      ec_powm (l4, z2, mpi_const (MPI_C_THREE), ctx);
1475
349k
      ec_mulm (l4, l4, y1, ctx);
1476
      /* l5 = y2 z1^3  */
1477
349k
      ec_powm (l5, z1, mpi_const (MPI_C_THREE), ctx);
1478
349k
      ec_mulm (l5, l5, y2, ctx);
1479
      /* l6 = l4 - l5  */
1480
349k
      ec_subm (l6, l4, l5, ctx);
1481
1482
349k
      if (!mpi_cmp_ui (l3, 0))
1483
0
        {
1484
0
          if (!mpi_cmp_ui (l6, 0))
1485
0
            {
1486
              /* P1 and P2 are the same - use duplicate function.  */
1487
0
              _gcry_mpi_ec_dup_point (result, p1, ctx);
1488
0
            }
1489
0
          else
1490
0
            {
1491
              /* P1 is the inverse of P2.  */
1492
0
              mpi_set_ui (x3, 1);
1493
0
              mpi_set_ui (y3, 1);
1494
0
              mpi_set_ui (z3, 0);
1495
0
            }
1496
0
        }
1497
349k
      else
1498
349k
        {
1499
          /* l7 = l1 + l2  */
1500
349k
          ec_addm (l7, l1, l2, ctx);
1501
          /* l8 = l4 + l5  */
1502
349k
          ec_addm (l8, l4, l5, ctx);
1503
          /* z3 = z1 z2 l3  */
1504
349k
          ec_mulm (z3, z1, z2, ctx);
1505
349k
          ec_mulm (z3, z3, l3, ctx);
1506
          /* x3 = l6^2 - l7 l3^2  */
1507
349k
          ec_pow2 (t1, l6, ctx);
1508
349k
          ec_pow2 (t2, l3, ctx);
1509
349k
          ec_mulm (t2, t2, l7, ctx);
1510
349k
          ec_subm (x3, t1, t2, ctx);
1511
          /* l9 = l7 l3^2 - 2 x3  */
1512
349k
          ec_mul2 (t1, x3, ctx);
1513
349k
          ec_subm (l9, t2, t1, ctx);
1514
          /* y3 = (l9 l6 - l8 l3^3)/2  */
1515
349k
          ec_mulm (l9, l9, l6, ctx);
1516
349k
          ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/
1517
349k
          ec_mulm (t1, t1, l8, ctx);
1518
349k
          ec_subm (y3, l9, t1, ctx);
1519
349k
          ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
1520
349k
        }
1521
349k
    }
1522
1523
349k
#undef x1
1524
349k
#undef y1
1525
349k
#undef z1
1526
349k
#undef x2
1527
349k
#undef y2
1528
349k
#undef z2
1529
349k
#undef x3
1530
349k
#undef y3
1531
349k
#undef z3
1532
349k
#undef l1
1533
349k
#undef l2
1534
349k
#undef l3
1535
349k
#undef l4
1536
349k
#undef l5
1537
349k
#undef l6
1538
349k
#undef l7
1539
349k
#undef l8
1540
349k
#undef l9
1541
349k
#undef t1
1542
349k
#undef t2
1543
349k
}
1544
1545
1546
/* RESULT = P1 + P2  (Montgomery version).*/
1547
static void
1548
add_points_montgomery (mpi_point_t result,
1549
                       mpi_point_t p1, mpi_point_t p2,
1550
                       mpi_ec_t ctx)
1551
0
{
1552
0
  (void)result;
1553
0
  (void)p1;
1554
0
  (void)p2;
1555
0
  (void)ctx;
1556
0
  log_fatal ("%s: %s not yet supported\n",
1557
0
             "_gcry_mpi_ec_add_points", "Montgomery");
1558
0
}
1559
1560
1561
/* RESULT = P1 + P2  (Twisted Edwards version).*/
1562
static void
1563
add_points_edwards (mpi_point_t result,
1564
                    mpi_point_t p1, mpi_point_t p2,
1565
                    mpi_ec_t ctx)
1566
1.41M
{
1567
2.83M
#define X1 (p1->x)
1568
2.83M
#define Y1 (p1->y)
1569
1.41M
#define Z1 (p1->z)
1570
2.83M
#define X2 (p2->x)
1571
2.83M
#define Y2 (p2->y)
1572
1.41M
#define Z2 (p2->z)
1573
15.5M
#define X3 (result->x)
1574
7.07M
#define Y3 (result->y)
1575
1.41M
#define Z3 (result->z)
1576
5.66M
#define A (ctx->t.scratch[0])
1577
4.24M
#define B (ctx->t.scratch[1])
1578
5.66M
#define C (ctx->t.scratch[2])
1579
5.66M
#define D (ctx->t.scratch[3])
1580
7.07M
#define E (ctx->t.scratch[4])
1581
4.24M
#define F (ctx->t.scratch[5])
1582
4.24M
#define G (ctx->t.scratch[6])
1583
2.83M
#define tmp (ctx->t.scratch[7])
1584
1585
1.41M
  mpi_point_resize (result, ctx);
1586
1587
  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3)  */
1588
1589
  /* A = Z1 · Z2 */
1590
1.41M
  ctx->mulm (A, Z1, Z2, ctx);
1591
1592
  /* B = A^2 */
1593
1.41M
  ctx->pow2 (B, A, ctx);
1594
1595
  /* C = X1 · X2 */
1596
1.41M
  ctx->mulm (C, X1, X2, ctx);
1597
1598
  /* D = Y1 · Y2 */
1599
1.41M
  ctx->mulm (D, Y1, Y2, ctx);
1600
1601
  /* E = d · C · D */
1602
1.41M
  ctx->mulm (E, ctx->b, C, ctx);
1603
1.41M
  ctx->mulm (E, E, D, ctx);
1604
1605
  /* F = B - E */
1606
1.41M
  ctx->subm (F, B, E, ctx);
1607
1608
  /* G = B + E */
1609
1.41M
  ctx->addm (G, B, E, ctx);
1610
1611
  /* X_3 = A · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
1612
1.41M
  ctx->addm (tmp, X1, Y1, ctx);
1613
1.41M
  ctx->addm (X3, X2, Y2, ctx);
1614
1.41M
  ctx->mulm (X3, X3, tmp, ctx);
1615
1.41M
  ctx->subm (X3, X3, C, ctx);
1616
1.41M
  ctx->subm (X3, X3, D, ctx);
1617
1.41M
  ctx->mulm (X3, X3, F, ctx);
1618
1.41M
  ctx->mulm (X3, X3, A, ctx);
1619
1620
  /* Y_3 = A · G · (D - aC) */
1621
1.41M
  if (ctx->dialect == ECC_DIALECT_ED25519)
1622
1.41M
    {
1623
1.41M
      ctx->addm (Y3, D, C, ctx);
1624
1.41M
    }
1625
0
  else
1626
0
    {
1627
0
      ctx->mulm (Y3, ctx->a, C, ctx);
1628
0
      ctx->subm (Y3, D, Y3, ctx);
1629
0
    }
1630
1.41M
  ctx->mulm (Y3, Y3, G, ctx);
1631
1.41M
  ctx->mulm (Y3, Y3, A, ctx);
1632
1633
  /* Z_3 = F · G */
1634
1.41M
  ctx->mulm (Z3, F, G, ctx);
1635
1636
1637
1.41M
#undef X1
1638
1.41M
#undef Y1
1639
1.41M
#undef Z1
1640
1.41M
#undef X2
1641
1.41M
#undef Y2
1642
1.41M
#undef Z2
1643
1.41M
#undef X3
1644
1.41M
#undef Y3
1645
1.41M
#undef Z3
1646
1.41M
#undef A
1647
1.41M
#undef B
1648
1.41M
#undef C
1649
1.41M
#undef D
1650
1.41M
#undef E
1651
1.41M
#undef F
1652
1.41M
#undef G
1653
1.41M
#undef tmp
1654
1.41M
}
1655
1656
1657
/* Compute a step of Montgomery Ladder (only use X and Z in the point).
1658
   Inputs:  P1, P2, and x-coordinate of DIF = P1 - P1.
1659
   Outputs: PRD = 2 * P1 and  SUM = P1 + P2. */
1660
static void
1661
montgomery_ladder (mpi_point_t prd, mpi_point_t sum,
1662
                   mpi_point_t p1, mpi_point_t p2, gcry_mpi_t dif_x,
1663
                   mpi_ec_t ctx)
1664
0
{
1665
0
  ctx->addm (sum->x, p2->x, p2->z, ctx);
1666
0
  ctx->subm (p2->z, p2->x, p2->z, ctx);
1667
0
  ctx->addm (prd->x, p1->x, p1->z, ctx);
1668
0
  ctx->subm (p1->z, p1->x, p1->z, ctx);
1669
0
  ctx->mulm (p2->x, p1->z, sum->x, ctx);
1670
0
  ctx->mulm (p2->z, prd->x, p2->z, ctx);
1671
0
  ctx->pow2 (p1->x, prd->x, ctx);
1672
0
  ctx->pow2 (p1->z, p1->z, ctx);
1673
0
  ctx->addm (sum->x, p2->x, p2->z, ctx);
1674
0
  ctx->subm (p2->z, p2->x, p2->z, ctx);
1675
0
  ctx->mulm (prd->x, p1->x, p1->z, ctx);
1676
0
  ctx->subm (p1->z, p1->x, p1->z, ctx);
1677
0
  ctx->pow2 (sum->x, sum->x, ctx);
1678
0
  ctx->pow2 (sum->z, p2->z, ctx);
1679
0
  ctx->mulm (prd->z, p1->z, ctx->a, ctx); /* CTX->A: (a-2)/4 */
1680
0
  ctx->mulm (sum->z, sum->z, dif_x, ctx);
1681
0
  ctx->addm (prd->z, p1->x, prd->z, ctx);
1682
0
  ctx->mulm (prd->z, prd->z, p1->z, ctx);
1683
0
}
1684
1685
1686
/* RESULT = P1 + P2 */
1687
void
1688
_gcry_mpi_ec_add_points (mpi_point_t result,
1689
                         mpi_point_t p1, mpi_point_t p2,
1690
                         mpi_ec_t ctx)
1691
1.76M
{
1692
1.76M
  switch (ctx->model)
1693
1.76M
    {
1694
349k
    case MPI_EC_WEIERSTRASS:
1695
349k
      add_points_weierstrass (result, p1, p2, ctx);
1696
349k
      break;
1697
0
    case MPI_EC_MONTGOMERY:
1698
0
      add_points_montgomery (result, p1, p2, ctx);
1699
0
      break;
1700
1.41M
    case MPI_EC_EDWARDS:
1701
1.41M
      add_points_edwards (result, p1, p2, ctx);
1702
1.41M
      break;
1703
1.76M
    }
1704
1.76M
}
1705
1706
1707
/* RESULT = P1 - P2  (Weierstrass version).*/
1708
static void
1709
sub_points_weierstrass (mpi_point_t result,
1710
                        mpi_point_t p1, mpi_point_t p2,
1711
                        mpi_ec_t ctx)
1712
0
{
1713
0
  (void)result;
1714
0
  (void)p1;
1715
0
  (void)p2;
1716
0
  (void)ctx;
1717
0
  log_fatal ("%s: %s not yet supported\n",
1718
0
             "_gcry_mpi_ec_sub_points", "Weierstrass");
1719
0
}
1720
1721
1722
/* RESULT = P1 - P2  (Montgomery version).*/
1723
static void
1724
sub_points_montgomery (mpi_point_t result,
1725
                       mpi_point_t p1, mpi_point_t p2,
1726
                       mpi_ec_t ctx)
1727
0
{
1728
0
  (void)result;
1729
0
  (void)p1;
1730
0
  (void)p2;
1731
0
  (void)ctx;
1732
0
  log_fatal ("%s: %s not yet supported\n",
1733
0
             "_gcry_mpi_ec_sub_points", "Montgomery");
1734
0
}
1735
1736
1737
/* RESULT = P1 - P2  (Twisted Edwards version).*/
1738
static void
1739
sub_points_edwards (mpi_point_t result,
1740
                    mpi_point_t p1, mpi_point_t p2,
1741
                    mpi_ec_t ctx)
1742
0
{
1743
0
  mpi_point_t p2i = _gcry_mpi_point_new (0);
1744
0
  point_set (p2i, p2);
1745
0
  ctx->subm (p2i->x, ctx->p, p2i->x, ctx);
1746
0
  add_points_edwards (result, p1, p2i, ctx);
1747
0
  _gcry_mpi_point_release (p2i);
1748
0
}
1749
1750
1751
/* RESULT = P1 - P2 */
1752
void
1753
_gcry_mpi_ec_sub_points (mpi_point_t result,
1754
                         mpi_point_t p1, mpi_point_t p2,
1755
                         mpi_ec_t ctx)
1756
0
{
1757
0
  switch (ctx->model)
1758
0
    {
1759
0
    case MPI_EC_WEIERSTRASS:
1760
0
      sub_points_weierstrass (result, p1, p2, ctx);
1761
0
      break;
1762
0
    case MPI_EC_MONTGOMERY:
1763
0
      sub_points_montgomery (result, p1, p2, ctx);
1764
0
      break;
1765
0
    case MPI_EC_EDWARDS:
1766
0
      sub_points_edwards (result, p1, p2, ctx);
1767
0
      break;
1768
0
    }
1769
0
}
1770
1771
1772
/* Scalar point multiplication - the main function for ECC.  It takes
1773
   an integer SCALAR and a POINT as well as the usual context CTX.
1774
   RESULT will be set to the resulting point. */
1775
void
1776
_gcry_mpi_ec_mul_point (mpi_point_t result,
1777
                        gcry_mpi_t scalar, mpi_point_t point,
1778
                        mpi_ec_t ctx)
1779
13.0k
{
1780
13.0k
  gcry_mpi_t x1, y1, z1, k, h, yy;
1781
13.0k
  unsigned int i, loops;
1782
13.0k
  mpi_point_struct p1, p2, p1inv;
1783
1784
  /* First try HW accelerated scalar multiplications.  Error
1785
     is returned if acceleration is not supported or if HW
1786
     does not support acceleration of given input.  */
1787
13.0k
  if (mpi_ec_hw_mul_point (result, scalar, point, ctx) >= 0)
1788
0
    {
1789
0
      return;
1790
0
    }
1791
1792
13.0k
  if (ctx->model == MPI_EC_EDWARDS
1793
13.0k
      || (ctx->model == MPI_EC_WEIERSTRASS
1794
3.89k
          && mpi_is_secure (scalar)))
1795
9.18k
    {
1796
      /* Simple left to right binary method.  Algorithm 3.27 from
1797
       * {author={Hankerson, Darrel and Menezes, Alfred J. and Vanstone, Scott},
1798
       *  title = {Guide to Elliptic Curve Cryptography},
1799
       *  year = {2003}, isbn = {038795273X},
1800
       *  url = {http://www.cacr.math.uwaterloo.ca/ecc/},
1801
       *  publisher = {Springer-Verlag New York, Inc.}} */
1802
9.18k
      unsigned int nbits;
1803
9.18k
      int j;
1804
1805
9.18k
      if (mpi_cmp (scalar, ctx->p) >= 0)
1806
4.91k
        nbits = mpi_get_nbits (scalar);
1807
4.27k
      else
1808
4.27k
        nbits = mpi_get_nbits (ctx->p);
1809
1810
9.18k
      if (ctx->model == MPI_EC_WEIERSTRASS)
1811
0
        {
1812
0
          mpi_set_ui (result->x, 1);
1813
0
          mpi_set_ui (result->y, 1);
1814
0
          mpi_set_ui (result->z, 0);
1815
0
        }
1816
9.18k
      else
1817
9.18k
        {
1818
9.18k
          mpi_set_ui (result->x, 0);
1819
9.18k
          mpi_set_ui (result->y, 1);
1820
9.18k
          mpi_set_ui (result->z, 1);
1821
9.18k
          mpi_point_resize (point, ctx);
1822
9.18k
        }
1823
1824
9.18k
      if (mpi_is_secure (scalar))
1825
0
        {
1826
          /* If SCALAR is in secure memory we assume that it is the
1827
             secret key we use constant time operation.  */
1828
0
          mpi_point_struct tmppnt;
1829
1830
0
          point_init (&tmppnt);
1831
0
          mpi_point_resize (result, ctx);
1832
0
          mpi_point_resize (&tmppnt, ctx);
1833
0
          for (j=nbits-1; j >= 0; j--)
1834
0
            {
1835
0
              _gcry_mpi_ec_dup_point (result, result, ctx);
1836
0
              _gcry_mpi_ec_add_points (&tmppnt, result, point, ctx);
1837
0
              point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
1838
0
            }
1839
0
          point_free (&tmppnt);
1840
0
        }
1841
9.18k
      else
1842
9.18k
        {
1843
9.18k
          if (ctx->model == MPI_EC_EDWARDS)
1844
9.18k
            {
1845
9.18k
              mpi_point_resize (result, ctx);
1846
9.18k
              mpi_point_resize (point, ctx);
1847
9.18k
            }
1848
1849
3.52M
          for (j=nbits-1; j >= 0; j--)
1850
3.51M
            {
1851
3.51M
              _gcry_mpi_ec_dup_point (result, result, ctx);
1852
3.51M
              if (mpi_test_bit (scalar, j))
1853
1.41M
                _gcry_mpi_ec_add_points (result, result, point, ctx);
1854
3.51M
            }
1855
9.18k
        }
1856
9.18k
      return;
1857
9.18k
    }
1858
3.89k
  else if (ctx->model == MPI_EC_MONTGOMERY)
1859
0
    {
1860
0
      unsigned int nbits;
1861
0
      int j;
1862
0
      mpi_point_struct p1_, p2_;
1863
0
      mpi_point_t q1, q2, prd, sum;
1864
0
      unsigned long sw;
1865
0
      mpi_size_t rsize;
1866
0
      int scalar_copied = 0;
1867
1868
      /* Compute scalar point multiplication with Montgomery Ladder.
1869
         Note that we don't use Y-coordinate in the points at all.
1870
         RESULT->Y will be filled by zero.  */
1871
1872
0
      nbits = mpi_get_nbits (scalar);
1873
0
      point_init (&p1);
1874
0
      point_init (&p2);
1875
0
      point_init (&p1_);
1876
0
      point_init (&p2_);
1877
0
      mpi_set_ui (p1.x, 1);
1878
0
      mpi_free (p2.x);
1879
0
      p2.x  = mpi_copy (point->x);
1880
0
      mpi_set_ui (p2.z, 1);
1881
1882
0
      if (mpi_is_opaque (scalar))
1883
0
        {
1884
0
          const unsigned int pbits = ctx->nbits;
1885
0
          gcry_mpi_t a;
1886
0
          unsigned int n;
1887
0
          unsigned char *raw;
1888
1889
0
          scalar_copied = 1;
1890
1891
0
          raw = _gcry_mpi_get_opaque_copy (scalar, &n);
1892
0
          if ((n+7)/8 != (pbits+7)/8)
1893
0
            log_fatal ("scalar size (%d) != prime size (%d)\n",
1894
0
                       (n+7)/8, (pbits+7)/8);
1895
1896
0
          reverse_buffer (raw, (n+7)/8);
1897
0
          if ((pbits % 8))
1898
0
            raw[0] &= (1 << (pbits % 8)) - 1;
1899
0
          raw[0] |= (1 << ((pbits + 7) % 8));
1900
0
          raw[(pbits+7)/8 - 1] &= (256 - ctx->h);
1901
0
          a = mpi_is_secure (scalar) ? mpi_snew (pbits): mpi_new (pbits);
1902
0
          _gcry_mpi_set_buffer (a, raw, (n+7)/8, 0);
1903
0
          xfree (raw);
1904
1905
0
          scalar = a;
1906
0
        }
1907
1908
0
      mpi_point_resize (&p1, ctx);
1909
0
      mpi_point_resize (&p2, ctx);
1910
0
      mpi_point_resize (&p1_, ctx);
1911
0
      mpi_point_resize (&p2_, ctx);
1912
1913
0
      mpi_resize (point->x, ctx->p->nlimbs);
1914
0
      point->x->nlimbs = ctx->p->nlimbs;
1915
1916
0
      q1 = &p1;
1917
0
      q2 = &p2;
1918
0
      prd = &p1_;
1919
0
      sum = &p2_;
1920
1921
0
      for (j=nbits-1; j >= 0; j--)
1922
0
        {
1923
0
          mpi_point_t t;
1924
1925
0
          sw = mpi_test_bit (scalar, j);
1926
0
          point_swap_cond (q1, q2, sw, ctx);
1927
0
          montgomery_ladder (prd, sum, q1, q2, point->x, ctx);
1928
0
          point_swap_cond (prd, sum, sw, ctx);
1929
0
          t = q1;  q1 = prd;  prd = t;
1930
0
          t = q2;  q2 = sum;  sum = t;
1931
0
        }
1932
1933
0
      mpi_clear (result->y);
1934
0
      sw = (nbits & 1);
1935
0
      point_swap_cond (&p1, &p1_, sw, ctx);
1936
1937
0
      rsize = p1.z->nlimbs;
1938
0
      MPN_NORMALIZE (p1.z->d, rsize);
1939
0
      if (rsize == 0)
1940
0
        {
1941
0
          mpi_set_ui (result->x, 1);
1942
0
          mpi_set_ui (result->z, 0);
1943
0
        }
1944
0
      else
1945
0
        {
1946
0
          z1 = mpi_new (0);
1947
0
          ec_invm (z1, p1.z, ctx);
1948
0
          ec_mulm (result->x, p1.x, z1, ctx);
1949
0
          mpi_set_ui (result->z, 1);
1950
0
          mpi_free (z1);
1951
0
        }
1952
1953
0
      point_free (&p1);
1954
0
      point_free (&p2);
1955
0
      point_free (&p1_);
1956
0
      point_free (&p2_);
1957
0
      if (scalar_copied)
1958
0
        _gcry_mpi_release (scalar);
1959
0
      return;
1960
0
    }
1961
1962
3.89k
  x1 = mpi_alloc_like (ctx->p);
1963
3.89k
  y1 = mpi_alloc_like (ctx->p);
1964
3.89k
  h  = mpi_alloc_like (ctx->p);
1965
3.89k
  k  = mpi_copy (scalar);
1966
3.89k
  yy = mpi_copy (point->y);
1967
1968
3.89k
  if ( mpi_has_sign (k) )
1969
0
    {
1970
0
      k->sign = 0;
1971
0
      ec_invm (yy, yy, ctx);
1972
0
    }
1973
1974
3.89k
  if (!mpi_cmp_ui (point->z, 1))
1975
3.89k
    {
1976
3.89k
      mpi_set (x1, point->x);
1977
3.89k
      mpi_set (y1, yy);
1978
3.89k
    }
1979
0
  else
1980
0
    {
1981
0
      gcry_mpi_t z2, z3;
1982
1983
0
      z2 = mpi_alloc_like (ctx->p);
1984
0
      z3 = mpi_alloc_like (ctx->p);
1985
0
      ec_mulm (z2, point->z, point->z, ctx);
1986
0
      ec_mulm (z3, point->z, z2, ctx);
1987
0
      ec_invm (z2, z2, ctx);
1988
0
      ec_mulm (x1, point->x, z2, ctx);
1989
0
      ec_invm (z3, z3, ctx);
1990
0
      ec_mulm (y1, yy, z3, ctx);
1991
0
      mpi_free (z2);
1992
0
      mpi_free (z3);
1993
0
    }
1994
3.89k
  z1 = mpi_copy (mpi_const (MPI_C_ONE));
1995
1996
3.89k
  mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */
1997
3.89k
  loops = mpi_get_nbits (h);
1998
3.89k
  if (loops < 2)
1999
0
    {
2000
      /* If SCALAR is zero, the above mpi_mul sets H to zero and thus
2001
         LOOPs will be zero.  To avoid an underflow of I in the main
2002
         loop we set LOOP to 2 and the result to (0,0,0).  */
2003
0
      loops = 2;
2004
0
      mpi_clear (result->x);
2005
0
      mpi_clear (result->y);
2006
0
      mpi_clear (result->z);
2007
0
    }
2008
3.89k
  else
2009
3.89k
    {
2010
3.89k
      mpi_set (result->x, point->x);
2011
3.89k
      mpi_set (result->y, yy);
2012
3.89k
      mpi_set (result->z, point->z);
2013
3.89k
    }
2014
3.89k
  mpi_free (yy); yy = NULL;
2015
2016
3.89k
  p1.x = x1; x1 = NULL;
2017
3.89k
  p1.y = y1; y1 = NULL;
2018
3.89k
  p1.z = z1; z1 = NULL;
2019
3.89k
  point_init (&p2);
2020
3.89k
  point_init (&p1inv);
2021
2022
  /* Invert point: y = p - y mod p  */
2023
3.89k
  point_set (&p1inv, &p1);
2024
3.89k
  ec_subm (p1inv.y, ctx->p, p1inv.y, ctx);
2025
2026
1.05M
  for (i=loops-2; i > 0; i--)
2027
1.05M
    {
2028
1.05M
      _gcry_mpi_ec_dup_point (result, result, ctx);
2029
1.05M
      if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0)
2030
171k
        {
2031
171k
          point_set (&p2, result);
2032
171k
          _gcry_mpi_ec_add_points (result, &p2, &p1, ctx);
2033
171k
        }
2034
1.05M
      if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1)
2035
175k
        {
2036
175k
          point_set (&p2, result);
2037
175k
          _gcry_mpi_ec_add_points (result, &p2, &p1inv, ctx);
2038
175k
        }
2039
1.05M
    }
2040
2041
3.89k
  point_free (&p1);
2042
3.89k
  point_free (&p2);
2043
3.89k
  point_free (&p1inv);
2044
3.89k
  mpi_free (h);
2045
3.89k
  mpi_free (k);
2046
3.89k
}
2047
2048
2049
/* Return true if POINT is on the curve described by CTX.  */
2050
int
2051
_gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
2052
7.31k
{
2053
7.31k
  int res = 0;
2054
7.31k
  gcry_mpi_t x, y, w;
2055
2056
7.31k
  x = mpi_new (0);
2057
7.31k
  y = mpi_new (0);
2058
7.31k
  w = mpi_new (0);
2059
2060
  /* Check that the point is in range.  This needs to be done here and
2061
   * not after conversion to affine coordinates.  */
2062
7.31k
  if (mpi_cmpabs (point->x, ctx->p) >= 0)
2063
0
    goto leave;
2064
7.31k
  if (mpi_cmpabs (point->y, ctx->p) >= 0)
2065
0
    goto leave;
2066
7.31k
  if (mpi_cmpabs (point->z, ctx->p) >= 0)
2067
0
    goto leave;
2068
2069
7.31k
  switch (ctx->model)
2070
7.31k
    {
2071
2.72k
    case MPI_EC_WEIERSTRASS:
2072
2.72k
      {
2073
2.72k
        gcry_mpi_t xxx;
2074
2075
2.72k
        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
2076
0
          goto leave;
2077
2078
2.72k
        xxx = mpi_new (0);
2079
2080
        /* y^2 == x^3 + a·x + b */
2081
2.72k
        ec_pow2 (y, y, ctx);
2082
2083
2.72k
        ec_pow3 (xxx, x, ctx);
2084
2.72k
        ec_mulm (w, ctx->a, x, ctx);
2085
2.72k
        ec_addm (w, w, ctx->b, ctx);
2086
2.72k
        ec_addm (w, w, xxx, ctx);
2087
2088
2.72k
        if (!mpi_cmp (y, w))
2089
2.72k
          res = 1;
2090
2091
2.72k
        _gcry_mpi_release (xxx);
2092
2.72k
      }
2093
0
      break;
2094
0
    case MPI_EC_MONTGOMERY:
2095
0
      {
2096
0
#define xx y
2097
        /* With Montgomery curve, only X-coordinate is valid.  */
2098
0
        if (_gcry_mpi_ec_get_affine (x, NULL, point, ctx))
2099
0
          goto leave;
2100
2101
        /* The equation is: b * y^2 == x^3 + a · x^2 + x */
2102
        /* We check if right hand is quadratic residue or not by
2103
           Euler's criterion.  */
2104
        /* CTX->A has (a-2)/4 and CTX->B has b^-1 */
2105
0
        ec_mulm (w, ctx->a, mpi_const (MPI_C_FOUR), ctx);
2106
0
        ec_addm (w, w, mpi_const (MPI_C_TWO), ctx);
2107
0
        ec_mulm (w, w, x, ctx);
2108
0
        ec_pow2 (xx, x, ctx);
2109
0
        ec_addm (w, w, xx, ctx);
2110
0
        ec_addm (w, w, mpi_const (MPI_C_ONE), ctx);
2111
0
        ec_mulm (w, w, x, ctx);
2112
0
        ec_mulm (w, w, ctx->b, ctx);
2113
0
#undef xx
2114
        /* Compute Euler's criterion: w^(p-1)/2 */
2115
0
#define p_minus1 y
2116
0
        ec_subm (p_minus1, ctx->p, mpi_const (MPI_C_ONE), ctx);
2117
0
        mpi_rshift (p_minus1, p_minus1, 1);
2118
0
        ec_powm (w, w, p_minus1, ctx);
2119
2120
0
        res = !mpi_cmp_ui (w, 1);
2121
0
#undef p_minus1
2122
0
      }
2123
0
      break;
2124
4.59k
    case MPI_EC_EDWARDS:
2125
4.59k
      {
2126
4.59k
        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
2127
0
          goto leave;
2128
2129
4.59k
        mpi_resize (w, ctx->p->nlimbs);
2130
4.59k
        w->nlimbs = ctx->p->nlimbs;
2131
2132
        /* a · x^2 + y^2 - 1 - b · x^2 · y^2 == 0 */
2133
4.59k
        ctx->pow2 (x, x, ctx);
2134
4.59k
        ctx->pow2 (y, y, ctx);
2135
4.59k
        if (ctx->dialect == ECC_DIALECT_ED25519)
2136
4.59k
          ctx->subm (w, ctx->p, x, ctx);
2137
0
        else
2138
0
          ctx->mulm (w, ctx->a, x, ctx);
2139
4.59k
        ctx->addm (w, w, y, ctx);
2140
4.59k
        ctx->mulm (x, x, y, ctx);
2141
4.59k
        ctx->mulm (x, x, ctx->b, ctx);
2142
4.59k
        ctx->subm (w, w, x, ctx);
2143
4.59k
        if (!mpi_cmp_ui (w, 1))
2144
4.59k
          res = 1;
2145
4.59k
      }
2146
0
      break;
2147
7.31k
    }
2148
2149
7.31k
 leave:
2150
7.31k
  _gcry_mpi_release (w);
2151
7.31k
  _gcry_mpi_release (x);
2152
7.31k
  _gcry_mpi_release (y);
2153
2154
7.31k
  return res;
2155
7.31k
}
2156
2157
2158
int
2159
_gcry_mpi_ec_bad_point (gcry_mpi_point_t point, mpi_ec_t ctx)
2160
0
{
2161
0
  int i;
2162
0
  gcry_mpi_t x_bad;
2163
2164
0
  for (i = 0; (x_bad = ctx->t.scratch[i]); i++)
2165
0
    if (!mpi_cmp (point->x, x_bad))
2166
0
      return 1;
2167
2168
0
  return 0;
2169
0
}