]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ec2_smpl.c
Implement coordinate blinding for EC_POINT
[thirdparty/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