GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/ec/ec2_smpl.c Lines: 230 379 60.7 %
Date: 2016-12-06 Branches: 123 268 45.9 %

Line Branch Exec Source
1
/* $OpenBSD: ec2_smpl.c,v 1.14 2015/02/09 15:49:22 jsing 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
138
{
81
	static const EC_METHOD ret = {
82
		.flags = EC_FLAGS_DEFAULT_OCT,
83
		.field_type = NID_X9_62_characteristic_two_field,
84
		.group_init = ec_GF2m_simple_group_init,
85
		.group_finish = ec_GF2m_simple_group_finish,
86
		.group_clear_finish = ec_GF2m_simple_group_clear_finish,
87
		.group_copy = ec_GF2m_simple_group_copy,
88
		.group_set_curve = ec_GF2m_simple_group_set_curve,
89
		.group_get_curve = ec_GF2m_simple_group_get_curve,
90
		.group_get_degree = ec_GF2m_simple_group_get_degree,
91
		.group_check_discriminant =
92
		ec_GF2m_simple_group_check_discriminant,
93
		.point_init = ec_GF2m_simple_point_init,
94
		.point_finish = ec_GF2m_simple_point_finish,
95
		.point_clear_finish = ec_GF2m_simple_point_clear_finish,
96
		.point_copy = ec_GF2m_simple_point_copy,
97
		.point_set_to_infinity = ec_GF2m_simple_point_set_to_infinity,
98
		.point_set_affine_coordinates =
99
		ec_GF2m_simple_point_set_affine_coordinates,
100
		.point_get_affine_coordinates =
101
		ec_GF2m_simple_point_get_affine_coordinates,
102
		.add = ec_GF2m_simple_add,
103
		.dbl = ec_GF2m_simple_dbl,
104
		.invert = ec_GF2m_simple_invert,
105
		.is_at_infinity = ec_GF2m_simple_is_at_infinity,
106
		.is_on_curve = ec_GF2m_simple_is_on_curve,
107
		.point_cmp = ec_GF2m_simple_cmp,
108
		.make_affine = ec_GF2m_simple_make_affine,
109
		.points_make_affine = ec_GF2m_simple_points_make_affine,
110
111
		/*
112
		 * the following three method functions are defined in
113
		 * ec2_mult.c
114
		 */
115
		.mul = ec_GF2m_simple_mul,
116
		.precompute_mult = ec_GF2m_precompute_mult,
117
		.have_precompute_mult = ec_GF2m_have_precompute_mult,
118
119
		.field_mul = ec_GF2m_simple_field_mul,
120
		.field_sqr = ec_GF2m_simple_field_sqr,
121
		.field_div = ec_GF2m_simple_field_div,
122
	};
123
124
138
	return &ret;
125
}
126
127
128
/* Initialize a GF(2^m)-based EC_GROUP structure.
129
 * Note that all other members are handled by EC_GROUP_new.
130
 */
131
int
132
ec_GF2m_simple_group_init(EC_GROUP * group)
133
224
{
134
224
	BN_init(&group->field);
135
224
	BN_init(&group->a);
136
224
	BN_init(&group->b);
137
224
	return 1;
138
}
139
140
141
/* Free a GF(2^m)-based EC_GROUP structure.
142
 * Note that all other members are handled by EC_GROUP_free.
143
 */
144
void
145
ec_GF2m_simple_group_finish(EC_GROUP * group)
146
224
{
147
224
	BN_free(&group->field);
148
224
	BN_free(&group->a);
149
224
	BN_free(&group->b);
150
224
}
151
152
153
/* Clear and free a GF(2^m)-based EC_GROUP structure.
154
 * Note that all other members are handled by EC_GROUP_clear_free.
155
 */
