Coverage Report

Created: 2022-12-08 06:09

/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
0
#define point_init(a)  _gcry_mpi_point_init ((a))
36
0
#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
0
{
90
0
  mpi_point_t p;
91
92
0
  (void)nbits;  /* Currently not used.  */
93
94
0
  p = xmalloc (sizeof *p);
95
0
  _gcry_mpi_point_init (p);
96
0
  return p;
97
0
}
98
99
100
/* Release the point object P.  P may be NULL. */
101
void
102
_gcry_mpi_point_release (mpi_point_t p)
103
0
{
104
0
  if (p)
105
0
    {
106
0
      _gcry_mpi_point_free_parts (p);
107
0
      xfree (p);
108
0
    }
109
0
}
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
0
{
117
0
  p->x = mpi_new (0);
118
0
  p->y = mpi_new (0);
119
0
  p->z = mpi_new (0);
120
0
}
121
122
123
/* Release the parts of a point object. */
124
void
125
_gcry_mpi_point_free_parts (mpi_point_t p)
126
0
{
127
0
  mpi_free (p->x); p->x = NULL;
128
0
  mpi_free (p->y); p->y = NULL;
129
0
  mpi_free (p->z); p->z = NULL;
130
0
}
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
0
{
137
0
  mpi_set (d->x, s->x);
138
0
  mpi_set (d->y, s->y);
139
0
  mpi_set (d->z, s->z);
140
0
}
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
0
{
160
0
  size_t nlimbs = ctx->p->nlimbs;
161
162
0
  mpi_resize (p->x, nlimbs);
163
0
  p->x->nlimbs = nlimbs;
164
0
  mpi_resize (p->z, nlimbs);
165
0
  p->z->nlimbs = nlimbs;
166
167
0
  if (ctx->model != MPI_EC_MONTGOMERY)
168
0
    {
169
0
      mpi_resize (p->y, nlimbs);
170
0
      p->y->nlimbs = nlimbs;
171
0
    }
172
0
}
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
0
{
252
0
  if (!point)
253
0
    point = mpi_point_new (0);
254
255
0
  if (x)
256
0
    mpi_snatch (point->x, x);
257
0
  else
258
0
    mpi_clear (point->x);
259
0
  if (y)
260
0
    mpi_snatch (point->y, y);
261
0
  else
262
0
    mpi_clear (point->y);
263
0
  if (z)
264
0
    mpi_snatch (point->z, z);
265
0
  else
266
0
    mpi_clear (point->z);
267
268
0
  return point;
269
0
}
270
271
272
/* W = W mod P.  */
273
static void
274
ec_mod (gcry_mpi_t w, mpi_ec_t ec)
275
0
{
276
0
  if (0 && ec->dialect == ECC_DIALECT_ED25519)
277
0
    _gcry_mpi_ec_ed25519_mod (w);
278
0
  else if (ec->t.p_barrett)
279
0
    _gcry_mpi_mod_barrett (w, w, ec->t.p_barrett);
280
0
  else
281
0
    _gcry_mpi_mod (w, w, ec->p);
282
0
}
283
284
static void
285
ec_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
286
0
{
287
0
  mpi_add (w, u, v);
288
0
  ctx->mod (w, ctx);
289
0
}
290
291
static void
292
ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ec)
293
0
{
294
0
  mpi_sub (w, u, v);
295
0
  while (w->sign)
296
0
    mpi_add (w, w, ec->p);
297
  /*ctx->mod (w, ec);*/
298
0
}
299
300
static void
301
ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
302
0
{
303
0
  mpi_mul (w, u, v);
304
0
  ctx->mod (w, ctx);
305
0
}
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
0
{
311
0
  mpi_lshift (w, u, 1);
312
0
  ctx->mod (w, ctx);
313
0
}
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
0
{
319
0
  mpi_powm (w, b, e, ctx->p);
320
  /* _gcry_mpi_abs (w); */
321
0
}
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
0
{
330
  /* Using mpi_mul is slightly faster (at least on amd64).  */
331
  /* mpi_powm (w, b, mpi_const (MPI_C_TWO), ctx->p); */
332
0
  ec_mulm (w, b, b, ctx);
333
0
}
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
0
{
342
0
  mpi_powm (w, b, mpi_const (MPI_C_THREE), ctx->p);
343
0
}
344
345
346
static void
347
ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
348
0
{
349
0
  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
0
}
356

