Example #1
0
EC_KEY *
EC_KEY_new_method(ENGINE *engine)
{
	EC_KEY *ret;

	if ((ret = calloc(1, sizeof(EC_KEY))) == NULL) {
		ECerror(ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	ret->meth = EC_KEY_get_default_method();
#ifndef OPENSSL_NO_ENGINE
	if (engine != NULL) {
		if (!ENGINE_init(engine)) {
			ECerror(ERR_R_ENGINE_LIB);
			goto err;
		}
		ret->engine = engine;
	} else
		ret->engine = ENGINE_get_default_EC();
	if (ret->engine) {
		ret->meth = ENGINE_get_EC(ret->engine);
		if (ret->meth == NULL) {
			ECerror(ERR_R_ENGINE_LIB);
			goto err;
		}
	}
#endif
	ret->version = 1;
	ret->flags = 0;
	ret->group = NULL;
	ret->pub_key = NULL;
	ret->priv_key = NULL;
	ret->enc_flag = 0;
	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
	ret->references = 1;
	ret->method_data = NULL;

	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
		goto err;
	if (ret->meth->init != NULL && ret->meth->init(ret) == 0)
		goto err;

	return ret;

 err:
	EC_KEY_free(ret);
	return NULL;
}
Example #2
0
int 
ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
    BN_CTX *ctx)
{
	if (group->field_data1 == NULL) {
		ECerror(EC_R_NOT_INITIALIZED);
		return 0;
	}
	return BN_from_montgomery(r, a, group->field_data1, ctx);
}
Example #3
0
int 
ec_GFp_simple_group_set_curve(EC_GROUP * group,
    const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
{
	int ret = 0;
	BN_CTX *new_ctx = NULL;
	BIGNUM *tmp_a;

	/* p must be a prime > 3 */
	if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
		ECerror(EC_R_INVALID_FIELD);
		return 0;
	}
	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	BN_CTX_start(ctx);
	if ((tmp_a = BN_CTX_get(ctx)) == NULL)
		goto err;

	/* group->field */
	if (!BN_copy(&group->field, p))
		goto err;
	BN_set_negative(&group->field, 0);

	/* group->a */
	if (!BN_nnmod(tmp_a, a, p, ctx))
		goto err;
	if (group->meth->field_encode) {
		if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))
			goto err;
	} else if (!BN_copy(&group->a, tmp_a))
		goto err;

	/* group->b */
	if (!BN_nnmod(&group->b, b, p, ctx))
		goto err;
	if (group->meth->field_encode)
		if (!group->meth->field_encode(group, &group->b, &group->b, ctx))
			goto err;

	/* group->a_is_minus3 */
	if (!BN_add_word(tmp_a, 3))
		goto err;
	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));

	ret = 1;

