5a83b0565c5ccb8428bc591a70293b5b8bdbef26
[openssl.git] / crypto / ec / ec2_smpl.c
1 /*
2  * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
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
11 #include <openssl/err.h>
12
13 #include "internal/bn_int.h"
14 #include "ec_lcl.h"
15
16 #ifndef OPENSSL_NO_EC2M
17
18 const EC_METHOD *EC_GF2m_simple_method(void)
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,
30         ec_group_simple_order_bits,
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,
50         0 /* mul */,
51         0 /* precompute_mul */,
52         0 /* have_precompute_mul */,
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 */ ,
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
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.
76  */
77 int ec_GF2m_simple_group_init(EC_GROUP *group)
78 {
79     group->field = BN_new();
80     group->a = BN_new();
81     group->b = BN_new();
82
83     if (group->field == NULL || group->a == NULL || group->b == NULL) {
84         BN_free(group->field);
85         BN_free(group->a);
86         BN_free(group->b);
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.
95  */
96 void ec_GF2m_simple_group_finish(EC_GROUP *group)
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.
106  */
107 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
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.
123  */
124 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
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 }
148
149 /* Set the curve parameters of an EC_GROUP structure. */
150 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
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.
189  */
190 int 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     }
204
205     if (b != NULL) {
206         if (!BN_copy(b, group->b))
207             goto err;
208     }
209
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  */
220 int 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)
228  */
229 int 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;
260
261  err:
262     if (ctx != NULL)
263         BN_CTX_end(ctx);
264     BN_CTX_free(new_ctx);
265     return ret;
266 }
267
268 /* Initializes an EC_POINT. */
269 int ec_GF2m_simple_point_init(EC_POINT *point)
270 {
271     point->X = BN_new();
272     point->Y = BN_new();
273     point->Z = BN_new();
274
275     if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
276         BN_free(point->X);
277         BN_free(point->Y);
278         BN_free(point->Z);
279         return 0;
280     }
281     return 1;
282 }
283
284 /* Frees an EC_POINT. */
285 void ec_GF2m_simple_point_finish(EC_POINT *point)
286 {
287     BN_free(point->X);
288     BN_free(point->Y);
289     BN_free(point->Z);
290 }
291
292 /* Clears and frees an EC_POINT. */
293 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
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.
304  */
305 int 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     dest->curve_name = src->curve_name;
315
316     return 1;
317 }
318
319 /*
320  * Set an EC_POINT to the point at infinity. A point at infinity is
321  * represented by having Z=0.
322  */
323 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
324                                          EC_POINT *point)
325 {
326     point->Z_is_one = 0;
327     BN_zero(point->Z);
328     return 1;
329 }
330
331 /*
332  * Set the coordinates of an EC_POINT using affine coordinates. Note that
333  * the simple implementation only uses affine coordinates.
334  */
335 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
336                                                 EC_POINT *point,
337                                                 const BIGNUM *x,
338                                                 const BIGNUM *y, BN_CTX *ctx)
339 {
340     int ret = 0;
341     if (x == NULL || y == NULL) {
342         ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
343               ERR_R_PASSED_NULL_PARAMETER);
344         return 0;
345     }
346
347     if (!BN_copy(point->X, x))
348         goto err;
349     BN_set_negative(point->X, 0);
350     if (!BN_copy(point->Y, y))
351         goto err;
352     BN_set_negative(point->Y, 0);
353     if (!BN_copy(point->Z, BN_value_one()))
354         goto err;
355     BN_set_negative(point->Z, 0);
356     point->Z_is_one = 1;
357     ret = 1;
358
359  err:
360     return ret;
361 }
362
363 /*
364  * Gets the affine coordinates of an EC_POINT. Note that the simple
365  * implementation only uses affine coordinates.
366  */
367 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
368                                                 const EC_POINT *point,
369                                                 BIGNUM *x, BIGNUM *y,
370                                                 BN_CTX *ctx)
371 {
372     int ret = 0;
373
374     if (EC_POINT_is_at_infinity(group, point)) {
375         ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
376               EC_R_POINT_AT_INFINITY);
377         return 0;
378     }
379
380     if (BN_cmp(point->Z, BN_value_one())) {
381         ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
382               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
383         return 0;
384     }
385     if (x != NULL) {
386         if (!BN_copy(x, point->X))
387             goto err;
388         BN_set_negative(x, 0);
389     }
390     if (y != NULL) {
391         if (!BN_copy(y, point->Y))
392             goto err;
393         BN_set_negative(y, 0);
394     }
395     ret = 1;
396
397  err:
398     return ret;
399 }
400
401 /*
402  * Computes a + b and stores the result in r.  r could be a or b, a could be
403  * b. Uses algorithm A.10.2 of IEEE P1363.
404  */
405 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
406                        const EC_POINT *b, BN_CTX *ctx)
407 {
408     BN_CTX *new_ctx = NULL;
409     BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
410     int ret = 0;
411
412     if (EC_POINT_is_at_infinity(group, a)) {
413         if (!EC_POINT_copy(r, b))
414             return 0;
415         return 1;
416     }
417
418     if (EC_POINT_is_at_infinity(group, b)) {
419         if (!EC_POINT_copy(r, a))
420             return 0;
421         return 1;
422     }
423
424     if (ctx == NULL) {
425         ctx = new_ctx = BN_CTX_new();
426         if (ctx == NULL)
427             return 0;
428     }
429
430     BN_CTX_start(ctx);
431     x0 = BN_CTX_get(ctx);
432     y0 = BN_CTX_get(ctx);
433     x1 = BN_CTX_get(ctx);
434     y1 = BN_CTX_get(ctx);
435     x2 = BN_CTX_get(ctx);
436     y2 = BN_CTX_get(ctx);
437     s = BN_CTX_get(ctx);
438     t = BN_CTX_get(ctx);
439     if (t == NULL)
440         goto err;
441
442     if (a->Z_is_one) {
443         if (!BN_copy(x0, a->X))
444             goto err;
445         if (!BN_copy(y0, a->Y))
446             goto err;
447     } else {
448         if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
449             goto err;
450     }
451     if (b->Z_is_one) {
452         if (!BN_copy(x1, b->X))
453             goto err;
454         if (!BN_copy(y1, b->Y))
455             goto err;
456     } else {
457         if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
458             goto err;
459     }
460
461     if (BN_GF2m_cmp(x0, x1)) {
462         if (!BN_GF2m_add(t, x0, x1))
463             goto err;
464         if (!BN_GF2m_add(s, y0, y1))
465             goto err;
466         if (!group->meth->field_div(group, s, s, t, ctx))
467             goto err;
468         if (!group->meth->field_sqr(group, x2, s, ctx))
469             goto err;
470         if (!BN_GF2m_add(x2, x2, group->a))
471             goto err;
472         if (!BN_GF2m_add(x2, x2, s))
473             goto err;
474         if (!BN_GF2m_add(x2, x2, t))
475             goto err;
476     } else {
477         if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
478             if (!EC_POINT_set_to_infinity(group, r))
479                 goto err;
480             ret = 1;
481             goto err;
482         }
483         if (!group->meth->field_div(group, s, y1, x1, ctx))
484             goto err;
485         if (!BN_GF2m_add(s, s, x1))
486             goto err;
487
488         if (!group->meth->field_sqr(group, x2, s, ctx))
489             goto err;
490         if (!BN_GF2m_add(x2, x2, s))
491             goto err;
492         if (!BN_GF2m_add(x2, x2, group->a))
493             goto err;
494     }
495
496     if (!BN_GF2m_add(y2, x1, x2))
497         goto err;
498     if (!group->meth->field_mul(group, y2, y2, s, ctx))
499         goto err;
500     if (!BN_GF2m_add(y2, y2, x2))
501         goto err;
502     if (!BN_GF2m_add(y2, y2, y1))
503         goto err;
504
505     if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
506         goto err;
507
508     ret = 1;
509
510  err:
511     BN_CTX_end(ctx);
512     BN_CTX_free(new_ctx);
513     return ret;
514 }
515
516 /*
517  * Computes 2 * a and stores the result in r.  r could be a. Uses algorithm
518  * A.10.2 of IEEE P1363.
519  */
520 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
521                        BN_CTX *ctx)
522 {
523     return ec_GF2m_simple_add(group, r, a, a, ctx);
524 }
525
526 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
527 {
528     if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
529         /* point is its own inverse */
530         return 1;
531
532     if (!EC_POINT_make_affine(group, point, ctx))
533         return 0;
534     return BN_GF2m_add(point->Y, point->X, point->Y);
535 }
536
537 /* Indicates whether the given point is the point at infinity. */
538 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
539                                   const EC_POINT *point)
540 {
541     return BN_is_zero(point->Z);
542 }
543
544 /*-
545  * Determines whether the given EC_POINT is an actual point on the curve defined
546  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
547  *      y^2 + x*y = x^3 + a*x^2 + b.
548  */
549 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
550                                BN_CTX *ctx)
551 {
552     int ret = -1;
553     BN_CTX *new_ctx = NULL;
554     BIGNUM *lh, *y2;
555     int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
556                       const BIGNUM *, BN_CTX *);
557     int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
558
559     if (EC_POINT_is_at_infinity(group, point))
560         return 1;
561
562     field_mul = group->meth->field_mul;
563     field_sqr = group->meth->field_sqr;
564
565     /* only support affine coordinates */
566     if (!point->Z_is_one)
567         return -1;
568
569     if (ctx == NULL) {
570         ctx = new_ctx = BN_CTX_new();
571         if (ctx == NULL)
572             return -1;
573     }
574
575     BN_CTX_start(ctx);
576     y2 = BN_CTX_get(ctx);
577     lh = BN_CTX_get(ctx);
578     if (lh == NULL)
579         goto err;
580
581     /*-
582      * We have a curve defined by a Weierstrass equation
583      *      y^2 + x*y = x^3 + a*x^2 + b.
584      *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
585      *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
586      */
587     if (!BN_GF2m_add(lh, point->X, group->a))
588         goto err;
589     if (!field_mul(group, lh, lh, point->X, ctx))
590         goto err;
591     if (!BN_GF2m_add(lh, lh, point->Y))
592         goto err;
593     if (!field_mul(group, lh, lh, point->X, ctx))
594         goto err;
595     if (!BN_GF2m_add(lh, lh, group->b))
596         goto err;
597     if (!field_sqr(group, y2, point->Y, ctx))
598         goto err;
599     if (!BN_GF2m_add(lh, lh, y2))
600         goto err;
601     ret = BN_is_zero(lh);
602
603  err:
604     BN_CTX_end(ctx);
605     BN_CTX_free(new_ctx);
606     return ret;
607 }
608
609 /*-
610  * Indicates whether two points are equal.
611  * Return values:
612  *  -1   error
613  *   0   equal (in affine coordinates)
614  *   1   not equal
615  */
616 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
617                        const EC_POINT *b, BN_CTX *ctx)
618 {
619     BIGNUM *aX, *aY, *bX, *bY;
620     BN_CTX *new_ctx = NULL;
621     int ret = -1;
622
623     if (EC_POINT_is_at_infinity(group, a)) {
624         return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
625     }
626
627     if (EC_POINT_is_at_infinity(group, b))
628         return 1;
629
630     if (a->Z_is_one && b->Z_is_one) {
631         return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
632     }
633
634     if (ctx == NULL) {
635         ctx = new_ctx = BN_CTX_new();
636         if (ctx == NULL)
637             return -1;
638     }
639
640     BN_CTX_start(ctx);
641     aX = BN_CTX_get(ctx);
642     aY = BN_CTX_get(ctx);
643     bX = BN_CTX_get(ctx);
644     bY = BN_CTX_get(ctx);
645     if (bY == NULL)
646         goto err;
647
648     if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
649         goto err;
650     if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
651         goto err;
652     ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
653
654  err:
655     BN_CTX_end(ctx);
656     BN_CTX_free(new_ctx);
657     return ret;
658 }
659
660 /* Forces the given EC_POINT to internally use affine coordinates. */
661 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
662                                BN_CTX *ctx)
663 {
664     BN_CTX *new_ctx = NULL;
665     BIGNUM *x, *y;
666     int ret = 0;
667
668     if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
669         return 1;
670
671     if (ctx == NULL) {
672         ctx = new_ctx = BN_CTX_new();
673         if (ctx == NULL)
674             return 0;
675     }
676
677     BN_CTX_start(ctx);
678     x = BN_CTX_get(ctx);
679     y = BN_CTX_get(ctx);
680     if (y == NULL)
681         goto err;
682
683     if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
684         goto err;
685     if (!BN_copy(point->X, x))
686         goto err;
687     if (!BN_copy(point->Y, y))
688         goto err;
689     if (!BN_one(point->Z))
690         goto err;
691     point->Z_is_one = 1;
692
693     ret = 1;
694
695  err:
696     BN_CTX_end(ctx);
697     BN_CTX_free(new_ctx);
698     return ret;
699 }
700
701 /*
702  * Forces each of the EC_POINTs in the given array to use affine coordinates.
703  */
704 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
705                                       EC_POINT *points[], BN_CTX *ctx)
706 {
707     size_t i;
708
709     for (i = 0; i < num; i++) {
710         if (!group->meth->make_affine(group, points[i], ctx))
711             return 0;
712     }
713
714     return 1;
715 }
716
717 /* Wrapper to simple binary polynomial field multiplication implementation. */
718 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
719                              const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
720 {
721     return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
722 }
723
724 /* Wrapper to simple binary polynomial field squaring implementation. */
725 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
726                              const BIGNUM *a, BN_CTX *ctx)
727 {
728     return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
729 }
730
731 /* Wrapper to simple binary polynomial field division implementation. */
732 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
733                              const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
734 {
735     return BN_GF2m_mod_div(r, a, b, group->field, ctx);
736 }
737
738 #endif