b73805a21efe559e0068df40d7b3ae107650e37b
[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
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.
321  */
322 int 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.
333  */
334 int 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
358  err:
359     return ret;
360 }
361
362 /*
363  * Gets the affine coordinates of an EC_POINT. Note that the simple
364  * implementation only uses affine coordinates.
365  */
366 int 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;
395
396  err:
397     return ret;
398 }
399
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.
403  */
404 int 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;
508
509  err:
510     BN_CTX_end(ctx);
511     BN_CTX_free(new_ctx);
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  */
519 int 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 }
524
525 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
526 {
527     if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
528         /* point is its own inverse */
529         return 1;
530
531     if (!EC_POINT_make_affine(group, point, ctx))
532         return 0;
533     return BN_GF2m_add(point->Y, point->X, point->Y);
534 }
535
536 /* Indicates whether the given point is the point at infinity. */
537 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
538                                   const EC_POINT *point)
539 {
540     return BN_is_zero(point->Z);
541 }
542
543 /*-
544  * Determines whether the given EC_POINT is an actual point on the curve defined
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  */
548 int 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
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      */
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);
601
602  err:
603     BN_CTX_end(ctx);
604     BN_CTX_free(new_ctx);
605     return ret;
606 }
607
608 /*-
609  * Indicates whether two points are equal.
610  * Return values:
611  *  -1   error
612  *   0   equal (in affine coordinates)
613  *   1   not equal
614  */
615 int 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;
652
653  err:
654     BN_CTX_end(ctx);
655     BN_CTX_free(new_ctx);
656     return ret;
657 }
658
659 /* Forces the given EC_POINT to internally use affine coordinates. */
660 int 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;
690     point->Z_is_one = 1;
691
692     ret = 1;
693
694  err:
695     BN_CTX_end(ctx);
696     BN_CTX_free(new_ctx);
697     return ret;
698 }
699
700 /*
701  * Forces each of the EC_POINTs in the given array to use affine coordinates.
702  */
703 int 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;
707
708     for (i = 0; i < num; i++) {
709         if (!group->meth->make_affine(group, points[i], ctx))
710             return 0;
711     }
712
713     return 1;
714 }
715
716 /* Wrapper to simple binary polynomial field multiplication implementation. */
717 int 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 }
722
723 /* Wrapper to simple binary polynomial field squaring implementation. */
724 int 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 }
729
730 /* Wrapper to simple binary polynomial field division implementation. */
731 int 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 }
736
737 #endif