156
void
157
ec_GF2m_simple_group_clear_finish(EC_GROUP * group)
158
{
159
	BN_clear_free(&group->field);
160
	BN_clear_free(&group->a);
161
	BN_clear_free(&group->b);
162
	group->poly[0] = 0;
163
	group->poly[1] = 0;
164
	group->poly[2] = 0;
165
	group->poly[3] = 0;
166
	group->poly[4] = 0;
167
	group->poly[5] = -1;
168
}
169
170
171
/* Copy a GF(2^m)-based EC_GROUP structure.
172
 * Note that all other members are handled by EC_GROUP_copy.
173
 */
174
int
175
ec_GF2m_simple_group_copy(EC_GROUP * dest, const EC_GROUP * src)
176
86
{
177
	int i;
178
179
86
	if (!BN_copy(&dest->field, &src->field))
180
		return 0;
181
86
	if (!BN_copy(&dest->a, &src->a))
182
		return 0;
183
86
	if (!BN_copy(&dest->b, &src->b))
184
		return 0;
185
86
	dest->poly[0] = src->poly[0];
186
86
	dest->poly[1] = src->poly[1];
187
86
	dest->poly[2] = src->poly[2];
188
86
	dest->poly[3] = src->poly[3];
189
86
	dest->poly[4] = src->poly[4];
190
86
	dest->poly[5] = src->poly[5];
191

86
	if (bn_wexpand(&dest->a, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
192
		return 0;
193

86
	if (bn_wexpand(&dest->b, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
194
		return 0;
195
276
	for (i = dest->a.top; i < dest->a.dmax; i++)
196
190
		dest->a.d[i] = 0;
197
178
	for (i = dest->b.top; i < dest->b.dmax; i++)
198
92
		dest->b.d[i] = 0;
199
86
	return 1;
200
}
201
202
203
/* Set the curve parameters of an EC_GROUP structure. */
204
int
205
ec_GF2m_simple_group_set_curve(EC_GROUP * group,
206
    const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
207
148
{
208
148
	int ret = 0, i;
209
210
	/* group->field */
211
148
	if (!BN_copy(&group->field, p))
212
		goto err;
213
148
	i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
214
148
	if ((i != 5) && (i != 3)) {
215
		ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
216
		goto err;
217
	}
218
	/* group->a */
219
148
	if (!BN_GF2m_mod_arr(&group->a, a, group->poly))
220
		goto err;
221

148
	if (bn_wexpand(&group->a, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
222
		goto err;
223
513
	for (i = group->a.top; i < group->a.dmax; i++)
224
365
		group->a.d[i] = 0;
225
226
	/* group->b */
227
148
	if (!BN_GF2m_mod_arr(&group->b, b, group->poly))
228
		goto err;
229

148
	if (bn_wexpand(&group->b, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
230
		goto err;
231
324
	for (i = group->b.top; i < group->b.dmax; i++)
232
176
		group->b.d[i] = 0;
233
234
148
	ret = 1;
235
148
err:
236
148
	return ret;
237
}
238
239
240
/* Get the curve parameters of an EC_GROUP structure.
241
 * If p, a, or b are NULL then there values will not be set but the method will return with success.
242
 */
243
int
244
ec_GF2m_simple_group_get_curve(const EC_GROUP *group,
245
    BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
246
1
{
247
1
	int ret = 0;
248
249
1
	if (p != NULL) {
250
1
		if (!BN_copy(p, &group->field))
251
			return 0;
252
	}
253
1
	if (a != NULL) {
254
1
		if (!BN_copy(a, &group->a))
255
			goto err;
256
	}
257
1
	if (b != NULL) {
258
1
		if (!BN_copy(b, &group->b))
259
			goto err;
260
	}
261
1
	ret = 1;
262
263
1
err:
264
1
	return ret;
265
}
266
267
268
/* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
269
int
270
ec_GF2m_simple_group_get_degree(const EC_GROUP * group)
271
73
{
272
73
	return BN_num_bits(&group->field) - 1;
273
}
274
275
276
/* Checks the discriminant of the curve.
277
 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
278
 */
279
int
280
ec_GF2m_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
281
42
{
282
42
	int ret = 0;
283
	BIGNUM *b;
284
42
	BN_CTX *new_ctx = NULL;
285
286
42
	if (ctx == NULL) {
287
		ctx = new_ctx = BN_CTX_new();
288
		if (ctx == NULL) {
289
			ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
290
			goto err;
291
		}
292
	}
293
42
	BN_CTX_start(ctx);
294
42
	if ((b = BN_CTX_get(ctx)) == NULL)
295
		goto err;
296
297
42
	if (!BN_GF2m_mod_arr(b, &group->b, group->poly))
298
		goto err;
299
300
	/*
301
	 * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
302
	 * curve <=> b != 0 (mod p)
303
	 */
304
42
	if (BN_is_zero(b))
305
		goto err;
306
307
42
	ret = 1;
308
309
42
err:
310
42
	if (ctx != NULL)
311
42
		BN_CTX_end(ctx);
312
42
	BN_CTX_free(new_ctx);
313
42
	return ret;
314
}
315
316
317
/* Initializes an EC_POINT. */
318
int
319
ec_GF2m_simple_point_init(EC_POINT * point)
320
5168
{
321
5168
	BN_init(&point->X);
322
5168
	BN_init(&point->Y);
323
5168
	BN_init(&point->Z);
324
5168
	return 1;
325
}
326
327
328
/* Frees an EC_POINT. */
329
void
330
ec_GF2m_simple_point_finish(EC_POINT * point)
331
5076
{
332
5076
	BN_free(&point->X);
333
5076
	BN_free(&point->Y);
334
5076
	BN_free(&point->Z);
335
5076
}
336
337
338
/* Clears and frees an EC_POINT. */
339
void
340
ec_GF2m_simple_point_clear_finish(EC_POINT * point)
341
92
{
342
92
	BN_clear_free(&point->X);
343
92
	BN_clear_free(&point->Y);
344
92
	BN_clear_free(&point->Z);
345
92
	point->Z_is_one = 0;
346
92
}
347
348
349
/* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
350
int
351
ec_GF2m_simple_point_copy(EC_POINT * dest, const EC_POINT * src)
352
1653
{
353
1653
	if (!BN_copy(&dest->X, &src->X))
354
		return 0;
355
1653
	if (!BN_copy(&dest->Y, &src->Y))
356
		return 0;
357
1653
	if (!BN_copy(&dest->Z, &src->Z))
358
		return 0;
359
1653
	dest->Z_is_one = src->Z_is_one;
360
361
1653
	return 1;
362
}
363
364
365
/* Set an EC_POINT to the point at infinity.
366
 * A point at infinity is represented by having Z=0.
367
 */
368
int
369
ec_GF2m_simple_point_set_to_infinity(const EC_GROUP * group, EC_POINT * point)
370
625
{
371
625
	point->Z_is_one = 0;
372
625
	BN_zero(&point->Z);
373
625
	return 1;
374
}
375
376
377
/* Set the coordinates of an EC_POINT using affine coordinates.
378
 * Note that the simple implementation only uses affine coordinates.
379
 */
380
int
381
ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point,
382
    const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx)
383
11742
{
384
11742
	int ret = 0;
385
11742
	if (x == NULL || y == NULL) {
386
		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
387
		return 0;
388
	}
389
11742
	if (!BN_copy(&point->X, x))
390
		goto err;
391
11742
	BN_set_negative(&point->X, 0);
392
11742
	if (!BN_copy(&point->Y, y))
393
		goto err;
394
11742
	BN_set_negative(&point->Y, 0);
395
11742
	if (!BN_copy(&point->Z, BN_value_one()))
396
		goto err;
397
11742
	BN_set_negative(&point->Z, 0);
398
11742
	point->Z_is_one = 1;
399
11742
	ret = 1;
400
401
11742
err:
402
11742
	return ret;
403
}
404
405
406
/* Gets the affine coordinates of an EC_POINT.
407
 * Note that the simple implementation only uses affine coordinates.
408
 */
409
int
410
ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
411
    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
412
250
{
413
250
	int ret = 0;
414
415
250
	if (EC_POINT_is_at_infinity(group, point) > 0) {
416
		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
417
		return 0;
418
	}
419
250
	if (BN_cmp(&point->Z, BN_value_one())) {
420
		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
421
		return 0;
422
	}
423
250
	if (x != NULL) {
424
250
		if (!BN_copy(x, &point->X))
425
			goto err;
426
250
		BN_set_negative(x, 0);
427
	}
428
250
	if (y != NULL) {
429
48
		if (!BN_copy(y, &point->Y))
430
			goto err;
431
48
		BN_set_negative(y, 0);
432
	}
433
250
	ret = 1;
434
435
250
err:
436
250
	return ret;
437
}
438
439
/* Computes a + b and stores the result in r.  r could be a or b, a could be b.
440
 * Uses algorithm A.10.2 of IEEE P1363.
441
 */
442
int
443
ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
444
    const EC_POINT *b, BN_CTX *ctx)
445
12314
{
446
12314
	BN_CTX *new_ctx = NULL;
447
	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
448
12314
	int ret = 0;
449
450
12314
	if (EC_POINT_is_at_infinity(group, a) > 0) {
451
658
		if (!EC_POINT_copy(r, b))
452
			return 0;
453
658
		return 1;
454
	}
455
11656
	if (EC_POINT_is_at_infinity(group, b) > 0) {
456
		if (!EC_POINT_copy(r, a))
457
			return 0;
458
		return 1;
459
	}
460
11656
	if (ctx == NULL) {
461
		ctx = new_ctx = BN_CTX_new();
462
		if (ctx == NULL)
463
			return 0;
464
	}
465
11656
	BN_CTX_start(ctx);
466
11656
	if ((x0 = BN_CTX_get(ctx)) == NULL)
467
		goto err;
468
11656
	if ((y0 = BN_CTX_get(ctx)) == NULL)
469
		goto err;
470
11656
	if ((x1 = BN_CTX_get(ctx)) == NULL)
471
		goto err;
472
11656
	if ((y1 = BN_CTX_get(ctx)) == NULL)
473
		goto err;
474
11656
	if ((x2 = BN_CTX_get(ctx)) == NULL)
475
		goto err;
476
11656
	if ((y2 = BN_CTX_get(ctx)) == NULL)
477
		goto err;
478
11656
	if ((s = BN_CTX_get(ctx)) == NULL)
479
		goto err;
480
11656
	if ((t = BN_CTX_get(ctx)) == NULL)
481
		goto err;
482
483
11656
	if (a->Z_is_one) {
484
11656
		if (!BN_copy(x0, &a->X))
485
			goto err;
486
11656
		if (!BN_copy(y0, &a->Y))
487
			goto err;
488
	} else {
489
		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
490
			goto err;
491
	}
492
11656
	if (b->Z_is_one) {
493
11656
		if (!BN_copy(x1, &b->X))
494
			goto err;
495
11656
		if (!BN_copy(y1, &b->Y))
496
			goto err;
497
	} else {
498
		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
499
			goto err;
500
	}
501
502
503
11656
	if (BN_GF2m_cmp(x0, x1)) {
504
4099
		if (!BN_GF2m_add(t, x0, x1))
505
			goto err;
506
4099
		if (!BN_GF2m_add(s, y0, y1))
507
			goto err;
508
4099
		if (!group->meth->field_div(group, s, s, t, ctx))
509
			goto err;
510
4099
		if (!group->meth->field_sqr(group, x2, s, ctx))
511
			goto err;
512
4099
		if (!BN_GF2m_add(x2, x2, &group->a))
513
			goto err;
514
4099
		if (!BN_GF2m_add(x2, x2, s))
515
			goto err;
516
4099
		if (!BN_GF2m_add(x2, x2, t))
517
			goto err;
518
	} else {
519

7557
		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
520
63
			if (!EC_POINT_set_to_infinity(group, r))
521
				goto err;
522
63
			ret = 1;
523
63
			goto err;
524
		}
525
7494
		if (!group->meth->field_div(group, s, y1, x1, ctx))
526
			goto err;
527
7494
		if (!BN_GF2m_add(s, s, x1))
528
			goto err;
529
530
7494
		if (!group->meth->field_sqr(group, x2, s, ctx))
531
			goto err;
532
7494
		if (!BN_GF2m_add(x2, x2, s))
533
			goto err;
534
7494
		if (!BN_GF2m_add(x2, x2, &group->a))
535
			goto err;
536
	}
537
538
11593
	if (!BN_GF2m_add(y2, x1, x2))
539
		goto err;
540
11593
	if (!group->meth->field_mul(group, y2, y2, s, ctx))
541
		goto err;
542
11593
	if (!BN_GF2m_add(y2, y2, x2))
543
		goto err;
544
11593
	if (!BN_GF2m_add(y2, y2, y1))
545
		goto err;
546
547
11593
	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
548
		goto err;
549
550
11593
	ret = 1;
551
552
11656
err:
553
11656
	BN_CTX_end(ctx);
554
11656
	BN_CTX_free(new_ctx);
555
11656
	return ret;
556
}
557
558
559
/* Computes 2 * a and stores the result in r.  r could be a.
560
 * Uses algorithm A.10.2 of IEEE P1363.
561
 */
562
int
563
ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
564
    BN_CTX *ctx)
565
7655
{
566
7655
	return ec_GF2m_simple_add(group, r, a, a, ctx);
567
}
568
569
int
570
ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
571
514
{
572

514
	if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y))
573
		/* point is its own inverse */
574
48
		return 1;
575
576
466
	if (!EC_POINT_make_affine(group, point, ctx))
577
		return 0;
578
466
	return BN_GF2m_add(&point->Y, &point->X, &point->Y);
579
}
580
581
582
/* Indicates whether the given point is the point at infinity. */
583
int
584
ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
585
25777
{
586
25777
	return BN_is_zero(&point->Z);
587
}
588
589
590
/* Determines whether the given EC_POINT is an actual point on the curve defined
591
 * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
592
 *      y^2 + x*y = x^3 + a*x^2 + b.
593
 */
594
int
595
ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
596
89
{
597
89
	int ret = -1;
598
89
	BN_CTX *new_ctx = NULL;
599
	BIGNUM *lh, *y2;
600
	int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
601
	int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
602
603
89
	if (EC_POINT_is_at_infinity(group, point) > 0)
604
		return 1;
605
606
89
	field_mul = group->meth->field_mul;
607
89
	field_sqr = group->meth->field_sqr;
608
609
	/* only support affine coordinates */
610
89
	if (!point->Z_is_one)
611
		return -1;
612
613
89
	if (ctx == NULL) {
614
		ctx = new_ctx = BN_CTX_new();
615
		if (ctx == NULL)
616
			return -1;
617
	}
618
89
	BN_CTX_start(ctx);
619
89
	if ((y2 = BN_CTX_get(ctx)) == NULL)
620
		goto err;
621
89
	if ((lh = BN_CTX_get(ctx)) == NULL)
622
		goto err;
623
624
	/*
625
	 * We have a curve defined by a Weierstrass equation y^2 + x*y = x^3
626
	 * + a*x^2 + b. <=> x^3 + a*x^2 + x*y + b + y^2 = 0 <=> ((x + a) * x
627
	 * + y ) * x + b + y^2 = 0
628
	 */
629
89
	if (!BN_GF2m_add(lh, &point->X, &group->a))
630
		goto err;
631
89
	if (!field_mul(group, lh, lh, &point->X, ctx))
632
		goto err;
633
89
	if (!BN_GF2m_add(lh, lh, &point->Y))
634
		goto err;
635
89
	if (!field_mul(group, lh, lh, &point->X, ctx))
636
		goto err;
637
89
	if (!BN_GF2m_add(lh, lh, &group->b))
638
		goto err;
639
89
	if (!field_sqr(group, y2, &point->Y, ctx))
640
		goto err;
641
89
	if (!BN_GF2m_add(lh, lh, y2))
642
		goto err;
643
89
	ret = BN_is_zero(lh);
644
89
err:
645
89
	if (ctx)
646
89
		BN_CTX_end(ctx);
647
89
	BN_CTX_free(new_ctx);
648
89
	return ret;
649
}
650
651
652
/* Indicates whether two points are equal.
653
 * Return values:
654
 *  -1   error
655
 *   0   equal (in affine coordinates)
656
 *   1   not equal
657
 */
658
int
659
ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
660
    const EC_POINT *b, BN_CTX *ctx)
661
88
{
662
	BIGNUM *aX, *aY, *bX, *bY;
663
88
	BN_CTX *new_ctx = NULL;
664
88
	int ret = -1;
665
666
88
	if (EC_POINT_is_at_infinity(group, a) > 0) {
667
30
		return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1;
668
	}
669
58
	if (EC_POINT_is_at_infinity(group, b) > 0)
670
		return 1;
671
672

58
	if (a->Z_is_one && b->Z_is_one) {
673

58
		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
674
	}
675
	if (ctx == NULL) {
676
		ctx = new_ctx = BN_CTX_new();
677
		if (ctx == NULL)
678
			return -1;
679
	}
680
	BN_CTX_start(ctx);
681
	if ((aX = BN_CTX_get(ctx)) == NULL)
682
		goto err;
683
	if ((aY = BN_CTX_get(ctx)) == NULL)
684
		goto err;
685
	if ((bX = BN_CTX_get(ctx)) == NULL)
686
		goto err;
687
	if ((bY = BN_CTX_get(ctx)) == NULL)
688
		goto err;
689
690
	if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
691
		goto err;
692
	if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
693
		goto err;
694
	ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
695
696
err:
697
	if (ctx)
698
		BN_CTX_end(ctx);
699
	BN_CTX_free(new_ctx);
700
	return ret;
701
}
702
703
704
/* Forces the given EC_POINT to internally use affine coordinates. */
705
int
706
ec_GF2m_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
707
3918
{
708
3918
	BN_CTX *new_ctx = NULL;
709
	BIGNUM *x, *y;
710
3918
	int ret = 0;
711
712

3918
	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0)
713
3918
		return 1;
714
715
	if (ctx == NULL) {
716
		ctx = new_ctx = BN_CTX_new();
717
		if (ctx == NULL)
718
			return 0;
719
	}
720
	BN_CTX_start(ctx);
721
	if ((x = BN_CTX_get(ctx)) == NULL)
722
		goto err;
723
	if ((y = BN_CTX_get(ctx)) == NULL)
724
		goto err;
725
726
	if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
727
		goto err;
728
	if (!BN_copy(&point->X, x))
729
		goto err;
730
	if (!BN_copy(&point->Y, y))
731
		goto err;
732
	if (!BN_one(&point->Z))
733
		goto err;
734
735
	ret = 1;
736
737
err:
738
	if (ctx)
739
		BN_CTX_end(ctx);
740
	BN_CTX_free(new_ctx);
741
	return ret;
742
}
743
744
745
/* Forces each of the EC_POINTs in the given array to use affine coordinates. */
746
int
747
ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
748
    EC_POINT *points[], BN_CTX *ctx)
749
31
{
750
	size_t i;
751
752
3483
	for (i = 0; i < num; i++) {
753
3452
		if (!group->meth->make_affine(group, points[i], ctx))
754
			return 0;
755
	}
756
757
31
	return 1;
758
}
759
760
761
/* Wrapper to simple binary polynomial field multiplication implementation. */
762
int
763
ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
764
    const BIGNUM *b, BN_CTX *ctx)
765
938291
{
766
938291
	return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
767
}
768
769
770
/* Wrapper to simple binary polynomial field squaring implementation. */
771
int
772
ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
773
    BN_CTX *ctx)
774
781184
{
775
781184
	return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
776
}
777
778
779
/* Wrapper to simple binary polynomial field division implementation. */
780
int
781
ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
782
    const BIGNUM *b, BN_CTX *ctx)
783
12109
{
784
12109
	return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
785
}
786
787
#endif