Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/ec/ecp_smpl.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: ecp_smpl.c,v 1.34 2022/01/20 11:02:44 inoguchi Exp $ */
2
/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3
 * for the OpenSSL project.
4
 * Includes code written by Bodo Moeller for the OpenSSL project.
5
*/
6
/* ====================================================================
7
 * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    openssl-core@openssl.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
/* ====================================================================
60
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61
 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62
 * and contributed to the OpenSSL project.
63
 */
64
65
#include <openssl/err.h>
66
67
#include "bn_lcl.h"
68
#include "ec_lcl.h"
69
70
const EC_METHOD *
71
EC_GFp_simple_method(void)
72
0
{
73
0
  static const EC_METHOD ret = {
74
0
    .flags = EC_FLAGS_DEFAULT_OCT,
75
0
    .field_type = NID_X9_62_prime_field,
76
0
    .group_init = ec_GFp_simple_group_init,
77
0
    .group_finish = ec_GFp_simple_group_finish,
78
0
    .group_clear_finish = ec_GFp_simple_group_clear_finish,
79
0
    .group_copy = ec_GFp_simple_group_copy,
80
0
    .group_set_curve = ec_GFp_simple_group_set_curve,
81
0
    .group_get_curve = ec_GFp_simple_group_get_curve,
82
0
    .group_get_degree = ec_GFp_simple_group_get_degree,
83
0
    .group_order_bits = ec_group_simple_order_bits,
84
0
    .group_check_discriminant =
85
0
        ec_GFp_simple_group_check_discriminant,
86
0
    .point_init = ec_GFp_simple_point_init,
87
0
    .point_finish = ec_GFp_simple_point_finish,
88
0
    .point_clear_finish = ec_GFp_simple_point_clear_finish,
89
0
    .point_copy = ec_GFp_simple_point_copy,
90
0
    .point_set_to_infinity = ec_GFp_simple_point_set_to_infinity,
91
0
    .point_set_Jprojective_coordinates =
92
0
        ec_GFp_simple_set_Jprojective_coordinates,
93
0
    .point_get_Jprojective_coordinates =
94
0
        ec_GFp_simple_get_Jprojective_coordinates,
95
0
    .point_set_affine_coordinates =
96
0
        ec_GFp_simple_point_set_affine_coordinates,
97
0
    .point_get_affine_coordinates =
98
0
        ec_GFp_simple_point_get_affine_coordinates,
99
0
    .add = ec_GFp_simple_add,
100
0
    .dbl = ec_GFp_simple_dbl,
101
0
    .invert = ec_GFp_simple_invert,
102
0
    .is_at_infinity = ec_GFp_simple_is_at_infinity,
103
0
    .is_on_curve = ec_GFp_simple_is_on_curve,
104
0
    .point_cmp = ec_GFp_simple_cmp,
105
0
    .make_affine = ec_GFp_simple_make_affine,
106
0
    .points_make_affine = ec_GFp_simple_points_make_affine,
107
0
    .mul_generator_ct = ec_GFp_simple_mul_generator_ct,
108
0
    .mul_single_ct = ec_GFp_simple_mul_single_ct,
109
0
    .mul_double_nonct = ec_GFp_simple_mul_double_nonct,
110
0
    .field_mul = ec_GFp_simple_field_mul,
111
0
    .field_sqr = ec_GFp_simple_field_sqr,
112
0
    .blind_coordinates = ec_GFp_simple_blind_coordinates,
113
0
  };
114
115
0
  return &ret;
116
0
}
117
118
119
/* Most method functions in this file are designed to work with
120
 * non-trivial representations of field elements if necessary
121
 * (see ecp_mont.c): while standard modular addition and subtraction
122
 * are used, the field_mul and field_sqr methods will be used for
123
 * multiplication, and field_encode and field_decode (if defined)
124
 * will be used for converting between representations.
125
126
 * Functions ec_GFp_simple_points_make_affine() and
127
 * ec_GFp_simple_point_get_affine_coordinates() specifically assume
128
 * that if a non-trivial representation is used, it is a Montgomery
129
 * representation (i.e. 'encoding' means multiplying by some factor R).
130
 */
131
132
133
int
134
ec_GFp_simple_group_init(EC_GROUP * group)
135
5.36k
{
136
5.36k
  BN_init(&group->field);
137
5.36k
  BN_init(&group->a);
138
5.36k
  BN_init(&group->b);
139
5.36k
  group->a_is_minus3 = 0;
140
5.36k
  return 1;
141
5.36k
}
142
143
144
void
145
ec_GFp_simple_group_finish(EC_GROUP * group)
146
5.36k
{
147
5.36k
  BN_free(&group->field);
148
5.36k
  BN_free(&group->a);
149
5.36k
  BN_free(&group->b);
150
5.36k
}
151
152
153
void
154
ec_GFp_simple_group_clear_finish(EC_GROUP * group)
155
0
{
156
0
  BN_clear_free(&group->field);
157
0
  BN_clear_free(&group->a);
158
0
  BN_clear_free(&group->b);
159
0
}
160
161
162
int
163
ec_GFp_simple_group_copy(EC_GROUP * dest, const EC_GROUP * src)
164
2.73k
{
165
2.73k
  if (!BN_copy(&dest->field, &src->field))
166
0
    return 0;
167
2.73k
  if (!BN_copy(&dest->a, &src->a))
168
0
    return 0;
169
2.73k
  if (!BN_copy(&dest->b, &src->b))
170
0
    return 0;
171
172
2.73k
  dest->a_is_minus3 = src->a_is_minus3;
173
174
2.73k
  return 1;
175
2.73k
}
176
177
178
int
179
ec_GFp_simple_group_set_curve(EC_GROUP * group,
180
    const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
181
2.62k
{
182
2.62k
  int ret = 0;
183
2.62k
  BN_CTX *new_ctx = NULL;
184
2.62k
  BIGNUM *tmp_a;
185
186
  /* p must be a prime > 3 */
187
2.62k
  if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
188
0
    ECerror(EC_R_INVALID_FIELD);
189
0
    return 0;
190
0
  }
191
2.62k
  if (ctx == NULL) {
192
0
    ctx = new_ctx = BN_CTX_new();
193
0
    if (ctx == NULL)
194
0
      return 0;
195
0
  }
196
2.62k
  BN_CTX_start(ctx);
197
2.62k
  if ((tmp_a = BN_CTX_get(ctx)) == NULL)
198
0
    goto err;
199
200
  /* group->field */
201
2.62k
  if (!BN_copy(&group->field, p))
202
0
    goto err;
203
2.62k
  BN_set_negative(&group->field, 0);
204
205
  /* group->a */
206
2.62k
  if (!BN_nnmod(tmp_a, a, p, ctx))
207
0
    goto err;
208
2.62k
  if (group->meth->field_encode) {
209
2.62k
    if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))
210
0
      goto err;
211
2.62k
  } else if (!BN_copy(&group->a, tmp_a))
212
0
    goto err;
213
214
  /* group->b */
215
2.62k
  if (!BN_nnmod(&group->b, b, p, ctx))
216
0
    goto err;
217
2.62k
  if (group->meth->field_encode)
218
2.62k
    if (!group->meth->field_encode(group, &group->b, &group->b, ctx))
219
0
      goto err;
220
221
  /* group->a_is_minus3 */
222
2.62k
  if (!BN_add_word(tmp_a, 3))
223
0
    goto err;
224
2.62k
  group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
225
226
2.62k
  ret = 1;
227
228
2.62k
 err:
229
2.62k
  BN_CTX_end(ctx);
230
2.62k
  BN_CTX_free(new_ctx);
231
2.62k
  return ret;
