]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ec2_smpl.c
Improve compatibility of point and curve checks
[thirdparty/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