Home | History | Annotate | Download | only in ec
      1 /* crypto/ec/ecp_smpl.c */
      2 /* Includes code written by Lenka Fibikova <fibikova (at) exp-math.uni-essen.de>
      3  * for the OpenSSL project.
      4  * Includes code written by Bodo Moeller for the OpenSSL project.
      5 */
      6 /* ====================================================================
      7  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  *
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  *
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in
     18  *    the documentation and/or other materials provided with the
     19  *    distribution.
     20  *
     21  * 3. All advertising materials mentioning features or use of this
     22  *    software must display the following acknowledgment:
     23  *    "This product includes software developed by the OpenSSL Project
     24  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     25  *
     26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     27  *    endorse or promote products derived from this software without
     28  *    prior written permission. For written permission, please contact
     29  *    openssl-core (at) openssl.org.
     30  *
     31  * 5. Products derived from this software may not be called "OpenSSL"
     32  *    nor may "OpenSSL" appear in their names without prior written
     33  *    permission of the OpenSSL Project.
     34  *
     35  * 6. Redistributions of any form whatsoever must retain the following
     36  *    acknowledgment:
     37  *    "This product includes software developed by the OpenSSL Project
     38  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     51  * OF THE POSSIBILITY OF SUCH DAMAGE.
     52  * ====================================================================
     53  *
     54  * This product includes cryptographic software written by Eric Young
     55  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     56  * Hudson (tjh (at) cryptsoft.com).
     57  *
     58  */
     59 /* ====================================================================
     60  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
     61  * Portions of this software developed by SUN MICROSYSTEMS, INC.,
     62  * and contributed to the OpenSSL project.
     63  */
     64 
     65 #include <openssl/err.h>
     66 #include <openssl/symhacks.h>
     67 
     68 #include "ec_lcl.h"
     69 
     70 const EC_METHOD *EC_GFp_simple_method(void)
     71 	{
     72 	static const EC_METHOD ret = {
     73 		NID_X9_62_prime_field,
     74 		ec_GFp_simple_group_init,
     75 		ec_GFp_simple_group_finish,
     76 		ec_GFp_simple_group_clear_finish,
     77 		ec_GFp_simple_group_copy,
     78 		ec_GFp_simple_group_set_curve,
     79 		ec_GFp_simple_group_get_curve,
     80 		ec_GFp_simple_group_get_degree,
     81 		ec_GFp_simple_group_check_discriminant,
     82 		ec_GFp_simple_point_init,
     83 		ec_GFp_simple_point_finish,
     84 		ec_GFp_simple_point_clear_finish,
     85 		ec_GFp_simple_point_copy,
     86 		ec_GFp_simple_point_set_to_infinity,
     87 		ec_GFp_simple_set_Jprojective_coordinates_GFp,
     88 		ec_GFp_simple_get_Jprojective_coordinates_GFp,
     89 		ec_GFp_simple_point_set_affine_coordinates,
     90 		ec_GFp_simple_point_get_affine_coordinates,
     91 		ec_GFp_simple_set_compressed_coordinates,
     92 		ec_GFp_simple_point2oct,
     93 		ec_GFp_simple_oct2point,
     94 		ec_GFp_simple_add,
     95 		ec_GFp_simple_dbl,
     96 		ec_GFp_simple_invert,
     97 		ec_GFp_simple_is_at_infinity,
     98 		ec_GFp_simple_is_on_curve,
     99 		ec_GFp_simple_cmp,
    100 		ec_GFp_simple_make_affine,
    101 		ec_GFp_simple_points_make_affine,
    102 		0 /* mul */,
    103 		0 /* precompute_mult */,
    104 		0 /* have_precompute_mult */,
    105 		ec_GFp_simple_field_mul,
    106 		ec_GFp_simple_field_sqr,
    107 		0 /* field_div */,
    108 		0 /* field_encode */,
    109 		0 /* field_decode */,
    110 		0 /* field_set_to_one */ };
    111 
    112 	return &ret;
    113 	}
    114 
    115 
    116 /* Most method functions in this file are designed to work with
    117  * non-trivial representations of field elements if necessary
    118  * (see ecp_mont.c): while standard modular addition and subtraction
    119  * are used, the field_mul and field_sqr methods will be used for
    120  * multiplication, and field_encode and field_decode (if defined)
    121  * will be used for converting between representations.
    122 
    123  * Functions ec_GFp_simple_points_make_affine() and
    124  * ec_GFp_simple_point_get_affine_coordinates() specifically assume
    125  * that if a non-trivial representation is used, it is a Montgomery
    126  * representation (i.e. 'encoding' means multiplying by some factor R).
    127  */
    128 
    129 
    130 int ec_GFp_simple_group_init(EC_GROUP *group)
    131 	{
    132 	BN_init(&group->field);
    133 	BN_init(&group->a);
    134 	BN_init(&group->b);
    135 	group->a_is_minus3 = 0;
    136 	return 1;
    137 	}
    138 
    139 
    140 void ec_GFp_simple_group_finish(EC_GROUP *group)
    141 	{
    142 	BN_free(&group->field);
    143 	BN_free(&group->a);
    144 	BN_free(&group->b);
    145 	}
    146 
    147 
    148 void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
    149 	{
    150 	BN_clear_free(&group->field);
    151 	BN_clear_free(&group->a);
    152 	BN_clear_free(&group->b);
    153 	}
    154 
    155 
    156 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
    157 	{
    158 	if (!BN_copy(&dest->field, &src->field)) return 0;
    159 	if (!BN_copy(&dest->a, &src->a)) return 0;
    160 	if (!BN_copy(&dest->b, &src->b)) return 0;
    161 
    162 	dest->a_is_minus3 = src->a_is_minus3;
    163 
    164 	return 1;
    165 	}
    166 
    167 
    168 int ec_GFp_simple_group_set_curve(EC_GROUP *group,
    169 	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
    170 	{
    171 	int ret = 0;
    172 	BN_CTX *new_ctx = NULL;
    173 	BIGNUM *tmp_a;
    174 
    175 	/* p must be a prime > 3 */
    176 	if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
    177 		{
    178 		ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
    179 		return 0;
    180 		}
    181 
    182 	if (ctx == NULL)
    183 		{
    184 		ctx = new_ctx = BN_CTX_new();
    185 		if (ctx == NULL)
    186 			return 0;
    187 		}
    188 
    189 	BN_CTX_start(ctx);
    190 	tmp_a = BN_CTX_get(ctx);
    191 	if (tmp_a == NULL) goto err;
    192 
    193 	/* group->field */
    194 	if (!BN_copy(&group->field, p)) goto err;
    195 	BN_set_negative(&group->field, 0);
    196 
    197 	/* group->a */
    198 	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
    199 	if (group->meth->field_encode)
    200 		{ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }
    201 	else
    202 		if (!BN_copy(&group->a, tmp_a)) goto err;
    203 
    204 	/* group->b */
    205 	if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
    206 	if (group->meth->field_encode)
    207 		if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
    208 
    209 	/* group->a_is_minus3 */
    210 	if (!BN_add_word(tmp_a, 3)) goto err;
    211 	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
    212 
    213 	ret = 1;
    214 
    215  err:
    216 	BN_CTX_end(ctx);
    217 	if (new_ctx != NULL)
    218 		BN_CTX_free(new_ctx);
    219 	return ret;
    220 	}
    221 
    222 
    223 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
    224 	{
    225 	int ret = 0;
    226 	BN_CTX *new_ctx = NULL;
    227 
    228 	if (p != NULL)
    229 		{
    230 		if (!BN_copy(p, &group->field)) return 0;
    231 		}
    232 
    233 	if (a != NULL || b != NULL)
    234 		{
    235 		if (group->meth->field_decode)
    236 			{
    237 			if (ctx == NULL)
    238 				{
    239 				ctx = new_ctx = BN_CTX_new();
    240 				if (ctx == NULL)
    241 					return 0;
    242 				}
    243 			if (a != NULL)
    244 				{
    245 				if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
    246 				}
    247 			if (b != NULL)
    248 				{
    249 				if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
    250 				}
    251 			}
    252 		else
    253 			{
    254 			if (a != NULL)
    255 				{
    256 				if (!BN_copy(a, &group->a)) goto err;
    257 				}
    258 			if (b != NULL)
    259 				{
    260 				if (!BN_copy(b, &group->b)) goto err;
    261 				}
    262 			}
    263 		}
    264 
    265 	ret = 1;
    266 
    267  err:
    268 	if (new_ctx)
    269 		BN_CTX_free(new_ctx);
    270 	return ret;
    271 	}
    272 
    273 
    274 int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
    275 	{
    276 	return BN_num_bits(&group->field);
    277 	}
    278 
    279 
    280 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
    281 	{
    282 	int ret = 0;
    283 	BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
    284 	const BIGNUM *p = &group->field;
    285 	BN_CTX *new_ctx = NULL;
    286 
    287 	if (ctx == NULL)
    288 		{
    289 		ctx = new_ctx = BN_CTX_new();
    290 		if (ctx == NULL)
    291 			{
    292 			ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
    293 			goto err;
    294 			}
    295 		}
    296 	BN_CTX_start(ctx);
    297 	a = BN_CTX_get(ctx);
    298 	b = BN_CTX_get(ctx);
    299 	tmp_1 = BN_CTX_get(ctx);
    300 	tmp_2 = BN_CTX_get(ctx);
    301 	order = BN_CTX_get(ctx);
    302 	if (order == NULL) goto err;
    303 
    304 	if (group->meth->field_decode)
    305 		{
    306 		if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
    307 		if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
    308 		}
    309 	else
    310 		{
    311 		if (!BN_copy(a, &group->a)) goto err;
    312 		if (!BN_copy(b, &group->b)) goto err;
    313 		}
    314 
    315 	/* check the discriminant:
    316 	 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
    317          * 0 =< a, b < p */
    318 	if (BN_is_zero(a))
    319 		{
    320 		if (BN_is_zero(b)) goto err;
    321 		}
    322 	else if (!BN_is_zero(b))
    323 		{
    324 		if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
    325 		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
    326 		if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
    327 		/* tmp_1 = 4*a^3 */
    328 
    329 		if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
    330 		if (!BN_mul_word(tmp_2, 27)) goto err;
    331 		/* tmp_2 = 27*b^2 */
    332 
    333 		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
    334 		if (BN_is_zero(a)) goto err;
    335 		}
    336 	ret = 1;
    337 
    338 err:
    339 	if (ctx != NULL)
    340 		BN_CTX_end(ctx);
    341 	if (new_ctx != NULL)
    342 		BN_CTX_free(new_ctx);
    343 	return ret;
    344 	}
    345 
    346 
    347 int ec_GFp_simple_point_init(EC_POINT *point)
    348 	{
    349 	BN_init(&point->X);
    350 	BN_init(&point->Y);
    351 	BN_init(&point->Z);
    352 	point->Z_is_one = 0;
    353 
    354 	return 1;
    355 	}
    356 
    357 
    358 void ec_GFp_simple_point_finish(EC_POINT *point)
    359 	{
    360 	BN_free(&point->X);
    361 	BN_free(&point->Y);
    362 	BN_free(&point->Z);
    363 	}
    364 
    365 
    366 void ec_GFp_simple_point_clear_finish(EC_POINT *point)
    367 	{
    368 	BN_clear_free(&point->X);
    369 	BN_clear_free(&point->Y);
    370 	BN_clear_free(&point->Z);
    371 	point->Z_is_one = 0;
    372 	}
    373 
    374 
    375 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
    376 	{
    377 	if (!BN_copy(&dest->X, &src->X)) return 0;
    378 	if (!BN_copy(&dest->Y, &src->Y)) return 0;
    379 	if (!BN_copy(&dest->Z, &src->Z)) return 0;
    380 	dest->Z_is_one = src->Z_is_one;
    381 
    382 	return 1;
    383 	}
    384 
    385 
    386 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
    387 	{
    388 	point->Z_is_one = 0;
    389 	BN_zero(&point->Z);
    390 	return 1;
    391 	}
    392 
    393 
    394 int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
    395 	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
    396 	{
    397 	BN_CTX *new_ctx = NULL;
    398 	int ret = 0;
    399 
    400 	if (ctx == NULL)
    401 		{
    402 		ctx = new_ctx = BN_CTX_new();
    403 		if (ctx == NULL)
    404 			return 0;
    405 		}
    406 
    407 	if (x != NULL)
    408 		{
    409 		if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
    410 		if (group->meth->field_encode)
    411 			{
    412 			if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
    413 			}
    414 		}
    415 
    416 	if (y != NULL)
    417 		{
    418 		if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
    419 		if (group->meth->field_encode)
    420 			{
    421 			if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
    422 			}
    423 		}
    424 
    425 	if (z != NULL)
    426 		{
    427 		int Z_is_one;
    428 
    429 		if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
    430 		Z_is_one = BN_is_one(&point->Z);
    431 		if (group->meth->field_encode)
    432 			{
    433 			if (Z_is_one && (group->meth->field_set_to_one != 0))
    434 				{
    435 				if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
    436 				}
    437 			else
    438 				{
    439 				if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
    440 				}
    441 			}
    442 		point->Z_is_one = Z_is_one;
    443 		}
    444 
    445 	ret = 1;
    446 
    447  err:
    448 	if (new_ctx != NULL)
    449 		BN_CTX_free(new_ctx);
    450 	return ret;
    451 	}
    452 
    453 
    454 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
    455 	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
    456 	{
    457 	BN_CTX *new_ctx = NULL;
    458 	int ret = 0;
    459 
    460 	if (group->meth->field_decode != 0)
    461 		{
    462 		if (ctx == NULL)
    463 			{
    464 			ctx = new_ctx = BN_CTX_new();
    465 			if (ctx == NULL)
    466 				return 0;
    467 			}
    468 
    469 		if (x != NULL)
    470 			{
    471 			if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
    472 			}
    473 		if (y != NULL)
    474 			{
    475 			if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
    476 			}
    477 		if (z != NULL)
    478 			{
    479 			if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
    480 			}
    481 		}
    482 	else
    483 		{
    484 		if (x != NULL)
    485 			{
    486 			if (!BN_copy(x, &point->X)) goto err;
    487 			}
    488 		if (y != NULL)
    489 			{
    490 			if (!BN_copy(y, &point->Y)) goto err;
    491 			}
    492 		if (z != NULL)
    493 			{
    494 			if (!BN_copy(z, &point->Z)) goto err;
    495 			}
    496 		}
    497 
    498 	ret = 1;
    499 
    500  err:
    501 	if (new_ctx != NULL)
    502 		BN_CTX_free(new_ctx);
    503 	return ret;
    504 	}
    505 
    506 
    507 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
    508 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
    509 	{
    510 	if (x == NULL || y == NULL)
    511 		{
    512 		/* unlike for projective coordinates, we do not tolerate this */
    513 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
    514 		return 0;
    515 		}
    516 
    517 	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
    518 	}
    519 
    520 
    521 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
    522 	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
    523 	{
    524 	BN_CTX *new_ctx = NULL;
    525 	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
    526 	const BIGNUM *Z_;
    527 	int ret = 0;
    528 
    529 	if (EC_POINT_is_at_infinity(group, point))
    530 		{
    531 		ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
    532 		return 0;
    533 		}
    534 
    535 	if (ctx == NULL)
    536 		{
    537 		ctx = new_ctx = BN_CTX_new();
    538 		if (ctx == NULL)
    539 			return 0;
    540 		}
    541 
    542 	BN_CTX_start(ctx);
    543 	Z = BN_CTX_get(ctx);
    544 	Z_1 = BN_CTX_get(ctx);
    545 	Z_2 = BN_CTX_get(ctx);
    546 	Z_3 = BN_CTX_get(ctx);
    547 	if (Z_3 == NULL) goto err;
    548 
    549 	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
    550 
    551 	if (group->meth->field_decode)
    552 		{
    553 		if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
    554 		Z_ = Z;
    555 		}
    556 	else
    557 		{
    558 		Z_ = &point->Z;
    559 		}
    560 
    561 	if (BN_is_one(Z_))
    562 		{
    563 		if (group->meth->field_decode)
    564 			{
    565 			if (x != NULL)
    566 				{
    567 				if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
    568 				}
    569 			if (y != NULL)
    570 				{
    571 				if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
    572 				}
    573 			}
    574 		else
    575 			{
    576 			if (x != NULL)
    577 				{
    578 				if (!BN_copy(x, &point->X)) goto err;
    579 				}
    580 			if (y != NULL)
    581 				{
    582 				if (!BN_copy(y, &point->Y)) goto err;
    583 				}
    584 			}
    585 		}
    586 	else
    587 		{
    588 		if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
    589 			{
    590 			ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
    591 			goto err;
    592 			}
    593 
    594 		if (group->meth->field_encode == 0)
    595 			{
    596 			/* field_sqr works on standard representation */
    597 			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
    598 			}
    599 		else
    600 			{
    601 			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
    602 			}
    603 
    604 		if (x != NULL)
    605 			{
    606 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
    607 			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
    608 			}
    609 
    610 		if (y != NULL)
    611 			{
    612 			if (group->meth->field_encode == 0)
    613 				{
    614 				/* field_mul works on standard representation */
    615 				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
    616 				}
    617 			else
    618 				{
    619 				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
    620 				}
    621 
    622 			/* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
    623 			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
    624 			}
    625 		}
    626 
    627 	ret = 1;
    628 
    629  err:
    630 	BN_CTX_end(ctx);
    631 	if (new_ctx != NULL)
    632 		BN_CTX_free(new_ctx);
    633 	return ret;
    634 	}
    635 
    636 
    637 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
    638 	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
    639 	{
    640 	BN_CTX *new_ctx = NULL;
    641 	BIGNUM *tmp1, *tmp2, *x, *y;
    642 	int ret = 0;
    643 
    644 	/* clear error queue*/
    645 	ERR_clear_error();
    646 
    647 	if (ctx == NULL)
    648 		{
    649 		ctx = new_ctx = BN_CTX_new();
    650 		if (ctx == NULL)
    651 			return 0;
    652 		}
    653 
    654 	y_bit = (y_bit != 0);
    655 
    656 	BN_CTX_start(ctx);
    657 	tmp1 = BN_CTX_get(ctx);
    658 	tmp2 = BN_CTX_get(ctx);
    659 	x = BN_CTX_get(ctx);
    660 	y = BN_CTX_get(ctx);
    661 	if (y == NULL) goto err;
    662 
    663 	/* Recover y.  We have a Weierstrass equation
    664 	 *     y^2 = x^3 + a*x + b,
    665 	 * so  y  is one of the square roots of  x^3 + a*x + b.
    666 	 */
    667 
    668 	/* tmp1 := x^3 */
    669 	if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
    670 	if (group->meth->field_decode == 0)
    671 		{
    672 		/* field_{sqr,mul} work on standard representation */
    673 		if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
    674 		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
    675 		}
    676 	else
    677 		{
    678 		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
    679 		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
    680 		}
    681 
    682 	/* tmp1 := tmp1 + a*x */
    683 	if (group->a_is_minus3)
    684 		{
    685 		if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
    686 		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
    687 		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
    688 		}
    689 	else
    690 		{
    691 		if (group->meth->field_decode)
    692 			{
    693 			if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
    694 			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
    695 			}
    696 		else
    697 			{
    698 			/* field_mul works on standard representation */
    699 			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
    700 			}
    701 
    702 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
    703 		}
    704 
    705 	/* tmp1 := tmp1 + b */
    706 	if (group->meth->field_decode)
    707 		{
    708 		if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
    709 		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
    710 		}
    711 	else
    712 		{
    713 		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
    714 		}
    715 
    716 	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
    717 		{
    718 		unsigned long err = ERR_peek_last_error();
    719 
    720 		if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
    721 			{
    722 			ERR_clear_error();
    723 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
    724 			}
    725 		else
    726 			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
    727 		goto err;
    728 		}
    729 
    730 	if (y_bit != BN_is_odd(y))
    731 		{
    732 		if (BN_is_zero(y))
    733 			{
    734 			int kron;
    735 
    736 			kron = BN_kronecker(x, &group->field, ctx);
    737 			if (kron == -2) goto err;
    738 
    739 			if (kron == 1)
    740 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
    741 			else
    742 				/* BN_mod_sqrt() should have cought this error (not a square) */
    743 				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
    744 			goto err;
    745 			}
    746 		if (!BN_usub(y, &group->field, y)) goto err;
    747 		}
    748 	if (y_bit != BN_is_odd(y))
    749 		{
    750 		ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
    751 		goto err;
    752 		}
    753 
    754 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
    755 
    756 	ret = 1;
    757 
    758  err:
    759 	BN_CTX_end(ctx);
    760 	if (new_ctx != NULL)
    761 		BN_CTX_free(new_ctx);
    762 	return ret;
    763 	}
    764 
    765 
    766 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
    767 	unsigned char *buf, size_t len, BN_CTX *ctx)
    768 	{
    769 	size_t ret;
    770 	BN_CTX *new_ctx = NULL;
    771 	int used_ctx = 0;
    772 	BIGNUM *x, *y;
    773 	size_t field_len, i, skip;
    774 
    775 	if ((form != POINT_CONVERSION_COMPRESSED)
    776 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
    777 		&& (form != POINT_CONVERSION_HYBRID))
    778 		{
    779 		ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
    780 		goto err;
    781 		}
    782 
    783 	if (EC_POINT_is_at_infinity(group, point))
    784 		{
    785 		/* encodes to a single 0 octet */
    786 		if (buf != NULL)
    787 			{
    788 			if (len < 1)
    789 				{
    790 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
    791 				return 0;
    792 				}
    793 			buf[0] = 0;
    794 			}
    795 		return 1;
    796 		}
    797 
    798 
    799 	/* ret := required output buffer length */
    800 	field_len = BN_num_bytes(&group->field);
    801 	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
    802 
    803 	/* if 'buf' is NULL, just return required length */
    804 	if (buf != NULL)
    805 		{
    806 		if (len < ret)
    807 			{
    808 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
    809 			goto err;
    810 			}
    811 
    812 		if (ctx == NULL)
    813 			{
    814 			ctx = new_ctx = BN_CTX_new();
    815 			if (ctx == NULL)
    816 				return 0;
    817 			}
    818 
    819 		BN_CTX_start(ctx);
    820 		used_ctx = 1;
    821 		x = BN_CTX_get(ctx);
    822 		y = BN_CTX_get(ctx);
    823 		if (y == NULL) goto err;
    824 
    825 		if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
    826 
    827 		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
    828 			buf[0] = form + 1;
    829 		else
    830 			buf[0] = form;
    831 
    832 		i = 1;
    833 
    834 		skip = field_len - BN_num_bytes(x);
    835 		if (skip > field_len)
    836 			{
    837 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    838 			goto err;
    839 			}
    840 		while (skip > 0)
    841 			{
    842 			buf[i++] = 0;
    843 			skip--;
    844 			}
    845 		skip = BN_bn2bin(x, buf + i);
    846 		i += skip;
    847 		if (i != 1 + field_len)
    848 			{
    849 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    850 			goto err;
    851 			}
    852 
    853 		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
    854 			{
    855 			skip = field_len - BN_num_bytes(y);
    856 			if (skip > field_len)
    857 				{
    858 				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    859 				goto err;
    860 				}
    861 			while (skip > 0)
    862 				{
    863 				buf[i++] = 0;
    864 				skip--;
    865 				}
    866 			skip = BN_bn2bin(y, buf + i);
    867 			i += skip;
    868 			}
    869 
    870 		if (i != ret)
    871 			{
    872 			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
    873 			goto err;
    874 			}
    875 		}
    876 
    877 	if (used_ctx)
    878 		BN_CTX_end(ctx);
    879 	if (new_ctx != NULL)
    880 		BN_CTX_free(new_ctx);
    881 	return ret;
    882 
    883  err:
    884 	if (used_ctx)
    885 		BN_CTX_end(ctx);
    886 	if (new_ctx != NULL)
    887 		BN_CTX_free(new_ctx);
    888 	return 0;
    889 	}
    890 
    891 
    892 int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
    893 	const unsigned char *buf, size_t len, BN_CTX *ctx)
    894 	{
    895 	point_conversion_form_t form;
    896 	int y_bit;
    897 	BN_CTX *new_ctx = NULL;
    898 	BIGNUM *x, *y;
    899 	size_t field_len, enc_len;
    900 	int ret = 0;
    901 
    902 	if (len == 0)
    903 		{
    904 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
    905 		return 0;
    906 		}
    907 	form = buf[0];
    908 	y_bit = form & 1;
    909 	form = form & ~1U;
    910 	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
    911 		&& (form != POINT_CONVERSION_UNCOMPRESSED)
    912 		&& (form != POINT_CONVERSION_HYBRID))
    913 		{
    914 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    915 		return 0;
    916 		}
    917 	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
    918 		{
    919 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    920 		return 0;
    921 		}
    922 
    923 	if (form == 0)
    924 		{
    925 		if (len != 1)
    926 			{
    927 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    928 			return 0;
    929 			}
    930 
    931 		return EC_POINT_set_to_infinity(group, point);
    932 		}
    933 
    934 	field_len = BN_num_bytes(&group->field);
    935 	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
    936 
    937 	if (len != enc_len)
    938 		{
    939 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    940 		return 0;
    941 		}
    942 
    943 	if (ctx == NULL)
    944 		{
    945 		ctx = new_ctx = BN_CTX_new();
    946 		if (ctx == NULL)
    947 			return 0;
    948 		}
    949 
    950 	BN_CTX_start(ctx);
    951 	x = BN_CTX_get(ctx);
    952 	y = BN_CTX_get(ctx);
    953 	if (y == NULL) goto err;
    954 
    955 	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
    956 	if (BN_ucmp(x, &group->field) >= 0)
    957 		{
    958 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    959 		goto err;
    960 		}
    961 
    962 	if (form == POINT_CONVERSION_COMPRESSED)
    963 		{
    964 		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
    965 		}
    966 	else
    967 		{
    968 		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
    969 		if (BN_ucmp(y, &group->field) >= 0)
    970 			{
    971 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    972 			goto err;
    973 			}
    974 		if (form == POINT_CONVERSION_HYBRID)
    975 			{
    976 			if (y_bit != BN_is_odd(y))
    977 				{
    978 				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
    979 				goto err;
    980 				}
    981 			}
    982 
    983 		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
    984 		}
    985 
    986 	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
    987 		{
    988 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
    989 		goto err;
    990 		}
    991 
    992 	ret = 1;
    993 
    994  err:
    995 	BN_CTX_end(ctx);
    996 	if (new_ctx != NULL)
    997 		BN_CTX_free(new_ctx);
    998 	return ret;
    999 	}
   1000 
   1001 
   1002 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
   1003 	{
   1004 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
   1005 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
   1006 	const BIGNUM *p;
   1007 	BN_CTX *new_ctx = NULL;
   1008 	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
   1009 	int ret = 0;
   1010 
   1011 	if (a == b)
   1012 		return EC_POINT_dbl(group, r, a, ctx);
   1013 	if (EC_POINT_is_at_infinity(group, a))
   1014 		return EC_POINT_copy(r, b);
   1015 	if (EC_POINT_is_at_infinity(group, b))
   1016 		return EC_POINT_copy(r, a);
   1017 
   1018 	field_mul = group->meth->field_mul;
   1019 	field_sqr = group->meth->field_sqr;
   1020 	p = &group->field;
   1021 
   1022 	if (ctx == NULL)
   1023 		{
   1024 		ctx = new_ctx = BN_CTX_new();
   1025 		if (ctx == NULL)
   1026 			return 0;
   1027 		}
   1028 
   1029 	BN_CTX_start(ctx);
   1030 	n0 = BN_CTX_get(ctx);
   1031 	n1 = BN_CTX_get(ctx);
   1032 	n2 = BN_CTX_get(ctx);
   1033 	n3 = BN_CTX_get(ctx);
   1034 	n4 = BN_CTX_get(ctx);
   1035 	n5 = BN_CTX_get(ctx);
   1036 	n6 = BN_CTX_get(ctx);
   1037 	if (n6 == NULL) goto end;
   1038 
   1039 	/* Note that in this function we must not read components of 'a' or 'b'
   1040 	 * once we have written the corresponding components of 'r'.
   1041 	 * ('r' might be one of 'a' or 'b'.)
   1042 	 */
   1043 
   1044 	/* n1, n2 */
   1045 	if (b->Z_is_one)
   1046 		{
   1047 		if (!BN_copy(n1, &a->X)) goto end;
   1048 		if (!BN_copy(n2, &a->Y)) goto end;
   1049 		/* n1 = X_a */
   1050 		/* n2 = Y_a */
   1051 		}
   1052 	else
   1053 		{
   1054 		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
   1055 		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
   1056 		/* n1 = X_a * Z_b^2 */
   1057 
   1058 		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
   1059 		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
   1060 		/* n2 = Y_a * Z_b^3 */
   1061 		}
   1062 
   1063 	/* n3, n4 */
   1064 	if (a->Z_is_one)
   1065 		{
   1066 		if (!BN_copy(n3, &b->X)) goto end;
   1067 		if (!BN_copy(n4, &b->Y)) goto end;
   1068 		/* n3 = X_b */
   1069 		/* n4 = Y_b */
   1070 		}
   1071 	else
   1072 		{
   1073 		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
   1074 		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
   1075 		/* n3 = X_b * Z_a^2 */
   1076 
   1077 		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
   1078 		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
   1079 		/* n4 = Y_b * Z_a^3 */
   1080 		}
   1081 
   1082 	/* n5, n6 */
   1083 	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
   1084 	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
   1085 	/* n5 = n1 - n3 */
   1086 	/* n6 = n2 - n4 */
   1087 
   1088 	if (BN_is_zero(n5))
   1089 		{
   1090 		if (BN_is_zero(n6))
   1091 			{
   1092 			/* a is the same point as b */
   1093 			BN_CTX_end(ctx);
   1094 			ret = EC_POINT_dbl(group, r, a, ctx);
   1095 			ctx = NULL;
   1096 			goto end;
   1097 			}
   1098 		else
   1099 			{
   1100 			/* a is the inverse of b */
   1101 			BN_zero(&r->Z);
   1102 			r->Z_is_one = 0;
   1103 			ret = 1;
   1104 			goto end;
   1105 			}
   1106 		}
   1107 
   1108 	/* 'n7', 'n8' */
   1109 	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
   1110 	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
   1111 	/* 'n7' = n1 + n3 */
   1112 	/* 'n8' = n2 + n4 */
   1113 
   1114 	/* Z_r */
   1115 	if (a->Z_is_one && b->Z_is_one)
   1116 		{
   1117 		if (!BN_copy(&r->Z, n5)) goto end;
   1118 		}
   1119 	else
   1120 		{
   1121 		if (a->Z_is_one)
   1122 			{ if (!BN_copy(n0, &b->Z)) goto end; }
   1123 		else if (b->Z_is_one)
   1124 			{ if (!BN_copy(n0, &a->Z)) goto end; }
   1125 		else
   1126 			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
   1127 		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
   1128 		}
   1129 	r->Z_is_one = 0;
   1130 	/* Z_r = Z_a * Z_b * n5 */
   1131 
   1132 	/* X_r */
   1133 	if (!field_sqr(group, n0, n6, ctx)) goto end;
   1134 	if (!field_sqr(group, n4, n5, ctx)) goto end;
   1135 	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
   1136 	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
   1137 	/* X_r = n6^2 - n5^2 * 'n7' */
   1138 
   1139 	/* 'n9' */
   1140 	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
   1141 	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
   1142 	/* n9 = n5^2 * 'n7' - 2 * X_r */
   1143 
   1144 	/* Y_r */
   1145 	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
   1146 	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
   1147 	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
   1148 	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
   1149 	if (BN_is_odd(n0))
   1150 		if (!BN_add(n0, n0, p)) goto end;
   1151 	/* now  0 <= n0 < 2*p,  and n0 is even */
   1152 	if (!BN_rshift1(&r->Y, n0)) goto end;
   1153 	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
   1154 
   1155 	ret = 1;
   1156 
   1157  end:
   1158 	if (ctx) /* otherwise we already called BN_CTX_end */
   1159 		BN_CTX_end(ctx);
   1160 	if (new_ctx != NULL)
   1161 		BN_CTX_free(new_ctx);
   1162 	return ret;
   1163 	}
   1164 
   1165 
   1166 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
   1167 	{
   1168 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
   1169 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
   1170 	const BIGNUM *p;
   1171 	BN_CTX *new_ctx = NULL;
   1172 	BIGNUM *n0, *n1, *n2, *n3;
   1173 	int ret = 0;
   1174 
   1175 	if (EC_POINT_is_at_infinity(group, a))
   1176 		{
   1177 		BN_zero(&r->Z);
   1178 		r->Z_is_one = 0;
   1179 		return 1;
   1180 		}
   1181 
   1182 	field_mul = group->meth->field_mul;
   1183 	field_sqr = group->meth->field_sqr;
   1184 	p = &group->field;
   1185 
   1186 	if (ctx == NULL)
   1187 		{
   1188 		ctx = new_ctx = BN_CTX_new();
   1189 		if (ctx == NULL)
   1190 			return 0;
   1191 		}
   1192 
   1193 	BN_CTX_start(ctx);
   1194 	n0 = BN_CTX_get(ctx);
   1195 	n1 = BN_CTX_get(ctx);
   1196 	n2 = BN_CTX_get(ctx);
   1197 	n3 = BN_CTX_get(ctx);
   1198 	if (n3 == NULL) goto err;
   1199 
   1200 	/* Note that in this function we must not read components of 'a'
   1201 	 * once we have written the corresponding components of 'r'.
   1202 	 * ('r' might the same as 'a'.)
   1203 	 */
   1204 
   1205 	/* n1 */
   1206 	if (a->Z_is_one)
   1207 		{
   1208 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
   1209 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
   1210 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
   1211 		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
   1212 		/* n1 = 3 * X_a^2 + a_curve */
   1213 		}
   1214 	else if (group->a_is_minus3)
   1215 		{
   1216 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
   1217 		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
   1218 		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
   1219 		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
   1220 		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
   1221 		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
   1222 		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
   1223 		 *    = 3 * X_a^2 - 3 * Z_a^4 */
   1224 		}
   1225 	else
   1226 		{
   1227 		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
   1228 		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
   1229 		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
   1230 		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
   1231 		if (!field_sqr(group, n1, n1, ctx)) goto err;
   1232 		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
   1233 		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
   1234 		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
   1235 		}
   1236 
   1237 	/* Z_r */
   1238 	if (a->Z_is_one)
   1239 		{
   1240 		if (!BN_copy(n0, &a->Y)) goto err;
   1241 		}
   1242 	else
   1243 		{
   1244 		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
   1245 		}
   1246 	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
   1247 	r->Z_is_one = 0;
   1248 	/* Z_r = 2 * Y_a * Z_a */
   1249 
   1250 	/* n2 */
   1251 	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
   1252 	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
   1253 	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
   1254 	/* n2 = 4 * X_a * Y_a^2 */
   1255 
   1256 	/* X_r */
   1257 	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
   1258 	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
   1259 	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
   1260 	/* X_r = n1^2 - 2 * n2 */
   1261 
   1262 	/* n3 */
   1263 	if (!field_sqr(group, n0, n3, ctx)) goto err;
   1264 	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
   1265 	/* n3 = 8 * Y_a^4 */
   1266 
   1267 	/* Y_r */
   1268 	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
   1269 	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
   1270 	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
   1271 	/* Y_r = n1 * (n2 - X_r) - n3 */
   1272 
   1273 	ret = 1;
   1274 
   1275  err:
   1276 	BN_CTX_end(ctx);
   1277 	if (new_ctx != NULL)
   1278 		BN_CTX_free(new_ctx);
   1279 	return ret;
   1280 	}
   1281 
   1282 
   1283 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
   1284 	{
   1285 	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
   1286 		/* point is its own inverse */
   1287 		return 1;
   1288 
   1289 	return BN_usub(&point->Y, &group->field, &point->Y);
   1290 	}
   1291 
   1292 
   1293 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
   1294 	{
   1295 	return BN_is_zero(&point->Z);
   1296 	}
   1297 
   1298 
   1299 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
   1300 	{
   1301 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
   1302 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
   1303 	const BIGNUM *p;
   1304 	BN_CTX *new_ctx = NULL;
   1305 	BIGNUM *rh, *tmp, *Z4, *Z6;
   1306 	int ret = -1;
   1307 
   1308 	if (EC_POINT_is_at_infinity(group, point))
   1309 		return 1;
   1310 
   1311 	field_mul = group->meth->field_mul;
   1312 	field_sqr = group->meth->field_sqr;
   1313 	p = &group->field;
   1314 
   1315 	if (ctx == NULL)
   1316 		{
   1317 		ctx = new_ctx = BN_CTX_new();
   1318 		if (ctx == NULL)
   1319 			return -1;
   1320 		}
   1321 
   1322 	BN_CTX_start(ctx);
   1323 	rh = BN_CTX_get(ctx);
   1324 	tmp = BN_CTX_get(ctx);
   1325 	Z4 = BN_CTX_get(ctx);
   1326 	Z6 = BN_CTX_get(ctx);
   1327 	if (Z6 == NULL) goto err;
   1328 
   1329 	/* We have a curve defined by a Weierstrass equation
   1330 	 *      y^2 = x^3 + a*x + b.
   1331 	 * The point to consider is given in Jacobian projective coordinates
   1332 	 * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
   1333 	 * Substituting this and multiplying by  Z^6  transforms the above equation into
   1334 	 *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
   1335 	 * To test this, we add up the right-hand side in 'rh'.
   1336 	 */
   1337 
   1338 	/* rh := X^2 */
   1339 	if (!field_sqr(group, rh, &point->X, ctx)) goto err;
   1340 
   1341 	if (!point->Z_is_one)
   1342 		{
   1343 		if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
   1344 		if (!field_sqr(group, Z4, tmp, ctx)) goto err;
   1345 		if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
   1346 
   1347 		/* rh := (rh + a*Z^4)*X */
   1348 		if (group->a_is_minus3)
   1349 			{
   1350 			if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
   1351 			if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
   1352 			if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
   1353 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
   1354 			}
   1355 		else
   1356 			{
   1357 			if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
   1358 			if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
   1359 			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
   1360 			}
   1361 
   1362 		/* rh := rh + b*Z^6 */
   1363 		if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
   1364 		if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
   1365 		}
   1366 	else
   1367 		{
   1368 		/* point->Z_is_one */
   1369 
   1370 		/* rh := (rh + a)*X */
   1371 		if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
   1372 		if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
   1373 		/* rh := rh + b */
   1374 		if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
   1375 		}
   1376 
   1377 	/* 'lh' := Y^2 */
   1378 	if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
   1379 
   1380 	ret = (0 == BN_ucmp(tmp, rh));
   1381 
   1382  err:
   1383 	BN_CTX_end(ctx);
   1384 	if (new_ctx != NULL)
   1385 		BN_CTX_free(new_ctx);
   1386 	return ret;
   1387 	}
   1388 
   1389 
   1390 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
   1391 	{
   1392 	/* return values:
   1393 	 *  -1   error
   1394 	 *   0   equal (in affine coordinates)
   1395 	 *   1   not equal
   1396 	 */
   1397 
   1398 	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
   1399 	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
   1400 	BN_CTX *new_ctx = NULL;
   1401 	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
   1402 	const BIGNUM *tmp1_, *tmp2_;
   1403 	int ret = -1;
   1404 
   1405 	if (EC_POINT_is_at_infinity(group, a))
   1406 		{
   1407 		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
   1408 		}
   1409 
   1410 	if (a->Z_is_one && b->Z_is_one)
   1411 		{
   1412 		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
   1413 		}
   1414 
   1415 	field_mul = group->meth->field_mul;
   1416 	field_sqr = group->meth->field_sqr;
   1417 
   1418 	if (ctx == NULL)
   1419 		{
   1420 		ctx = new_ctx = BN_CTX_new();
   1421 		if (ctx == NULL)
   1422 			return -1;
   1423 		}
   1424 
   1425 	BN_CTX_start(ctx);
   1426 	tmp1 = BN_CTX_get(ctx);
   1427 	tmp2 = BN_CTX_get(ctx);
   1428 	Za23 = BN_CTX_get(ctx);
   1429 	Zb23 = BN_CTX_get(ctx);
   1430 	if (Zb23 == NULL) goto end;
   1431 
   1432 	/* We have to decide whether
   1433 	 *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
   1434 	 * or equivalently, whether
   1435 	 *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
   1436 	 */
   1437 
   1438 	if (!b->Z_is_one)
   1439 		{
   1440 		if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
   1441 		if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
   1442 		tmp1_ = tmp1;
   1443 		}
   1444 	else
   1445 		tmp1_ = &a->X;
   1446 	if (!a->Z_is_one)
   1447 		{
   1448 		if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
   1449 		if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
   1450 		tmp2_ = tmp2;
   1451 		}
   1452 	else
   1453 		tmp2_ = &b->X;
   1454 
   1455 	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
   1456 	if (BN_cmp(tmp1_, tmp2_) != 0)
   1457 		{
   1458 		ret = 1; /* points differ */
   1459 		goto end;
   1460 		}
   1461 
   1462 
   1463 	if (!b->Z_is_one)
   1464 		{
   1465 		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
   1466 		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
   1467 		/* tmp1_ = tmp1 */
   1468 		}
   1469 	else
   1470 		tmp1_ = &a->Y;
   1471 	if (!a->Z_is_one)
   1472 		{
   1473 		if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
   1474 		if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
   1475 		/* tmp2_ = tmp2 */
   1476 		}
   1477 	else
   1478 		tmp2_ = &b->Y;
   1479 
   1480 	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
   1481 	if (BN_cmp(tmp1_, tmp2_) != 0)
   1482 		{
   1483 		ret = 1; /* points differ */
   1484 		goto end;
   1485 		}
   1486 
   1487 	/* points are equal */
   1488 	ret = 0;
   1489 
   1490  end:
   1491 	BN_CTX_end(ctx);
   1492 	if (new_ctx != NULL)
   1493 		BN_CTX_free(new_ctx);
   1494 	return ret;
   1495 	}
   1496 
   1497 
   1498 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
   1499 	{
   1500 	BN_CTX *new_ctx = NULL;
   1501 	BIGNUM *x, *y;
   1502 	int ret = 0;
   1503 
   1504 	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
   1505 		return 1;
   1506 
   1507 	if (ctx == NULL)
   1508 		{
   1509 		ctx = new_ctx = BN_CTX_new();
   1510 		if (ctx == NULL)
   1511 			return 0;
   1512 		}
   1513 
   1514 	BN_CTX_start(ctx);
   1515 	x = BN_CTX_get(ctx);
   1516 	y = BN_CTX_get(ctx);
   1517 	if (y == NULL) goto err;
   1518 
   1519 	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
   1520 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
   1521 	if (!point->Z_is_one)
   1522 		{
   1523 		ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
   1524 		goto err;
   1525 		}
   1526 
   1527 	ret = 1;
   1528 
   1529  err:
   1530 	BN_CTX_end(ctx);
   1531 	if (new_ctx != NULL)
   1532 		BN_CTX_free(new_ctx);
   1533 	return ret;
   1534 	}
   1535 
   1536 
   1537 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
   1538 	{
   1539 	BN_CTX *new_ctx = NULL;
   1540 	BIGNUM *tmp0, *tmp1;
   1541 	size_t pow2 = 0;
   1542 	BIGNUM **heap = NULL;
   1543 	size_t i;
   1544 	int ret = 0;
   1545 
   1546 	if (num == 0)
   1547 		return 1;
   1548 
   1549 	if (ctx == NULL)
   1550 		{
   1551 		ctx = new_ctx = BN_CTX_new();
   1552 		if (ctx == NULL)
   1553 			return 0;
   1554 		}
   1555 
   1556 	BN_CTX_start(ctx);
   1557 	tmp0 = BN_CTX_get(ctx);
   1558 	tmp1 = BN_CTX_get(ctx);
   1559 	if (tmp0  == NULL || tmp1 == NULL) goto err;
   1560 
   1561 	/* Before converting the individual points, compute inverses of all Z values.
   1562 	 * Modular inversion is rather slow, but luckily we can do with a single
   1563 	 * explicit inversion, plus about 3 multiplications per input value.
   1564 	 */
   1565 
   1566 	pow2 = 1;
   1567 	while (num > pow2)
   1568 		pow2 <<= 1;
   1569 	/* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
   1570 	 * We need twice that. */
   1571 	pow2 <<= 1;
   1572 
   1573 	heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
   1574 	if (heap == NULL) goto err;
   1575 
   1576 	/* The array is used as a binary tree, exactly as in heapsort:
   1577 	 *
   1578 	 *                               heap[1]
   1579 	 *                 heap[2]                     heap[3]
   1580 	 *          heap[4]       heap[5]       heap[6]       heap[7]
   1581 	 *   heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
   1582 	 *
   1583 	 * We put the Z's in the last line;
   1584 	 * then we set each other node to the product of its two child-nodes (where
   1585 	 * empty or 0 entries are treated as ones);
   1586 	 * then we invert heap[1];
   1587 	 * then we invert each other node by replacing it by the product of its
   1588 	 * parent (after inversion) and its sibling (before inversion).
   1589 	 */
   1590 	heap[0] = NULL;
   1591 	for (i = pow2/2 - 1; i > 0; i--)
   1592 		heap[i] = NULL;
   1593 	for (i = 0; i < num; i++)
   1594 		heap[pow2/2 + i] = &points[i]->Z;
   1595 	for (i = pow2/2 + num; i < pow2; i++)
   1596 		heap[i] = NULL;
   1597 
   1598 	/* set each node to the product of its children */
   1599 	for (i = pow2/2 - 1; i > 0; i--)
   1600 		{
   1601 		heap[i] = BN_new();
   1602 		if (heap[i] == NULL) goto err;
   1603 
   1604 		if (heap[2*i] != NULL)
   1605 			{
   1606 			if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
   1607 				{
   1608 				if (!BN_copy(heap[i], heap[2*i])) goto err;
   1609 				}
   1610 			else
   1611 				{
   1612 				if (BN_is_zero(heap[2*i]))
   1613 					{
   1614 					if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
   1615 					}
   1616 				else
   1617 					{
   1618 					if (!group->meth->field_mul(group, heap[i],
   1619 						heap[2*i], heap[2*i + 1], ctx)) goto err;
   1620 					}
   1621 				}
   1622 			}
   1623 		}
   1624 
   1625 	/* invert heap[1] */
   1626 	if (!BN_is_zero(heap[1]))
   1627 		{
   1628 		if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
   1629 			{
   1630 			ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
   1631 			goto err;
   1632 			}
   1633 		}
   1634 	if (group->meth->field_encode != 0)
   1635 		{
   1636 		/* in the Montgomery case, we just turned  R*H  (representing H)
   1637 		 * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
   1638 		 * i.e. we have need to multiply by the Montgomery factor twice */
   1639 		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
   1640 		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
   1641 		}
   1642 
   1643 	/* set other heap[i]'s to their inverses */
   1644 	for (i = 2; i < pow2/2 + num; i += 2)
   1645 		{
   1646 		/* i is even */
   1647 		if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
   1648 			{
   1649 			if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
   1650 			if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
   1651 			if (!BN_copy(heap[i], tmp0)) goto err;
   1652 			if (!BN_copy(heap[i + 1], tmp1)) goto err;
   1653 			}
   1654 		else
   1655 			{
   1656 			if (!BN_copy(heap[i], heap[i/2])) goto err;
   1657 			}
   1658 		}
   1659 
   1660 	/* we have replaced all non-zero Z's by their inverses, now fix up all the points */
   1661 	for (i = 0; i < num; i++)
   1662 		{
   1663 		EC_POINT *p = points[i];
   1664 
   1665 		if (!BN_is_zero(&p->Z))
   1666 			{
   1667 			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
   1668 
   1669 			if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
   1670 			if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
   1671 
   1672 			if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
   1673 			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
   1674 
   1675 			if (group->meth->field_set_to_one != 0)
   1676 				{
   1677 				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
   1678 				}
   1679 			else
   1680 				{
   1681 				if (!BN_one(&p->Z)) goto err;
   1682 				}
   1683 			p->Z_is_one = 1;
   1684 			}
   1685 		}
   1686 
   1687 	ret = 1;
   1688 
   1689  err:
   1690 	BN_CTX_end(ctx);
   1691 	if (new_ctx != NULL)
   1692 		BN_CTX_free(new_ctx);
   1693 	if (heap != NULL)
   1694 		{
   1695 		/* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
   1696 		for (i = pow2/2 - 1; i > 0; i--)
   1697 			{
   1698 			if (heap[i] != NULL)
   1699 				BN_clear_free(heap[i]);
   1700 			}
   1701 		OPENSSL_free(heap);
   1702 		}
   1703 	return ret;
   1704 	}
   1705 
   1706 
   1707 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
   1708 	{
   1709 	return BN_mod_mul(r, a, b, &group->field, ctx);
   1710 	}
   1711 
   1712 
   1713 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
   1714 	{
   1715 	return BN_mod_sqr(r, a, &group->field, ctx);
   1716 	}
   1717