357
/* Routines for 2^255 - 19.  */
358
359
0
#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
0
{
364
0
  mpi_ptr_t wp, up, vp;
365
0
  mpi_size_t wsize = LIMB_SIZE_25519;
366
0
  mpi_limb_t n[LIMB_SIZE_25519];
367
0
  mpi_limb_t borrow;
368
369
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
370
0
    log_bug ("addm_25519: different sizes\n");
371
372
0
  up = u->d;
373
0
  vp = v->d;
374
0
  wp = w->d;
375
376
0
  _gcry_mpih_add_n (wp, up, vp, wsize);
377
0
  borrow = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
378
0
  mpih_set_cond (wp, n, wsize, (borrow == 0UL));
379
0
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
380
0
}
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
0
{
385
0
  mpi_ptr_t wp, up, vp;
386
0
  mpi_size_t wsize = LIMB_SIZE_25519;
387
0
  mpi_limb_t n[LIMB_SIZE_25519];
388
0
  mpi_limb_t borrow;
389
390
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
391
0
    log_bug ("subm_25519: different sizes\n");
392
393
0
  up = u->d;
394
0
  vp = v->d;
395
0
  wp = w->d;
396
397
0
  borrow = _gcry_mpih_sub_n (wp, up, vp, wsize);
398
0
  _gcry_mpih_add_n (n, wp, ctx->p->d, wsize);
399
0
  mpih_set_cond (wp, n, wsize, (borrow != 0UL));
400
0
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
401
0
}
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
0
{
406
0
  mpi_ptr_t wp, up, vp;
407
0
  mpi_size_t wsize = LIMB_SIZE_25519;
408
0
  mpi_limb_t n[LIMB_SIZE_25519*2];
409
0
  mpi_limb_t cy;
410
0
  int msb;
411
412
0
  (void)ctx;
413
0
  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
414
0
    log_bug ("mulm_25519: different sizes\n");
415
416
0
  up = u->d;
417
0
  vp = v->d;
418
0
  wp = w->d;
419
420
0
  _gcry_mpih_mul_n (n, up, vp, wsize);
421
0
  memcpy (wp, n, wsize * BYTES_PER_MPI_LIMB);
422
0
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
423
424
0
  _gcry_mpih_rshift (n, n+LIMB_SIZE_25519-1, LIMB_SIZE_25519+1,
425
0
         (255 % BITS_PER_MPI_LIMB));
426
427
0
  cy = _gcry_mpih_addmul_1 (wp, n, wsize, 19);
428
429
0
  memset (n, 0, wsize * BYTES_PER_MPI_LIMB);
430
0
  msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
431
0
  n[0] = (cy * 2 + msb) * 19;
432
0
  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
433
0
  _gcry_mpih_add_n (wp, wp, n, wsize);
434
435
0
  cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
436
0
  mpih_set_cond (wp, n, wsize, (cy == 0UL));
437
0
}
438
439
static void
440
ec_mul2_25519 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
441
0
{
442
0
  ec_addm_25519 (w, u, u, ctx);
443
0
}
444
445
static void
446
ec_pow2_25519 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
447
0
{
448
0
  ec_mulm_25519 (w, b, b, ctx);
449
0
}
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
0
{
584
0
  mpi_limb_t s[(256 + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB + 1];
585
0
  mpi_limb_t n[DIM(s)];
586
0
  const mpi_size_t wsize = DIM(s) - 1;
587
0
  mpi_limb_t cy, borrow;
588
0
  mpi_ptr_t wp;
589
590
0
  MPN_NORMALIZE (w->d, w->nlimbs);
591
0
  if (w->nlimbs > 2 * 256 / BITS_PER_MPI_LIMB)
592
0
    log_bug ("W must be less than m^2\n");
593
594
0
  RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2);
595
596
0
  wp = w->d;
597
598
  /* mod P (2^256 - 2^32 - 977) */
599
600
  /* first pass of reduction */
601
0
  memcpy (n, wp + wsize, wsize * BYTES_PER_MPI_LIMB);
602
0
#if BITS_PER_MPI_LIMB == 64
603
0
  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
0
  wp[wsize] = _gcry_mpih_addmul_1 (wp, n, wsize, 977);
609
0
  cy = _gcry_mpih_add_n (wp, wp, s, wsize + 1);
610
611
  /* second pass of reduction */
612
0
#if BITS_PER_MPI_LIMB == 64
613
  /* cy == 0 */
614
0
  memset (n + 1, 0, (wsize - 1) * BYTES_PER_MPI_LIMB);
615
0
  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
0
  cy = _gcry_mpih_add_n (wp, wp, n, wsize);
623
624
0
  borrow = _gcry_mpih_sub_n (s, wp, ctx->p->d, wsize);
625
0
  mpih_set_cond (wp, s, wsize, (cy != 0UL) | (borrow == 0UL));
626
627
0
  w->nlimbs = wsize;
628
0
  MPN_NORMALIZE (wp, w->nlimbs);
629
0
}
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
0
{
730
0
  ec->t.valid.a_is_pminus3 = 0;
731
0
  ec->t.valid.two_inv_p = 0;
732
0
}
733
734
735
/* Accessor for helper variable.  */
736
static int
737
ec_get_a_is_pminus3 (mpi_ec_t ec)
738
0
{
739
0
  gcry_mpi_t tmp;
740
741
0
  if (!ec->t.valid.a_is_pminus3)
742
0
    {
743
0
      ec->t.valid.a_is_pminus3 = 1;
744
0
      tmp = mpi_alloc_like (ec->p);
745
0
      mpi_sub_ui (tmp, ec->p, 3);
746
0
      ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
747
0
      mpi_free (tmp);
748
0
    }
749
750
0
  return ec->t.a_is_pminus3;
751
0
}
752
753
754
/* Accessor for helper variable.  */
755
static gcry_mpi_t
756
ec_get_two_inv_p (mpi_ec_t ec)
757
0
{
758
0
  if (!ec->t.valid.two_inv_p)
759
0
    {
760
0
      ec->t.valid.two_inv_p = 1;
761
0
      if (!ec->t.two_inv_p)
762
0
        ec->t.two_inv_p = mpi_alloc (0);
763
0
      ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
764
0
    }
765
0
  return ec->t.two_inv_p;
766
0
}
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
0
{
822
0
  int i;
823
0
  static int use_barrett;
824
825
0
  if (!use_barrett)
826
0
    {
827
0
      if (getenv ("GCRYPT_BARRETT"))
828
0
        use_barrett = 1;
829
0
      else
830
0
        use_barrett = -1;
831
0
    }
832
833
  /* Fixme: Do we want to check some constraints? e.g.  a < p  */
834
835
0
  ctx->model = model;
836
0
  ctx->dialect = dialect;
837
0
  ctx->flags = flags;
838
0
  ctx->nbits = mpi_get_nbits (p);
839
0
  ctx->p = mpi_copy (p);
840
0
  ctx->a = mpi_copy (a);
841
0
  ctx->b = mpi_copy (b);
842
843
0
  ctx->t.p_barrett = use_barrett > 0? _gcry_mpi_barrett_init (ctx->p, 0):NULL;
844
845
0
  _gcry_mpi_ec_get_reset (ctx);
846
847
0
  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
0
  else
864
0
    {
865
      /* Allocate scratch variables.  */
866
0
      for (i=0; i< DIM(ctx->t.scratch); i++)
867
0
        ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
868
0
    }
869
870
0
  ctx->addm = ec_addm;
871
0
  ctx->subm = ec_subm;
872
0
  ctx->mulm = ec_mulm;
873
0
  ctx->mul2 = ec_mul2;
874
0
  ctx->pow2 = ec_pow2;
875
0
  ctx->mod = ec_mod;
876
877
0
  for (i=0; field_table[i].p; i++)
878
0
    {
879
0
      gcry_mpi_t f_p;
880
0
      gpg_err_code_t rc;
881
882
0
      if (field_table_mpis[i] == NULL)
883
0
  {
884
0
    rc = _gcry_mpi_scan (&f_p, GCRYMPI_FMT_HEX, field_table[i].p, 0,
885
0
             NULL);
886
0
    if (rc)
887
0
      log_fatal ("scanning ECC parameter failed: %s\n",
888
0
           gpg_strerror (rc));
889
0
    field_table_mpis[i] = f_p; /* cache */
890
0
  }
891
0
      else
892
0
  {
893
0
    f_p = field_table_mpis[i];
894
0
  }
895
896
0
      if (!mpi_cmp (p, f_p))
897
0
        {
898
0
          ctx->addm = field_table[i].addm ? field_table[i].addm : ctx->addm;
899
0
          ctx->subm = field_table[i].subm ? field_table[i].subm : ctx->subm;
900
0
          ctx->mulm = field_table[i].mulm ? field_table[i].mulm : ctx->mulm;
901
0
          ctx->mul2 = field_table[i].mul2 ? field_table[i].mul2 : ctx->mul2;
902
0
          ctx->pow2 = field_table[i].pow2 ? field_table[i].pow2 : ctx->pow2;
903
0
          ctx->mod = field_table[i].mod ? field_table[i].mod : ctx->mod;
904
905
0
    if (ctx->a)
906
0
      {
907
0
        mpi_resize (ctx->a, ctx->p->nlimbs);
908
0
        ctx->a->nlimbs = ctx->p->nlimbs;
909
0
      }
910
911
0
    if (ctx->b)
912
0
      {
913
0
        mpi_resize (ctx->b, ctx->p->nlimbs);
914
0
        ctx->b->nlimbs = ctx->p->nlimbs;
915
0
      }
916
917
0
          for (i=0; i< DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++)
918
0
            ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs;
919
920
0
          break;
921
0
        }
922
0
    }
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
0
}
942
943
944
static void
945
ec_deinit (void *opaque)
946
0
{
947
0
  mpi_ec_t ctx = opaque;
948
0
  int i;
949
950
0
  _gcry_mpi_barrett_free (ctx->t.p_barrett);
951
952
  /* Domain parameter.  */
953
0
  mpi_free (ctx->p);
954
0
  mpi_free (ctx->a);
955
0
  mpi_free (ctx->b);
956
0
  _gcry_mpi_point_release (ctx->G);
957
0
  mpi_free (ctx->n);
958
959
  /* The key.  */
960
0
  _gcry_mpi_point_release (ctx->Q);
961
0
  mpi_free (ctx->d);
962
963
  /* Private data of ec.c.  */
964
0
  mpi_free (ctx->t.two_inv_p);
965
966
0
  for (i=0; i< DIM(ctx->t.scratch); i++)
967
0
    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
0
}
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
0
{
997
0
  mpi_ec_t ctx;
998
999
0
  ctx = xcalloc (1, sizeof *ctx);
1000
0
  ec_p_init (ctx, model, dialect, flags, p, a, b);
1001
1002
0
  return ctx;
1003
0
}
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
0
{
1041
0
  if (ctx)
1042
0
    {
1043
0
      ec_deinit (ctx);
1044
0
      xfree (ctx);
1045
0
    }
1046
0
}
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
0
{
1097
0
  gpg_err_code_t rc;
1098
1099
0
  if (ec
1100
0
      && (ec->dialect == ECC_DIALECT_ED25519
1101
0
          || (ec->model == MPI_EC_EDWARDS
1102
0
              && ec->dialect == ECC_DIALECT_SAFECURVE)))
1103
0
    rc = _gcry_ecc_eddsa_decodepoint (value, ec, result, NULL, NULL);
1104
0
  else if (ec && ec->model == MPI_EC_MONTGOMERY)
1105
0
    rc = _gcry_ecc_mont_decodepoint (value, ec, result);
1106
0
  else
1107
0
    rc = _gcry_ecc_sec_decodepoint (value, ec, result);
1108
1109
0
  return rc;
1110
0
}
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
0
{
1121
0
  if (!mpi_cmp_ui (point->z, 0))
1122
0
    return -1;
1123
1124
0
  switch (ctx->model)
1125
0
    {
1126
0
    case MPI_EC_WEIERSTRASS: /* Using Jacobian coordinates.  */
1127
0
      {
1128
0
        gcry_mpi_t z1, z2, z3;
1129
1130
0
  if (!mpi_cmp_ui (point->z, 1))
1131
0
    {
1132
0
      if (x)
1133
0
        mpi_set (x, point->x);
1134
0
      if (y)
1135
0
        mpi_set (y, point->y);
1136
0
      return 0;
1137
0
    }
1138
1139
0
        z1 = mpi_new (0);
1140
0
        z2 = mpi_new (0);
1141
0
        ec_invm (z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
1142
0
        ec_mulm (z2, z1, z1, ctx);    /* z2 = z^(-2) mod p  */
1143
1144
0
        if (x)
1145
0
          ec_mulm (x, point->x, z2, ctx);
1146
1147
0
        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
0
        mpi_free (z2);
1156
0
        mpi_free (z1);
1157
0
      }
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
0
    case MPI_EC_EDWARDS:
1175
0
      {
1176
0
        gcry_mpi_t z;
1177
1178
0
  if (!mpi_cmp_ui (point->z, 1))
1179
0
    {
1180
0
      if (x)
1181
0
        mpi_set (x, point->x);
1182
0
      if (y)
1183
0
        mpi_set (y, point->y);
1184
0
      return 0;
1185
0
    }
1186
1187
0
        z = mpi_new (0);
1188
0
        ec_invm (z, point->z, ctx);
1189
1190
0
        mpi_resize (z, ctx->p->nlimbs);
1191
0
        z->nlimbs = ctx->p->nlimbs;
1192
1193
0
        if (x)
1194
0
          {
1195
0
            mpi_resize (x, ctx->p->nlimbs);
1196
0
            x->nlimbs = ctx->p->nlimbs;
1197
0
            ctx->mulm (x, point->x, z, ctx);
1198
0
          }
1199
0
        if (y)
1200
0
          {
1201
0
            mpi_resize (y, ctx->p->nlimbs);
1202
0
            y->nlimbs = ctx->p->nlimbs;
1203
0
            ctx->mulm (y, point->y, z, ctx);
1204
0
          }
1205
1206
0
        _gcry_mpi_release (z);
1207
0
      }
1208
0
      return 0;
1209
1210
0
    default:
1211
0
      return -1;
1212
0
    }
1213
0
}
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
0
{
1221
0
#define x3 (result->x)
1222
0
#define y3 (result->y)
1223
0
#define z3 (result->z)
1224
0
#define t1 (ctx->t.scratch[0])
1225
0
#define t2 (ctx->t.scratch[1])
1226
0
#define t3 (ctx->t.scratch[2])
1227
0
#define l1 (ctx->t.scratch[3])
1228
0
#define l2 (ctx->t.scratch[4])
1229
0
#define l3 (ctx->t.scratch[5])
1230
1231
0
  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
0
  else
1239
0
    {
1240
0
      if (ec_get_a_is_pminus3 (ctx))  /* Use the faster case.  */
1241
0
        {
1242
          /* L1 = 3(X - Z^2)(X + Z^2) */
1243
          /*                          T1: used for Z^2. */
1244
          /*                          T2: used for the right term.  */
1245
0
          ec_pow2 (t1, point->z, ctx);
1246
0
          ec_subm (l1, point->x, t1, ctx);
1247
0
          ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
1248
0
          ec_addm (t2, point->x, t1, ctx);
1249
0
          ec_mulm (l1, l1, t2, ctx);
1250
0
        }
1251
0
      else /* Standard case. */
1252
0
        {
1253
          /* L1 = 3X^2 + aZ^4 */
1254
          /*                          T1: used for aZ^4. */
1255
0
          ec_pow2 (l1, point->x, ctx);
1256
0
          ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
1257
0
          ec_powm (t1, point->z, mpi_const (MPI_C_FOUR), ctx);
1258
0
          ec_mulm (t1, t1, ctx->a, ctx);
1259
0
          ec_addm (l1, l1, t1, ctx);
1260
0
        }
1261
      /* Z3 = 2YZ */
1262
0
      ec_mulm (z3, point->y, point->z, ctx);
1263
0
      ec_mul2 (z3, z3, ctx);
1264
1265
      /* L2 = 4XY^2 */
1266
      /*                              T2: used for Y2; required later. */
1267
0
      ec_pow2 (t2, point->y, ctx);
1268
0
      ec_mulm (l2, t2, point->x, ctx);
1269
0
      ec_mulm (l2, l2, mpi_const (MPI_C_FOUR), ctx);
1270
1271
      /* X3 = L1^2 - 2L2 */
1272
      /*                              T1: used for L2^2. */
1273
0
      ec_pow2 (x3, l1, ctx);
1274
0
      ec_mul2 (t1, l2, ctx);
1275
0
      ec_subm (x3, x3, t1, ctx);
1276
1277
      /* L3 = 8Y^4 */
1278
      /*                              T2: taken from above. */
1279
0
      ec_pow2 (t2, t2, ctx);
1280
0
      ec_mulm (l3, t2, mpi_const (MPI_C_EIGHT), ctx);
1281
1282
      /* Y3 = L1(L2 - X3) - L3 */
1283
0
      ec_subm (y3, l2, x3, ctx);
1284
0
      ec_mulm (y3, y3, l1, ctx);
1285
0
      ec_subm (y3, y3, l3, ctx);
1286
0
    }
1287
1288
0
#undef x3
1289
0
#undef y3
1290
0
#undef z3
1291
0
#undef t1
1292
0
#undef t2
1293
0
#undef t3
1294
0
#undef l1
1295
0
#undef l2
1296
0
#undef l3
1297
0
}
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
0
{
1316
0
#define X1 (point->x)
1317
0
#define Y1 (point->y)
1318
0
#define Z1 (point->z)
1319
0
#define X3 (result->x)
1320
0
#define Y3 (result->y)
1321
0
#define Z3 (result->z)
1322
0
#define B (ctx->t.scratch[0])
1323
0
#define C (ctx->t.scratch[1])
1324
0
#define D (ctx->t.scratch[2])
1325
0
#define E (ctx->t.scratch[3])
1326
0
#define F (ctx->t.scratch[4])
1327
0
#define H (ctx->t.scratch[5])
1328
0
#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
0
  ctx->addm (B, X1, Y1, ctx);
1334
0
  ctx->pow2 (B, B, ctx);
1335
1336
  /* C = X_1^2 */
1337
  /* D = Y_1^2 */
1338
0
  ctx->pow2 (C, X1, ctx);
1339
0
  ctx->pow2 (D, Y1, ctx);
1340
1341
  /* E = aC */
1342
0
  if (ctx->dialect == ECC_DIALECT_ED25519)
1343
0
    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
0
  ctx->addm (F, E, D, ctx);
1349
1350
  /* H = Z_1^2 */
1351
0
  ctx->pow2 (H, Z1, ctx);
1352
1353
  /* J = F - 2H */
1354
0
  ctx->mul2 (J, H, ctx);
1355
0
  ctx->subm (J, F, J, ctx);
1356
1357
  /* X_3 = (B - C - D) · J */
1358
0
  ctx->subm (X3, B, C, ctx);
1359
0
  ctx->subm (X3, X3, D, ctx);
1360
0
  ctx->mulm (X3, X3, J, ctx);
1361
1362
  /* Y_3 = F · (E - D) */
1363
0
  ctx->subm (Y3, E, D, ctx);
1364
0
  ctx->mulm (Y3, Y3, F, ctx);
1365
1366
  /* Z_3 = F · J */
1367
0
  ctx->mulm (Z3, F, J, ctx);
1368
1369
0
#undef X1
1370
0
#undef Y1
1371
0
#undef Z1
1372
0
#undef X3
1373
0
#undef Y3
1374
0
#undef Z3
1375
0
#undef B
1376
0
#undef C
1377
0
#undef D
1378
0
#undef E
1379
0
#undef F
1380
0
#undef H
1381
0
#undef J
1382
0
}
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
0
{
1389
0
  switch (ctx->model)
1390
0
    {
1391
0
    case MPI_EC_WEIERSTRASS:
1392
0
      dup_point_weierstrass (result, point, ctx);
1393
0
      break;
1394
0
    case MPI_EC_MONTGOMERY:
1395
0
      dup_point_montgomery (result, point, ctx);
1396
0
      break;
1397
0
    case MPI_EC_EDWARDS:
1398
0
      dup_point_edwards (result, point, ctx);
1399
0
      break;
1400
0
    }
1401
0
}
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
0
{
1410
0
#define x1 (p1->x    )
1411
0
#define y1 (p1->y    )
1412
0
#define z1 (p1->z    )
1413
0
#define x2 (p2->x    )
1414
0
#define y2 (p2->y    )
1415
0
#define z2 (p2->z    )
1416
0
#define x3 (result->x)
1417
0
#define y3 (result->y)
1418
0
#define z3 (result->z)
1419
0
#define l1 (ctx->t.scratch[0])
1420
0
#define l2 (ctx->t.scratch[1])
1421
0
#define l3 (ctx->t.scratch[2])
1422
0
#define l4 (ctx->t.scratch[3])
1423
0
#define l5 (ctx->t.scratch[4])
1424
0
#define l6 (ctx->t.scratch[5])
1425
0
#define l7 (ctx->t.scratch[6])
1426
0
#define l8 (ctx->t.scratch[7])
1427
0
#define l9 (ctx->t.scratch[8])
1428
0
#define t1 (ctx->t.scratch[9])
1429
0
#define t2 (ctx->t.scratch[10])
1430
1431
0
  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
0
  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
0
  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
0
  else
1451
0
    {
1452
0
      int z1_is_one = !mpi_cmp_ui (z1, 1);
1453
0
      int z2_is_one = !mpi_cmp_ui (z2, 1);
1454
1455
      /* l1 = x1 z2^2  */
1456
      /* l2 = x2 z1^2  */
1457
0
      if (z2_is_one)
1458
0
        mpi_set (l1, x1);
1459
0
      else
1460
0
        {
1461
0
          ec_pow2 (l1, z2, ctx);
1462
0
          ec_mulm (l1, l1, x1, ctx);
1463
0
        }
1464
0
      if (z1_is_one)
1465
0
        mpi_set (l2, x2);
1466
0
      else
1467
0
        {
1468
0
          ec_pow2 (l2, z1, ctx);
1469
0
          ec_mulm (l2, l2, x2, ctx);
1470
0
        }
1471
      /* l3 = l1 - l2 */
1472
0
      ec_subm (l3, l1, l2, ctx);
1473
      /* l4 = y1 z2^3  */
1474
0
      ec_powm (l4, z2, mpi_const (MPI_C_THREE), ctx);
1475
0
      ec_mulm (l4, l4, y1, ctx);
1476
      /* l5 = y2 z1^3  */
1477
0
      ec_powm (l5, z1, mpi_const (MPI_C_THREE), ctx);
1478
0
      ec_mulm (l5, l5, y2, ctx);
1479
      /* l6 = l4 - l5  */
1480
0
      ec_subm (l6, l4, l5, ctx);
1481
1482
0
      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
0
      else
1498
0
        {
1499
          /* l7 = l1 + l2  */
1500
0
          ec_addm (l7, l1, l2, ctx);
1501
          /* l8 = l4 + l5  */
1502
0
          ec_addm (l8, l4, l5, ctx);
1503
          /* z3 = z1 z2 l3  */
1504
0
          ec_mulm (z3, z1, z2, ctx);
1505
0
          ec_mulm (z3, z3, l3, ctx);
1506
          /* x3 = l6^2 - l7 l3^2  */
1507
0
          ec_pow2 (t1, l6, ctx);
1508
0
          ec_pow2 (t2, l3, ctx);
1509
0
          ec_mulm (t2, t2, l7, ctx);
1510
0
          ec_subm (x3, t1, t2, ctx);
1511
          /* l9 = l7 l3^2 - 2 x3  */
1512
0
          ec_mul2 (t1, x3, ctx);
1513
0
          ec_subm (l9, t2, t1, ctx);
1514
          /* y3 = (l9 l6 - l8 l3^3)/2  */
1515
0
          ec_mulm (l9, l9, l6, ctx);
1516
0
          ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/
1517
0
          ec_mulm (t1, t1, l8, ctx);
1518
0
          ec_subm (y3, l9, t1, ctx);
1519
0
          ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
1520
0
        }
1521
0
    }
1522
1523
0
#undef x1
1524
0
#undef y1
1525
0
#undef z1
1526
0
#undef x2
1527
0
#undef y2
1528
0
#undef z2
1529
0
#undef x3
1530
0
#undef y3
1531
0
#undef z3
1532
0
#undef l1
1533
0
#undef l2
1534
0
#undef l3
1535
0
#undef l4
1536
0
#undef l5
1537
0
#undef l6
1538
0
#undef l7
1539
0
#undef l8
1540
0
#undef l9
1541
0
#undef t1
1542
0
#undef t2
1543
0
}
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
0
{
1567
0
#define X1 (p1->x)
1568
0
#define Y1 (p1->y)
1569
0
#define Z1 (p1->z)
1570
0
#define X2 (p2->x)
1571
0
#define Y2 (p2->y)
1572
0
#define Z2 (p2->z)
1573
0
#define X3 (result->x)
1574
0
#define Y3 (result->y)
1575
0
#define Z3 (result->z)
1576
0
#define A (ctx->t.scratch[0])
1577
0
#define B (ctx->t.scratch[1])
1578
0
#define C (ctx->t.scratch[2])
1579
0
#define D (ctx->t.scratch[3])
1580
0
#define E (ctx->t.scratch[4])
1581
0
#define F (ctx->t.scratch[5])
1582
0
#define G (ctx->t.scratch[6])
1583
0
#define tmp (ctx->t.scratch[7])
1584
1585
0
  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
0
  ctx->mulm (A, Z1, Z2, ctx);
1591
1592
  /* B = A^2 */
1593
0
  ctx->pow2 (B, A, ctx);
1594
1595
  /* C = X1 · X2 */
1596
0
  ctx->mulm (C, X1, X2, ctx);
1597
1598
  /* D = Y1 · Y2 */
1599
0
  ctx->mulm (D, Y1, Y2, ctx);
1600
1601
  /* E = d · C · D */
1602
0
  ctx->mulm (E, ctx->b, C, ctx);
1603
0
  ctx->mulm (E, E, D, ctx);
1604
1605
  /* F = B - E */
1606
0
  ctx->subm (F, B, E, ctx);
1607
1608
  /* G = B + E */
1609
0
  ctx->addm (G, B, E, ctx);
1610
1611
  /* X_3 = A · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
1612
0
  ctx->addm (tmp, X1, Y1, ctx);
1613
0
  ctx->addm (X3, X2, Y2, ctx);
1614
0
  ctx->mulm (X3, X3, tmp, ctx);
1615
0
  ctx->subm (X3, X3, C, ctx);
1616
0
  ctx->subm (X3, X3, D, ctx);
1617
0
  ctx->mulm (X3, X3, F, ctx);
1618
0
  ctx->mulm (X3, X3, A, ctx);
1619
1620
  /* Y_3 = A · G · (D - aC) */
1621
0
  if (ctx->dialect == ECC_DIALECT_ED25519)
1622
0
    {
1623
0
      ctx->addm (Y3, D, C, ctx);
1624
0
    }
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
0
  ctx->mulm (Y3, Y3, G, ctx);
1631
0
  ctx->mulm (Y3, Y3, A, ctx);
1632
1633
  /* Z_3 = F · G */
1634
0
  ctx->mulm (Z3, F, G, ctx);
1635
1636
1637
0
#undef X1
1638
0
#undef Y1
1639
0
#undef Z1
1640
0
#undef X2
1641
0
#undef Y2
1642
0
#undef Z2
1643
0
#undef X3
1644
0
#undef Y3
1645
0
#undef Z3
1646
0
#undef A
1647
0
#undef B
1648
0
#undef C
1649
0
#undef D
1650
0
#undef E
1651
0
#undef F
1652
0
#undef G
1653
0
#undef tmp
1654
0
}
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
0
{
1692
0
  switch (ctx->model)
1693
0
    {
1694
0
    case MPI_EC_WEIERSTRASS:
1695
0
      add_points_weierstrass (result, p1, p2, ctx);
1696
0
      break;
1697
0
    case MPI_EC_MONTGOMERY:
1698
0
      add_points_montgomery (result, p1, p2, ctx);
1699
0
      break;
1700
0
    case MPI_EC_EDWARDS:
1701
0
      add_points_edwards (result, p1, p2, ctx);
1702
0
      break;
1703
0
    }
1704
0
}
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
0
{
1780
0
  gcry_mpi_t x1, y1, z1, k, h, yy;
1781
0
  unsigned int i, loops;
1782
0
  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
0
  if (mpi_ec_hw_mul_point (result, scalar, point, ctx) >= 0)
1788
0
    {
1789
0
      return;
1790
0
    }
1791
1792
0
  if (ctx->model == MPI_EC_EDWARDS
1793
0
      || (ctx->model == MPI_EC_WEIERSTRASS
1794
0
          && mpi_is_secure (scalar)))
1795
0
    {
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
0
      unsigned int nbits;
1803
0
      int j;
1804
1805
0
      if (mpi_cmp (scalar, ctx->p) >= 0)
1806
0
        nbits = mpi_get_nbits (scalar);
1807
0
      else
1808
0
        nbits = mpi_get_nbits (ctx->p);
1809
1810
0
      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
0
      else
1817
0
        {
1818
0
          mpi_set_ui (result->x, 0);
1819
0
          mpi_set_ui (result->y, 1);
1820
0
          mpi_set_ui (result->z, 1);
1821
0
          mpi_point_resize (point, ctx);
1822
0
        }
1823
1824
0
      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
0
      else
1842
0
        {
1843
0
          if (ctx->model == MPI_EC_EDWARDS)
1844
0
            {
1845
0
              mpi_point_resize (result, ctx);
1846
0
              mpi_point_resize (point, ctx);
1847
0
            }
1848
1849
0
          for (j=nbits-1; j >= 0; j--)
1850
0
            {
1851
0
              _gcry_mpi_ec_dup_point (result, result, ctx);
1852
0
              if (mpi_test_bit (scalar, j))
1853
0
                _gcry_mpi_ec_add_points (result, result, point, ctx);
1854
0
            }
1855
0
        }
1856
0
      return;
1857
0
    }
1858
0
  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
0
  x1 = mpi_alloc_like (ctx->p);
1963
0
  y1 = mpi_alloc_like (ctx->p);
1964
0
  h  = mpi_alloc_like (ctx->p);
1965
0
  k  = mpi_copy (scalar);
1966
0
  yy = mpi_copy (point->y);
1967
1968
0
  if ( mpi_has_sign (k) )
1969
0
    {
1970
0
      k->sign = 0;
1971
0
      ec_invm (yy, yy, ctx);
1972
0
    }
1973
1974
0
  if (!mpi_cmp_ui (point->z, 1))
1975
0
    {
1976
0
      mpi_set (x1, point->x);
1977
0
      mpi_set (y1, yy);
1978
0
    }
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
0
  z1 = mpi_copy (mpi_const (MPI_C_ONE));
1995
1996
0
  mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */
1997
0
  loops = mpi_get_nbits (h);
1998
0
  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
0
  else
2009
0
    {
2010
0
      mpi_set (result->x, point->x);
2011
0
      mpi_set (result->y, yy);
2012
0
      mpi_set (result->z, point->z);
2013
0
    }
2014
0
  mpi_free (yy); yy = NULL;
2015
2016
0
  p1.x = x1; x1 = NULL;
2017
0
  p1.y = y1; y1 = NULL;
2018
0
  p1.z = z1; z1 = NULL;
2019
0
  point_init (&p2);
2020
0
  point_init (&p1inv);
2021
2022
  /* Invert point: y = p - y mod p  */
2023
0
  point_set (&p1inv, &p1);
2024
0
  ec_subm (p1inv.y, ctx->p, p1inv.y, ctx);
2025
2026
0
  for (i=loops-2; i > 0; i--)
2027
0
    {
2028
0
      _gcry_mpi_ec_dup_point (result, result, ctx);
2029
0
      if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0)
2030
0
        {
2031
0
          point_set (&p2, result);
2032
0
          _gcry_mpi_ec_add_points (result, &p2, &p1, ctx);
2033
0
        }
2034
0
      if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1)
2035
0
        {
2036
0
          point_set (&p2, result);
2037
0
          _gcry_mpi_ec_add_points (result, &p2, &p1inv, ctx);
2038
0
        }
2039
0
    }
