Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/ec/ec2_smpl.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: ec2_smpl.c,v 1.23 2021/09/08 17:29:21 tb Exp $ */
2
/* ====================================================================
3
 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4
 *
5
 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6
 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7
 * to the OpenSSL project.
8
 *
9
 * The ECC Code is licensed pursuant to the OpenSSL open source
10
 * license provided below.
11
 *
12
 * The software is originally written by Sheueling Chang Shantz and
13
 * Douglas Stebila of Sun Microsystems Laboratories.
14
 *
15
 */
16
/* ====================================================================
17
 * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
18
 *
19
 * Redistribution and use in source and binary forms, with or without
20
 * modification, are permitted provided that the following conditions
21
 * are met:
22
 *
23
 * 1. Redistributions of source code must retain the above copyright
24
 *    notice, this list of conditions and the following disclaimer.
25
 *
26
 * 2. Redistributions in binary form must reproduce the above copyright
27
 *    notice, this list of conditions and the following disclaimer in
28
 *    the documentation and/or other materials provided with the
29
 *    distribution.
30
 *
31
 * 3. All advertising materials mentioning features or use of this
32
 *    software must display the following acknowledgment:
33
 *    "This product includes software developed by the OpenSSL Project
34
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35
 *
36
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37
 *    endorse or promote products derived from this software without
38
 *    prior written permission. For written permission, please contact
39
 *    openssl-core@openssl.org.
40
 *
41
 * 5. Products derived from this software may not be called "OpenSSL"
42
 *    nor may "OpenSSL" appear in their names without prior written
43
 *    permission of the OpenSSL Project.
44
 *
45
 * 6. Redistributions of any form whatsoever must retain the following
46
 *    acknowledgment:
47
 *    "This product includes software developed by the OpenSSL Project
48
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49
 *
50
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61
 * OF THE POSSIBILITY OF SUCH DAMAGE.
62
 * ====================================================================
63
 *
64
 * This product includes cryptographic software written by Eric Young
65
 * (eay@cryptsoft.com).  This product includes software written by Tim
66
 * Hudson (tjh@cryptsoft.com).
67
 *
68
 */
69
70
#include <openssl/opensslconf.h>
71
72
#include <openssl/err.h>
73
74
#include "ec_lcl.h"
75
76
#ifndef OPENSSL_NO_EC2M
77
78
const EC_METHOD *
79
EC_GF2m_simple_method(void)
80
583
{
81
583
  static const EC_METHOD ret = {
82
583
    .flags = EC_FLAGS_DEFAULT_OCT,
83
583
    .field_type = NID_X9_62_characteristic_two_field,
84
583
    .group_init = ec_GF2m_simple_group_init,
85
583
    .group_finish = ec_GF2m_simple_group_finish,
86
583
    .group_clear_finish = ec_GF2m_simple_group_clear_finish,
87
583
    .group_copy = ec_GF2m_simple_group_copy,
88
583
    .group_set_curve = ec_GF2m_simple_group_set_curve,
89
583
    .group_get_curve = ec_GF2m_simple_group_get_curve,
90
583
    .group_get_degree = ec_GF2m_simple_group_get_degree,
91
583
    .group_order_bits = ec_group_simple_order_bits,
92
583
    .group_check_discriminant =
93
583
        ec_GF2m_simple_group_check_discriminant,
94
583
    .point_init = ec_GF2m_simple_point_init,
95
583
    .point_finish = ec_GF2m_simple_point_finish,
96
583
    .point_clear_finish = ec_GF2m_simple_point_clear_finish,
97
583
    .point_copy = ec_GF2m_simple_point_copy,
98
583
    .point_set_to_infinity = ec_GF2m_simple_point_set_to_infinity,
99
583
    .point_set_affine_coordinates =
100
583
        ec_GF2m_simple_point_set_affine_coordinates,
101
583
    .point_get_affine_coordinates =
102
583
        ec_GF2m_simple_point_get_affine_coordinates,
103
583
    .add = ec_GF2m_simple_add,
104
583
    .dbl = ec_GF2m_simple_dbl,
105
583
    .invert = ec_GF2m_simple_invert,
106
583
    .is_at_infinity = ec_GF2m_simple_is_at_infinity,
107
583
    .is_on_curve = ec_GF2m_simple_is_on_curve,
108
583
    .point_cmp = ec_GF2m_simple_cmp,
109
583
    .make_affine = ec_GF2m_simple_make_affine,
110
583
    .points_make_affine = ec_GF2m_simple_points_make_affine,
111
583
    .mul_generator_ct = ec_GFp_simple_mul_generator_ct,
112
583
    .mul_single_ct = ec_GFp_simple_mul_single_ct,
113
583
    .mul_double_nonct = ec_GFp_simple_mul_double_nonct,
114
583
    .precompute_mult = ec_GF2m_precompute_mult,
115
583
    .have_precompute_mult = ec_GF2m_have_precompute_mult,
116
583
    .field_mul = ec_GF2m_simple_field_mul,
117
583
    .field_sqr = ec_GF2m_simple_field_sqr,
118
583
    .field_div = ec_GF2m_simple_field_div,
119
583
    .blind_coordinates = NULL,
120
583
  };
121
122
583
  return &ret;
123
583
}
124
125
126
/* Initialize a GF(2^m)-based EC_GROUP structure.
127
 * Note that all other members are handled by EC_GROUP_new.
128
 */