232
2.62k
}
233
234
235
int
236
ec_GFp_simple_group_get_curve(const EC_GROUP * group, BIGNUM * p, BIGNUM * a, BIGNUM * b, BN_CTX * ctx)
237
0
{
238
0
  int ret = 0;
239
0
  BN_CTX *new_ctx = NULL;
240
241
0
  if (p != NULL) {
242
0
    if (!BN_copy(p, &group->field))
243
0
      return 0;
244
0
  }
245
0
  if (a != NULL || b != NULL) {
246
0
    if (group->meth->field_decode) {
247
0
      if (ctx == NULL) {
248
0
        ctx = new_ctx = BN_CTX_new();
249
0
        if (ctx == NULL)
250
0
          return 0;
251
0
      }
252
0
      if (a != NULL) {
253
0
        if (!group->meth->field_decode(group, a, &group->a, ctx))
254
0
          goto err;
255
0
      }
256
0
      if (b != NULL) {
257
0
        if (!group->meth->field_decode(group, b, &group->b, ctx))
258
0
          goto err;
259
0
      }
260
0
    } else {
261
0
      if (a != NULL) {
262
0
        if (!BN_copy(a, &group->a))
263
0
          goto err;
264
0
      }
265
0
      if (b != NULL) {
266
0
        if (!BN_copy(b, &group->b))
267
0
          goto err;
268
0
      }
269
0
    }
270
0
  }
271
0
  ret = 1;
272
273
0
 err:
274
0
  BN_CTX_free(new_ctx);
275
0
  return ret;
276
0
}
277
278
279
int
280
ec_GFp_simple_group_get_degree(const EC_GROUP * group)
281
0
{
282
0
  return BN_num_bits(&group->field);
283
0
}
284
285
286
int
287
ec_GFp_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
288
0
{
289
0
  int ret = 0;
290
0
  BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
291
0
  const BIGNUM *p = &group->field;
292
0
  BN_CTX *new_ctx = NULL;
293
294
0
  if (ctx == NULL) {
295
0
    ctx = new_ctx = BN_CTX_new();
296
0
    if (ctx == NULL) {
297
0
      ECerror(ERR_R_MALLOC_FAILURE);
298
0
      goto err;
299
0
    }
300
0
  }
301
0
  BN_CTX_start(ctx);
302
0
  if ((a = BN_CTX_get(ctx)) == NULL)
303
0
    goto err;
304
0
  if ((b = BN_CTX_get(ctx)) == NULL)
305
0
    goto err;
306
0
  if ((tmp_1 = BN_CTX_get(ctx)) == NULL)
307
0
    goto err;
308
0
  if ((tmp_2 = BN_CTX_get(ctx)) == NULL)
309
0
    goto err;
310
0
  if ((order = BN_CTX_get(ctx)) == NULL)
311
0
    goto err;
312
313
0
  if (group->meth->field_decode) {
314
0
    if (!group->meth->field_decode(group, a, &group->a, ctx))
315
0
      goto err;
316
0
    if (!group->meth->field_decode(group, b, &group->b, ctx))
317
0
      goto err;
318
0
  } else {
319
0
    if (!BN_copy(a, &group->a))
320
0
      goto err;
321
0
    if (!BN_copy(b, &group->b))
322
0
      goto err;
323
0
  }
324
325
  /*
326
   * check the discriminant: y^2 = x^3 + a*x + b is an elliptic curve
327
   * <=> 4*a^3 + 27*b^2 != 0 (mod p) 0 =< a, b < p
328
   */
329
0
  if (BN_is_zero(a)) {
330
0
    if (BN_is_zero(b))
331
0
      goto err;
332
0
  } else if (!BN_is_zero(b)) {
333
0
    if (!BN_mod_sqr(tmp_1, a, p, ctx))
334
0
      goto err;
335
0
    if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
336
0
      goto err;
337
0
    if (!BN_lshift(tmp_1, tmp_2, 2))
338
0
      goto err;
339
    /* tmp_1 = 4*a^3 */
340
341
0
    if (!BN_mod_sqr(tmp_2, b, p, ctx))
342
0
      goto err;
343
0
    if (!BN_mul_word(tmp_2, 27))
344
0
      goto err;
345
    /* tmp_2 = 27*b^2 */
346
347
0
    if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
348
0
      goto err;
349
0
    if (BN_is_zero(a))
350
0
      goto err;
351
0
  }
352
0
  ret = 1;
353
354
0
 err:
355
0
  if (ctx != NULL)
356
0
    BN_CTX_end(ctx);
357
0
  BN_CTX_free(new_ctx);
358
0
  return ret;
359
0
}
360
361
362
int
363
ec_GFp_simple_point_init(EC_POINT * point)
364
23.5k
{
365
23.5k
  BN_init(&point->X);
366
23.5k
  BN_init(&point->Y);
367
23.5k
  BN_init(&point->Z);
368
23.5k
  point->Z_is_one = 0;
369
370
23.5k
  return 1;
371
23.5k
}
372
373
374
void
375
ec_GFp_simple_point_finish(EC_POINT * point)
376
18.3k
{
377
18.3k
  BN_free(&point->X);
378
18.3k
  BN_free(&point->Y);
379
18.3k
  BN_free(&point->Z);
380
18.3k
}
381
382
383
void
384
ec_GFp_simple_point_clear_finish(EC_POINT * point)
385
5.23k
{
386
5.23k
  BN_clear_free(&point->X);
387
5.23k
  BN_clear_free(&point->Y);
388
5.23k
  BN_clear_free(&point->Z);
389
5.23k
  point->Z_is_one = 0;
390
5.23k
}
391
392
393
int
394
ec_GFp_simple_point_copy(EC_POINT * dest, const EC_POINT * src)
395
15.4k
{
396
15.4k
  if (!BN_copy(&dest->X, &src->X))
397
0
    return 0;
398
15.4k
  if (!BN_copy(&dest->Y, &src->Y))
399
0
    return 0;
400
15.4k
  if (!BN_copy(&dest->Z, &src->Z))
401
0
    return 0;
402
15.4k
  dest->Z_is_one = src->Z_is_one;
403
404
15.4k
  return 1;
405
15.4k
}
406
407
408
int
409
ec_GFp_simple_point_set_to_infinity(const EC_GROUP * group, EC_POINT * point)
410
0
{
411
0
  point->Z_is_one = 0;
412
0
  BN_zero(&point->Z);
413
0
  return 1;
414
0
}
415
416
417
int
418
ec_GFp_simple_set_Jprojective_coordinates(const EC_GROUP *group,
419
    EC_POINT *point, const BIGNUM *x, const BIGNUM *y, const BIGNUM *z,
420
    BN_CTX *ctx)
421
3.28k
{
422
3.28k
  BN_CTX *new_ctx = NULL;
423
3.28k
  int ret = 0;
424
425
3.28k
  if (ctx == NULL) {
426
660
    ctx = new_ctx = BN_CTX_new();
427
660
    if (ctx == NULL)
428
0
      return 0;
429
660
  }
430
3.28k
  if (x != NULL) {
431
3.28k
    if (!BN_nnmod(&point->X, x, &group->field, ctx))
432
0
      goto err;
433
3.28k
    if (group->meth->field_encode) {
434
3.28k
      if (!group->meth->field_encode(group, &point->X, &point->X, ctx))
435
0
        goto err;
436
3.28k
    }
437
3.28k
  }
438
3.28k
  if (y != NULL) {
439
3.28k
    if (!BN_nnmod(&point->Y, y, &group->field, ctx))
440
0
      goto err;
441
3.28k
    if (group->meth->field_encode) {
442
3.28k
      if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx))
443
0
        goto err;
444
3.28k
    }
445
3.28k
  }
446
3.28k
  if (z != NULL) {
447
3.28k
    int Z_is_one;
448
449
3.28k
    if (!BN_nnmod(&point->Z, z, &group->field, ctx))
450
0
      goto err;
451
3.28k
    Z_is_one = BN_is_one(&point->Z);
452
3.28k
    if (group->meth->field_encode) {
453
3.28k
      if (Z_is_one && (group->meth->field_set_to_one != 0)) {
454
3.28k
        if (!group->meth->field_set_to_one(group, &point->Z, ctx))
455
0
          goto err;
456
3.28k
      } else {
457
0
        if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx))
458
0
          goto err;
459
0
      }
460
3.28k
    }
461
3.28k
    point->Z_is_one = Z_is_one;
462
3.28k
  }
463
3.28k
  ret = 1;
464
465
3.28k
 err:
466
3.28k
  BN_CTX_free(new_ctx);
467
3.28k
  return ret;
468
3.28k
}
469
470
int
471
ec_GFp_simple_get_Jprojective_coordinates(const EC_GROUP *group,
472
    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
473
0
{
474
0
  BN_CTX *new_ctx = NULL;
475
0
  int ret = 0;
476
477
0
  if (group->meth->field_decode != 0) {
478
0
    if (ctx == NULL) {
479
0
      ctx = new_ctx = BN_CTX_new();
480
0
      if (ctx == NULL)
481
0
        return 0;
482
0
    }
483
0
    if (x != NULL) {
484
0
      if (!group->meth->field_decode(group, x, &point->X, ctx))
485
0
        goto err;
486
0
    }
487
0
    if (y != NULL) {
488
0
      if (!group->meth->field_decode(group, y, &point->Y, ctx))
489
0
        goto err;
490
0
    }
491
0
    if (z != NULL) {
492
0
      if (!group->meth->field_decode(group, z, &point->Z, ctx))
493
0
        goto err;
494
0
    }
495
0
  } else {
496
0
    if (x != NULL) {
497
0
      if (!BN_copy(x, &point->X))
498
0
        goto err;
499
0
    }
500
0
    if (y != NULL) {
501
0
      if (!BN_copy(y, &point->Y))
502
0
        goto err;
503
0
    }
504
0
    if (z != NULL) {
505
0
      if (!BN_copy(z, &point->Z))
506
0
        goto err;
507
0
    }
508
0
  }
509
510
0
  ret = 1;
511
512
0
 err:
513
0
  BN_CTX_free(new_ctx);
514
0
  return ret;
515
0
}
516
517
int
518
ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point,
519
    const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx)