err:
	BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	return ret;
}
Example #4
0
int 
ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
{
	if (group->field_data2 == NULL) {
		ECerror(EC_R_NOT_INITIALIZED);
		return 0;
	}
	if (!BN_copy(r, group->field_data2))
		return 0;
	return 1;
}
Example #5
0
int 
ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point,
    const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx)
{
	if (x == NULL || y == NULL) {
		/* unlike for projective coordinates, we do not tolerate this */
		ECerror(ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
}
Example #6
0
int 
ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
    const BIGNUM *b, BN_CTX *ctx)
{
	BN_CTX *new_ctx = NULL;
	BN_MONT_CTX *mont = NULL;
	BIGNUM *one = NULL;
	int ret = 0;

	BN_MONT_CTX_free(group->field_data1);
	group->field_data1 = NULL;
	BN_free(group->field_data2);
	group->field_data2 = NULL;
	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	mont = BN_MONT_CTX_new();
	if (mont == NULL)
		goto err;
	if (!BN_MONT_CTX_set(mont, p, ctx)) {
		ECerror(ERR_R_BN_LIB);
		goto err;
	}
	one = BN_new();
	if (one == NULL)
		goto err;
	if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))
		goto err;

	group->field_data1 = mont;
	mont = NULL;
	group->field_data2 = one;
	one = NULL;

	ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);

	if (!ret) {
		BN_MONT_CTX_free(group->field_data1);
		group->field_data1 = NULL;
		BN_free(group->field_data2);
		group->field_data2 = NULL;
	}
 err:
	BN_CTX_free(new_ctx);
	BN_MONT_CTX_free(mont);
	BN_free(one);
	return ret;
}
Example #7
0
int 
EC_GROUP_check(const EC_GROUP * group, BN_CTX * ctx)
{
	int ret = 0;
	BIGNUM *order;
	BN_CTX *new_ctx = NULL;
	EC_POINT *point = NULL;

	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL) {
			ECerror(ERR_R_MALLOC_FAILURE);
			goto err;
		}
	}
	BN_CTX_start(ctx);
	if ((order = BN_CTX_get(ctx)) == NULL)
		goto err;

	/* check the discriminant */
	if (!EC_GROUP_check_discriminant(group, ctx)) {
		ECerror(EC_R_DISCRIMINANT_IS_ZERO);
		goto err;
	}
	/* check the generator */
	if (group->generator == NULL) {
		ECerror(EC_R_UNDEFINED_GENERATOR);
		goto err;
	}
	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
		goto err;
	}
	/* check the order of the generator */
	if ((point = EC_POINT_new(group)) == NULL)
		goto err;
	if (!EC_GROUP_get_order(group, order, ctx))
		goto err;
	if (BN_is_zero(order)) {
		ECerror(EC_R_UNDEFINED_ORDER);
		goto err;
	}
	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))
		goto err;
	if (EC_POINT_is_at_infinity(group, point) <= 0) {
		ECerror(EC_R_INVALID_GROUP_ORDER);
		goto err;
	}
	ret = 1;

err:
	if (ctx != NULL)
		BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	EC_POINT_free(point);
	return ret;
}
Example #8
0
int 
EC_KEY_print_fp(FILE * fp, const EC_KEY * x, int off)
{
	BIO *b;
	int ret;

	if ((b = BIO_new(BIO_s_file())) == NULL) {
		ECerror(ERR_R_BIO_LIB);
		return (0);
	}
	BIO_set_fp(b, fp, BIO_NOCLOSE);
	ret = EC_KEY_print(b, x, off);
	BIO_free(b);
	return (ret);
}
Example #9
0
int 
EC_GROUP_get_trinomial_basis(const EC_GROUP * group, unsigned int *k)
{
	if (group == NULL)
		return 0;

	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
	    NID_X9_62_characteristic_two_field
	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0))) {
		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
		return 0;
	}
	if (k)
		*k = group->poly[1];

	return 1;
}
Example #10
0
static EC_PRE_COMP *
ec_pre_comp_new(const EC_GROUP * group)
{
	EC_PRE_COMP *ret = NULL;

	if (!group)
		return NULL;

	ret = malloc(sizeof(EC_PRE_COMP));
	if (!ret) {
		ECerror(ERR_R_MALLOC_FAILURE);
		return ret;
	}
	ret->group = group;
	ret->blocksize = 8;	/* default */
	ret->numblocks = 0;
	ret->w = 4;		/* default */
	ret->points = NULL;
	ret->num = 0;
	ret->references = 1;
	return ret;
}
Example #11
0
int 
ec_GFp_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
{
	BN_CTX *new_ctx = NULL;
	BIGNUM *x, *y;
	int ret = 0;

	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0)
		return 1;

	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	BN_CTX_start(ctx);
	if ((x = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((y = BN_CTX_get(ctx)) == NULL)
		goto err;

	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
		goto err;
	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
		goto err;
	if (!point->Z_is_one) {
		ECerror(ERR_R_INTERNAL_ERROR);
		goto err;
	}
	ret = 1;

err:
	BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	return ret;
}
Example #12
0
int 
ECPKParameters_print(BIO * bp, const EC_GROUP * x, int off)
{
	unsigned char *buffer = NULL;
	size_t buf_len = 0, i;
	int ret = 0, reason = ERR_R_BIO_LIB;
	BN_CTX *ctx = NULL;
	const EC_POINT *point = NULL;
	BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, *order = NULL,
	*cofactor = NULL;
	const unsigned char *seed;
	size_t seed_len = 0;
	const char *nname;

	static const char *gen_compressed = "Generator (compressed):";
	static const char *gen_uncompressed = "Generator (uncompressed):";
	static const char *gen_hybrid = "Generator (hybrid):";

	if (!x) {
		reason = ERR_R_PASSED_NULL_PARAMETER;
		goto err;
	}
	ctx = BN_CTX_new();
	if (ctx == NULL) {
		reason = ERR_R_MALLOC_FAILURE;
		goto err;
	}
	if (EC_GROUP_get_asn1_flag(x)) {
		/* the curve parameter are given by an asn1 OID */
		int nid;

		if (!BIO_indent(bp, off, 128))
			goto err;

		nid = EC_GROUP_get_curve_name(x);
		if (nid == 0)
			goto err;

		if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
			goto err;
		if (BIO_printf(bp, "\n") <= 0)
			goto err;

		nname = EC_curve_nid2nist(nid);
		if (nname) {
			if (!BIO_indent(bp, off, 128))
				goto err;
			if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0)
				goto err;
		}
	} else {
		/* explicit parameters */
		int is_char_two = 0;
		point_conversion_form_t form;
		int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));

		if (tmp_nid == NID_X9_62_characteristic_two_field)
			is_char_two = 1;

		if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
		    (b = BN_new()) == NULL || (order = BN_new()) == NULL ||
		    (cofactor = BN_new()) == NULL) {
			reason = ERR_R_MALLOC_FAILURE;
			goto err;
		}