129
int 
130
ec_GF2m_simple_group_init(EC_GROUP * group)
131
1.22k
{
132
1.22k
  BN_init(&group->field);
133
1.22k
  BN_init(&group->a);
134
1.22k
  BN_init(&group->b);
135
1.22k
  return 1;
136
1.22k
}
137
138
139
/* Free a GF(2^m)-based EC_GROUP structure.
140
 * Note that all other members are handled by EC_GROUP_free.
141
 */
142
void 
143
ec_GF2m_simple_group_finish(EC_GROUP * group)
144
1.22k
{
145
1.22k
  BN_free(&group->field);
146
1.22k
  BN_free(&group->a);
147
1.22k
  BN_free(&group->b);
148
1.22k
}
149
150
151
/* Clear and free a GF(2^m)-based EC_GROUP structure.
152
 * Note that all other members are handled by EC_GROUP_clear_free.
153
 */
154
void 
155
ec_GF2m_simple_group_clear_finish(EC_GROUP * group)
156
0
{
157
0
  BN_clear_free(&group->field);
158
0
  BN_clear_free(&group->a);
159
0
  BN_clear_free(&group->b);
160
0
  group->poly[0] = 0;
161
0
  group->poly[1] = 0;
162
0
  group->poly[2] = 0;
163
0
  group->poly[3] = 0;
164
0
  group->poly[4] = 0;
165
0
  group->poly[5] = -1;
166
0
}
167
168
169
/* Copy a GF(2^m)-based EC_GROUP structure.
170
 * Note that all other members are handled by EC_GROUP_copy.
171
 */