520
3.28k
{
521
3.28k
  if (x == NULL || y == NULL) {
522
    /* unlike for projective coordinates, we do not tolerate this */
523
0
    ECerror(ERR_R_PASSED_NULL_PARAMETER);
524
0
    return 0;
525
0
  }
526
3.28k
  return EC_POINT_set_Jprojective_coordinates(group, point, x, y,
527
3.28k
      BN_value_one(), ctx);
528
3.28k
}
529
530
int
531
ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP * group, const EC_POINT * point,
532
    BIGNUM * x, BIGNUM * y, BN_CTX * ctx)
533
1.99k
{
534
1.99k
  BN_CTX *new_ctx = NULL;
535
1.99k
  BIGNUM *Z, *Z_1, *Z_2, *Z_3;
536
1.99k
  const BIGNUM *Z_;
537
1.99k
  int ret = 0;
538
539
1.99k
  if (EC_POINT_is_at_infinity(group, point) > 0) {
540
31
    ECerror(EC_R_POINT_AT_INFINITY);
541
31
    return 0;
542
31
  }
543
1.96k
  if (ctx == NULL) {
544
1.23k
    ctx = new_ctx = BN_CTX_new();
545
1.23k
    if (ctx == NULL)
546
0
      return 0;
547
1.23k
  }
548
1.96k
  BN_CTX_start(ctx);
549
1.96k
  if ((Z = BN_CTX_get(ctx)) == NULL)
550
0
    goto err;
551
1.96k
  if ((Z_1 = BN_CTX_get(ctx)) == NULL)
552
0
    goto err;
553
1.96k
  if ((Z_2 = BN_CTX_get(ctx)) == NULL)
554
0
    goto err;
555
1.96k
  if ((Z_3 = BN_CTX_get(ctx)) == NULL)
556
0
    goto err;
557
558
  /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
559
560
1.96k
  if (group->meth->field_decode) {
561
1.96k
    if (!group->meth->field_decode(group, Z, &point->Z, ctx))
562
0
      goto err;
563
1.96k
    Z_ = Z;
564
1.96k
  } else {
565
0
    Z_ = &point->Z;
566
0
  }
567
568
1.96k
  if (BN_is_one(Z_)) {
569
9
    if (group->meth->field_decode) {
570
9
      if (x != NULL) {
571
9
        if (!group->meth->field_decode(group, x, &point->X, ctx))
572
0
          goto err;
573
9
      }
574
9
      if (y != NULL) {
575
7
        if (!group->meth->field_decode(group, y, &point->Y, ctx))
576
0
          goto err;
577
7
      }
578
9
    } else {
579
0
      if (x != NULL) {
580
0
        if (!BN_copy(x, &point->X))
581
0
          goto err;
582
0
      }
583
0
      if (y != NULL) {
584
0
        if (!BN_copy(y, &point->Y))
585
0
          goto err;
586
0
      }
587
0
    }
588
1.95k
  } else {
589
1.95k
    if (BN_mod_inverse_ct(Z_1, Z_, &group->field, ctx) == NULL) {
590
0
      ECerror(ERR_R_BN_LIB);
591
0
      goto err;
592
0
    }
593
1.95k
    if (group->meth->field_encode == 0) {
594
      /* field_sqr works on standard representation */
595
0
      if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
596
0
        goto err;
597
1.95k
    } else {
598
1.95k
      if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))
599
0
        goto err;
600
1.95k
    }
601
602
1.95k
    if (x != NULL) {
603
      /*
604
       * in the Montgomery case, field_mul will cancel out
605
       * Montgomery factor in X:
606
       */
607
1.95k
      if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))
608
0
        goto err;
609
1.95k
    }
610
1.95k
    if (y != NULL) {
611
1.22k
      if (group->meth->field_encode == 0) {
612
        /* field_mul works on standard representation */
613
0
        if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
614
0
          goto err;
615
1.22k
      } else {
616
1.22k
        if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))
617
0
          goto err;
618
1.22k
      }
619
620
      /*
621
       * in the Montgomery case, field_mul will cancel out
622
       * Montgomery factor in Y:
623
       */
624
1.22k
      if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx))
625
0
        goto err;
626
1.22k
    }
627
1.95k
  }
628
629
1.96k
  ret = 1;
630
631
1.96k
 err:
632
1.96k
  BN_CTX_end(ctx);
633
1.96k
  BN_CTX_free(new_ctx);
634
1.96k
  return ret;
