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