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