635
1.96k
}
636
637
int
638
ec_GFp_simple_add(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, const EC_POINT * b, BN_CTX * ctx)
639
1.12M
{
640
1.12M
  int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
641
1.12M
  int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
642
1.12M
  const BIGNUM *p;
643
1.12M
  BN_CTX *new_ctx = NULL;
644
1.12M
  BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
645
1.12M
  int ret = 0;
646
647
1.12M
  if (a == b)
648
0
    return EC_POINT_dbl(group, r, a, ctx);
649
1.12M
  if (EC_POINT_is_at_infinity(group, a) > 0)
650
50
    return EC_POINT_copy(r, b);
651
1.12M
  if (EC_POINT_is_at_infinity(group, b) > 0)
652
8
    return EC_POINT_copy(r, a);
653
654
1.12M
  field_mul = group->meth->field_mul;
655
1.12M
  field_sqr = group->meth->field_sqr;
656
1.12M
  p = &group->field;
657
658
1.12M
  if (ctx == NULL) {
659
1
    ctx = new_ctx = BN_CTX_new();
660
1
    if (ctx == NULL)
661
0
      return 0;
662
1
  }
663
1.12M
  BN_CTX_start(ctx);
664
1.12M
  if ((n0 = BN_CTX_get(ctx)) == NULL)
665
0
    goto end;
666
1.12M
  if ((n1 = BN_CTX_get(ctx)) == NULL)
667
0
    goto end;
668
1.12M
  if ((n2 = BN_CTX_get(ctx)) == NULL)
669
0
    goto end;
670
1.12M
  if ((n3 = BN_CTX_get(ctx)) == NULL)
671
0
    goto end;
672
1.12M
  if ((n4 = BN_CTX_get(ctx)) == NULL)
673
0
    goto end;
674
1.12M
  if ((n5 = BN_CTX_get(ctx)) == NULL)
675
0
    goto end;
676
1.12M
  if ((n6 = BN_CTX_get(ctx)) == NULL)
677
0
    goto end;
678
679
  /*
680
   * Note that in this function we must not read components of 'a' or
681
   * 'b' once we have written the corresponding components of 'r'. ('r'
682
   * might be one of 'a' or 'b'.)
683
   */
684
685
  /* n1, n2 */
686
1.12M
  if (b->Z_is_one) {
687
53.8k
    if (!BN_copy(n1, &a->X))
688
0
      goto end;
689
53.8k
    if (!BN_copy(n2, &a->Y))
690
0
      goto end;
691
    /* n1 = X_a */
692
    /* n2 = Y_a */
693
1.06M
  } else {
694
1.06M
    if (!field_sqr(group, n0, &b->Z, ctx))
695
0
      goto end;
696
1.06M
    if (!field_mul(group, n1, &a->X, n0, ctx))
697
0
      goto end;
698
    /* n1 = X_a * Z_b^2 */
699
700
1.06M
    if (!field_mul(group, n0, n0, &b->Z, ctx))
701
0
      goto end;
702
1.06M
    if (!field_mul(group, n2, &a->Y, n0, ctx))
703
0
      goto end;
704
    /* n2 = Y_a * Z_b^3 */
705
1.06M
  }
706
707
  /* n3, n4 */
708
1.12M
  if (a->Z_is_one) {
709
776
    if (!BN_copy(n3, &b->X))
710
0
      goto end;
711
776
    if (!BN_copy(n4, &b->Y))
712
0
      goto end;
713
    /* n3 = X_b */
714
    /* n4 = Y_b */
715
1.12M
  } else {
716
1.12M
    if (!field_sqr(group, n0, &a->Z, ctx))
717
0
      goto end;
718
1.12M
    if (!field_mul(group, n3, &b->X, n0, ctx))
719
0
      goto end;
720
    /* n3 = X_b * Z_a^2 */
721
722
1.12M
    if (!field_mul(group, n0, n0, &a->Z, ctx))
723
0
      goto end;
724
1.12M
    if (!field_mul(group, n4, &b->Y, n0, ctx))
725
0
      goto end;
726
    /* n4 = Y_b * Z_a^3 */
727
1.12M
  }
728
729
  /* n5, n6 */
730
1.12M
  if (!BN_mod_sub_quick(n5, n1, n3, p))
731
0
    goto end;
732
1.12M
  if (!BN_mod_sub_quick(n6, n2, n4, p))
733
0
    goto end;
734
  /* n5 = n1 - n3 */
735
  /* n6 = n2 - n4 */
736
737
1.12M
  if (BN_is_zero(n5)) {
738
59
    if (BN_is_zero(n6)) {
739
      /* a is the same point as b */
740
5
      BN_CTX_end(ctx);
741
5
      ret = EC_POINT_dbl(group, r, a, ctx);
742
5
      ctx = NULL;
743
5
      goto end;
744
54
    } else {
745
      /* a is the inverse of b */
746
54
      BN_zero(&r->Z);
747
54
      r->Z_is_one = 0;
748
54
      ret = 1;
749
54
      goto end;
750
54
    }
751
59
  }
752
  /* 'n7', 'n8' */
753
1.12M
  if (!BN_mod_add_quick(n1, n1, n3, p))
754
0
    goto end;
755
1.12M
  if (!BN_mod_add_quick(n2, n2, n4, p))
756
0
    goto end;
757
  /* 'n7' = n1 + n3 */
758
  /* 'n8' = n2 + n4 */
759
760
  /* Z_r */
761
1.12M
  if (a->Z_is_one && b->Z_is_one) {
762
50
    if (!BN_copy(&r->Z, n5))
763
0
      goto end;
764
1.12M
  } else {
765
1.12M
    if (a->Z_is_one) {
766
708
      if (!BN_copy(n0, &b->Z))
767
0
        goto end;
768
1.12M
    } else if (b->Z_is_one) {
769
53.7k
      if (!BN_copy(n0, &a->Z))
770
0
        goto end;
771
1.06M
    } else {
772
1.06M
      if (!field_mul(group, n0, &a->Z, &b->Z, ctx))
773
0
        goto end;
774
1.06M
    }
775
1.12M
    if (!field_mul(group, &r->Z, n0, n5, ctx))
776
0
      goto end;
777
1.12M
  }
778
1.12M
  r->Z_is_one = 0;
779
  /* Z_r = Z_a * Z_b * n5 */
780
781
  /* X_r */
782
1.12M
  if (!field_sqr(group, n0, n6, ctx))
783
0
    goto end;
784
1.12M
  if (!field_sqr(group, n4, n5, ctx))
785
0
    goto end;
786
1.12M
  if (!field_mul(group, n3, n1, n4, ctx))
787
0
    goto end;
788
1.12M
  if (!BN_mod_sub_quick(&r->X, n0, n3, p))
789
0
    goto end;
790
  /* X_r = n6^2 - n5^2 * 'n7' */
791
792
  /* 'n9' */
793
1.12M
  if (!BN_mod_lshift1_quick(n0, &r->X, p))
794
0
    goto end;
795
1.12M
  if (!BN_mod_sub_quick(n0, n3, n0, p))
796
0
    goto end;
797
  /* n9 = n5^2 * 'n7' - 2 * X_r */
798
799
  /* Y_r */
800
1.12M
  if (!field_mul(group, n0, n0, n6, ctx))
801
0
    goto end;
802
1.12M
  if (!field_mul(group, n5, n4, n5, ctx))
803
0
    goto end; /* now n5 is n5^3 */
804
1.12M
  if (!field_mul(group, n1, n2, n5, ctx))
805
0
    goto end;
806
1.12M
  if (!BN_mod_sub_quick(n0, n0, n1, p))
807
0
    goto end;
808
1.12M
  if (BN_is_odd(n0))
809
562k
    if (!BN_add(n0, n0, p))
810
0
      goto end;
811
  /* now  0 <= n0 < 2*p,  and n0 is even */
812
1.12M
  if (!BN_rshift1(&r->Y, n0))
813
0
    goto end;
814
  /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
815
816
1.12M
  ret = 1;
817
818
1.12M
 end:
819
1.12M
  if (ctx)    /* otherwise we already called BN_CTX_end */
820
1.12M
    BN_CTX_end(ctx);
821
1.12M
  BN_CTX_free(new_ctx);
822
1.12M
  return ret;
823
1.12M
}
824
825
826
int
827
ec_GFp_simple_dbl(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, BN_CTX * ctx)
828
1.23M
{
829
1.23M
  int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
830
1.23M
  int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
831
1.23M
  const BIGNUM *p;
832
1.23M
  BN_CTX *new_ctx = NULL;
833
1.23M
  BIGNUM *n0, *n1, *n2, *n3;
834
1.23M
  int ret = 0;
835
836
1.23M
  if (EC_POINT_is_at_infinity(group, a) > 0) {
837
90
    BN_zero(&r->Z);
838
90
    r->Z_is_one = 0;
839
90
    return 1;
840
90
  }
841
1.23M
  field_mul = group->meth->field_mul;
842
1.23M
  field_sqr = group->meth->field_sqr;
843
1.23M
  p = &group->field;
844
845
1.23M
  if (ctx == NULL) {
846
7
    ctx = new_ctx = BN_CTX_new();
847
7
    if (ctx == NULL)
848
0
      return 0;
849
7
  }
850
1.23M
  BN_CTX_start(ctx);
851
1.23M
  if ((n0 = BN_CTX_get(ctx)) == NULL)
852
0
    goto err;
853
1.23M
  if ((n1 = BN_CTX_get(ctx)) == NULL)
854
0
    goto err;
855
1.23M
  if ((n2 = BN_CTX_get(ctx)) == NULL)
856
0
    goto err;
857
1.23M
  if ((n3 = BN_CTX_get(ctx)) == NULL)
858
0
    goto err;
859
860
  /*
861
   * Note that in this function we must not read components of 'a' once
862
   * we have written the corresponding components of 'r'. ('r' might
863
   * the same as 'a'.)
864
   */
865
866
  /* n1 */
867
1.23M
  if (a->Z_is_one) {
868
1.04k
    if (!field_sqr(group, n0, &a->X, ctx))
869
0
      goto err;
870
1.04k
    if (!BN_mod_lshift1_quick(n1, n0, p))
871
0
      goto err;
872
1.04k
    if (!BN_mod_add_quick(n0, n0, n1, p))
873
0
      goto err;
874
1.04k
    if (!BN_mod_add_quick(n1, n0, &group->a, p))
875
0
      goto err;
876
    /* n1 = 3 * X_a^2 + a_curve */
877
1.23M
  } else if (group->a_is_minus3) {
878
753k
    if (!field_sqr(group, n1, &a->Z, ctx))
879
0
      goto err;
880
753k
    if (!BN_mod_add_quick(n0, &a->X, n1, p))
881
0
      goto err;
882
753k
    if (!BN_mod_sub_quick(n2, &a->X, n1, p))
883
0
      goto err;
884
753k
    if (!field_mul(group, n1, n0, n2, ctx))
885
0
      goto err;
886
753k
    if (!BN_mod_lshift1_quick(n0, n1, p))
887
0
      goto err;
888
753k
    if (!BN_mod_add_quick(n1, n0, n1, p))
889
0
      goto err;
890
    /*
891
     * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) = 3 * X_a^2 - 3 *
892
     * Z_a^4
893
     */
894
753k
  } else {
895
479k
    if (!field_sqr(group, n0, &a->X, ctx))
896
0
      goto err;
897
479k
    if (!BN_mod_lshift1_quick(n1, n0, p))
898
0
      goto err;
899
479k
    if (!BN_mod_add_quick(n0, n0, n1, p))
900
0
      goto err;
901
479k
    if (!field_sqr(group, n1, &a->Z, ctx))
902
0
      goto err;
903
479k
    if (!field_sqr(group, n1, n1, ctx))
904
0
      goto err;
905
479k
    if (!field_mul(group, n1, n1, &group->a, ctx))
906
0
      goto err;
907
479k
    if (!BN_mod_add_quick(n1, n1, n0, p))
908
0
      goto err;
909
    /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
910
479k
  }
911
912
  /* Z_r */
913
1.23M
  if (a->Z_is_one) {
914
1.04k
    if (!BN_copy(n0, &a->Y))
915
0
      goto err;
916
1.23M
  } else {
917
1.23M
    if (!field_mul(group, n0, &a->Y, &a->Z, ctx))
918
0
      goto err;
919
1.23M
  }
920
1.23M
  if (!BN_mod_lshift1_quick(&r->Z, n0, p))
921
0
    goto err;
922
1.23M
  r->Z_is_one = 0;
923
  /* Z_r = 2 * Y_a * Z_a */
924
925
  /* n2 */
926
1.23M
  if (!field_sqr(group, n3, &a->Y, ctx))
927
0
    goto err;
928
1.23M
  if (!field_mul(group, n2, &a->X, n3, ctx))
929
0
    goto err;
930
1.23M
  if (!BN_mod_lshift_quick(n2, n2, 2, p))
931
0
    goto err;
932
  /* n2 = 4 * X_a * Y_a^2 */
933
934
  /* X_r */
935
1.23M
  if (!BN_mod_lshift1_quick(n0, n2, p))
936
0
    goto err;
937
1.23M
  if (!field_sqr(group, &r->X, n1, ctx))
938
0
    goto err;
939
1.23M
  if (!BN_mod_sub_quick(&r->X, &r->X, n0, p))
940
0
    goto err;
941
  /* X_r = n1^2 - 2 * n2 */
942
943
  /* n3 */
944
1.23M
  if (!field_sqr(group, n0, n3, ctx))
945
0
    goto err;
946
1.23M
  if (!BN_mod_lshift_quick(n3, n0, 3, p))
947
0
    goto err;
948
  /* n3 = 8 * Y_a^4 */
949
950
  /* Y_r */
951
1.23M
  if (!BN_mod_sub_quick(n0, n2, &r->X, p))
952
0
    goto err;
953
1.23M
  if (!field_mul(group, n0, n1, n0, ctx))
954
0
    goto err;
955
1.23M
  if (!BN_mod_sub_quick(&r->Y, n0, n3, p))
956
0
    goto err;
957
  /* Y_r = n1 * (n2 - X_r) - n3 */
958
959
1.23M
  ret = 1;
960
961
1.23M
 err:
962
1.23M
  BN_CTX_end(ctx);
963
1.23M
  BN_CTX_free(new_ctx);
964
1.23M
  return ret;
965
1.23M
}
966
967
968
int
969
ec_GFp_simple_invert(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
970
26.6k
{
971
26.6k
  if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y))
