]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ec2_smpl.c
Add default operations to EC_METHOD
[thirdparty/openssl.git] / crypto / ec / ec2_smpl.c
1 /* ====================================================================
2 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
3 *
4 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
5 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
6 * to the OpenSSL project.
7 *
8 * The ECC Code is licensed pursuant to the OpenSSL open source
9 * license provided below.
10 *
11 * The software is originally written by Sheueling Chang Shantz and
12 * Douglas Stebila of Sun Microsystems Laboratories.
13 *
14 */
15 /* ====================================================================
16 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. All advertising materials mentioning features or use of this
31 * software must display the following acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
34 *
35 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
36 * endorse or promote products derived from this software without
37 * prior written permission. For written permission, please contact
38 * openssl-core@openssl.org.
39 *
40 * 5. Products derived from this software may not be called "OpenSSL"
41 * nor may "OpenSSL" appear in their names without prior written
42 * permission of the OpenSSL Project.
43 *
44 * 6. Redistributions of any form whatsoever must retain the following
45 * acknowledgment:
46 * "This product includes software developed by the OpenSSL Project
47 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
50 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
60 * OF THE POSSIBILITY OF SUCH DAMAGE.
61 * ====================================================================
62 *
63 * This product includes cryptographic software written by Eric Young
64 * (eay@cryptsoft.com). This product includes software written by Tim
65 * Hudson (tjh@cryptsoft.com).
66 *
67 */
68
69 #include <openssl/err.h>
70
71 #include "internal/bn_int.h"
72 #include "ec_lcl.h"
73
74 #ifndef OPENSSL_NO_EC2M
75
76 const EC_METHOD *EC_GF2m_simple_method(void)
77 {
78 static const EC_METHOD ret = {
79 EC_FLAGS_DEFAULT_OCT,
80 NID_X9_62_characteristic_two_field,
81 ec_GF2m_simple_group_init,
82 ec_GF2m_simple_group_finish,
83 ec_GF2m_simple_group_clear_finish,
84 ec_GF2m_simple_group_copy,
85 ec_GF2m_simple_group_set_curve,
86 ec_GF2m_simple_group_get_curve,
87 ec_GF2m_simple_group_get_degree,
88 ec_group_simple_order_bits,
89 ec_GF2m_simple_group_check_discriminant,
90 ec_GF2m_simple_point_init,
91 ec_GF2m_simple_point_finish,
92 ec_GF2m_simple_point_clear_finish,
93 ec_GF2m_simple_point_copy,
94 ec_GF2m_simple_point_set_to_infinity,
95 0 /* set_Jprojective_coordinates_GFp */ ,
96 0 /* get_Jprojective_coordinates_GFp */ ,
97 ec_GF2m_simple_point_set_affine_coordinates,
98 ec_GF2m_simple_point_get_affine_coordinates,
99 0, 0, 0,
100 ec_GF2m_simple_add,
101 ec_GF2m_simple_dbl,
102 ec_GF2m_simple_invert,
103 ec_GF2m_simple_is_at_infinity,
104 ec_GF2m_simple_is_on_curve,
105 ec_GF2m_simple_cmp,
106 ec_GF2m_simple_make_affine,
107 ec_GF2m_simple_points_make_affine,
108
109 /*
110 * the following three method functions are defined in ec2_mult.c
111 */
112 ec_GF2m_simple_mul,
113 ec_GF2m_precompute_mult,
114 ec_GF2m_have_precompute_mult,
115
116 ec_GF2m_simple_field_mul,
117 ec_GF2m_simple_field_sqr,
118 ec_GF2m_simple_field_div,
119 0 /* field_encode */ ,
120 0 /* field_decode */ ,
121 0, /* field_set_to_one */
122 ec_key_simple_priv2oct,
123 ec_key_simple_oct2priv,
124 0, /* set private */
125 ec_key_simple_generate_key,
126 ec_key_simple_check_key,
127 ec_key_simple_generate_public_key,
128 0, /* keycopy */
129 0, /* keyfinish */
130 ecdh_simple_compute_key
131 };
132
133 return &ret;
134 }
135
136 /*
137 * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
138 * are handled by EC_GROUP_new.
139 */
140 int ec_GF2m_simple_group_init(EC_GROUP *group)
141 {
142 group->field = BN_new();
143 group->a = BN_new();
144 group->b = BN_new();
145
146 if (group->field == NULL || group->a == NULL || group->b == NULL) {
147 BN_free(group->field);
148 BN_free(group->a);
149 BN_free(group->b);
150 return 0;
151 }
152 return 1;
153 }
154
155 /*
156 * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
157 * handled by EC_GROUP_free.
158 */
159 void ec_GF2m_simple_group_finish(EC_GROUP *group)
160 {
161 BN_free(group->field);
162 BN_free(group->a);
163 BN_free(group->b);
164 }
165
166 /*
167 * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
168 * members are handled by EC_GROUP_clear_free.
169 */
170 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
171 {
172 BN_clear_free(group->field);
173 BN_clear_free(group->a);
174 BN_clear_free(group->b);
175 group->poly[0] = 0;
176 group->poly[1] = 0;
177 group->poly[2] = 0;
178 group->poly[3] = 0;
179 group->poly[4] = 0;
180 group->poly[5] = -1;
181 }
182
183 /*
184 * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
185 * handled by EC_GROUP_copy.
186 */
187 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
188 {
189 if (!BN_copy(dest->field, src->field))
190 return 0;
191 if (!BN_copy(dest->a, src->a))
192 return 0;
193 if (!BN_copy(dest->b, src->b))
194 return 0;
195 dest->poly[0] = src->poly[0];
196 dest->poly[1] = src->poly[1];
197 dest->poly[2] = src->poly[2];
198 dest->poly[3] = src->poly[3];
199 dest->poly[4] = src->poly[4];
200 dest->poly[5] = src->poly[5];
201 if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
202 NULL)
203 return 0;
204 if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
205 NULL)
206 return 0;
207 bn_set_all_zero(dest->a);
208 bn_set_all_zero(dest->b);
209 return 1;
210 }
211
212 /* Set the curve parameters of an EC_GROUP structure. */
213 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
214 const BIGNUM *p, const BIGNUM *a,
215 const BIGNUM *b, BN_CTX *ctx)
216 {
217 int ret = 0, i;
218
219 /* group->field */
220 if (!BN_copy(group->field, p))
221 goto err;
222 i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
223 if ((i != 5) && (i != 3)) {
224 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
225 goto err;
226 }
227
228 /* group->a */
229 if (!BN_GF2m_mod_arr(group->a, a, group->poly))
230 goto err;
231 if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
232 == NULL)
233 goto err;
234 bn_set_all_zero(group->a);
235
236 /* group->b */
237 if (!BN_GF2m_mod_arr(group->b, b, group->poly))
238 goto err;
239 if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
240 == NULL)
241 goto err;
242 bn_set_all_zero(group->b);
243
244 ret = 1;
245 err:
246 return ret;
247 }
248
249 /*
250 * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
251 * then there values will not be set but the method will return with success.
252 */
253 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
254 BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
255 {
256 int ret = 0;
257
258 if (p != NULL) {
259 if (!BN_copy(p, group->field))
260 return 0;
261 }
262
263 if (a != NULL) {
264 if (!BN_copy(a, group->a))
265 goto err;
266 }
267
268 if (b != NULL) {
269 if (!BN_copy(b, group->b))
270 goto err;
271 }
272
273 ret = 1;
274
275 err:
276 return ret;
277 }
278
279 /*
280 * Gets the degree of the field. For a curve over GF(2^m) this is the value
281 * m.
282 */
283 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
284 {
285 return BN_num_bits(group->field) - 1;
286 }
287
288 /*
289 * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
290 * elliptic curve <=> b != 0 (mod p)
291 */
292 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
293 BN_CTX *ctx)
294 {
295 int ret = 0;
296 BIGNUM *b;
297 BN_CTX *new_ctx = NULL;
298
299 if (ctx == NULL) {
300 ctx = new_ctx = BN_CTX_new();
301 if (ctx == NULL) {
302 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
303 ERR_R_MALLOC_FAILURE);
304 goto err;
305 }
306 }
307 BN_CTX_start(ctx);
308 b = BN_CTX_get(ctx);
309 if (b == NULL)
310 goto err;
311
312 if (!BN_GF2m_mod_arr(b, group->b, group->poly))
313 goto err;
314
315 /*
316 * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
317 * curve <=> b != 0 (mod p)
318 */
319 if (BN_is_zero(b))
320 goto err;
321
322 ret = 1;
323
324 err:
325 if (ctx != NULL)
326 BN_CTX_end(ctx);
327 BN_CTX_free(new_ctx);
328 return ret;
329 }
330
331 /* Initializes an EC_POINT. */
332 int ec_GF2m_simple_point_init(EC_POINT *point)
333 {
334 point->X = BN_new();
335 point->Y = BN_new();
336 point->Z = BN_new();
337
338 if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
339 BN_free(point->X);
340 BN_free(point->Y);
341 BN_free(point->Z);
342 return 0;
343 }
344 return 1;
345 }
346
347 /* Frees an EC_POINT. */
348 void ec_GF2m_simple_point_finish(EC_POINT *point)
349 {
350 BN_free(point->X);
351 BN_free(point->Y);
352 BN_free(point->Z);
353 }
354
355 /* Clears and frees an EC_POINT. */
356 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
357 {
358 BN_clear_free(point->X);
359 BN_clear_free(point->Y);
360 BN_clear_free(point->Z);
361 point->Z_is_one = 0;
362 }
363
364 /*
365 * Copy the contents of one EC_POINT into another. Assumes dest is
366 * initialized.
367 */
368 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
369 {
370 if (!BN_copy(dest->X, src->X))
371 return 0;
372 if (!BN_copy(dest->Y, src->Y))
373 return 0;
374 if (!BN_copy(dest->Z, src->Z))
375 return 0;
376 dest->Z_is_one = src->Z_is_one;
377
378 return 1;
379 }
380
381 /*
382 * Set an EC_POINT to the point at infinity. A point at infinity is
383 * represented by having Z=0.
384 */
385 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
386 EC_POINT *point)
387 {
388 point->Z_is_one = 0;
389 BN_zero(point->Z);
390 return 1;
391 }
392
393 /*
394 * Set the coordinates of an EC_POINT using affine coordinates. Note that
395 * the simple implementation only uses affine coordinates.
396 */
397 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
398 EC_POINT *point,
399 const BIGNUM *x,
400 const BIGNUM *y, BN_CTX *ctx)
401 {
402 int ret = 0;
403 if (x == NULL || y == NULL) {
404 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
405 ERR_R_PASSED_NULL_PARAMETER);
406 return 0;
407 }
408
409 if (!BN_copy(point->X, x))
410 goto err;
411 BN_set_negative(point->X, 0);
412 if (!BN_copy(point->Y, y))
413 goto err;
414 BN_set_negative(point->Y, 0);
415 if (!BN_copy(point->Z, BN_value_one()))
416 goto err;
417 BN_set_negative(point->Z, 0);
418 point->Z_is_one = 1;
419 ret = 1;
420
421 err:
422 return ret;
423 }
424
425 /*
426 * Gets the affine coordinates of an EC_POINT. Note that the simple
427 * implementation only uses affine coordinates.
428 */
429 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
430 const EC_POINT *point,
431 BIGNUM *x, BIGNUM *y,
432 BN_CTX *ctx)
433 {
434 int ret = 0;
435
436 if (EC_POINT_is_at_infinity(group, point)) {
437 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
438 EC_R_POINT_AT_INFINITY);
439 return 0;
440 }
441
442 if (BN_cmp(point->Z, BN_value_one())) {
443 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
444 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
445 return 0;
446 }
447 if (x != NULL) {
448 if (!BN_copy(x, point->X))
449 goto err;
450 BN_set_negative(x, 0);
451 }
452 if (y != NULL) {
453 if (!BN_copy(y, point->Y))
454 goto err;
455 BN_set_negative(y, 0);
456 }
457 ret = 1;
458
459 err:
460 return ret;
461 }
462
463 /*
464 * Computes a + b and stores the result in r. r could be a or b, a could be
465 * b. Uses algorithm A.10.2 of IEEE P1363.
466 */
467 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
468 const EC_POINT *b, BN_CTX *ctx)
469 {
470 BN_CTX *new_ctx = NULL;
471 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
472 int ret = 0;
473
474 if (EC_POINT_is_at_infinity(group, a)) {
475 if (!EC_POINT_copy(r, b))
476 return 0;
477 return 1;
478 }
479
480 if (EC_POINT_is_at_infinity(group, b)) {
481 if (!EC_POINT_copy(r, a))
482 return 0;
483 return 1;
484 }
485
486 if (ctx == NULL) {
487 ctx = new_ctx = BN_CTX_new();
488 if (ctx == NULL)
489 return 0;
490 }
491
492 BN_CTX_start(ctx);
493 x0 = BN_CTX_get(ctx);
494 y0 = BN_CTX_get(ctx);
495 x1 = BN_CTX_get(ctx);
496 y1 = BN_CTX_get(ctx);
497 x2 = BN_CTX_get(ctx);
498 y2 = BN_CTX_get(ctx);
499 s = BN_CTX_get(ctx);
500 t = BN_CTX_get(ctx);
501 if (t == NULL)
502 goto err;
503
504 if (a->Z_is_one) {
505 if (!BN_copy(x0, a->X))
506 goto err;
507 if (!BN_copy(y0, a->Y))
508 goto err;
509 } else {
510 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
511 goto err;
512 }
513 if (b->Z_is_one) {
514 if (!BN_copy(x1, b->X))
515 goto err;
516 if (!BN_copy(y1, b->Y))
517 goto err;
518 } else {
519 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
520 goto err;
521 }
522
523 if (BN_GF2m_cmp(x0, x1)) {
524 if (!BN_GF2m_add(t, x0, x1))
525 goto err;
526 if (!BN_GF2m_add(s, y0, y1))
527 goto err;
528 if (!group->meth->field_div(group, s, s, t, ctx))
529 goto err;
530 if (!group->meth->field_sqr(group, x2, s, ctx))
531 goto err;
532 if (!BN_GF2m_add(x2, x2, group->a))
533 goto err;
534 if (!BN_GF2m_add(x2, x2, s))
535 goto err;
536 if (!BN_GF2m_add(x2, x2, t))
537 goto err;
538 } else {
539 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
540 if (!EC_POINT_set_to_infinity(group, r))
541 goto err;
542 ret = 1;
543 goto err;
544 }
545 if (!group->meth->field_div(group, s, y1, x1, ctx))
546 goto err;
547 if (!BN_GF2m_add(s, s, x1))
548 goto err;
549
550 if (!group->meth->field_sqr(group, x2, s, ctx))
551 goto err;
552 if (!BN_GF2m_add(x2, x2, s))
553 goto err;
554 if (!BN_GF2m_add(x2, x2, group->a))
555 goto err;
556 }
557
558 if (!BN_GF2m_add(y2, x1, x2))
559 goto err;
560 if (!group->meth->field_mul(group, y2, y2, s, ctx))
561 goto err;
562 if (!BN_GF2m_add(y2, y2, x2))
563 goto err;
564 if (!BN_GF2m_add(y2, y2, y1))
565 goto err;
566
567 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
568 goto err;
569
570 ret = 1;
571
572 err:
573 BN_CTX_end(ctx);
574 BN_CTX_free(new_ctx);
575 return ret;
576 }
577
578 /*
579 * Computes 2 * a and stores the result in r. r could be a. Uses algorithm
580 * A.10.2 of IEEE P1363.
581 */
582 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
583 BN_CTX *ctx)
584 {
585 return ec_GF2m_simple_add(group, r, a, a, ctx);
586 }
587
588 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
589 {
590 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
591 /* point is its own inverse */
592 return 1;
593
594 if (!EC_POINT_make_affine(group, point, ctx))
595 return 0;
596 return BN_GF2m_add(point->Y, point->X, point->Y);
597 }
598
599 /* Indicates whether the given point is the point at infinity. */
600 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
601 const EC_POINT *point)
602 {
603 return BN_is_zero(point->Z);
604 }
605
606 /*-
607 * Determines whether the given EC_POINT is an actual point on the curve defined
608 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
609 * y^2 + x*y = x^3 + a*x^2 + b.
610 */
611 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
612 BN_CTX *ctx)
613 {
614 int ret = -1;
615 BN_CTX *new_ctx = NULL;
616 BIGNUM *lh, *y2;
617 int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
618 const BIGNUM *, BN_CTX *);
619 int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
620
621 if (EC_POINT_is_at_infinity(group, point))
622 return 1;
623
624 field_mul = group->meth->field_mul;
625 field_sqr = group->meth->field_sqr;
626
627 /* only support affine coordinates */
628 if (!point->Z_is_one)
629 return -1;
630
631 if (ctx == NULL) {
632 ctx = new_ctx = BN_CTX_new();
633 if (ctx == NULL)
634 return -1;
635 }
636
637 BN_CTX_start(ctx);
638 y2 = BN_CTX_get(ctx);
639 lh = BN_CTX_get(ctx);
640 if (lh == NULL)
641 goto err;
642
643 /*-
644 * We have a curve defined by a Weierstrass equation
645 * y^2 + x*y = x^3 + a*x^2 + b.
646 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
647 * <=> ((x + a) * x + y ) * x + b + y^2 = 0
648 */
649 if (!BN_GF2m_add(lh, point->X, group->a))
650 goto err;
651 if (!field_mul(group, lh, lh, point->X, ctx))
652 goto err;
653 if (!BN_GF2m_add(lh, lh, point->Y))
654 goto err;
655 if (!field_mul(group, lh, lh, point->X, ctx))
656 goto err;
657 if (!BN_GF2m_add(lh, lh, group->b))
658 goto err;
659 if (!field_sqr(group, y2, point->Y, ctx))
660 goto err;
661 if (!BN_GF2m_add(lh, lh, y2))
662 goto err;
663 ret = BN_is_zero(lh);
664 err:
665 if (ctx)
666 BN_CTX_end(ctx);
667 BN_CTX_free(new_ctx);
668 return ret;
669 }
670
671 /*-
672 * Indicates whether two points are equal.
673 * Return values:
674 * -1 error
675 * 0 equal (in affine coordinates)
676 * 1 not equal
677 */
678 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
679 const EC_POINT *b, BN_CTX *ctx)
680 {
681 BIGNUM *aX, *aY, *bX, *bY;
682 BN_CTX *new_ctx = NULL;
683 int ret = -1;
684
685 if (EC_POINT_is_at_infinity(group, a)) {
686 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
687 }
688
689 if (EC_POINT_is_at_infinity(group, b))
690 return 1;
691
692 if (a->Z_is_one && b->Z_is_one) {
693 return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
694 }
695
696 if (ctx == NULL) {
697 ctx = new_ctx = BN_CTX_new();
698 if (ctx == NULL)
699 return -1;
700 }
701
702 BN_CTX_start(ctx);
703 aX = BN_CTX_get(ctx);
704 aY = BN_CTX_get(ctx);
705 bX = BN_CTX_get(ctx);
706 bY = BN_CTX_get(ctx);
707 if (bY == NULL)
708 goto err;
709
710 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
711 goto err;
712 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
713 goto err;
714 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
715
716 err:
717 if (ctx)
718 BN_CTX_end(ctx);
719 BN_CTX_free(new_ctx);
720 return ret;
721 }
722
723 /* Forces the given EC_POINT to internally use affine coordinates. */
724 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
725 BN_CTX *ctx)
726 {
727 BN_CTX *new_ctx = NULL;
728 BIGNUM *x, *y;
729 int ret = 0;
730
731 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
732 return 1;
733
734 if (ctx == NULL) {
735 ctx = new_ctx = BN_CTX_new();
736 if (ctx == NULL)
737 return 0;
738 }
739
740 BN_CTX_start(ctx);
741 x = BN_CTX_get(ctx);
742 y = BN_CTX_get(ctx);
743 if (y == NULL)
744 goto err;
745
746 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
747 goto err;
748 if (!BN_copy(point->X, x))
749 goto err;
750 if (!BN_copy(point->Y, y))
751 goto err;
752 if (!BN_one(point->Z))
753 goto err;
754 point->Z_is_one = 1;
755
756 ret = 1;
757
758 err:
759 if (ctx)
760 BN_CTX_end(ctx);
761 BN_CTX_free(new_ctx);
762 return ret;
763 }
764
765 /*
766 * Forces each of the EC_POINTs in the given array to use affine coordinates.
767 */
768 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
769 EC_POINT *points[], BN_CTX *ctx)
770 {
771 size_t i;
772
773 for (i = 0; i < num; i++) {
774 if (!group->meth->make_affine(group, points[i], ctx))
775 return 0;
776 }
777
778 return 1;
779 }
780
781 /* Wrapper to simple binary polynomial field multiplication implementation. */
782 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
783 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
784 {
785 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
786 }
787
788 /* Wrapper to simple binary polynomial field squaring implementation. */
789 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
790 const BIGNUM *a, BN_CTX *ctx)
791 {
792 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
793 }
794
795 /* Wrapper to simple binary polynomial field division implementation. */
796 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
797 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
798 {
799 return BN_GF2m_mod_div(r, a, b, group->field, ctx);
800 }
801
802 #endif