* The ECC Code is licensed pursuant to the OpenSSL open source
* license provided below.
*
- * In addition, Sun covenants to all licensees who provide a reciprocal
- * covenant with respect to their own patents if any, not to sue under
- * current and future patent claims necessarily infringed by the making,
- * using, practicing, selling, offering for sale and/or otherwise
- * disposing of the ECC Code as delivered hereunder (or portions thereof),
- * provided that such covenant shall not apply:
- * 1) for code that a licensee deletes from the ECC Code;
- * 2) separates from the ECC Code; or
- * 3) for infringements caused by:
- * i) the modification of the ECC Code or
- * ii) the combination of the ECC Code with other software or
- * devices where such combination causes the infringement.
- *
* The software is originally written by Sheueling Chang Shantz and
* Douglas Stebila of Sun Microsystems Laboratories.
*
*/
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
ec_GF2m_simple_add,
ec_GF2m_simple_dbl,
ec_GF2m_simple_invert,
- ec_GF2m_mont_mul,
- ec_GF2m_mont_precompute_mult,
ec_GF2m_simple_is_at_infinity,
ec_GF2m_simple_is_on_curve,
ec_GF2m_simple_cmp,
ec_GF2m_simple_make_affine,
ec_GF2m_simple_points_make_affine,
+
+ /* the following three method functions are defined in ec2_mult.c */
+ ec_GF2m_simple_mul,
+ ec_GF2m_precompute_mult,
+ ec_GF2m_have_precompute_mult,
+
ec_GF2m_simple_field_mul,
ec_GF2m_simple_field_sqr,
ec_GF2m_simple_field_div,
group->poly[2] = 0;
group->poly[3] = 0;
group->poly[4] = 0;
+ group->poly[5] = -1;
}
dest->poly[2] = src->poly[2];
dest->poly[3] = src->poly[3];
dest->poly[4] = src->poly[4];
- bn_wexpand(&dest->a, (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2);
- bn_wexpand(&dest->b, (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2);
+ dest->poly[5] = src->poly[5];
+ if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
+ if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
return 1;
/* group->field */
if (!BN_copy(&group->field, p)) goto err;
- i = BN_GF2m_poly2arr(&group->field, group->poly, 5);
+ i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
if ((i != 5) && (i != 3))
{
ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
/* group->a */
if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
- bn_wexpand(&group->a, (group->poly[0] + BN_BITS2 - 1) / BN_BITS2);
+ if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
/* group->b */
if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
- bn_wexpand(&group->b, (group->poly[0] + BN_BITS2 - 1) / BN_BITS2);
+ if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
ret = 1;
if (!BN_copy(p, &group->field)) return 0;
}
- if (a != NULL || b != NULL)
+ if (a != NULL)
{
- if (a != NULL)
- {
- if (!BN_copy(a, &group->a)) goto err;
- }
- if (b != NULL)
- {
- if (!BN_copy(b, &group->b)) goto err;
- }
+ if (!BN_copy(a, &group->a)) goto err;
+ }
+
+ if (b != NULL)
+ {
+ if (!BN_copy(b, &group->b)) goto err;
}
ret = 1;
ret = 1;
err:
- BN_CTX_end(ctx);
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
if (new_ctx != NULL)
BN_CTX_free(new_ctx);
return ret;
int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
{
point->Z_is_one = 0;
- return (BN_zero(&point->Z));
+ BN_zero(&point->Z);
+ return 1;
}
}
if (!BN_copy(&point->X, x)) goto err;
+ BN_set_negative(&point->X, 0);
if (!BN_copy(&point->Y, y)) goto err;
+ BN_set_negative(&point->Y, 0);
if (!BN_copy(&point->Z, BN_value_one())) goto err;
+ BN_set_negative(&point->Z, 0);
point->Z_is_one = 1;
- ret = 1;
+ if (BN_num_bits(x) > BN_num_bits(&group->field))
+ ret = 2;
+ else if (BN_num_bits(y) > BN_num_bits(&group->field))
+ ret = 2;
+ else
+ ret = 1;
err:
return ret;
if (x != NULL)
{
if (!BN_copy(x, &point->X)) goto err;
+ BN_set_negative(x, 0);
}
if (y != NULL)
{
if (!BN_copy(y, &point->Y)) goto err;
+ BN_set_negative(y, 0);
}
ret = 1;
}
-/* Include patented algorithms. */
-#include "ec2_smpt.c"
+/* Calculates and sets the affine coordinates of an EC_POINT from the given
+ * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
+ * Note that the simple implementation only uses affine coordinates.
+ *
+ * The method is from the following publication:
+ *
+ * Harper, Menezes, Vanstone:
+ * "Public-Key Cryptosystems with Very Small Key Lengths",
+ * EUROCRYPT '92, Springer-Verlag LNCS 658,
+ * published February 1993
+ *
+ * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
+ * the same method, but claim no priority date earlier than July 29, 1994
+ * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
+ */
+int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
+ const BIGNUM *x_, int y_bit, BN_CTX *ctx)
+ {
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *tmp, *x, *y, *z;
+ int ret = 0, z0;
+
+ /* clear error queue */
+ ERR_clear_error();
+
+ if (ctx == NULL)
+ {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ y_bit = (y_bit != 0) ? 1 : 0;
+
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ if (z == NULL) goto err;
+
+ if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
+ if (BN_is_zero(x))
+ {
+ if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
+ }
+ else
+ {
+ if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
+ if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
+ if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
+ if (!BN_GF2m_add(tmp, x, tmp)) goto err;
+ if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
+ {
+ unsigned long err = ERR_peek_last_error();
+
+ if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
+ {
+ ERR_clear_error();
+ ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
+ }
+ else
+ ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
+ goto err;
+ }
+ z0 = (BN_is_odd(z)) ? 1 : 0;
+ if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
+ if (z0 != y_bit)
+ {
+ if (!BN_GF2m_add(y, y, x)) goto err;
+ }
+ }
+
+ if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
+
+ ret = 1;
+
+ err:
+ BN_CTX_end(ctx);
+ if (new_ctx != NULL)
+ BN_CTX_free(new_ctx);
+ return ret;
+ }
/* Converts an EC_POINT to an octet string.
* If buf is NULL, the encoded length will be returned.
* If the length len of buf is smaller than required an error will be returned.
- *
- * The point compression section of this function is patented by Certicom Corp.
- * under US Patent 6,141,420. Point compression is disabled by default and can
- * be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at
- * Configure-time.
*/
size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
unsigned char *buf, size_t len, BN_CTX *ctx)
BIGNUM *x, *y, *yxi;
size_t field_len, i, skip;
-#ifndef OPENSSL_EC_BIN_PT_COMP
- if ((form == POINT_CONVERSION_COMPRESSED) || (form == POINT_CONVERSION_HYBRID))
- {
- ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED);
- goto err;
- }
-#endif
-
if ((form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID))
if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
buf[0] = form;
-#ifdef OPENSSL_EC_BIN_PT_COMP
if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
{
if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
if (BN_is_odd(yxi)) buf[0]++;
}
-#endif
i = 1;
}
form = buf[0];
y_bit = form & 1;
- form = form & ~1;
+ form = form & ~1U;
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID))
*/
int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
{
- BN_CTX *new_ctx = NULL;
- BIGNUM *rh, *lh, *tmp1;
int ret = -1;
+ BN_CTX *new_ctx = NULL;
+ BIGNUM *lh, *y2;
+ int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+ int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
if (EC_POINT_is_at_infinity(group, point))
return 1;
-
+
+ field_mul = group->meth->field_mul;
+ field_sqr = group->meth->field_sqr;
+
/* only support affine coordinates */
if (!point->Z_is_one) goto err;
}
BN_CTX_start(ctx);
- rh = BN_CTX_get(ctx);
+ y2 = BN_CTX_get(ctx);
lh = BN_CTX_get(ctx);
- tmp1 = BN_CTX_get(ctx);
- if (tmp1 == NULL) goto err;
+ if (lh == NULL) goto err;
/* We have a curve defined by a Weierstrass equation
* y^2 + x*y = x^3 + a*x^2 + b.
- * To test this, we add up the right-hand side in 'rh'
- * and the left-hand side in 'lh'.
+ * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
+ * <=> ((x + a) * x + y ) * x + b + y^2 = 0
*/
-
- /* rh := X^3 */
- if (!group->meth->field_sqr(group, tmp1, &point->X, ctx)) goto err;
- if (!group->meth->field_mul(group, rh, tmp1, &point->X, ctx)) goto err;
-
- /* rh := rh + a*X^2 */
- if (!group->meth->field_mul(group, tmp1, tmp1, &group->a, ctx)) goto err;
- if (!BN_GF2m_add(rh, rh, tmp1)) goto err;
-
- /* rh := rh + b */
- if (!BN_GF2m_add(rh, rh, &group->b)) goto err;
-
- /* lh := Y^2 */
- if (!group->meth->field_sqr(group, lh, &point->Y, ctx)) goto err;
-
- /* lh := lh + x*y */
- if (!group->meth->field_mul(group, tmp1, &point->X, &point->Y, ctx)) goto err;
- if (!BN_GF2m_add(lh, lh, tmp1)) goto err;
-
- ret = (0 == BN_GF2m_cmp(lh, rh));
-
+ if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
+ if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
+ if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
+ if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
+ if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
+ if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
+ if (!BN_GF2m_add(lh, lh, y2)) goto err;
+ ret = BN_is_zero(lh);
err:
if (ctx) BN_CTX_end(ctx);
if (new_ctx) BN_CTX_free(new_ctx);
{
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
}
+
+ if (EC_POINT_is_at_infinity(group, b))
+ return 1;
if (a->Z_is_one && b->Z_is_one)
{
return ret;
}
+int ec_GF2m_simple_range(const EC_GROUP *group, const EC_POINT *a)
+ {
+ if (BN_num_bits(&a->X) > BN_num_bits(&group->field))
+ return 0;
+ if (BN_num_bits(&a->Y) > BN_num_bits(&group->field))
+ return 0;
+ return 1;
+ }
+
/* Forces the given EC_POINT to internally use affine coordinates. */
int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)