972
    /* point is its own inverse */
973
7
    return 1;
974
975
26.6k
  return BN_usub(&point->Y, &group->field, &point->Y);
976
26.6k
}
977
978
979
int
980
ec_GFp_simple_is_at_infinity(const EC_GROUP * group, const EC_POINT * point)
981
3.51M
{
982
3.51M
  return BN_is_zero(&point->Z);
983
3.51M
}
984
985
986
int
987
ec_GFp_simple_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX * ctx)
988
3.28k
{
989
3.28k
  int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
990
3.28k
  int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
991
3.28k
  const BIGNUM *p;
992
3.28k
  BN_CTX *new_ctx = NULL;
993
3.28k
  BIGNUM *rh, *tmp, *Z4, *Z6;
994
3.28k
  int ret = -1;
995
996
3.28k
  if (EC_POINT_is_at_infinity(group, point) > 0)
997
0
    return 1;
998
999
3.28k
  field_mul = group->meth->field_mul;
1000
3.28k
  field_sqr = group->meth->field_sqr;
1001
3.28k
  p = &group->field;
1002
1003
3.28k
  if (ctx == NULL) {
1004
660
    ctx = new_ctx = BN_CTX_new();
1005
660
    if (ctx == NULL)
1006
0
      return -1;
1007
660
  }
1008
3.28k
  BN_CTX_start(ctx);
1009
3.28k
  if ((rh = BN_CTX_get(ctx)) == NULL)
1010
0
    goto err;
1011
3.28k
  if ((tmp = BN_CTX_get(ctx)) == NULL)
1012
0
    goto err;
1013
3.28k
  if ((Z4 = BN_CTX_get(ctx)) == NULL)
1014
0
    goto err;
1015
3.28k
  if ((Z6 = BN_CTX_get(ctx)) == NULL)
1016
0
    goto err;
1017
1018
  /*
1019
   * We have a curve defined by a Weierstrass equation y^2 = x^3 + a*x
1020
   * + b. The point to consider is given in Jacobian projective
1021
   * coordinates where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
1022
   * Substituting this and multiplying by  Z^6  transforms the above
1023
   * equation into Y^2 = X^3 + a*X*Z^4 + b*Z^6. To test this, we add up
1024
   * the right-hand side in 'rh'.
1025
   */
1026
1027
  /* rh := X^2 */
1028
3.28k
  if (!field_sqr(group, rh, &point->X, ctx))
1029
0
    goto err;
1030
1031
3.28k
  if (!point->Z_is_one) {
1032
0
    if (!field_sqr(group, tmp, &point->Z, ctx))
1033
0
      goto err;
1034
0
    if (!field_sqr(group, Z4, tmp, ctx))
1035
0
      goto err;
1036
0
    if (!field_mul(group, Z6, Z4, tmp, ctx))
1037
0
      goto err;
1038
1039
    /* rh := (rh + a*Z^4)*X */
1040
0
    if (group->a_is_minus3) {
1041
0
      if (!BN_mod_lshift1_quick(tmp, Z4, p))
1042
0
        goto err;
1043
0
      if (!BN_mod_add_quick(tmp, tmp, Z4, p))
1044
0
        goto err;
1045
0
      if (!BN_mod_sub_quick(rh, rh, tmp, p))
1046
0
        goto err;
1047
0
      if (!field_mul(group, rh, rh, &point->X, ctx))
1048
0
        goto err;
1049
0
    } else {
1050
0
      if (!field_mul(group, tmp, Z4, &group->a, ctx))
1051
0
        goto err;
1052
0
      if (!BN_mod_add_quick(rh, rh, tmp, p))
1053
0
        goto err;
1054
0
      if (!field_mul(group, rh, rh, &point->X, ctx))
1055
0
        goto err;
1056
0
    }
1057
1058
    /* rh := rh + b*Z^6 */
1059
0
    if (!field_mul(group, tmp, &group->b, Z6, ctx))
1060
0
      goto err;
1061
0
    if (!BN_mod_add_quick(rh, rh, tmp, p))
1062
0
      goto err;
1063
3.28k
  } else {
1064
    /* point->Z_is_one */
1065
1066
    /* rh := (rh + a)*X */
1067
3.28k
    if (!BN_mod_add_quick(rh, rh, &group->a, p))
1068
0
      goto err;
1069
3.28k
    if (!field_mul(group, rh, rh, &point->X, ctx))
1070
0
      goto err;
1071
    /* rh := rh + b */
1072
3.28k
    if (!BN_mod_add_quick(rh, rh, &group->b, p))
1073
0
      goto err;
1074
3.28k
  }
1075
1076
  /* 'lh' := Y^2 */
1077
3.28k
  if (!field_sqr(group, tmp, &point->Y, ctx))
1078
0
    goto err;
1079
1080
3.28k
  ret = (0 == BN_ucmp(tmp, rh));
1081
1082
3.28k
 err:
1083
3.28k
  BN_CTX_end(ctx);
1084
3.28k
  BN_CTX_free(new_ctx);
1085
3.28k
  return ret;
1086
3.28k
}
1087
1088
1089
int
1090
ec_GFp_simple_cmp(const EC_GROUP * group, const EC_POINT * a, const EC_POINT * b, BN_CTX * ctx)
1091
0
{
1092
  /*
1093
   * return values: -1   error 0   equal (in affine coordinates) 1
1094
   * not equal
1095
   */
1096
1097
0
  int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1098
0
  int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1099
0
  BN_CTX *new_ctx = NULL;
1100
0
  BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1101
0
  const BIGNUM *tmp1_, *tmp2_;
1102
0
  int ret = -1;
1103
1104
0
  if (EC_POINT_is_at_infinity(group, a) > 0) {
1105
0
    return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1;
1106
0
  }
1107
0
  if (EC_POINT_is_at_infinity(group, b) > 0)
1108
0
    return 1;
1109
1110
0
  if (a->Z_is_one && b->Z_is_one) {
1111
0
    return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1112
0
  }
1113
0
  field_mul = group->meth->field_mul;
1114
0
  field_sqr = group->meth->field_sqr;
1115
1116
0
  if (ctx == NULL) {
1117
0
    ctx = new_ctx = BN_CTX_new();
1118
0
    if (ctx == NULL)
1119
0
      return -1;
1120
0
  }
1121
0
  BN_CTX_start(ctx);
1122
0
  if ((tmp1 = BN_CTX_get(ctx)) == NULL)
1123
0
    goto end;
1124
0
  if ((tmp2 = BN_CTX_get(ctx)) == NULL)
1125
0
    goto end;
1126
0
  if ((Za23 = BN_CTX_get(ctx)) == NULL)
1127
0
    goto end;
1128
0
  if ((Zb23 = BN_CTX_get(ctx)) == NULL)
1129
0
    goto end;
1130
1131
  /*
1132
   * We have to decide whether (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2,
1133
   * Y_b/Z_b^3), or equivalently, whether (X_a*Z_b^2, Y_a*Z_b^3) =
1134
   * (X_b*Z_a^2, Y_b*Z_a^3).
1135
   */
1136
1137
0
  if (!b->Z_is_one) {
1138
0
    if (!field_sqr(group, Zb23, &b->Z, ctx))
1139
0
      goto end;
1140
0
    if (!field_mul(group, tmp1, &a->X, Zb23, ctx))
1141
0
      goto end;
1142
0
    tmp1_ = tmp1;
1143
0
  } else
1144
0
    tmp1_ = &a->X;
1145
0
  if (!a->Z_is_one) {
1146
0
    if (!field_sqr(group, Za23, &a->Z, ctx))
1147
0
      goto end;
1148
0
    if (!field_mul(group, tmp2, &b->X, Za23, ctx))
1149
0
      goto end;
1150
0
    tmp2_ = tmp2;
1151
0
  } else
1152
0
    tmp2_ = &b->X;
1153
1154
  /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
1155
0
  if (BN_cmp(tmp1_, tmp2_) != 0) {
1156
0
    ret = 1;  /* points differ */
1157
0
    goto end;
1158
0
  }
1159
0
  if (!b->Z_is_one) {
1160
0
    if (!field_mul(group, Zb23, Zb23, &b->Z, ctx))
1161
0
      goto end;
1162
0
    if (!field_mul(group, tmp1, &a->Y, Zb23, ctx))
1163
0
      goto end;
1164
    /* tmp1_ = tmp1 */
1165
0
  } else
1166
0
    tmp1_ = &a->Y;
1167
0
  if (!a->Z_is_one) {
1168
0
    if (!field_mul(group, Za23, Za23, &a->Z, ctx))
1169
0
      goto end;
1170
0
    if (!field_mul(group, tmp2, &b->Y, Za23, ctx))
1171
0
      goto end;
1172
    /* tmp2_ = tmp2 */
1173
0
  } else
1174
0
    tmp2_ = &b->Y;
1175
1176
  /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
1177
0
  if (BN_cmp(tmp1_, tmp2_) != 0) {
1178
0
    ret = 1;  /* points differ */
1179
0
    goto end;
1180
0
  }
1181
  /* points are equal */
1182
0
  ret = 0;
1183
1184
0
 end:
1185
0
  BN_CTX_end(ctx);
1186
0
  BN_CTX_free(new_ctx);
1187
0
  return ret;
1188
0
}
1189
1190
1191
int
1192
ec_GFp_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
1193
0
{
1194
0
  BN_CTX *new_ctx = NULL;
1195
0
  BIGNUM *x, *y;
1196
0
  int ret = 0;
1197
1198
0
  if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0)
