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