172
int 
173
ec_GF2m_simple_group_copy(EC_GROUP * dest, const EC_GROUP * src)
174
645
{
175
645
  int i;
176
177
645
  if (!BN_copy(&dest->field, &src->field))
178
0
    return 0;
179
645
  if (!BN_copy(&dest->a, &src->a))
180
0
    return 0;
181
645
  if (!BN_copy(&dest->b, &src->b))
182
0
    return 0;
183
645
  dest->poly[0] = src->poly[0];
184
645
  dest->poly[1] = src->poly[1];
185
645
  dest->poly[2] = src->poly[2];
186
645
  dest->poly[3] = src->poly[3];
187
645
  dest->poly[4] = src->poly[4];
188
645
  dest->poly[5] = src->poly[5];
189
645
  if (bn_wexpand(&dest->a, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
190
0
    return 0;
191
645
  if (bn_wexpand(&dest->b, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
192
0
    return 0;
193
3.32k
  for (i = dest->a.top; i < dest->a.dmax; i++)
194
2.67k
    dest->a.d[i] = 0;
195
2.08k
  for (i = dest->b.top; i < dest->b.dmax; i++)
196
1.44k
    dest->b.d[i] = 0;
197
645
  return 1;
198
645
}
199
200
201
/* Set the curve parameters of an EC_GROUP structure. */
202
int 
203
ec_GF2m_simple_group_set_curve(EC_GROUP * group,
204
    const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
205
583
{
206
583
  int ret = 0, i;
207
208
  /* group->field */
209
583
  if (!BN_copy(&group->field, p))
210
0
    goto err;
211
583
  i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
212
583
  if ((i != 5) && (i != 3)) {
213
0
    ECerror(EC_R_UNSUPPORTED_FIELD);
214
0
    goto err;
215
0
  }
216
  /* group->a */
217
583
  if (!BN_GF2m_mod_arr(&group->a, a, group->poly))
218
0
    goto err;
219
583
  if (bn_wexpand(&group->a, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
220
0
    goto err;
221
2.50k
  for (i = group->a.top; i < group->a.dmax; i++)
222
1.92k
    group->a.d[i] = 0;
223
224
  /* group->b */
225
583
  if (!BN_GF2m_mod_arr(&group->b, b, group->poly))
226
0
    goto err;
227
583
  if (bn_wexpand(&group->b, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
228
0
    goto err;
229
1.75k
  for (i = group->b.top; i < group->b.dmax; i++)
230
1.17k
    group->b.d[i] = 0;
231
232
583
  ret = 1;
233
583
 err:
234
583
  return ret;
235
583
}
236
237
238
/* Get the curve parameters of an EC_GROUP structure.
239
 * If p, a, or b are NULL then there values will not be set but the method will return with success.
240
 */
241
int 
242
ec_GF2m_simple_group_get_curve(const EC_GROUP *group,
243
    BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
244
0
{
245
0
  int ret = 0;
246
247
0
  if (p != NULL) {
248
0
    if (!BN_copy(p, &group->field))
249
0
      return 0;
250
0
  }
251
0
  if (a != NULL) {
252
0
    if (!BN_copy(a, &group->a))
253
0
      goto err;
254
0
  }
255
0
  if (b != NULL) {
256
0
    if (!BN_copy(b, &group->b))
257
0
      goto err;
258
0
  }
259
0
  ret = 1;
260
261
0
 err:
262
0
  return ret;
263
0
}
264
265
266
/* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
267
int 
268
ec_GF2m_simple_group_get_degree(const EC_GROUP * group)
269
0
{
270
0
  return BN_num_bits(&group->field) - 1;
271
0
}
272
273
274
/* Checks the discriminant of the curve.
275
 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
276
 */
277
int 
278
ec_GF2m_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
279
0
{
280
0
  int ret = 0;
281
0
  BIGNUM *b;
282
0
  BN_CTX *new_ctx = NULL;
283
284
0
  if (ctx == NULL) {
285
0
    ctx = new_ctx = BN_CTX_new();
286
0
    if (ctx == NULL) {
287
0
      ECerror(ERR_R_MALLOC_FAILURE);
288
0
      goto err;
289
0
    }
290
0
  }
291
0
  BN_CTX_start(ctx);
292
0
  if ((b = BN_CTX_get(ctx)) == NULL)
293
0
    goto err;
294
295
0
  if (!BN_GF2m_mod_arr(b, &group->b, group->poly))
296
0
    goto err;
297
298
  /*
299
   * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
300
   * curve <=> b != 0 (mod p)
301
   */
302
0
  if (BN_is_zero(b))
303
0
    goto err;
304
305
0
  ret = 1;
306
307
0
 err:
308
0
  if (ctx != NULL)
309
0
    BN_CTX_end(ctx);
310
0
  BN_CTX_free(new_ctx);
311
0
  return ret;
312
0
}
313
314
315
/* Initializes an EC_POINT. */
316
int 
317
ec_GF2m_simple_point_init(EC_POINT * point)
318
4.72k
{
319
4.72k
  BN_init(&point->X);
320
4.72k
  BN_init(&point->Y);
321
4.72k
  BN_init(&point->Z);
322
4.72k
  return 1;
323
4.72k
}
324
325
326
/* Frees an EC_POINT. */
327
void 
328
ec_GF2m_simple_point_finish(EC_POINT * point)
329
4.18k
{
330
4.18k
  BN_free(&point->X);
331
4.18k
  BN_free(&point->Y);
332
4.18k
  BN_free(&point->Z);
333
4.18k
}
334
335
336
/* Clears and frees an EC_POINT. */
337
void 
338
ec_GF2m_simple_point_clear_finish(EC_POINT * point)
339
545
{
340
545
  BN_clear_free(&point->X);
341
545
  BN_clear_free(&point->Y);
342
545
  BN_clear_free(&point->Z);
343
545
  point->Z_is_one = 0;
344
545
}
345
346
347
/* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
348
int 
349
ec_GF2m_simple_point_copy(EC_POINT * dest, const EC_POINT * src)
350
5.66k
{
351
5.66k
  if (!BN_copy(&dest->X, &src->X))
352
0
    return 0;
353
5.66k
  if (!BN_copy(&dest->Y, &src->Y))
354
0
    return 0;
355
5.66k
  if (!BN_copy(&dest->Z, &src->Z))
356
0
    return 0;
357
5.66k
  dest->Z_is_one = src->Z_is_one;
358
359
5.66k
  return 1;
360
5.66k
}
361
362
363
/* Set an EC_POINT to the point at infinity.
364
 * A point at infinity is represented by having Z=0.
365
 */
366
int 
367
ec_GF2m_simple_point_set_to_infinity(const EC_GROUP * group, EC_POINT * point)
368
2.32k
{
369
2.32k
  point->Z_is_one = 0;
370
2.32k
  BN_zero(&point->Z);
371
2.32k
  return 1;
372
2.32k
}
373
374
375
/* Set the coordinates of an EC_POINT using affine coordinates.
376
 * Note that the simple implementation only uses affine coordinates.
377
 */
378
int 
379
ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point,
380
    const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx)
381
202k
{
382
202k
  int ret = 0;
383
202k
  if (x == NULL || y == NULL) {
384
0
    ECerror(ERR_R_PASSED_NULL_PARAMETER);
385
0
    return 0;
386
0
  }
387
202k
  if (!BN_copy(&point->X, x))
388
0
    goto err;
389
202k
  BN_set_negative(&point->X, 0);
390
202k
  if (!BN_copy(&point->Y, y))
391
0
    goto err;
392
202k
  BN_set_negative(&point->Y, 0);
393
202k
  if (!BN_copy(&point->Z, BN_value_one()))
394
0
    goto err;
395
202k
  BN_set_negative(&point->Z, 0);
396
202k
  point->Z_is_one = 1;
397
202k
  ret = 1;
398
399
202k
 err:
400
202k
  return ret;
401
202k
}
402
403
404
/* Gets the affine coordinates of an EC_POINT.
405
 * Note that the simple implementation only uses affine coordinates.
406
 */
407
int 
408
ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
409
    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
410
412
{
411
412
  int ret = 0;
412
413
412
  if (EC_POINT_is_at_infinity(group, point) > 0) {
414
36
    ECerror(EC_R_POINT_AT_INFINITY);
415
36
    return 0;
416
36
  }
417
376
  if (BN_cmp(&point->Z, BN_value_one())) {
418
0
    ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
419
0
    return 0;
420
0
  }
421
376
  if (x != NULL) {
422
376
    if (!BN_copy(x, &point->X))
423
0
      goto err;
424
376
    BN_set_negative(x, 0);
425
376
  }
426
376
  if (y != NULL) {
427
270
    if (!BN_copy(y, &point->Y))
428
0
      goto err;
429
270
    BN_set_negative(y, 0);
430
270
  }
431
376
  ret = 1;
432
433
376
 err:
434
376
  return ret;
435
376
}
436
437
/* Computes a + b and stores the result in r.  r could be a or b, a could be b.
438
 * Uses algorithm A.10.2 of IEEE P1363.
439
 */
440
int 
441
ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
442
    const EC_POINT *b, BN_CTX *ctx)
443
214k
{
444
214k
  BN_CTX *new_ctx = NULL;
445
214k
  BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
446
214k
  int ret = 0;
447
448
214k
  if (EC_POINT_is_at_infinity(group, a) > 0) {
449
9.04k
    if (!EC_POINT_copy(r, b))
450
0
      return 0;
451
9.04k
    return 1;
452
9.04k
  }
453
205k
  if (EC_POINT_is_at_infinity(group, b) > 0) {
454
1.36k
    if (!EC_POINT_copy(r, a))
455
0
      return 0;
456
1.36k
    return 1;
457
1.36k
  }
458
204k
  if (ctx == NULL) {
459
23
    ctx = new_ctx = BN_CTX_new();
460
23
    if (ctx == NULL)
461
0
      return 0;
462
23
  }
463
204k
  BN_CTX_start(ctx);
464
204k
  if ((x0 = BN_CTX_get(ctx)) == NULL)
465
0
    goto err;
466
204k
  if ((y0 = BN_CTX_get(ctx)) == NULL)
467
0
    goto err;
468
204k
  if ((x1 = BN_CTX_get(ctx)) == NULL)
469
0
    goto err;
470
204k
  if ((y1 = BN_CTX_get(ctx)) == NULL)
471
0
    goto err;
472
204k
  if ((x2 = BN_CTX_get(ctx)) == NULL)
473
0
    goto err;
474
204k
  if ((y2 = BN_CTX_get(ctx)) == NULL)
475
0
    goto err;
476
204k
  if ((s = BN_CTX_get(ctx)) == NULL)
477
0
    goto err;
478
204k
  if ((t = BN_CTX_get(ctx)) == NULL)
479
0
    goto err;
480
481
204k
  if (a->Z_is_one) {
482
204k
    if (!BN_copy(x0, &a->X))
483
0
      goto err;
484
204k
    if (!BN_copy(y0, &a->Y))
485
0
      goto err;
486
204k
  } else {
487
0
    if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx))
488
0
      goto err;
489
0
  }
490
204k
  if (b->Z_is_one) {
491
204k
    if (!BN_copy(x1, &b->X))
492
0
      goto err;
493
204k
    if (!BN_copy(y1, &b->Y))
494
0
      goto err;
495
204k
  } else {
496
0
    if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx))
497
0
      goto err;
498
0
  }
499
500
501
204k
  if (BN_GF2m_cmp(x0, x1)) {
502
96.1k
    if (!BN_GF2m_add(t, x0, x1))
503
0
      goto err;
504
96.1k
    if (!BN_GF2m_add(s, y0, y1))
505
0
      goto err;
506
96.1k
    if (!group->meth->field_div(group, s, s, t, ctx))
507
0
      goto err;
508
96.1k
    if (!group->meth->field_sqr(group, x2, s, ctx))
509
0
      goto err;
510
96.1k
    if (!BN_GF2m_add(x2, x2, &group->a))
511
0
      goto err;
512
96.1k
    if (!BN_GF2m_add(x2, x2, s))
513
0
      goto err;
514
96.1k
    if (!BN_GF2m_add(x2, x2, t))
515
0
      goto err;
516
107k
  } else {
517
107k
    if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
518
2.32k
      if (!EC_POINT_set_to_infinity(group, r))
519
0
        goto err;
520
2.32k
      ret = 1;
521
2.32k
      goto err;
522
2.32k
    }
523
105k
    if (!group->meth->field_div(group, s, y1, x1, ctx))
524
0
      goto err;
525
105k
    if (!BN_GF2m_add(s, s, x1))
526
0
      goto err;
527
528
105k
    if (!group->meth->field_sqr(group, x2, s, ctx))
529
0
      goto err;
530
105k
    if (!BN_GF2m_add(x2, x2, s))
531
0
      goto err;
532
105k
    if (!BN_GF2m_add(x2, x2, &group->a))
533
0
      goto err;
534
105k
  }
535
536
201k
  if (!BN_GF2m_add(y2, x1, x2))
537
0
    goto err;
538
201k
  if (!group->meth->field_mul(group, y2, y2, s, ctx))
539
0
    goto err;
540
201k
  if (!BN_GF2m_add(y2, y2, x2))
541
0
    goto err;
542
201k
  if (!BN_GF2m_add(y2, y2, y1))
543
0
    goto err;
544
545
201k
  if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx))
546
0
    goto err;
547
548
201k
  ret = 1;
549
550
204k
 err:
551
204k
  BN_CTX_end(ctx);
552
204k
  BN_CTX_free(new_ctx);
553
204k
  return ret;
554
201k
}
555
556
557
/* Computes 2 * a and stores the result in r.  r could be a.
558
 * Uses algorithm A.10.2 of IEEE P1363.
559
 */
560
int 
561
ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
562
    BN_CTX *ctx)
