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