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