563
113k
{
564
113k
  return ec_GF2m_simple_add(group, r, a, a, ctx);
565
113k
}
566
567
int 
568
ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
569
2.76k
{
570
2.76k
  if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y))
571
    /* point is its own inverse */
572
632
    return 1;
573
574
2.13k
  if (!EC_POINT_make_affine(group, point, ctx))
575
0
    return 0;
576
2.13k
  return BN_GF2m_add(&point->Y, &point->X, &point->Y);
577
2.13k
}
578
579
580
/* Indicates whether the given point is the point at infinity. */
581
int 
582
ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
583
625k
{
584
625k
  return BN_is_zero(&point->Z);
585
625k
}
586
587
588
/* Determines whether the given EC_POINT is an actual point on the curve defined
589
 * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
590
 *      y^2 + x*y = x^3 + a*x^2 + b.
591
 */
592
int 
593
ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
594
202k
{
595
202k
  int ret = -1;
596
202k
  BN_CTX *new_ctx = NULL;
597
202k
  BIGNUM *lh, *y2;
598
202k
  int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
599
202k
  int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
600
601
202k
  if (EC_POINT_is_at_infinity(group, point) > 0)
602
0
    return 1;
603
604
202k
  field_mul = group->meth->field_mul;
605
202k
  field_sqr = group->meth->field_sqr;
606
607
  /* only support affine coordinates */
608
202k
  if (!point->Z_is_one)
609
0
    return -1;
610
611
202k
  if (ctx == NULL) {
612
266
    ctx = new_ctx = BN_CTX_new();
613
266
    if (ctx == NULL)
614
0
      return -1;
615
266
  }
616
202k
  BN_CTX_start(ctx);
617
202k
  if ((y2 = BN_CTX_get(ctx)) == NULL)
618
0
    goto err;
619
202k
  if ((lh = BN_CTX_get(ctx)) == NULL)
620
0
    goto err;
621
622
  /*
623
   * We have a curve defined by a Weierstrass equation y^2 + x*y = x^3
624
   * + a*x^2 + b. <=> x^3 + a*x^2 + x*y + b + y^2 = 0 <=> ((x + a) * x
625
   * + y ) * x + b + y^2 = 0
626
   */
627
202k
  if (!BN_GF2m_add(lh, &point->X, &group->a))
628
0
    goto err;
629
202k
  if (!field_mul(group, lh, lh, &point->X, ctx))
630
0
    goto err;
631
202k
  if (!BN_GF2m_add(lh, lh, &point->Y))
632
0
    goto err;
633
202k
  if (!field_mul(group, lh, lh, &point->X, ctx))
634
0
    goto err;
635
202k
  if (!BN_GF2m_add(lh, lh, &group->b))
636
0
    goto err;
637
202k
  if (!field_sqr(group, y2, &point->Y, ctx))
638
0
    goto err;
639
202k
  if (!BN_GF2m_add(lh, lh, y2))
640
0
    goto err;
641
202k
  ret = BN_is_zero(lh);
642
202k
 err:
643
202k
  if (ctx)
644
202k
    BN_CTX_end(ctx);
645
202k
  BN_CTX_free(new_ctx);
646
202k
  return ret;
647
202k
}
648
649
650
/* Indicates whether two points are equal.
651
 * Return values:
652
 *  -1   error
653
 *   0   equal (in affine coordinates)
654
 *   1   not equal
655
 */