1199
0
    return 1;
1200
1201
0
  if (ctx == NULL) {
1202
0
    ctx = new_ctx = BN_CTX_new();
1203
0
    if (ctx == NULL)
1204
0
      return 0;
1205
0
  }
1206
0
  BN_CTX_start(ctx);
1207
0
  if ((x = BN_CTX_get(ctx)) == NULL)
1208
0
    goto err;
1209
0
  if ((y = BN_CTX_get(ctx)) == NULL)
1210
0
    goto err;
1211
1212
0
  if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
1213
0
    goto err;
1214
0
  if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
1215
0
    goto err;
1216
0
  if (!point->Z_is_one) {
1217
0
    ECerror(ERR_R_INTERNAL_ERROR);
1218
0
    goto err;
1219
0
  }
1220
0
  ret = 1;
1221
1222
0
 err:
1223
0
  BN_CTX_end(ctx);
1224
0
  BN_CTX_free(new_ctx);
1225
0
  return ret;
1226
0
}
1227
1228
1229
int
1230
ec_GFp_simple_points_make_affine(const EC_GROUP * group, size_t num, EC_POINT * points[], BN_CTX * ctx)
1231
379
{
1232
379
  BN_CTX *new_ctx = NULL;
1233
379
  BIGNUM *tmp0, *tmp1;
1234
379
  size_t pow2 = 0;
1235
379
  BIGNUM **heap = NULL;
1236
379
  size_t i;
1237
379
  int ret = 0;
1238
1239
379
  if (num == 0)
1240
0
    return 1;
1241
1242
379
  if (ctx == NULL) {
1243
0
    ctx = new_ctx = BN_CTX_new();
1244
0
    if (ctx == NULL)
1245
0
      return 0;
1246
0
  }
1247
379
  BN_CTX_start(ctx);
1248
379
  if ((tmp0 = BN_CTX_get(ctx)) == NULL)
1249
0
    goto err;
1250
379
  if ((tmp1 = BN_CTX_get(ctx)) == NULL)
1251
0
    goto err;
1252
1253
  /*
1254
   * Before converting the individual points, compute inverses of all Z
1255
   * values. Modular inversion is rather slow, but luckily we can do
1256
   * with a single explicit inversion, plus about 3 multiplications per
1257
   * input value.
1258
   */
1259
1260
379
  pow2 = 1;
1261
1.80k
  while (num > pow2)
1262
1.42k
    pow2 <<= 1;
1263
  /*
1264
   * Now pow2 is the smallest power of 2 satifsying pow2 >= num. We
1265
   * need twice that.
1266
   */
1267
379
  pow2 <<= 1;
1268
1269
379
  heap = reallocarray(NULL, pow2, sizeof heap[0]);
1270
379
  if (heap == NULL)
1271
0
    goto err;
1272
1273
  /*
1274
   * The array is used as a binary tree, exactly as in heapsort:
1275
   *
1276
   * heap[1] heap[2]                     heap[3] heap[4]       heap[5]
1277
   * heap[6]       heap[7] heap[8]heap[9] heap[10]heap[11]
1278
   * heap[12]heap[13] heap[14] heap[15]
1279
   *
1280
   * We put the Z's in the last line; then we set each other node to the
1281
   * product of its two child-nodes (where empty or 0 entries are
1282
   * treated as ones); then we invert heap[1]; then we invert each
1283
   * other node by replacing it by the product of its parent (after
1284
   * inversion) and its sibling (before inversion).
1285
   */
1286
379
  heap[0] = NULL;
1287
5.43k
  for (i = pow2 / 2 - 1; i > 0; i--)
1288
5.05k
    heap[i] = NULL;
1289
5.61k
  for (i = 0; i < num; i++)
1290
5.23k
    heap[pow2 / 2 + i] = &points[i]->Z;
1291
581
  for (i = pow2 / 2 + num; i < pow2; i++)
1292
202
    heap[i] = NULL;
1293
1294
  /* set each node to the product of its children */
1295
5.43k
  for (i = pow2 / 2 - 1; i > 0; i--) {
1296
5.05k
    heap[i] = BN_new();
1297
5.05k
    if (heap[i] == NULL)
1298
0
      goto err;
1299
1300
5.05k
    if (heap[2 * i] != NULL) {
1301
4.97k
      if ((heap[2 * i + 1] == NULL) || BN_is_zero(heap[2 * i + 1])) {
1302
123
        if (!BN_copy(heap[i], heap[2 * i]))
1303
0
          goto err;
1304
4.85k
      } else {
1305
4.85k
        if (BN_is_zero(heap[2 * i])) {
1306
0
          if (!BN_copy(heap[i], heap[2 * i + 1]))
1307
0
            goto err;
1308
4.85k
        } else {
1309
4.85k
          if (!group->meth->field_mul(group, heap[i],
1310
4.85k
            heap[2 * i], heap[2 * i + 1], ctx))
1311
0
            goto err;
1312
4.85k
        }
1313
4.85k
      }
1314
4.97k
    }
1315
5.05k
  }
1316
1317
  /* invert heap[1] */
1318
379
  if (!BN_is_zero(heap[1])) {
1319
379
    if (BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx) == NULL) {
1320
0
      ECerror(ERR_R_BN_LIB);
1321
0
      goto err;
1322
0
    }
1323
379
  }
