]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec2_smpl.c
[test] test some important ladder corner cases
[thirdparty/openssl.git] / crypto / ec / ec2_smpl.c
CommitLineData
4f22f405 1/*
83cf7abf 2 * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
aa8f3d76 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4f22f405
RS
4 *
5 * Licensed under the OpenSSL license (the "License"). You may not use
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
9 */
10
7793f30e
BM
11#include <openssl/err.h>
12
5784a521 13#include "internal/bn_int.h"
7793f30e
BM
14#include "ec_lcl.h"
15
b3310161
DSH
16#ifndef OPENSSL_NO_EC2M
17
7793f30e 18const EC_METHOD *EC_GF2m_simple_method(void)
0f113f3e
MC
19{
20 static const EC_METHOD ret = {
21 EC_FLAGS_DEFAULT_OCT,
22 NID_X9_62_characteristic_two_field,
23 ec_GF2m_simple_group_init,
24 ec_GF2m_simple_group_finish,
25 ec_GF2m_simple_group_clear_finish,
26 ec_GF2m_simple_group_copy,
27 ec_GF2m_simple_group_set_curve,
28 ec_GF2m_simple_group_get_curve,
29 ec_GF2m_simple_group_get_degree,
9ff9bccc 30 ec_group_simple_order_bits,
0f113f3e
MC
31 ec_GF2m_simple_group_check_discriminant,
32 ec_GF2m_simple_point_init,
33 ec_GF2m_simple_point_finish,
34 ec_GF2m_simple_point_clear_finish,
35 ec_GF2m_simple_point_copy,
36 ec_GF2m_simple_point_set_to_infinity,
37 0 /* set_Jprojective_coordinates_GFp */ ,
38 0 /* get_Jprojective_coordinates_GFp */ ,
39 ec_GF2m_simple_point_set_affine_coordinates,
40 ec_GF2m_simple_point_get_affine_coordinates,
41 0, 0, 0,
42 ec_GF2m_simple_add,
43 ec_GF2m_simple_dbl,
44 ec_GF2m_simple_invert,
45 ec_GF2m_simple_is_at_infinity,
46 ec_GF2m_simple_is_on_curve,
47 ec_GF2m_simple_cmp,
48 ec_GF2m_simple_make_affine,
49 ec_GF2m_simple_points_make_affine,
a7b0b69c
BB
50 0 /* mul */,
51 0 /* precompute_mul */,
52 0 /* have_precompute_mul */,
0f113f3e
MC
53 ec_GF2m_simple_field_mul,
54 ec_GF2m_simple_field_sqr,
55 ec_GF2m_simple_field_div,
56 0 /* field_encode */ ,
57 0 /* field_decode */ ,
9ff9bccc
DSH
58 0, /* field_set_to_one */
59 ec_key_simple_priv2oct,
60 ec_key_simple_oct2priv,
61 0, /* set private */
62 ec_key_simple_generate_key,
63 ec_key_simple_check_key,
64 ec_key_simple_generate_public_key,
65 0, /* keycopy */
66 0, /* keyfinish */
f667820c
SH
67 ecdh_simple_compute_key,
68 0, /* field_inverse_mod_ord */
37124360
NT
69 0, /* blind_coordinates */
70 0, /* ladder_pre */
71 0, /* ladder_step */
72 0 /* ladder_post */
0f113f3e
MC
73 };
74
75 return &ret;
76}
77
78/*
79 * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
80 * are handled by EC_GROUP_new.
7793f30e
BM
81 */
82int ec_GF2m_simple_group_init(EC_GROUP *group)
0f113f3e
MC
83{
84 group->field = BN_new();
85 group->a = BN_new();
86 group->b = BN_new();
87
90945fa3 88 if (group->field == NULL || group->a == NULL || group->b == NULL) {
23a1d5e9
RS
89 BN_free(group->field);
90 BN_free(group->a);
91 BN_free(group->b);
0f113f3e
MC
92 return 0;
93 }
94 return 1;
95}
96
97/*
98 * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
99 * handled by EC_GROUP_free.
7793f30e
BM
100 */
101void ec_GF2m_simple_group_finish(EC_GROUP *group)
0f113f3e
MC
102{
103 BN_free(group->field);
104 BN_free(group->a);
105 BN_free(group->b);
106}
107
108/*
109 * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
110 * members are handled by EC_GROUP_clear_free.
7793f30e
BM
111 */
112void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
0f113f3e
MC
113{
114 BN_clear_free(group->field);
115 BN_clear_free(group->a);
116 BN_clear_free(group->b);
117 group->poly[0] = 0;
118 group->poly[1] = 0;
119 group->poly[2] = 0;
120 group->poly[3] = 0;
121 group->poly[4] = 0;
122 group->poly[5] = -1;
123}
124
125/*
126 * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
127 * handled by EC_GROUP_copy.
7793f30e
BM
128 */
129int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
0f113f3e
MC
130{
131 if (!BN_copy(dest->field, src->field))
132 return 0;
133 if (!BN_copy(dest->a, src->a))
134 return 0;
135 if (!BN_copy(dest->b, src->b))
136 return 0;
137 dest->poly[0] = src->poly[0];
138 dest->poly[1] = src->poly[1];
139 dest->poly[2] = src->poly[2];
140 dest->poly[3] = src->poly[3];
141 dest->poly[4] = src->poly[4];
142 dest->poly[5] = src->poly[5];
143 if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
144 NULL)
145 return 0;
146 if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
147 NULL)
148 return 0;
149 bn_set_all_zero(dest->a);
150 bn_set_all_zero(dest->b);
151 return 1;
152}
7793f30e
BM
153
154/* Set the curve parameters of an EC_GROUP structure. */
35b73a1f 155int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
0f113f3e
MC
156 const BIGNUM *p, const BIGNUM *a,
157 const BIGNUM *b, BN_CTX *ctx)
158{
159 int ret = 0, i;
160
161 /* group->field */
162 if (!BN_copy(group->field, p))
163 goto err;
164 i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
165 if ((i != 5) && (i != 3)) {
166 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
167 goto err;
168 }
169
170 /* group->a */
171 if (!BN_GF2m_mod_arr(group->a, a, group->poly))
172 goto err;
173 if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
174 == NULL)
175 goto err;
176 bn_set_all_zero(group->a);
177
178 /* group->b */
179 if (!BN_GF2m_mod_arr(group->b, b, group->poly))
180 goto err;
181 if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
182 == NULL)
183 goto err;
184 bn_set_all_zero(group->b);
185
186 ret = 1;
187 err:
188 return ret;
189}
190
191/*
192 * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
193 * then there values will not be set but the method will return with success.
7793f30e 194 */
0f113f3e
MC
195int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
196 BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
197{
198 int ret = 0;
199
200 if (p != NULL) {
201 if (!BN_copy(p, group->field))
202 return 0;
203 }
204
205 if (a != NULL) {
206 if (!BN_copy(a, group->a))
207 goto err;
208 }
7793f30e 209
0f113f3e
MC
210 if (b != NULL) {
211 if (!BN_copy(b, group->b))
212 goto err;
213 }
7793f30e 214
0f113f3e
MC
215 ret = 1;
216
217 err:
218 return ret;
219}
220
221/*
222 * Gets the degree of the field. For a curve over GF(2^m) this is the value
223 * m.
224 */
225int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
226{
227 return BN_num_bits(group->field) - 1;
228}
229
230/*
231 * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
232 * elliptic curve <=> b != 0 (mod p)
7793f30e 233 */
0f113f3e
MC
234int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
235 BN_CTX *ctx)
236{
237 int ret = 0;
238 BIGNUM *b;
239 BN_CTX *new_ctx = NULL;
240
241 if (ctx == NULL) {
242 ctx = new_ctx = BN_CTX_new();
243 if (ctx == NULL) {
244 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
245 ERR_R_MALLOC_FAILURE);
246 goto err;
247 }
248 }
249 BN_CTX_start(ctx);
250 b = BN_CTX_get(ctx);
251 if (b == NULL)
252 goto err;
253
254 if (!BN_GF2m_mod_arr(b, group->b, group->poly))
255 goto err;
256
257 /*
258 * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
259 * curve <=> b != 0 (mod p)
260 */
261 if (BN_is_zero(b))
262 goto err;
263
264 ret = 1;
7793f30e 265
0f113f3e
MC
266 err:
267 if (ctx != NULL)
268 BN_CTX_end(ctx);
23a1d5e9 269 BN_CTX_free(new_ctx);
0f113f3e
MC
270 return ret;
271}
7793f30e
BM
272
273/* Initializes an EC_POINT. */
274int ec_GF2m_simple_point_init(EC_POINT *point)
0f113f3e
MC
275{
276 point->X = BN_new();
277 point->Y = BN_new();
278 point->Z = BN_new();
279
90945fa3 280 if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
23a1d5e9
RS
281 BN_free(point->X);
282 BN_free(point->Y);
283 BN_free(point->Z);
0f113f3e
MC
284 return 0;
285 }
286 return 1;
287}
7793f30e
BM
288
289/* Frees an EC_POINT. */
290void ec_GF2m_simple_point_finish(EC_POINT *point)
0f113f3e
MC
291{
292 BN_free(point->X);
293 BN_free(point->Y);
294 BN_free(point->Z);
295}
7793f30e
BM
296
297/* Clears and frees an EC_POINT. */
298void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
0f113f3e
MC
299{
300 BN_clear_free(point->X);
301 BN_clear_free(point->Y);
302 BN_clear_free(point->Z);
303 point->Z_is_one = 0;
304}
305
306/*
307 * Copy the contents of one EC_POINT into another. Assumes dest is
308 * initialized.
7793f30e 309 */
0f113f3e
MC
310int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
311{
312 if (!BN_copy(dest->X, src->X))
313 return 0;
314 if (!BN_copy(dest->Y, src->Y))
315 return 0;
316 if (!BN_copy(dest->Z, src->Z))
317 return 0;
318 dest->Z_is_one = src->Z_is_one;
b14e6015 319 dest->curve_name = src->curve_name;
0f113f3e
MC
320
321 return 1;
322}
323
324/*
325 * Set an EC_POINT to the point at infinity. A point at infinity is
326 * represented by having Z=0.
7793f30e 327 */
0f113f3e
MC
328int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
329 EC_POINT *point)
330{
331 point->Z_is_one = 0;
332 BN_zero(point->Z);
333 return 1;
334}
335
336/*
337 * Set the coordinates of an EC_POINT using affine coordinates. Note that
338 * the simple implementation only uses affine coordinates.
7793f30e 339 */
0f113f3e
MC
340int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
341 EC_POINT *point,
342 const BIGNUM *x,
343 const BIGNUM *y, BN_CTX *ctx)
344{
345 int ret = 0;
346 if (x == NULL || y == NULL) {
347 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
348 ERR_R_PASSED_NULL_PARAMETER);
349 return 0;
350 }
351
352 if (!BN_copy(point->X, x))
353 goto err;
354 BN_set_negative(point->X, 0);
355 if (!BN_copy(point->Y, y))
356 goto err;
357 BN_set_negative(point->Y, 0);
358 if (!BN_copy(point->Z, BN_value_one()))
359 goto err;
360 BN_set_negative(point->Z, 0);
361 point->Z_is_one = 1;
362 ret = 1;
363
7793f30e 364 err:
0f113f3e
MC
365 return ret;
366}
7793f30e 367
0f113f3e
MC
368/*
369 * Gets the affine coordinates of an EC_POINT. Note that the simple
370 * implementation only uses affine coordinates.
7793f30e 371 */
0f113f3e
MC
372int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
373 const EC_POINT *point,
374 BIGNUM *x, BIGNUM *y,
375 BN_CTX *ctx)
376{
377 int ret = 0;
378
379 if (EC_POINT_is_at_infinity(group, point)) {
380 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
381 EC_R_POINT_AT_INFINITY);
382 return 0;
383 }
384
385 if (BN_cmp(point->Z, BN_value_one())) {
386 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
387 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
388 return 0;
389 }
390 if (x != NULL) {
391 if (!BN_copy(x, point->X))
392 goto err;
393 BN_set_negative(x, 0);
394 }
395 if (y != NULL) {
396 if (!BN_copy(y, point->Y))
397 goto err;
398 BN_set_negative(y, 0);
399 }
400 ret = 1;
7793f30e
BM
401
402 err:
0f113f3e
MC
403 return ret;
404}
7793f30e 405
0f113f3e
MC
406/*
407 * Computes a + b and stores the result in r. r could be a or b, a could be
408 * b. Uses algorithm A.10.2 of IEEE P1363.
7793f30e 409 */
0f113f3e
MC
410int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
411 const EC_POINT *b, BN_CTX *ctx)
412{
413 BN_CTX *new_ctx = NULL;
414 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
415 int ret = 0;
416
417 if (EC_POINT_is_at_infinity(group, a)) {
418 if (!EC_POINT_copy(r, b))
419 return 0;
420 return 1;
421 }
422
423 if (EC_POINT_is_at_infinity(group, b)) {
424 if (!EC_POINT_copy(r, a))
425 return 0;
426 return 1;
427 }
428
429 if (ctx == NULL) {
430 ctx = new_ctx = BN_CTX_new();
431 if (ctx == NULL)
432 return 0;
433 }
434
435 BN_CTX_start(ctx);
436 x0 = BN_CTX_get(ctx);
437 y0 = BN_CTX_get(ctx);
438 x1 = BN_CTX_get(ctx);
439 y1 = BN_CTX_get(ctx);
440 x2 = BN_CTX_get(ctx);
441 y2 = BN_CTX_get(ctx);
442 s = BN_CTX_get(ctx);
443 t = BN_CTX_get(ctx);
444 if (t == NULL)
445 goto err;
446
447 if (a->Z_is_one) {
448 if (!BN_copy(x0, a->X))
449 goto err;
450 if (!BN_copy(y0, a->Y))
451 goto err;
452 } else {
453 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
454 goto err;
455 }
456 if (b->Z_is_one) {
457 if (!BN_copy(x1, b->X))
458 goto err;
459 if (!BN_copy(y1, b->Y))
460 goto err;
461 } else {
462 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
463 goto err;
464 }
465
466 if (BN_GF2m_cmp(x0, x1)) {
467 if (!BN_GF2m_add(t, x0, x1))
468 goto err;
469 if (!BN_GF2m_add(s, y0, y1))
470 goto err;
471 if (!group->meth->field_div(group, s, s, t, ctx))
472 goto err;
473 if (!group->meth->field_sqr(group, x2, s, ctx))
474 goto err;
475 if (!BN_GF2m_add(x2, x2, group->a))
476 goto err;
477 if (!BN_GF2m_add(x2, x2, s))
478 goto err;
479 if (!BN_GF2m_add(x2, x2, t))
480 goto err;
481 } else {
482 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
483 if (!EC_POINT_set_to_infinity(group, r))
484 goto err;
485 ret = 1;
486 goto err;
487 }
488 if (!group->meth->field_div(group, s, y1, x1, ctx))
489 goto err;
490 if (!BN_GF2m_add(s, s, x1))
491 goto err;
492
493 if (!group->meth->field_sqr(group, x2, s, ctx))
494 goto err;
495 if (!BN_GF2m_add(x2, x2, s))
496 goto err;
497 if (!BN_GF2m_add(x2, x2, group->a))
498 goto err;
499 }
500
501 if (!BN_GF2m_add(y2, x1, x2))
502 goto err;
503 if (!group->meth->field_mul(group, y2, y2, s, ctx))
504 goto err;
505 if (!BN_GF2m_add(y2, y2, x2))
506 goto err;
507 if (!BN_GF2m_add(y2, y2, y1))
508 goto err;
509
510 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
511 goto err;
512
513 ret = 1;
7793f30e 514
0f113f3e
MC
515 err:
516 BN_CTX_end(ctx);
23a1d5e9 517 BN_CTX_free(new_ctx);
0f113f3e
MC
518 return ret;
519}
520
521/*
522 * Computes 2 * a and stores the result in r. r could be a. Uses algorithm
523 * A.10.2 of IEEE P1363.
524 */
525int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
526 BN_CTX *ctx)
527{
528 return ec_GF2m_simple_add(group, r, a, a, ctx);
529}
7793f30e
BM
530
531int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
0f113f3e
MC
532{
533 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
534 /* point is its own inverse */
535 return 1;
7793f30e 536
0f113f3e
MC
537 if (!EC_POINT_make_affine(group, point, ctx))
538 return 0;
539 return BN_GF2m_add(point->Y, point->X, point->Y);
540}
7793f30e
BM
541
542/* Indicates whether the given point is the point at infinity. */
0f113f3e
MC
543int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
544 const EC_POINT *point)
545{
546 return BN_is_zero(point->Z);
547}
7793f30e 548
23a22b4c
MC
549/*-
550 * Determines whether the given EC_POINT is an actual point on the curve defined
7793f30e
BM
551 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
552 * y^2 + x*y = x^3 + a*x^2 + b.
553 */
0f113f3e
MC
554int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
555 BN_CTX *ctx)
556{
557 int ret = -1;
558 BN_CTX *new_ctx = NULL;
559 BIGNUM *lh, *y2;
560 int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
561 const BIGNUM *, BN_CTX *);
562 int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
563
564 if (EC_POINT_is_at_infinity(group, point))
565 return 1;
566
567 field_mul = group->meth->field_mul;
568 field_sqr = group->meth->field_sqr;
569
570 /* only support affine coordinates */
571 if (!point->Z_is_one)
572 return -1;
573
574 if (ctx == NULL) {
575 ctx = new_ctx = BN_CTX_new();
576 if (ctx == NULL)
577 return -1;
578 }
579
580 BN_CTX_start(ctx);
581 y2 = BN_CTX_get(ctx);
582 lh = BN_CTX_get(ctx);
583 if (lh == NULL)
584 goto err;
585
50e735f9
MC
586 /*-
587 * We have a curve defined by a Weierstrass equation
588 * y^2 + x*y = x^3 + a*x^2 + b.
589 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
590 * <=> ((x + a) * x + y ) * x + b + y^2 = 0
591 */
0f113f3e
MC
592 if (!BN_GF2m_add(lh, point->X, group->a))
593 goto err;
594 if (!field_mul(group, lh, lh, point->X, ctx))
595 goto err;
596 if (!BN_GF2m_add(lh, lh, point->Y))
597 goto err;
598 if (!field_mul(group, lh, lh, point->X, ctx))
599 goto err;
600 if (!BN_GF2m_add(lh, lh, group->b))
601 goto err;
602 if (!field_sqr(group, y2, point->Y, ctx))
603 goto err;
604 if (!BN_GF2m_add(lh, lh, y2))
605 goto err;
606 ret = BN_is_zero(lh);
a0fda2cf 607
7793f30e 608 err:
a0fda2cf 609 BN_CTX_end(ctx);
23a1d5e9 610 BN_CTX_free(new_ctx);
0f113f3e
MC
611 return ret;
612}
7793f30e 613
1d97c843
TH
614/*-
615 * Indicates whether two points are equal.
7793f30e
BM
616 * Return values:
617 * -1 error
618 * 0 equal (in affine coordinates)
619 * 1 not equal
620 */
0f113f3e
MC
621int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
622 const EC_POINT *b, BN_CTX *ctx)
623{
624 BIGNUM *aX, *aY, *bX, *bY;
625 BN_CTX *new_ctx = NULL;
626 int ret = -1;
627
628 if (EC_POINT_is_at_infinity(group, a)) {
629 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
630 }
631
632 if (EC_POINT_is_at_infinity(group, b))
633 return 1;
634
635 if (a->Z_is_one && b->Z_is_one) {
636 return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
637 }
638
639 if (ctx == NULL) {
640 ctx = new_ctx = BN_CTX_new();
641 if (ctx == NULL)
642 return -1;
643 }
644
645 BN_CTX_start(ctx);
646 aX = BN_CTX_get(ctx);
647 aY = BN_CTX_get(ctx);
648 bX = BN_CTX_get(ctx);
649 bY = BN_CTX_get(ctx);
650 if (bY == NULL)
651 goto err;
652
653 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
654 goto err;
655 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
656 goto err;
657 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
7793f30e 658
0f113f3e 659 err:
a0fda2cf 660 BN_CTX_end(ctx);
23a1d5e9 661 BN_CTX_free(new_ctx);
0f113f3e
MC
662 return ret;
663}
7793f30e
BM
664
665/* Forces the given EC_POINT to internally use affine coordinates. */
0f113f3e
MC
666int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
667 BN_CTX *ctx)
668{
669 BN_CTX *new_ctx = NULL;
670 BIGNUM *x, *y;
671 int ret = 0;
672
673 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
674 return 1;
675
676 if (ctx == NULL) {
677 ctx = new_ctx = BN_CTX_new();
678 if (ctx == NULL)
679 return 0;
680 }
681
682 BN_CTX_start(ctx);
683 x = BN_CTX_get(ctx);
684 y = BN_CTX_get(ctx);
685 if (y == NULL)
686 goto err;
687
688 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
689 goto err;
690 if (!BN_copy(point->X, x))
691 goto err;
692 if (!BN_copy(point->Y, y))
693 goto err;
694 if (!BN_one(point->Z))
695 goto err;
dd67493c 696 point->Z_is_one = 1;
0f113f3e
MC
697
698 ret = 1;
699
700 err:
a0fda2cf 701 BN_CTX_end(ctx);
23a1d5e9 702 BN_CTX_free(new_ctx);
0f113f3e
MC
703 return ret;
704}
705
706/*
707 * Forces each of the EC_POINTs in the given array to use affine coordinates.
708 */
709int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
710 EC_POINT *points[], BN_CTX *ctx)
711{
712 size_t i;
7793f30e 713
0f113f3e
MC
714 for (i = 0; i < num; i++) {
715 if (!group->meth->make_affine(group, points[i], ctx))
716 return 0;
717 }
7793f30e 718
0f113f3e
MC
719 return 1;
720}
7793f30e 721
0f113f3e
MC
722/* Wrapper to simple binary polynomial field multiplication implementation. */
723int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
724 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
725{
726 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
727}
7793f30e
BM
728
729/* Wrapper to simple binary polynomial field squaring implementation. */
0f113f3e
MC
730int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
731 const BIGNUM *a, BN_CTX *ctx)
732{
733 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
734}
7793f30e
BM
735
736/* Wrapper to simple binary polynomial field division implementation. */
0f113f3e
MC
737int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
738 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
739{
740 return BN_GF2m_mod_div(r, a, b, group->field, ctx);
741}
b3310161
DSH
742
743#endif