656
int 
657
ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
658
    const EC_POINT *b, BN_CTX *ctx)
659
0
{
660
0
  BIGNUM *aX, *aY, *bX, *bY;
661
0
  BN_CTX *new_ctx = NULL;
662
0
  int ret = -1;
663
664
0
  if (EC_POINT_is_at_infinity(group, a) > 0) {
665
0
    return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1;
666
0
  }
667
0
  if (EC_POINT_is_at_infinity(group, b) > 0)
668
0
    return 1;
669
670
0
  if (a->Z_is_one && b->Z_is_one) {
671
0
    return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
672
0
  }
673
0
  if (ctx == NULL) {
674
0
    ctx = new_ctx = BN_CTX_new();
675
0
    if (ctx == NULL)
676
0
      return -1;
677
0
  }
678
0
  BN_CTX_start(ctx);
679
0
  if ((aX = BN_CTX_get(ctx)) == NULL)
680
0
    goto err;
681
0
  if ((aY = BN_CTX_get(ctx)) == NULL)
682
0
    goto err;
683
0
  if ((bX = BN_CTX_get(ctx)) == NULL)
684
0
    goto err;
685
0
  if ((bY = BN_CTX_get(ctx)) == NULL)
686
0
    goto err;
687
688
0
  if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx))
689
0
    goto err;