1324
379
  if (group->meth->field_encode != 0) {
1325
    /*
1326
     * in the Montgomery case, we just turned  R*H  (representing
1327
     * H) into  1/(R*H),  but we need  R*(1/H)  (representing
1328
     * 1/H); i.e. we have need to multiply by the Montgomery
1329
     * factor twice
1330
     */
1331
379
    if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
1332
0
      goto err;
1333
379
    if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
1334
0
      goto err;
1335
379
  }
1336
  /* set other heap[i]'s to their inverses */
1337
5.35k
  for (i = 2; i < pow2 / 2 + num; i += 2) {
1338
    /* i is even */
1339
4.97k
    if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1])) {
1340
4.85k
      if (!group->meth->field_mul(group, tmp0, heap[i / 2], heap[i + 1], ctx))
1341
0
        goto err;
1342
4.85k
      if (!group->meth->field_mul(group, tmp1, heap[i / 2], heap[i], ctx))
1343
0
        goto err;
1344
4.85k
      if (!BN_copy(heap[i], tmp0))
1345
0
        goto err;
1346
4.85k
      if (!BN_copy(heap[i + 1], tmp1))
1347
0
        goto err;
1348
4.85k
    } else {
1349
123
      if (!BN_copy(heap[i], heap[i / 2]))
1350
0
        goto err;
1351
123
    }
1352
4.97k
  }
1353
1354
  /*
1355
   * we have replaced all non-zero Z's by their inverses, now fix up
1356
   * all the points
1357
   */
1358
5.61k
  for (i = 0; i < num; i++) {
1359
5.23k
    EC_POINT *p = points[i];
1360
1361
5.23k
    if (!BN_is_zero(&p->Z)) {
1362
      /* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
1363
1364
5.23k
      if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx))
1365
0
        goto err;
1366
5.23k
      if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx))
1367
0
        goto err;
1368
1369
5.23k
      if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx))
1370
0
        goto err;
1371
5.23k
      if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx))
1372
0
        goto err;
1373
1374
5.23k
      if (group->meth->field_set_to_one != 0) {
1375
5.23k
        if (!group->meth->field_set_to_one(group, &p->Z, ctx))
1376
0
          goto err;
1377
5.23k
      } else {
1378
0
        if (!BN_one(&p->Z))
1379
0
          goto err;
1380
0
      }
1381
5.23k
      p->Z_is_one = 1;
1382
5.23k
    }
1383
5.23k
  }
1384
1385
379
  ret = 1;
1386
1387
379
 err:
1388
379
  BN_CTX_end(ctx);
1389
379
  BN_CTX_free(new_ctx);
1390
379
  if (heap != NULL) {
1391
    /*
1392
     * heap[pow2/2] .. heap[pow2-1] have not been allocated
1393
     * locally!
1394
     */
1395
5.43k
    for (i = pow2 / 2 - 1; i > 0; i--) {
1396
5.05k
      BN_clear_free(heap[i]);
1397
5.05k
    }
1398
379
    free(heap);
1399
379
  }
1400
379
  return ret;
1401
379
}
1402
1403
1404
int
1405
ec_GFp_simple_field_mul(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
1406
0
{
1407
0
  return BN_mod_mul(r, a, b, &group->field, ctx);
1408
0
}
1409
1410
int
1411
ec_GFp_simple_field_sqr(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, BN_CTX * ctx)
1412
0
{
1413
0
  return BN_mod_sqr(r, a, &group->field, ctx);
1414
0
}
1415
1416
/*
1417
 * Apply randomization of EC point projective coordinates:
1418
 *
1419
 *  (X, Y, Z) = (lambda^2 * X, lambda^3 * Y, lambda * Z)
1420
 *
1421
 * where lambda is in the interval [1, group->field).
1422
 */
1423
int
1424
ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
1425
2.31k
{
1426
2.31k
  BIGNUM *lambda = NULL;
1427
2.31k
  BIGNUM *tmp = NULL;
1428
2.31k
  int ret = 0;
1429
1430
2.31k
  BN_CTX_start(ctx);
1431
2.31k
  if ((lambda = BN_CTX_get(ctx)) == NULL)
1432
0
    goto err;
1433
2.31k
  if ((tmp = BN_CTX_get(ctx)) == NULL)
1434
0
    goto err;
1435
1436
  /* Generate lambda in [1, group->field - 1] */
1437
2.31k
  if (!bn_rand_interval(lambda, BN_value_one(), &group->field))
1438
0
    goto err;
1439
1440
2.31k
  if (group->meth->field_encode != NULL &&
1441
2.31k
      !group->meth->field_encode(group, lambda, lambda, ctx))
1442
0
    goto err;
1443
1444
  /* Z = lambda * Z */
1445
2.31k
  if (!group->meth->field_mul(group, &p->Z, lambda, &p->Z, ctx))
1446
0
    goto err;
1447
1448
  /* tmp = lambda^2 */
1449
2.31k
  if (!group->meth->field_sqr(group, tmp, lambda, ctx))
1450
0
    goto err;
1451
1452
  /* X = lambda^2 * X */
1453
2.31k
  if (!group->meth->field_mul(group, &p->X, tmp, &p->X, ctx))
1454
0
    goto err;
1455
1456
  /* tmp = lambda^3 */
1457
2.31k
  if (!group->meth->field_mul(group, tmp, tmp, lambda, ctx))
1458
0
    goto err;
1459
1460
  /* Y = lambda^3 * Y */
1461
2.31k
  if (!group->meth->field_mul(group, &p->Y, tmp, &p->Y, ctx))
1462
0
    goto err;
1463
1464
  /* Disable optimized arithmetics after replacing Z by lambda * Z. */
1465
2.31k
  p->Z_is_one = 0;
1466
1467
2.31k
  ret = 1;
1468
1469
2.31k
 err:
1470
2.31k
  BN_CTX_end(ctx);
1471
2.31k
  return ret;
1472
2.31k
}
1473
1474
1475
5.45k
#define EC_POINT_BN_set_flags(P, flags) do {       \
1476
5.45k
  BN_set_flags(&(P)->X, (flags));               \
1477
5.45k
  BN_set_flags(&(P)->Y, (flags));               \
1478
5.45k
  BN_set_flags(&(P)->Z, (flags));               \
1479
5.45k
} while(0)
1480
1481
1.16M
#define EC_POINT_CSWAP(c, a, b, w, t) do {           \
1482
1.16M
  if (!BN_swap_ct(c, &(a)->X, &(b)->X, w)  ||      \
1483
1.16M
      !BN_swap_ct(c, &(a)->Y, &(b)->Y, w)  ||      \
1484
1.16M
      !BN_swap_ct(c, &(a)->Z, &(b)->Z, w))     \
1485
1.16M
    goto err;           \
1486
1.16M
  t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c);      \
1487
1.16M
  (a)->Z_is_one ^= (t);           \
1488
1.16M
  (b)->Z_is_one ^= (t);           \
1489
1.16M
} while(0)
1490
1491
/*
1492
 * This function computes (in constant time) a point multiplication over the
1493
 * EC group.
1494
 *
1495
 * At a high level, it is Montgomery ladder with conditional swaps.
1496
 *
1497
 * It performs either a fixed point multiplication
1498
 *          (scalar * generator)
1499
 * when point is NULL, or a variable point multiplication
1500
 *          (scalar * point)
1501
 * when point is not NULL.
1502
 *
1503
 * scalar should be in the range [0,n) otherwise all constant time bets are off.
1504
 *
1505
 * NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
1506
 * which of course are not constant time themselves.
1507
 *
1508
 * The product is stored in r.
1509
 *
1510
 * Returns 1 on success, 0 otherwise.
1511
 */
1512
static int
1513
ec_GFp_simple_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1514
    const EC_POINT *point, BN_CTX *ctx)