#ifndef OPENSSL_NO_EC2M
		if (is_char_two) {
			if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) {
				reason = ERR_R_EC_LIB;
				goto err;
			}
		} else		/* prime field */
#endif
		{
			if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) {
				reason = ERR_R_EC_LIB;
				goto err;
			}
		}

		if ((point = EC_GROUP_get0_generator(x)) == NULL) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		if (!EC_GROUP_get_order(x, order, NULL) ||
		    !EC_GROUP_get_cofactor(x, cofactor, NULL)) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		form = EC_GROUP_get_point_conversion_form(x);

		if ((gen = EC_POINT_point2bn(x, point,
			    form, NULL, ctx)) == NULL) {
			reason = ERR_R_EC_LIB;
			goto err;
		}
		buf_len = (size_t) BN_num_bytes(p);
		if (buf_len < (i = (size_t) BN_num_bytes(a)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(b)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(gen)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(order)))
			buf_len = i;
		if (buf_len < (i = (size_t) BN_num_bytes(cofactor)))
			buf_len = i;

		if ((seed = EC_GROUP_get0_seed(x)) != NULL)
			seed_len = EC_GROUP_get_seed_len(x);

		buf_len += 10;
		if ((buffer = malloc(buf_len)) == NULL) {
			reason = ERR_R_MALLOC_FAILURE;
			goto err;
		}
		if (!BIO_indent(bp, off, 128))
			goto err;

		/* print the 'short name' of the field type */
		if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
		    <= 0)
			goto err;

		if (is_char_two) {
			/* print the 'short name' of the base type OID */
			int basis_type = EC_GROUP_get_basis_type(x);
			if (basis_type == 0)
				goto err;

			if (!BIO_indent(bp, off, 128))
				goto err;

			if (BIO_printf(bp, "Basis Type: %s\n",
				OBJ_nid2sn(basis_type)) <= 0)
				goto err;

			/* print the polynomial */
			if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
				off))
				goto err;
		} else {
			if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off))
				goto err;
		}
		if ((a != NULL) && !ASN1_bn_print(bp, "A:   ", a, buffer, off))
			goto err;
		if ((b != NULL) && !ASN1_bn_print(bp, "B:   ", b, buffer, off))
			goto err;
		if (form == POINT_CONVERSION_COMPRESSED) {
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
				buffer, off))
				goto err;
		} else if (form == POINT_CONVERSION_UNCOMPRESSED) {
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
				buffer, off))
				goto err;
		} else {	/* form == POINT_CONVERSION_HYBRID */
			if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
				buffer, off))
				goto err;
		}
		if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
			buffer, off))
			goto err;
		if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
			buffer, off))
			goto err;
		if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
			goto err;
	}
	ret = 1;