690
0
  if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx))
691
0
    goto err;
692
0
  ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
693
694
0
 err:
695
0
  if (ctx)
696
0
    BN_CTX_end(ctx);
697
0
  BN_CTX_free(new_ctx);
698
0
  return ret;
699
0
}
700
701
702
/* Forces the given EC_POINT to internally use affine coordinates. */
703
int 
704
ec_GF2m_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
705
2.67k
{
706
2.67k
  BN_CTX *new_ctx = NULL;
707
2.67k
  BIGNUM *x, *y;
708
2.67k
  int ret = 0;
709
710
2.67k
  if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0)
711
2.67k
    return 1;
712
713
0
  if (ctx == NULL) {
714
0
    ctx = new_ctx = BN_CTX_new();
715
0
    if (ctx == NULL)
716
0
      return 0;
717
0
  }
718
0
  BN_CTX_start(ctx);
719
0
  if ((x = BN_CTX_get(ctx)) == NULL)
720
0
    goto err;
721
0
  if ((y = BN_CTX_get(ctx)) == NULL)
722
0
    goto err;
723
724
0
  if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
725
0
    goto err;
726
0
  if (!BN_copy(&point->X, x))
727
0
    goto err;
728
0
  if (!BN_copy(&point->Y, y))
729
0
    goto err;