1515
2.72k
{
1516
2.72k
  int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
1517
2.72k
  EC_POINT *s = NULL;
1518
2.72k
  BIGNUM *k = NULL;
1519
2.72k
  BIGNUM *lambda = NULL;
1520
2.72k
  BIGNUM *cardinality = NULL;
1521
2.72k
  BN_CTX *new_ctx = NULL;
1522
2.72k
  int ret = 0;
1523
1524
2.72k
  if (ctx == NULL && (ctx = new_ctx = BN_CTX_new()) == NULL)
1525
0
    return 0;
1526
1527
2.72k
  BN_CTX_start(ctx);
1528
1529
2.72k
  if ((s = EC_POINT_new(group)) == NULL)
1530
0
    goto err;
1531
1532
2.72k
  if (point == NULL) {
1533
2.69k
    if (!EC_POINT_copy(s, group->generator))
1534
0
      goto err;
1535
2.69k
  } else {
1536
27
    if (!EC_POINT_copy(s, point))
1537
0
      goto err;
1538
27
  }
1539
1540
2.72k
  EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
1541
1542
2.72k
  if ((cardinality = BN_CTX_get(ctx)) == NULL)
1543
0
    goto err;
1544
2.72k
  if ((lambda = BN_CTX_get(ctx)) == NULL)
1545
0
    goto err;
1546
2.72k
  if ((k = BN_CTX_get(ctx)) == NULL)
1547
0
    goto err;
1548
2.72k
  if (!BN_mul(cardinality, &group->order, &group->cofactor, ctx))
1549
0
    goto err;
1550
1551
  /*
1552
   * Group cardinalities are often on a word boundary.
1553
   * So when we pad the scalar, some timing diff might
1554
   * pop if it needs to be expanded due to carries.
1555
   * So expand ahead of time.
1556
   */
1557
2.72k
  cardinality_bits = BN_num_bits(cardinality);
1558
2.72k
  group_top = cardinality->top;
1559
2.72k
  if ((bn_wexpand(k, group_top + 2) == NULL) ||
1560
2.72k
      (bn_wexpand(lambda, group_top + 2) == NULL))
1561
0
    goto err;
1562
1563
2.72k
  if (!BN_copy(k, scalar))
1564
0
    goto err;
1565
1566
2.72k
  BN_set_flags(k, BN_FLG_CONSTTIME);
1567
1568
2.72k
  if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) {
1569
    /*
1570
     * This is an unusual input, and we don't guarantee
1571
     * constant-timeness
1572
     */
1573
434
    if (!BN_nnmod(k, k, cardinality, ctx))
1574
0
      goto err;
1575
434
  }
1576
1577
2.72k
  if (!BN_add(lambda, k, cardinality))
1578
0
    goto err;
1579
2.72k
  BN_set_flags(lambda, BN_FLG_CONSTTIME);
1580
2.72k
  if (!BN_add(k, lambda, cardinality))
1581
0
    goto err;
1582
  /*
1583
   * lambda := scalar + cardinality
1584
   * k := scalar + 2*cardinality
1585
   */
1586
2.72k
  kbit = BN_is_bit_set(lambda, cardinality_bits);
1587
2.72k
  if (!BN_swap_ct(kbit, k, lambda, group_top + 2))
1588
0
    goto err;
1589
1590
2.72k
  group_top = group->field.top;
1591
2.72k
  if ((bn_wexpand(&s->X, group_top) == NULL) ||
1592
2.72k
      (bn_wexpand(&s->Y, group_top) == NULL) ||
1593
2.72k
      (bn_wexpand(&s->Z, group_top) == NULL) ||
1594
2.72k
      (bn_wexpand(&r->X, group_top) == NULL) ||
1595
2.72k
      (bn_wexpand(&r->Y, group_top) == NULL) ||
1596
2.72k
      (bn_wexpand(&r->Z, group_top) == NULL))
1597
0
    goto err;
1598
1599
  /*
1600
   * Apply coordinate blinding for EC_POINT if the underlying EC_METHOD
1601
   * implements it.
1602
   */
1603
2.72k
  if (!ec_point_blind_coordinates(group, s, ctx))
1604
0
    goto err;
1605
1606
  /* top bit is a 1, in a fixed pos */
1607
2.72k
  if (!EC_POINT_copy(r, s))
1608
0
    goto err;
1609
1610
2.72k
  EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
1611
1612
2.72k
  if (!EC_POINT_dbl(group, s, s, ctx))
1613
0
    goto err;
1614
1615
2.72k
  pbit = 0;
1616
1617
  /*
1618
   * The ladder step, with branches, is
1619
   *
1620
   * k[i] == 0: S = add(R, S), R = dbl(R)
1621
   * k[i] == 1: R = add(S, R), S = dbl(S)
1622
   *
1623
   * Swapping R, S conditionally on k[i] leaves you with state
1624
   *
1625
   * k[i] == 0: T, U = R, S
1626
   * k[i] == 1: T, U = S, R
1627
   *
1628
   * Then perform the ECC ops.
1629
   *
1630
   * U = add(T, U)
1631
   * T = dbl(T)
1632
   *
1633
   * Which leaves you with state
1634
   *
1635
   * k[i] == 0: U = add(R, S), T = dbl(R)
1636
   * k[i] == 1: U = add(S, R), T = dbl(S)
1637
   *
1638
   * Swapping T, U conditionally on k[i] leaves you with state
1639
   *
1640
   * k[i] == 0: R, S = T, U
1641
   * k[i] == 1: R, S = U, T
1642
   *
1643
   * Which leaves you with state
1644
   *
1645
   * k[i] == 0: S = add(R, S), R = dbl(R)
1646
   * k[i] == 1: R = add(S, R), S = dbl(S)
1647
   *
1648
   * So we get the same logic, but instead of a branch it's a
1649
   * conditional swap, followed by ECC ops, then another conditional swap.
1650
   *
1651
   * Optimization: The end of iteration i and start of i-1 looks like
1652
   *
1653
   * ...
1654
   * CSWAP(k[i], R, S)
1655
   * ECC
1656
   * CSWAP(k[i], R, S)
1657
   * (next iteration)
1658
   * CSWAP(k[i-1], R, S)
1659
   * ECC
1660
   * CSWAP(k[i-1], R, S)
1661
   * ...
1662
   *
1663
   * So instead of two contiguous swaps, you can merge the condition
1664
   * bits and do a single swap.
1665
   *
1666
   * k[i]   k[i-1]    Outcome
1667
   * 0      0         No Swap
1668
   * 0      1         Swap
1669
   * 1      0         Swap
1670
   * 1      1         No Swap
1671
   *
1672
   * This is XOR. pbit tracks the previous bit of k.
1673
   */
1674
1675
1.16M
  for (i = cardinality_bits - 1; i >= 0; i--) {
1676
1.16M
    kbit = BN_is_bit_set(k, i) ^ pbit;
1677
1.16M
    EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
1678
1.16M
    if (!EC_POINT_add(group, s, r, s, ctx))
1679
0
      goto err;
1680
1.16M
    if (!EC_POINT_dbl(group, r, r, ctx))
1681
0
      goto err;
1682
    /*
1683
     * pbit logic merges this cswap with that of the
1684
     * next iteration
1685
     */
1686
1.16M
    pbit ^= kbit;
1687
1.16M
  }
1688
  /* one final cswap to move the right value into r */
1689
2.72k
  EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
1690
1691
2.72k
  ret = 1;
1692
1693
2.72k
 err:
1694
2.72k
  EC_POINT_free(s);
1695
2.72k
  if (ctx != NULL)
1696
2.72k
    BN_CTX_end(ctx);
1697
2.72k
  BN_CTX_free(new_ctx);
1698
1699
2.72k
  return ret;
1700
2.72k
}
1701
1702
#undef EC_POINT_BN_set_flags
1703
#undef EC_POINT_CSWAP
1704
1705
int
1706
ec_GFp_simple_mul_generator_ct(const EC_GROUP *group, EC_POINT *r,
1707
    const BIGNUM *scalar, BN_CTX *ctx)
1708
2.69k
{
1709
2.69k
  return ec_GFp_simple_mul_ct(group, r, scalar, NULL, ctx);
1710
2.69k
}
1711
1712
int
1713
ec_GFp_simple_mul_single_ct(const EC_GROUP *group, EC_POINT *r,
1714
    const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx)
1715
27
{
1716
27
  return ec_GFp_simple_mul_ct(group, r, scalar, point, ctx);
1717
27
}
1718
1719
int
1720
ec_GFp_simple_mul_double_nonct(const EC_GROUP *group, EC_POINT *r,
1721
    const BIGNUM *g_scalar, const BIGNUM *p_scalar, const EC_POINT *point,
1722
    BN_CTX *ctx)
1723
441
{
1724
441
  return ec_wNAF_mul(group, r, g_scalar, 1, &point, &p_scalar, ctx);
1725
441
}