2040
2041
0
  point_free (&p1);
2042
0
  point_free (&p2);
2043
0
  point_free (&p1inv);
2044
0
  mpi_free (h);
2045
0
  mpi_free (k);
2046
0
}
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
0
{
2053
0
  int res = 0;
2054
0
  gcry_mpi_t x, y, w;
2055
2056
0
  x = mpi_new (0);
2057
0
  y = mpi_new (0);
2058
0
  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
0
  if (mpi_cmpabs (point->x, ctx->p) >= 0)
2063
0
    goto leave;
2064
0
  if (mpi_cmpabs (point->y, ctx->p) >= 0)
2065
0
    goto leave;
2066
0
  if (mpi_cmpabs (point->z, ctx->p) >= 0)
2067
0
    goto leave;
2068
2069
0
  switch (ctx->model)
2070
0
    {
2071
0
    case MPI_EC_WEIERSTRASS:
2072
0
      {
2073
0
        gcry_mpi_t xxx;
2074
2075
0
        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
2076
0
          goto leave;
2077
2078
0
        xxx = mpi_new (0);
2079
2080
        /* y^2 == x^3 + a·x + b */
2081
0
        ec_pow2 (y, y, ctx);
2082
2083
0
        ec_pow3 (xxx, x, ctx);
2084
0
        ec_mulm (w, ctx->a, x, ctx);
2085
0
        ec_addm (w, w, ctx->b, ctx);
2086
0
        ec_addm (w, w, xxx, ctx);
2087
2088
0
        if (!mpi_cmp (y, w))
2089
0
          res = 1;
2090
2091
0
        _gcry_mpi_release (xxx);
2092
0
      }
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
0
    case MPI_EC_EDWARDS:
2125
0
      {
2126
0
        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
2127
0
          goto leave;
2128
2129
0
        mpi_resize (w, ctx->p->nlimbs);
2130
0
        w->nlimbs = ctx->p->nlimbs;
2131
2132
        /* a · x^2 + y^2 - 1 - b · x^2 · y^2 == 0 */
2133
0
        ctx->pow2 (x, x, ctx);
2134
0
        ctx->pow2 (y, y, ctx);
2135
0
        if (ctx->dialect == ECC_DIALECT_ED25519)
2136
0
          ctx->subm (w, ctx->p, x, ctx);
2137
0
        else
2138
0
          ctx->mulm (w, ctx->a, x, ctx);
2139
0
        ctx->addm (w, w, y, ctx);
2140
0
        ctx->mulm (x, x, y, ctx);
2141
0
        ctx->mulm (x, x, ctx->b, ctx);
2142
0
        ctx->subm (w, w, x, ctx);
2143
0
        if (!mpi_cmp_ui (w, 1))
2144
0
          res = 1;
2145
0
      }
2146
0
      break;
2147
0
    }
2148
2149
0
 leave:
2150
0
  _gcry_mpi_release (w);
2151
0
  _gcry_mpi_release (x);
2152
0
  _gcry_mpi_release (y);
2153
2154
0
  return res;
2155
0
}
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
}