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