err:
	if (!ret)
		ECerror(reason);
	BN_free(p);
	BN_free(a);
	BN_free(b);
	BN_free(gen);
	BN_free(order);
	BN_free(cofactor);
	BN_CTX_free(ctx);
	free(buffer);
	return (ret);
}
Example #13
0
/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
 * This is an array  r[]  of values that are either zero or odd with an
 * absolute value less than  2^w  satisfying
 *     scalar = \sum_j r[j]*2^j
 * where at most one of any  w+1  consecutive digits is non-zero
 * with the exception that the most significant digit may be only
 * w-1 zeros away from that next non-zero digit.
 */
static signed char *
compute_wNAF(const BIGNUM * scalar, int w, size_t * ret_len)
{
	int window_val;
	int ok = 0;
	signed char *r = NULL;
	int sign = 1;
	int bit, next_bit, mask;
	size_t len = 0, j;

	if (BN_is_zero(scalar)) {
		r = malloc(1);
		if (!r) {
			ECerror(ERR_R_MALLOC_FAILURE);
			goto err;
		}
		r[0] = 0;
		*ret_len = 1;
		return r;
	}
	if (w <= 0 || w > 7) {
		/* 'signed char' can represent integers with
		 * absolute values less than 2^7 */
		ECerror(ERR_R_INTERNAL_ERROR);
		goto err;
	}
	bit = 1 << w;		/* at most 128 */
	next_bit = bit << 1;	/* at most 256 */
	mask = next_bit - 1;	/* at most 255 */

	if (BN_is_negative(scalar)) {
		sign = -1;
	}
	if (scalar->d == NULL || scalar->top == 0) {
		ECerror(ERR_R_INTERNAL_ERROR);
		goto err;
	}
	len = BN_num_bits(scalar);
	r = malloc(len + 1);	/* modified wNAF may be one digit longer than
				 * binary representation (*ret_len will be
				 * set to the actual length, i.e. at most
				 * BN_num_bits(scalar) + 1) */
	if (r == NULL) {
		ECerror(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	window_val = scalar->d[0] & mask;
	j = 0;
	while ((window_val != 0) || (j + w + 1 < len)) {
		/* if j+w+1 >= len, window_val will not increase */
		int digit = 0;

		/* 0 <= window_val <= 2^(w+1) */
		if (window_val & 1) {
			/* 0 < window_val < 2^(w+1) */
			if (window_val & bit) {
				digit = window_val - next_bit;	/* -2^w < digit < 0 */

#if 1				/* modified wNAF */
				if (j + w + 1 >= len) {
					/*
					 * special case for generating
					 * modified wNAFs: no new bits will
					 * be added into window_val, so using
					 * a positive digit here will
					 * decrease the total length of the
					 * representation
					 */

					digit = window_val & (mask >> 1);	/* 0 < digit < 2^w */
				}
#endif
			} else {
Example #14
0
int 
ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP * group, const EC_POINT * point,
    BIGNUM * x, BIGNUM * y, BN_CTX * ctx)
{
	BN_CTX *new_ctx = NULL;
	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
	const BIGNUM *Z_;
	int ret = 0;

	if (EC_POINT_is_at_infinity(group, point) > 0) {
		ECerror(EC_R_POINT_AT_INFINITY);
		return 0;
	}
	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	BN_CTX_start(ctx);
	if ((Z = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_1 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_2 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((Z_3 = BN_CTX_get(ctx)) == NULL)
		goto err;

	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */

	if (group->meth->field_decode) {
		if (!group->meth->field_decode(group, Z, &point->Z, ctx))
			goto err;
		Z_ = Z;
	} else {
		Z_ = &point->Z;
	}

	if (BN_is_one(Z_)) {
		if (group->meth->field_decode) {
			if (x != NULL) {
				if (!group->meth->field_decode(group, x, &point->X, ctx))
					goto err;
			}
			if (y != NULL) {
				if (!group->meth->field_decode(group, y, &point->Y, ctx))
					goto err;
			}
		} else {
			if (x != NULL) {
				if (!BN_copy(x, &point->X))
					goto err;
			}
			if (y != NULL) {
				if (!BN_copy(y, &point->Y))
					goto err;
			}
		}
	} else {
		if (!BN_mod_inverse_ct(Z_1, Z_, &group->field, ctx)) {
			ECerror(ERR_R_BN_LIB);
			goto err;
		}
		if (group->meth->field_encode == 0) {
			/* field_sqr works on standard representation */
			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
				goto err;
		} else {
			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))
				goto err;
		}

		if (x != NULL) {
			/*
			 * in the Montgomery case, field_mul will cancel out
			 * Montgomery factor in X:
			 */
			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))
				goto err;
		}
		if (y != NULL) {
			if (group->meth->field_encode == 0) {
				/* field_mul works on standard representation */
				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
					goto err;
			} else {
				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))
					goto err;
			}

			/*
			 * in the Montgomery case, field_mul will cancel out
			 * Montgomery factor in Y:
			 */
			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx))
				goto err;
		}
	}

	ret = 1;