730
0
  if (!BN_one(&point->Z))
731
0
    goto err;
732
733
0
  ret = 1;
734
735
0
 err:
736
0
  if (ctx)
737
0
    BN_CTX_end(ctx);
738
0
  BN_CTX_free(new_ctx);
739
0
  return ret;
740
0
}
741
742
743
/* Forces each of the EC_POINTs in the given array to use affine coordinates. */
744
int 
745
ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
746
    EC_POINT *points[], BN_CTX *ctx)
747
62
{
748
62
  size_t i;
749
750
607
  for (i = 0; i < num; i++) {
751
545
    if (!group->meth->make_affine(group, points[i], ctx))
752
0
      return 0;
753
545
  }
754
755
62
  return 1;
756
62
}
757
758
759
/* Wrapper to simple binary polynomial field multiplication implementation. */
760
int 
761
ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
762
    const BIGNUM *b, BN_CTX *ctx)
763
607k
{
764
607k
  return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
765
607k
}
766
767
768
/* Wrapper to simple binary polynomial field squaring implementation. */
769
int 
770
ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
771
    BN_CTX *ctx)
772
404k
{
773
404k
  return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
774
404k
}
775
776
777
/* Wrapper to simple binary polynomial field division implementation. */
778
int 
779
ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
780
    const BIGNUM *b, BN_CTX *ctx)
781
201k
{
782
201k
  return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
783
201k
}
784
785
#endif