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