err:
	BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	return ret;
}
Example #15
0
int 
ec_GFp_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
{
	int ret = 0;
	BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
	const BIGNUM *p = &group->field;
	BN_CTX *new_ctx = NULL;

	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL) {
			ECerror(ERR_R_MALLOC_FAILURE);
			goto err;
		}
	}
	BN_CTX_start(ctx);
	if ((a = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((b = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((tmp_1 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((tmp_2 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((order = BN_CTX_get(ctx)) == NULL)
		goto err;

	if (group->meth->field_decode) {
		if (!group->meth->field_decode(group, a, &group->a, ctx))
			goto err;
		if (!group->meth->field_decode(group, b, &group->b, ctx))
			goto err;
	} else {
		if (!BN_copy(a, &group->a))
			goto err;
		if (!BN_copy(b, &group->b))
			goto err;
	}

	/*
	 * check the discriminant: y^2 = x^3 + a*x + b is an elliptic curve
	 * <=> 4*a^3 + 27*b^2 != 0 (mod p) 0 =< a, b < p
	 */
	if (BN_is_zero(a)) {
		if (BN_is_zero(b))
			goto err;
	} else if (!BN_is_zero(b)) {
		if (!BN_mod_sqr(tmp_1, a, p, ctx))
			goto err;
		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
			goto err;
		if (!BN_lshift(tmp_1, tmp_2, 2))
			goto err;
		/* tmp_1 = 4*a^3 */

		if (!BN_mod_sqr(tmp_2, b, p, ctx))
			goto err;
		if (!BN_mul_word(tmp_2, 27))
			goto err;
		/* tmp_2 = 27*b^2 */

		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
			goto err;
		if (BN_is_zero(a))
			goto err;
	}
	ret = 1;

err:
	if (ctx != NULL)
		BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	return ret;
}
Example #16
0
int 
ec_GFp_simple_points_make_affine(const EC_GROUP * group, size_t num, EC_POINT * points[], BN_CTX * ctx)
{
	BN_CTX *new_ctx = NULL;
	BIGNUM *tmp0, *tmp1;
	size_t pow2 = 0;
	BIGNUM **heap = NULL;
	size_t i;
	int ret = 0;

	if (num == 0)
		return 1;

	if (ctx == NULL) {
		ctx = new_ctx = BN_CTX_new();
		if (ctx == NULL)
			return 0;
	}
	BN_CTX_start(ctx);
	if ((tmp0 = BN_CTX_get(ctx)) == NULL)
		goto err;
	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
		goto err;

	/*
	 * Before converting the individual points, compute inverses of all Z
	 * values. Modular inversion is rather slow, but luckily we can do
	 * with a single explicit inversion, plus about 3 multiplications per
	 * input value.
	 */

	pow2 = 1;
	while (num > pow2)
		pow2 <<= 1;
	/*
	 * Now pow2 is the smallest power of 2 satifsying pow2 >= num. We
	 * need twice that.
	 */
	pow2 <<= 1;

	heap = reallocarray(NULL, pow2, sizeof heap[0]);
	if (heap == NULL)
		goto err;

	/*
	 * The array is used as a binary tree, exactly as in heapsort:
	 * 
	 * heap[1] heap[2]                     heap[3] heap[4]       heap[5]
	 * heap[6]       heap[7] heap[8]heap[9] heap[10]heap[11]
	 * heap[12]heap[13] heap[14] heap[15]
	 * 
	 * We put the Z's in the last line; then we set each other node to the
	 * product of its two child-nodes (where empty or 0 entries are
	 * treated as ones); then we invert heap[1]; then we invert each
	 * other node by replacing it by the product of its parent (after
	 * inversion) and its sibling (before inversion).
	 */
	heap[0] = NULL;
	for (i = pow2 / 2 - 1; i > 0; i--)
		heap[i] = NULL;
	for (i = 0; i < num; i++)
		heap[pow2 / 2 + i] = &points[i]->Z;
	for (i = pow2 / 2 + num; i < pow2; i++)
		heap[i] = NULL;

	/* set each node to the product of its children */
	for (i = pow2 / 2 - 1; i > 0; i--) {
		heap[i] = BN_new();
		if (heap[i] == NULL)
			goto err;

		if (heap[2 * i] != NULL) {
			if ((heap[2 * i + 1] == NULL) || BN_is_zero(heap[2 * i + 1])) {
				if (!BN_copy(heap[i], heap[2 * i]))
					goto err;
			} else {
				if (BN_is_zero(heap[2 * i])) {
					if (!BN_copy(heap[i], heap[2 * i + 1]))
						goto err;
				} else {
					if (!group->meth->field_mul(group, heap[i],
						heap[2 * i], heap[2 * i + 1], ctx))
						goto err;
				}
			}
		}
	}

	/* invert heap[1] */
	if (!BN_is_zero(heap[1])) {
		if (!BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx)) {
			ECerror(ERR_R_BN_LIB);
			goto err;
		}
	}
	if (group->meth->field_encode != 0) {
		/*
		 * in the Montgomery case, we just turned  R*H  (representing
		 * H) into  1/(R*H),  but we need  R*(1/H)  (representing
		 * 1/H); i.e. we have need to multiply by the Montgomery
		 * factor twice
		 */
		if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
			goto err;
		if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
			goto err;
	}
	/* set other heap[i]'s to their inverses */
	for (i = 2; i < pow2 / 2 + num; i += 2) {
		/* i is even */
		if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1])) {
			if (!group->meth->field_mul(group, tmp0, heap[i / 2], heap[i + 1], ctx))
				goto err;
			if (!group->meth->field_mul(group, tmp1, heap[i / 2], heap[i], ctx))
				goto err;
			if (!BN_copy(heap[i], tmp0))
				goto err;
			if (!BN_copy(heap[i + 1], tmp1))
				goto err;
		} else {
			if (!BN_copy(heap[i], heap[i / 2]))
				goto err;
		}
	}

	/*
	 * we have replaced all non-zero Z's by their inverses, now fix up
	 * all the points
	 */
	for (i = 0; i < num; i++) {
		EC_POINT *p = points[i];

		if (!BN_is_zero(&p->Z)) {
			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */

			if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx))
				goto err;
			if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx))
				goto err;

			if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx))
				goto err;
			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx))
				goto err;

			if (group->meth->field_set_to_one != 0) {
				if (!group->meth->field_set_to_one(group, &p->Z, ctx))
					goto err;
			} else {
				if (!BN_one(&p->Z))
					goto err;
			}
			p->Z_is_one = 1;
		}
	}

	ret = 1;

err:
	BN_CTX_end(ctx);
	BN_CTX_free(new_ctx);
	if (heap != NULL) {
		/*
		 * heap[pow2/2] .. heap[pow2-1] have not been allocated
		 * locally!
		 */
		for (i = pow2 / 2 - 1; i > 0; i--) {
			BN_clear_free(heap[i]);
		}
		free(heap);
	}
	return ret;
}