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