ec2_smpl.c revision 296341
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 "ec_lcl.h"
73
74#ifndef OPENSSL_NO_EC2M
75
76# ifdef OPENSSL_FIPS
77#  include <openssl/fips.h>
78# endif
79
80const 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        /*
113         * the following three method functions are defined in ec2_mult.c
114         */
115        ec_GF2m_simple_mul,
116        ec_GF2m_precompute_mult,
117        ec_GF2m_have_precompute_mult,
118
119        ec_GF2m_simple_field_mul,
120        ec_GF2m_simple_field_sqr,
121        ec_GF2m_simple_field_div,
122        0 /* field_encode */ ,
123        0 /* field_decode */ ,
124        0                       /* field_set_to_one */
125    };
126
127# ifdef OPENSSL_FIPS
128    if (FIPS_mode())
129        return fips_ec_gf2m_simple_method();
130# endif
131
132    return &ret;
133}
134
135/*
136 * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
137 * are handled by EC_GROUP_new.
138 */
139int ec_GF2m_simple_group_init(EC_GROUP *group)
140{
141    BN_init(&group->field);
142    BN_init(&group->a);
143    BN_init(&group->b);
144    return 1;
145}
146
147/*
148 * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
149 * handled by EC_GROUP_free.
150 */
151void 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. Note that all other
160 * members are handled by EC_GROUP_clear_free.
161 */
162void 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. Note that all other members are
177 * handled by EC_GROUP_copy.
178 */
179int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
180{
181    int i;
182    if (!BN_copy(&dest->field, &src->field))
183        return 0;
184    if (!BN_copy(&dest->a, &src->a))
185        return 0;
186    if (!BN_copy(&dest->b, &src->b))
187        return 0;
188    dest->poly[0] = src->poly[0];
189    dest->poly[1] = src->poly[1];
190    dest->poly[2] = src->poly[2];
191    dest->poly[3] = src->poly[3];
192    dest->poly[4] = src->poly[4];
193    dest->poly[5] = src->poly[5];
194    if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
195        == NULL)
196        return 0;
197    if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
198        == NULL)
199        return 0;
200    for (i = dest->a.top; i < dest->a.dmax; i++)
201        dest->a.d[i] = 0;
202    for (i = dest->b.top; i < dest->b.dmax; i++)
203        dest->b.d[i] = 0;
204    return 1;
205}
206
207/* Set the curve parameters of an EC_GROUP structure. */
208int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
209                                   const BIGNUM *p, const BIGNUM *a,
210                                   const BIGNUM *b, BN_CTX *ctx)
211{
212    int ret = 0, i;
213
214    /* group->field */
215    if (!BN_copy(&group->field, p))
216        goto err;
217    i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
218    if ((i != 5) && (i != 3)) {
219        ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
220        goto err;
221    }
222
223    /* group->a */
224    if (!BN_GF2m_mod_arr(&group->a, a, group->poly))
225        goto err;
226    if (bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
227        == NULL)
228        goto err;
229    for (i = group->a.top; i < group->a.dmax; i++)
230        group->a.d[i] = 0;
231
232    /* group->b */
233    if (!BN_GF2m_mod_arr(&group->b, b, group->poly))
234        goto err;
235    if (bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
236        == NULL)
237        goto err;
238    for (i = group->b.top; i < group->b.dmax; i++)
239        group->b.d[i] = 0;
240
241    ret = 1;
242 err:
243    return ret;
244}
245
246/*
247 * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
248 * then there values will not be set but the method will return with success.
249 */
250int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
251                                   BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
252{
253    int ret = 0;
254
255    if (p != NULL) {
256        if (!BN_copy(p, &group->field))
257            return 0;
258    }
259
260    if (a != NULL) {
261        if (!BN_copy(a, &group->a))
262            goto err;
263    }
264
265    if (b != NULL) {
266        if (!BN_copy(b, &group->b))
267            goto err;
268    }
269
270    ret = 1;
271
272 err:
273    return ret;
274}
275
276/*
277 * Gets the degree of the field.  For a curve over GF(2^m) this is the value
278 * m.
279 */
280int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
281{
282    return BN_num_bits(&group->field) - 1;
283}
284
285/*
286 * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
287 * elliptic curve <=> b != 0 (mod p)
288 */
289int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
290                                            BN_CTX *ctx)
291{
292    int ret = 0;
293    BIGNUM *b;
294    BN_CTX *new_ctx = NULL;
295
296    if (ctx == NULL) {
297        ctx = new_ctx = BN_CTX_new();
298        if (ctx == NULL) {
299            ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
300                  ERR_R_MALLOC_FAILURE);
301            goto err;
302        }
303    }
304    BN_CTX_start(ctx);
305    b = BN_CTX_get(ctx);
306    if (b == NULL)
307        goto err;
308
309    if (!BN_GF2m_mod_arr(b, &group->b, group->poly))
310        goto err;
311
312    /*
313     * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
314     * curve <=> b != 0 (mod p)
315     */
316    if (BN_is_zero(b))
317        goto err;
318
319    ret = 1;
320
321 err:
322    if (ctx != NULL)
323        BN_CTX_end(ctx);
324    if (new_ctx != NULL)
325        BN_CTX_free(new_ctx);
326    return ret;
327}
328
329/* Initializes an EC_POINT. */
330int ec_GF2m_simple_point_init(EC_POINT *point)
331{
332    BN_init(&point->X);
333    BN_init(&point->Y);
334    BN_init(&point->Z);
335    return 1;
336}
337
338/* Frees an EC_POINT. */
339void 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. */
347void 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 */
359int 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 */
376int 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 */
388int 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 */
420int 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 */
458int 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    if (new_ctx != NULL)
566        BN_CTX_free(new_ctx);
567    return ret;
568}
569
570/*
571 * Computes 2 * a and stores the result in r.  r could be a. Uses algorithm
572 * A.10.2 of IEEE P1363.
573 */
574int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
575                       BN_CTX *ctx)
576{
577    return ec_GF2m_simple_add(group, r, a, a, ctx);
578}
579
580int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
581{
582    if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
583        /* point is its own inverse */
584        return 1;
585
586    if (!EC_POINT_make_affine(group, point, ctx))
587        return 0;
588    return BN_GF2m_add(&point->Y, &point->X, &point->Y);
589}
590
591/* Indicates whether the given point is the point at infinity. */
592int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
593                                  const EC_POINT *point)
594{
595    return BN_is_zero(&point->Z);
596}
597
598/*-
599 * Determines whether the given EC_POINT is an actual point on the curve defined
600 * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
601 *      y^2 + x*y = x^3 + a*x^2 + b.
602 */
603int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
604                               BN_CTX *ctx)
605{
606    int ret = -1;
607    BN_CTX *new_ctx = NULL;
608    BIGNUM *lh, *y2;
609    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
610                      const BIGNUM *, BN_CTX *);
611    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
612
613    if (EC_POINT_is_at_infinity(group, point))
614        return 1;
615
616    field_mul = group->meth->field_mul;
617    field_sqr = group->meth->field_sqr;
618
619    /* only support affine coordinates */
620    if (!point->Z_is_one)
621        return -1;
622
623    if (ctx == NULL) {
624        ctx = new_ctx = BN_CTX_new();
625        if (ctx == NULL)
626            return -1;
627    }
628
629    BN_CTX_start(ctx);
630    y2 = BN_CTX_get(ctx);
631    lh = BN_CTX_get(ctx);
632    if (lh == NULL)
633        goto err;
634
635    /*-
636     * We have a curve defined by a Weierstrass equation
637     *      y^2 + x*y = x^3 + a*x^2 + b.
638     *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
639     *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
640     */
641    if (!BN_GF2m_add(lh, &point->X, &group->a))
642        goto err;
643    if (!field_mul(group, lh, lh, &point->X, ctx))
644        goto err;
645    if (!BN_GF2m_add(lh, lh, &point->Y))
646        goto err;
647    if (!field_mul(group, lh, lh, &point->X, ctx))
648        goto err;
649    if (!BN_GF2m_add(lh, lh, &group->b))
650        goto err;
651    if (!field_sqr(group, y2, &point->Y, ctx))
652        goto err;
653    if (!BN_GF2m_add(lh, lh, y2))
654        goto err;
655    ret = BN_is_zero(lh);
656 err:
657    if (ctx)
658        BN_CTX_end(ctx);
659    if (new_ctx)
660        BN_CTX_free(new_ctx);
661    return ret;
662}
663
664/*-
665 * Indicates whether two points are equal.
666 * Return values:
667 *  -1   error
668 *   0   equal (in affine coordinates)
669 *   1   not equal
670 */
671int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
672                       const EC_POINT *b, BN_CTX *ctx)
673{
674    BIGNUM *aX, *aY, *bX, *bY;
675    BN_CTX *new_ctx = NULL;
676    int ret = -1;
677
678    if (EC_POINT_is_at_infinity(group, a)) {
679        return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
680    }
681
682    if (EC_POINT_is_at_infinity(group, b))
683        return 1;
684
685    if (a->Z_is_one && b->Z_is_one) {
686        return ((BN_cmp(&a->X, &b->X) == 0)
687                && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
688    }
689
690    if (ctx == NULL) {
691        ctx = new_ctx = BN_CTX_new();
692        if (ctx == NULL)
693            return -1;
694    }
695
696    BN_CTX_start(ctx);
697    aX = BN_CTX_get(ctx);
698    aY = BN_CTX_get(ctx);
699    bX = BN_CTX_get(ctx);
700    bY = BN_CTX_get(ctx);
701    if (bY == NULL)
702        goto err;
703
704    if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
705        goto err;
706    if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
707        goto err;
708    ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
709
710 err:
711    if (ctx)
712        BN_CTX_end(ctx);
713    if (new_ctx)
714        BN_CTX_free(new_ctx);
715    return ret;
716}
717
718/* Forces the given EC_POINT to internally use affine coordinates. */
719int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
720                               BN_CTX *ctx)
721{
722    BN_CTX *new_ctx = NULL;
723    BIGNUM *x, *y;
724    int ret = 0;
725
726    if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
727        return 1;
728
729    if (ctx == NULL) {
730        ctx = new_ctx = BN_CTX_new();
731        if (ctx == NULL)
732            return 0;
733    }
734
735    BN_CTX_start(ctx);
736    x = BN_CTX_get(ctx);
737    y = BN_CTX_get(ctx);
738    if (y == NULL)
739        goto err;
740
741    if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
742        goto err;
743    if (!BN_copy(&point->X, x))
744        goto err;
745    if (!BN_copy(&point->Y, y))
746        goto err;
747    if (!BN_one(&point->Z))
748        goto err;
749
750    ret = 1;
751
752 err:
753    if (ctx)
754        BN_CTX_end(ctx);
755    if (new_ctx)
756        BN_CTX_free(new_ctx);
757    return ret;
758}
759
760/*
761 * Forces each of the EC_POINTs in the given array to use affine coordinates.
762 */
763int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
764                                      EC_POINT *points[], BN_CTX *ctx)
765{
766    size_t i;
767
768    for (i = 0; i < num; i++) {
769        if (!group->meth->make_affine(group, points[i], ctx))
770            return 0;
771    }
772
773    return 1;
774}
775
776/* Wrapper to simple binary polynomial field multiplication implementation. */
777int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
778                             const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
779{
780    return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
781}
782
783/* Wrapper to simple binary polynomial field squaring implementation. */
784int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
785                             const BIGNUM *a, BN_CTX *ctx)
786{
787    return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
788}
789
790/* Wrapper to simple binary polynomial field division implementation. */
791int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
792                             const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
793{
794    return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
795}
796
797#endif
798