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-2003 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 
     75 const EC_METHOD *EC_GF2m_simple_method(void)
     76 	{
     77 	static const EC_METHOD ret = {
     78 		NID_X9_62_characteristic_two_field,
     79 		ec_GF2m_simple_group_init,
     80 		ec_GF2m_simple_group_finish,
     81 		ec_GF2m_simple_group_clear_finish,
     82 		ec_GF2m_simple_group_copy,
     83 		ec_GF2m_simple_group_set_curve,
     84 		ec_GF2m_simple_group_get_curve,
     85 		ec_GF2m_simple_group_get_degree,
     86 		ec_GF2m_simple_group_check_discriminant,
     87 		ec_GF2m_simple_point_init,
     88 		ec_GF2m_simple_point_finish,
     89 		ec_GF2m_simple_point_clear_finish,
     90 		ec_GF2m_simple_point_copy,
     91 		ec_GF2m_simple_point_set_to_infinity,
     92 		0 /* set_Jprojective_coordinates_GFp */,
     93 		0 /* get_Jprojective_coordinates_GFp */,
     94 		ec_GF2m_simple_point_set_affine_coordinates,
     95 		ec_GF2m_simple_point_get_affine_coordinates,
     96 		ec_GF2m_simple_set_compressed_coordinates,
     97 		ec_GF2m_simple_point2oct,
     98 		ec_GF2m_simple_oct2point,
     99 		ec_GF2m_simple_add,
    100 		ec_GF2m_simple_dbl,
    101 		ec_GF2m_simple_invert,
    102 		ec_GF2m_simple_is_at_infinity,
    103 		ec_GF2m_simple_is_on_curve,
    104 		ec_GF2m_simple_cmp,
    105 		ec_GF2m_simple_make_affine,
    106 		ec_GF2m_simple_points_make_affine,
    107 
    108 		/* the following three method functions are defined in ec2_mult.c */
    109 		ec_GF2m_simple_mul,
    110 		ec_GF2m_precompute_mult,
    111 		ec_GF2m_have_precompute_mult,
    112 
    113 		ec_GF2m_simple_field_mul,
    114 		ec_GF2m_simple_field_sqr,
    115 		ec_GF2m_simple_field_div,
    116 		0 /* field_encode */,
    117 		0 /* field_decode */,
    118 		0 /* field_set_to_one */ };
    119 
    120 	return &ret;
    121 	}
    122 
    123 
    124 /* Initialize a GF(2^m)-based EC_GROUP structure.
    125  * Note that all other members are handled by EC_GROUP_new.
    126  */
    127 int ec_GF2m_simple_group_init(EC_GROUP *group)
    128 	{
    129 	BN_init(&group->field);
    130 	BN_init(&group->a);
    131 	BN_init(&group->b);
    132 	return 1;
    133 	}
    134 
    135 
    136 /* Free a GF(2^m)-based EC_GROUP structure.
    137  * Note that all other members are handled by EC_GROUP_free.
    138  */
    139 void ec_GF2m_simple_group_finish(EC_GROUP *group)
    140 	{
    141 	BN_free(&group->field);
    142 	BN_free(&group->a);
    143 	BN_free(&group->b);
    144 	}
    145 
    146 
    147 /* Clear and free a GF(2^m)-based EC_GROUP structure.
    148  * Note that all other members are handled by EC_GROUP_clear_free.
    149  */
    150 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
    151 	{
    152 	BN_clear_free(&group->field);
    153 	BN_clear_free(&group->a);
    154 	BN_clear_free(&group->b);
    155 	group->poly[0] = 0;
    156 	group->poly[1] = 0;
    157 	group->poly[2] = 0;
    158 	group->poly[3] = 0;
    159 	group->poly[4] = 0;
    160 	}
    161 
    162 
    163 /* Copy a GF(2^m)-based EC_GROUP structure.
    164  * Note that all other members are handled by EC_GROUP_copy.
    165  */
    166 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
    167 	{
    168 	int i;
    169 	if (!BN_copy(&dest->field, &src->field)) return 0;
    170 	if (!BN_copy(&dest->a, &src->a)) return 0;
    171 	if (!BN_copy(&dest->b, &src->b)) return 0;
    172 	dest->poly[0] = src->poly[0];
    173 	dest->poly[1] = src->poly[1];
    174 	dest->poly[2] = src->poly[2];
    175 	dest->poly[3] = src->poly[3];
    176 	dest->poly[4] = src->poly[4];
    177 	if(bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
    178 		return 0;
    179 	if(bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
    180 		return 0;
    181 	for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
    182 	for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
    183 	return 1;
    184 	}
    185 
    186 
    187 /* Set the curve parameters of an EC_GROUP structure. */
    188 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
    189 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
    190 	{
    191 	int ret = 0, i;
    192 
    193 	/* group->field */
    194 	if (!BN_copy(&group->field, p)) goto err;
    195 	i = BN_GF2m_poly2arr(&group->field, group->poly, 5);
    196 	if ((i != 5) && (i != 3))
    197 		{
    198 		ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
    199 		goto err;
    200 		}
    201 
    202 	/* group->a */
    203 	if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
    204 	if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
    205 	for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
    206 
    207 	/* group->b */
    208 	if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
    209 	if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
    210 	for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
    211 
    212 	ret = 1;
    213   err:
    214 	return ret;
    215 	}
    216 
    217 
    218 /* Get the curve parameters of an EC_GROUP structure.
    219  * If p, a, or b are NULL then there values will not be set but the method will return with success.
    220  */
    221 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
    222 	{
    223 	int ret = 0;
    224 
    225 	if (p != NULL)
    226 		{
    227 		if (!BN_copy(p, &group->field)) return 0;
    228 		}
    229 
    230 	if (a != NULL)
    231 		{
    232 		if (!BN_copy(a, &group->a)) goto err;
    233 		}
    234 
    235 	if (b != NULL)
    236 		{
    237 		if (!BN_copy(b, &group->b)) goto err;
    238 		}
    239 
    240 	ret = 1;
    241 
    242   err:
    243 	return ret;
    244 	}
    245 
    246 
    247 /* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
    248 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
    249 	{
    250 	return BN_num_bits(&group->field)-1;
    251 	}
    252 
    253 
    254 /* Checks the discriminant of the curve.
    255  * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
    256  */
    257 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
    258 	{
    259 	int ret = 0;
    260 	BIGNUM *b;
    261 	BN_CTX *new_ctx = NULL;
    262 
    263 	if (ctx == NULL)
    264 		{
    265 		ctx = new_ctx = BN_CTX_new();
    266 		if (ctx == NULL)
    267 			{
    268 			ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
    269 			goto err;
    270 			}
    271 		}
    272 	BN_CTX_start(ctx);
    273 	b = BN_CTX_get(ctx);
    274 	if (b == NULL) goto err;
    275 
    276 	if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
    277 
    278 	/* check the discriminant:
    279 	 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
    280 	 */
    281 	if (BN_is_zero(b)) goto err;
    282 
    283 	ret = 1;
    284 
    285 err:
    286 	if (ctx != NULL)
    287 		BN_CTX_end(ctx);
    288 	if (new_ctx != NULL)
    289 		BN_CTX_free(new_ctx);
    290 	return ret;
    291 	}
    292 
    293 
    294 /* Initializes an EC_POINT. */
    295 int ec_GF2m_simple_point_init(EC_POINT *point)
    296 	{
    297 	BN_init(&point->X);
    298 	BN_init(&point->Y);
    299 	BN_init(&point->Z);
    300 	return 1;
    301 	}
    302 
    303 
    304 /* Frees an EC_POINT. */
    305 void ec_GF2m_simple_point_finish(EC_POINT *point)
    306 	{
    307 	BN_free(&point->X);
    308 	BN_free(&point->Y);
    309 	BN_free(&point->Z);
    310 	}
    311 
    312 
    313 /* Clears and frees an EC_POINT. */
    314 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
    315 	{
    316 	BN_clear_free(&point->X);
    317 	BN_clear_free(&point->Y);
    318 	BN_clear_free(&point->Z);
    319 	point->Z_is_one = 0;
    320 	}
    321 
    322 
    323 /* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
    324 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
    325 	{
    326 	if (!BN_copy(&dest->X, &src->X)) return 0;
    327 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
    328 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
    329 	dest->Z_is_one = src->Z_is_one;
    330 
    331 	return 1;
    332 	}
    333 
    334 
    335 /* Set an EC_POINT to the point at infinity.
    336  * A point at infinity is represented by having Z=0.
    337  */
    338 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
    339 	{
    340 	point->Z_is_one = 0;
    341 	BN_zero(&point->Z);
    342 	return 1;
    343 	}
    344 
    345 
    346 /* Set the coordinates of an EC_POINT using affine coordinates.
    347  * Note that the simple implementation only uses affine coordinates.
    348  */
    349 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
    350 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
    351 	{
    352 	int ret = 0;
    353 	if (x == NULL || y == NULL)
    354 		{
    355 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
    356 		return 0;
    357 		}
    358 
    359 	if (!BN_copy(&point->X, x)) goto err;
    360 	BN_set_negative(&point->X, 0);
    361 	if (!BN_copy(&point->Y, y)) goto err;
    362 	BN_set_negative(&point->Y, 0);
    363 	if (!BN_copy(&point->Z, BN_value_one())) goto err;
    364 	BN_set_negative(&point->Z, 0);
    365 	point->Z_is_one = 1;
    366 	ret = 1;
    367 
    368   err:
    369 	return ret;
    370 	}
    371 
    372 
    373 /* Gets the affine coordinates of an EC_POINT.
    374  * Note that the simple implementation only uses affine coordinates.
    375  */
    376 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
    377 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
    378 	{
    379 	int ret = 0;
    380 
    381 	if (EC_POINT_is_at_infinity(group, point))
    382 		{
    383 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
    384 		return 0;
    385 		}
    386 
    387 	if (BN_cmp(&point->Z, BN_value_one()))
    388 		{
    389 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    390 		return 0;
    391 		}
    392 	if (x != NULL)
    393 		{
    394 		if (!BN_copy(x, &point->X)) goto err;
    395 		BN_set_negative(x, 0);
    396 		}
    397 	if (y != NULL)
    398 		{
    399 		if (!BN_copy(y, &point->Y)) goto err;
    400 		BN_set_negative(y, 0);
    401 		}
    402 	ret = 1;
    403 
    404  err:
    405 	return ret;
    406 	}
    407 
    408 
    409 /* Include patented algorithms. */
    410 #include "ec2_smpt.c"
    411 
    412 
    413 /* Converts an EC_POINT to an octet string.
    414  * If buf is NULL, the encoded length will be returned.
    415  * If the length len of buf is smaller than required an error will be returned.
    416  *
    417  * The point compression section of this function is patented by Certicom Corp.
    418  * under US Patent 6,141,420.  Point compression is disabled by default and can
    419  * be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at
    420  * Configure-time.
    421  */
    422 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
    423 	unsigned char *buf, size_t len, BN_CTX *ctx)
    424 	{
    425 	size_t ret;
    426 	BN_CTX *new_ctx = NULL;
    427 	int used_ctx = 0;
    428 	BIGNUM *x, *y, *yxi;
    429 	size_t field_len, i, skip;
    430 
    431 #ifndef OPENSSL_EC_BIN_PT_COMP
    432 	if ((form == POINT_CONVERSION_COMPRESSED) || (form == POINT_CONVERSION_HYBRID))
    433 		{
    434 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED);
    435 		goto err;
    436 		}
    437 #endif
    438 
    439 	if ((form != POINT_CONVERSION_COMPRESSED)
    440 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
    441 		&& (form != POINT_CONVERSION_HYBRID))
    442 		{
    443 		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
    444 		goto err;
    445 		}
    446 
    447 	if (EC_POINT_is_at_infinity(group, point))
    448 		{
    449 		/* encodes to a single 0 octet */
    450 		if (buf != NULL)
    451 			{
    452 			if (len < 1)
    453 				{
    454 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
    455 				return 0;
    456 				}
    457 			buf[0] = 0;
    458 			}
    459 		return 1;
    460 		}
    461 
    462 
    463 	/* ret := required output buffer length */
    464 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
    465 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
    466 
    467 	/* if 'buf' is NULL, just return required length */
    468 	if (buf != NULL)
    469 		{
    470 		if (len < ret)
    471 			{
    472 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
    473 			goto err;
    474 			}
    475 
    476 		if (ctx == NULL)
    477 			{
    478 			ctx = new_ctx = BN_CTX_new();
    479 			if (ctx == NULL)
    480 				return 0;
    481 			}
    482 
    483 		BN_CTX_start(ctx);
    484 		used_ctx = 1;
    485 		x = BN_CTX_get(ctx);
    486 		y = BN_CTX_get(ctx);
    487 		yxi = BN_CTX_get(ctx);
    488 		if (yxi == NULL) goto err;
    489 
    490 		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
    491 
    492 		buf[0] = form;
    493 #ifdef OPENSSL_EC_BIN_PT_COMP
    494 		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
    495 			{
    496 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
    497 			if (BN_is_odd(yxi)) buf[0]++;
    498 			}
    499 #endif
    500 
    501 		i = 1;
    502 
    503 		skip = field_len - BN_num_bytes(x);
    504 		if (skip > field_len)
    505 			{
    506 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    507 			goto err;
    508 			}
    509 		while (skip > 0)
    510 			{
    511 			buf[i++] = 0;
    512 			skip--;
    513 			}
    514 		skip = BN_bn2bin(x, buf + i);
    515 		i += skip;
    516 		if (i != 1 + field_len)
    517 			{
    518 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    519 			goto err;
    520 			}
    521 
    522 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
    523 			{
    524 			skip = field_len - BN_num_bytes(y);
    525 			if (skip > field_len)
    526 				{
    527 				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    528 				goto err;
    529 				}
    530 			while (skip > 0)
    531 				{
    532 				buf[i++] = 0;
    533 				skip--;
    534 				}
    535 			skip = BN_bn2bin(y, buf + i);
    536 			i += skip;
    537 			}
    538 
    539 		if (i != ret)
    540 			{
    541 			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    542 			goto err;
    543 			}
    544 		}
    545 
    546 	if (used_ctx)
    547 		BN_CTX_end(ctx);
    548 	if (new_ctx != NULL)
    549 		BN_CTX_free(new_ctx);
    550 	return ret;
    551 
    552  err:
    553 	if (used_ctx)
    554 		BN_CTX_end(ctx);
    555 	if (new_ctx != NULL)
    556 		BN_CTX_free(new_ctx);
    557 	return 0;
    558 	}
    559 
    560 
    561 /* Converts an octet string representation to an EC_POINT.
    562  * Note that the simple implementation only uses affine coordinates.
    563  */
    564 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
    565 	const unsigned char *buf, size_t len, BN_CTX *ctx)
    566 	{
    567 	point_conversion_form_t form;
    568 	int y_bit;
    569 	BN_CTX *new_ctx = NULL;
    570 	BIGNUM *x, *y, *yxi;
    571 	size_t field_len, enc_len;
    572 	int ret = 0;
    573 
    574 	if (len == 0)
    575 		{
    576 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
    577 		return 0;
    578 		}
    579 	form = buf[0];
    580 	y_bit = form & 1;
    581 	form = form & ~1U;
    582 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
    583 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
    584 		&& (form != POINT_CONVERSION_HYBRID))
    585 		{
    586 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    587 		return 0;
    588 		}
    589 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
    590 		{
    591 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    592 		return 0;
    593 		}
    594 
    595 	if (form == 0)
    596 		{
    597 		if (len != 1)
    598 			{
    599 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    600 			return 0;
    601 			}
    602 
    603 		return EC_POINT_set_to_infinity(group, point);
    604 		}
    605 
    606 	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
    607 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
    608 
    609 	if (len != enc_len)
    610 		{
    611 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    612 		return 0;
    613 		}
    614 
    615 	if (ctx == NULL)
    616 		{
    617 		ctx = new_ctx = BN_CTX_new();
    618 		if (ctx == NULL)
    619 			return 0;
    620 		}
    621 
    622 	BN_CTX_start(ctx);
    623 	x = BN_CTX_get(ctx);
    624 	y = BN_CTX_get(ctx);
    625 	yxi = BN_CTX_get(ctx);
    626 	if (yxi == NULL) goto err;
    627 
    628 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
    629 	if (BN_ucmp(x, &group->field) >= 0)
    630 		{
    631 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    632 		goto err;
    633 		}
    634 
    635 	if (form == POINT_CONVERSION_COMPRESSED)
    636 		{
    637 		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
    638 		}
    639 	else
    640 		{
    641 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
    642 		if (BN_ucmp(y, &group->field) >= 0)
    643 			{
    644 			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    645 			goto err;
    646 			}
    647 		if (form == POINT_CONVERSION_HYBRID)
    648 			{
    649 			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
    650 			if (y_bit != BN_is_odd(yxi))
    651 				{
    652 				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    653 				goto err;
    654 				}
    655 			}
    656 
    657 		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
    658 		}
    659 
    660 	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
    661 		{
    662 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
    663 		goto err;
    664 		}
    665 
    666 	ret = 1;
    667 
    668  err:
    669 	BN_CTX_end(ctx);
    670 	if (new_ctx != NULL)
    671 		BN_CTX_free(new_ctx);
    672 	return ret;
    673 	}
    674 
    675 
    676 /* Computes a + b and stores the result in r.  r could be a or b, a could be b.
    677  * Uses algorithm A.10.2 of IEEE P1363.
    678  */
    679 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
    680 	{
    681 	BN_CTX *new_ctx = NULL;
    682 	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
    683 	int ret = 0;
    684 
    685 	if (EC_POINT_is_at_infinity(group, a))
    686 		{
    687 		if (!EC_POINT_copy(r, b)) return 0;
    688 		return 1;
    689 		}
    690 
    691 	if (EC_POINT_is_at_infinity(group, b))
    692 		{
    693 		if (!EC_POINT_copy(r, a)) return 0;
    694 		return 1;
    695 		}
    696 
    697 	if (ctx == NULL)
    698 		{
    699 		ctx = new_ctx = BN_CTX_new();
    700 		if (ctx == NULL)
    701 			return 0;
    702 		}
    703 
    704 	BN_CTX_start(ctx);
    705 	x0 = BN_CTX_get(ctx);
    706 	y0 = BN_CTX_get(ctx);
    707 	x1 = BN_CTX_get(ctx);
    708 	y1 = BN_CTX_get(ctx);
    709 	x2 = BN_CTX_get(ctx);
    710 	y2 = BN_CTX_get(ctx);
    711 	s = BN_CTX_get(ctx);
    712 	t = BN_CTX_get(ctx);
    713 	if (t == NULL) goto err;
    714 
    715 	if (a->Z_is_one)
    716 		{
    717 		if (!BN_copy(x0, &a->X)) goto err;
    718 		if (!BN_copy(y0, &a->Y)) goto err;
    719 		}
    720 	else
    721 		{
    722 		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
    723 		}
    724 	if (b->Z_is_one)
    725 		{
    726 		if (!BN_copy(x1, &b->X)) goto err;
    727 		if (!BN_copy(y1, &b->Y)) goto err;
    728 		}
    729 	else
    730 		{
    731 		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
    732 		}
    733 
    734 
    735 	if (BN_GF2m_cmp(x0, x1))
    736 		{
    737 		if (!BN_GF2m_add(t, x0, x1)) goto err;
    738 		if (!BN_GF2m_add(s, y0, y1)) goto err;
    739 		if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
    740 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
    741 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
    742 		if (!BN_GF2m_add(x2, x2, s)) goto err;
    743 		if (!BN_GF2m_add(x2, x2, t)) goto err;
    744 		}
    745 	else
    746 		{
    747 		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
    748 			{
    749 			if (!EC_POINT_set_to_infinity(group, r)) goto err;
    750 			ret = 1;
    751 			goto err;
    752 			}
    753 		if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
    754 		if (!BN_GF2m_add(s, s, x1)) goto err;
    755 
    756 		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
    757 		if (!BN_GF2m_add(x2, x2, s)) goto err;
    758 		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
    759 		}
    760 
    761 	if (!BN_GF2m_add(y2, x1, x2)) goto err;
    762 	if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
    763 	if (!BN_GF2m_add(y2, y2, x2)) goto err;
    764 	if (!BN_GF2m_add(y2, y2, y1)) goto err;
    765 
    766 	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
    767 
    768 	ret = 1;
    769 
    770  err:
    771 	BN_CTX_end(ctx);
    772 	if (new_ctx != NULL)
    773 		BN_CTX_free(new_ctx);
    774 	return ret;
    775 	}
    776 
    777 
    778 /* Computes 2 * a and stores the result in r.  r could be a.
    779  * Uses algorithm A.10.2 of IEEE P1363.
    780  */
    781 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
    782 	{
    783 	return ec_GF2m_simple_add(group, r, a, a, ctx);
    784 	}
    785 
    786 
    787 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
    788 	{
    789 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
    790 		/* point is its own inverse */
    791 		return 1;
    792 
    793 	if (!EC_POINT_make_affine(group, point, ctx)) return 0;
    794 	return BN_GF2m_add(&point->Y, &point->X, &point->Y);
    795 	}
    796 
    797 
    798 /* Indicates whether the given point is the point at infinity. */
    799 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
    800 	{
    801 	return BN_is_zero(&point->Z);
    802 	}
    803 
    804 
    805 /* Determines whether the given EC_POINT is an actual point on the curve defined
    806  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
    807  *      y^2 + x*y = x^3 + a*x^2 + b.
    808  */
    809 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
    810 	{
    811 	int ret = -1;
    812 	BN_CTX *new_ctx = NULL;
    813 	BIGNUM *lh, *y2;
    814 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
    815 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
    816 
    817 	if (EC_POINT_is_at_infinity(group, point))
    818 		return 1;
    819 
    820 	field_mul = group->meth->field_mul;
    821 	field_sqr = group->meth->field_sqr;
    822 
    823 	/* only support affine coordinates */
    824 	if (!point->Z_is_one) goto err;
    825 
    826 	if (ctx == NULL)
    827 		{
    828 		ctx = new_ctx = BN_CTX_new();
    829 		if (ctx == NULL)
    830 			return -1;
    831 		}
    832 
    833 	BN_CTX_start(ctx);
    834 	y2 = BN_CTX_get(ctx);
    835 	lh = BN_CTX_get(ctx);
    836 	if (lh == NULL) goto err;
    837 
    838 	/* We have a curve defined by a Weierstrass equation
    839 	 *      y^2 + x*y = x^3 + a*x^2 + b.
    840 	 *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
    841 	 *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
    842 	 */
    843 	if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
    844 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
    845 	if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
    846 	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
    847 	if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
    848 	if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
    849 	if (!BN_GF2m_add(lh, lh, y2)) goto err;
    850 	ret = BN_is_zero(lh);
    851  err:
    852 	if (ctx) BN_CTX_end(ctx);
    853 	if (new_ctx) BN_CTX_free(new_ctx);
    854 	return ret;
    855 	}
    856 
    857 
    858 /* Indicates whether two points are equal.
    859  * Return values:
    860  *  -1   error
    861  *   0   equal (in affine coordinates)
    862  *   1   not equal
    863  */
    864 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
    865 	{
    866 	BIGNUM *aX, *aY, *bX, *bY;
    867 	BN_CTX *new_ctx = NULL;
    868 	int ret = -1;
    869 
    870 	if (EC_POINT_is_at_infinity(group, a))
    871 		{
    872 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
    873 		}
    874 
    875 	if (a->Z_is_one && b->Z_is_one)
    876 		{
    877 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
    878 		}
    879 
    880 	if (ctx == NULL)
    881 		{
    882 		ctx = new_ctx = BN_CTX_new();
    883 		if (ctx == NULL)
    884 			return -1;
    885 		}
    886 
    887 	BN_CTX_start(ctx);
    888 	aX = BN_CTX_get(ctx);
    889 	aY = BN_CTX_get(ctx);
    890 	bX = BN_CTX_get(ctx);
    891 	bY = BN_CTX_get(ctx);
    892 	if (bY == NULL) goto err;
    893 
    894 	if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
    895 	if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
    896 	ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
    897 
    898   err:
    899 	if (ctx) BN_CTX_end(ctx);
    900 	if (new_ctx) BN_CTX_free(new_ctx);
    901 	return ret;
    902 	}
    903 
    904 
    905 /* Forces the given EC_POINT to internally use affine coordinates. */
    906 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
    907 	{
    908 	BN_CTX *new_ctx = NULL;
    909 	BIGNUM *x, *y;
    910 	int ret = 0;
    911 
    912 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
    913 		return 1;
    914 
    915 	if (ctx == NULL)
    916 		{
    917 		ctx = new_ctx = BN_CTX_new();
    918 		if (ctx == NULL)
    919 			return 0;
    920 		}
    921 
    922 	BN_CTX_start(ctx);
    923 	x = BN_CTX_get(ctx);
    924 	y = BN_CTX_get(ctx);
    925 	if (y == NULL) goto err;
    926 
    927 	if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
    928 	if (!BN_copy(&point->X, x)) goto err;
    929 	if (!BN_copy(&point->Y, y)) goto err;
    930 	if (!BN_one(&point->Z)) goto err;
    931 
    932 	ret = 1;
    933 
    934   err:
    935 	if (ctx) BN_CTX_end(ctx);
    936 	if (new_ctx) BN_CTX_free(new_ctx);
    937 	return ret;
    938 	}
    939 
    940 
    941 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
    942 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
    943 	{
    944 	size_t i;
    945 
    946 	for (i = 0; i < num; i++)
    947 		{
    948 		if (!group->meth->make_affine(group, points[i], ctx)) return 0;
    949 		}
    950 
    951 	return 1;
    952 	}
    953 
    954 
    955 /* Wrapper to simple binary polynomial field multiplication implementation. */
    956 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
    957 	{
    958 	return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
    959 	}
    960 
    961 
    962 /* Wrapper to simple binary polynomial field squaring implementation. */
    963 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
    964 	{
    965 	return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
    966 	}
    967 
    968 
    969 /* Wrapper to simple binary polynomial field division implementation. */
    970 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
    971 	{
    972 	return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
    973 	}
    974