diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index 22e8c2d910..ed8cba5e3a 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -553,4 +553,3 @@ int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom); } #endif #endif - diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 93fde52ffa..db410c1e81 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -65,6 +65,7 @@ extern "C" { typedef enum { + /* values as defined in X9.62 (ECDSA) and elsewhere */ POINT_CONVERSION_COMPRESSED = 2, POINT_CONVERSION_UNCOMPRESSED = 4, POINT_CONVERSION_HYBRID = 6 @@ -120,7 +121,12 @@ void EC_POINT_free(EC_POINT *); void EC_POINT_clear_free(EC_POINT *); int EC_POINT_copy(EC_POINT *, const EC_POINT *); -/* TODO: 'set' and 'get' functions for EC_POINTs */ +int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *); +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); +/* TODO: other 'set' and 'get' functions for EC_POINTs */ size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *); @@ -149,33 +155,41 @@ int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); /* Error codes for the EC functions. */ /* Function codes. */ -#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 117 -#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 118 -#define EC_F_EC_GROUP_CLEAR_FREE 103 -#define EC_F_EC_GROUP_COPY 102 -#define EC_F_EC_GROUP_FREE 104 -#define EC_F_EC_GROUP_GET_EXTRA_DATA 115 -#define EC_F_EC_GROUP_NEW 100 -#define EC_F_EC_GROUP_SET_CURVE_GFP 101 -#define EC_F_EC_GROUP_SET_EXTRA_DATA 116 -#define EC_F_EC_GROUP_SET_GENERATOR 106 -#define EC_F_EC_POINT_ADD 107 -#define EC_F_EC_POINT_COPY 108 -#define EC_F_EC_POINT_DBL 109 -#define EC_F_EC_POINT_IS_AT_INFINITY 110 -#define EC_F_EC_POINT_IS_ON_CURVE 111 -#define EC_F_EC_POINT_MAKE_AFFINE 112 -#define EC_F_EC_POINT_NEW 105 -#define EC_F_EC_POINT_OCT2POINT 113 -#define EC_F_EC_POINT_POINT2OCT 114 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 100 +#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 101 +#define EC_F_EC_GFP_SIMPLE_OCT2POINT 102 +#define EC_F_EC_GFP_SIMPLE_POINT2OCT 103 +#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 104 +#define EC_F_EC_GROUP_COPY 105 +#define EC_F_EC_GROUP_GET_EXTRA_DATA 106 +#define EC_F_EC_GROUP_NEW 107 +#define EC_F_EC_GROUP_SET_CURVE_GFP 108 +#define EC_F_EC_GROUP_SET_EXTRA_DATA 109 +#define EC_F_EC_GROUP_SET_GENERATOR 110 +#define EC_F_EC_POINT_ADD 111 +#define EC_F_EC_POINT_COPY 112 +#define EC_F_EC_POINT_DBL 113 +#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 114 +#define EC_F_EC_POINT_IS_AT_INFINITY 115 +#define EC_F_EC_POINT_IS_ON_CURVE 116 +#define EC_F_EC_POINT_MAKE_AFFINE 117 +#define EC_F_EC_POINT_NEW 118 +#define EC_F_EC_POINT_OCT2POINT 119 +#define EC_F_EC_POINT_POINT2OCT 120 +#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 121 +#define EC_F_EC_POINT_SET_TO_INFINITY 122 /* Reason codes. */ -#define EC_R_INCOMPATIBLE_OBJECTS 100 -#define EC_R_NO_SUCH_EXTRA_DATA 101 -#define EC_R_SLOT_FULL 102 +#define EC_R_BUFFER_TOO_SMALL 100 +#define EC_R_INCOMPATIBLE_OBJECTS 101 +#define EC_R_INVALID_ENCODING 102 +#define EC_R_INVALID_FORM 103 +#define EC_R_NO_SUCH_EXTRA_DATA 104 +#define EC_R_POINT_AT_INFINITY 105 +#define EC_R_POINT_IS_NOT_ON_CURVE 106 +#define EC_R_SLOT_FULL 107 #ifdef __cplusplus } #endif #endif - diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index cd2d79267a..620dbd1131 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -68,9 +68,10 @@ static ERR_STRING_DATA EC_str_functs[]= { {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR,0), "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"}, {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_MAKE_AFFINE,0), "EC_GFP_SIMPLE_MAKE_AFFINE"}, -{ERR_PACK(0,EC_F_EC_GROUP_CLEAR_FREE,0), "EC_GROUP_clear_free"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_OCT2POINT,0), "EC_GFP_SIMPLE_OCT2POINT"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT2OCT,0), "EC_GFP_SIMPLE_POINT2OCT"}, +{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP,0), "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"}, {ERR_PACK(0,EC_F_EC_GROUP_COPY,0), "EC_GROUP_copy"}, -{ERR_PACK(0,EC_F_EC_GROUP_FREE,0), "EC_GROUP_free"}, {ERR_PACK(0,EC_F_EC_GROUP_GET_EXTRA_DATA,0), "EC_GROUP_GET_EXTRA_DATA"}, {ERR_PACK(0,EC_F_EC_GROUP_NEW,0), "EC_GROUP_new"}, {ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0), "EC_GROUP_set_curve_GFp"}, @@ -79,19 +80,27 @@ static ERR_STRING_DATA EC_str_functs[]= {ERR_PACK(0,EC_F_EC_POINT_ADD,0), "EC_POINT_add"}, {ERR_PACK(0,EC_F_EC_POINT_COPY,0), "EC_POINT_copy"}, {ERR_PACK(0,EC_F_EC_POINT_DBL,0), "EC_POINT_dbl"}, +{ERR_PACK(0,EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,0), "EC_POINT_get_affine_coordinates_GFp"}, {ERR_PACK(0,EC_F_EC_POINT_IS_AT_INFINITY,0), "EC_POINT_is_at_infinity"}, {ERR_PACK(0,EC_F_EC_POINT_IS_ON_CURVE,0), "EC_POINT_is_on_curve"}, {ERR_PACK(0,EC_F_EC_POINT_MAKE_AFFINE,0), "EC_POINT_make_affine"}, {ERR_PACK(0,EC_F_EC_POINT_NEW,0), "EC_POINT_new"}, {ERR_PACK(0,EC_F_EC_POINT_OCT2POINT,0), "EC_POINT_oct2point"}, {ERR_PACK(0,EC_F_EC_POINT_POINT2OCT,0), "EC_POINT_point2oct"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,0), "EC_POINT_set_affine_coordinates_GFp"}, +{ERR_PACK(0,EC_F_EC_POINT_SET_TO_INFINITY,0), "EC_POINT_set_to_infinity"}, {0,NULL} }; static ERR_STRING_DATA EC_str_reasons[]= { +{EC_R_BUFFER_TOO_SMALL ,"buffer too small"}, {EC_R_INCOMPATIBLE_OBJECTS ,"incompatible objects"}, +{EC_R_INVALID_ENCODING ,"invalid encoding"}, +{EC_R_INVALID_FORM ,"invalid form"}, {EC_R_NO_SUCH_EXTRA_DATA ,"no such extra data"}, +{EC_R_POINT_AT_INFINITY ,"point at infinity"}, +{EC_R_POINT_IS_NOT_ON_CURVE ,"point is not on curve"}, {EC_R_SLOT_FULL ,"slot full"}, {0,NULL} }; diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index 4bfcc916fd..b3f8354e7a 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -84,7 +84,12 @@ struct ec_method_st { void (*point_clear_finish)(EC_POINT *); int (*point_copy)(EC_POINT *, const EC_POINT *); - /* TODO: 'set' and 'get' functions for EC_POINTs */ + int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *); + int (*point_set_affine_coordinates_GFp)(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); + int (*point_get_affine_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + /* TODO: other 'set' and 'get' functions for EC_POINTs */ /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, @@ -188,7 +193,12 @@ int ec_GFp_simple_point_init(EC_POINT *); void ec_GFp_simple_point_finish(EC_POINT *); void ec_GFp_simple_point_clear_finish(EC_POINT *); int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); -/* TODO: 'set' and 'get' functions for EC_POINTs */ +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, BN_CTX *); +int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); +/* TODO: other 'set' and 'get' functions for EC_POINTs */ size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *); int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 90da84eb7d..d0af0d5794 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -108,7 +108,6 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } - return group->meth->group_set_curve_GFp(group, p, a, b, ctx); } @@ -315,12 +314,61 @@ int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); return 0; } - return dest->meth->point_copy(dest, src); } -/* TODO: 'set' and 'get' functions for EC_POINTs */ +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) + { + if (group->meth->point_set_to_infinity == 0) + { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_to_infinity(group, point); + } + + +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) + { + if (group->meth->point_set_affine_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_affine_coordinates_GFp(group, point, x, y, ctx); + } + + +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) + { + if (group->meth->point_get_affine_coordinates_GFp == 0) + { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) + { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_affine_coordinates_GFp(group, point, x, y, ctx); + } + + +/* TODO: other 'set' and 'get' functions for EC_POINTs */ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index 04d21e5c40..17d9a48657 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_mont_method(void) ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish, ec_GFp_simple_point_copy, - /* TODO: 'set' and 'get' functions for EC_POINTs */ + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + /* TODO: other 'set' and 'get' functions for EC_POINTs */ ec_GFp_simple_point2oct, ec_GFp_simple_oct2point, ec_GFp_simple_add, diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index 16fea7cd55..df2d614209 100644 --- a/crypto/ec/ecp_nist.c +++ b/crypto/ec/ecp_nist.c @@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_nist_method(void) ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish, ec_GFp_simple_point_copy, - /* TODO: 'set' and 'get' functions for EC_POINTs */ + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + /* TODO: other 'set' and 'get' functions for EC_POINTs */ ec_GFp_simple_point2oct, ec_GFp_simple_oct2point, ec_GFp_simple_add, diff --git a/crypto/ec/ecp_recp.c b/crypto/ec/ecp_recp.c index b2a8da92b0..df7b52bce5 100644 --- a/crypto/ec/ecp_recp.c +++ b/crypto/ec/ecp_recp.c @@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_recp_method(void) ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish, ec_GFp_simple_point_copy, - /* TODO: 'set' and 'get' functions for EC_POINTs */ + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + /* TODO: other 'set' and 'get' functions for EC_POINTs */ ec_GFp_simple_point2oct, ec_GFp_simple_oct2point, ec_GFp_simple_add, diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 5306efdf15..9d9fe86352 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -74,7 +74,10 @@ const EC_METHOD *EC_GFp_simple_method(void) ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish, ec_GFp_simple_point_copy, - /* TODO: 'set' and 'get' functions for EC_POINTs */ + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_point_set_affine_coordinates_GFp, + ec_GFp_simple_point_get_affine_coordinates_GFp, + /* TODO: other 'set' and 'get' functions for EC_POINTs */ ec_GFp_simple_point2oct, ec_GFp_simple_oct2point, ec_GFp_simple_add, @@ -117,8 +120,8 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group, if (ctx == NULL) return 0; } - BN_CTX_start(ctx); + BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) goto err; @@ -285,17 +288,404 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) } -/* TODO: 'set' and 'get' functions for EC_POINTs */ +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) + { + point->Z_is_one = 0; + return (BN_zero(&point->Z)); + } + + +int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (!BN_copy(&point->X, x)) goto err; + if (!BN_copy(&point->Y, y)) goto err; + if (!BN_one(&point->Z)) goto err; + + if (group->meth->field_encode) + { + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err; + if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err; + if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err; + } + + point->Z_is_one = 1; + + err: + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) + { + BN_CTX *new_ctx = NULL; + BIGNUM *X, *Y, *Z, *Z_1, *Z_2, *Z_3; + const BIGNUM *X_, *Y_, *Z_; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, 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); + X = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + Z = BN_CTX_get(ctx); + Z_1 = BN_CTX_get(ctx); + Z_2 = BN_CTX_get(ctx); + Z_3 = BN_CTX_get(ctx); + if (Z_3 == 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, X, &point->X, ctx)) goto err; + if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err; + if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err; + X_ = X; Y_ = Y; Z_ = Z; + } + else + { + X_ = &point->X; + Y_ = &point->Y; + Z_ = &point->Z; + } + + if (BN_is_one(Z_)) + { + if (!BN_copy(x, X_)) goto err; + if (!BN_copy(y, Y_)) goto err; + } + else + { + if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_BN_LIB); + goto err; + } + if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err; + if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err; + + if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err; + if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } + + +/* TODO: other 'set' and 'get' functions for EC_POINTs */ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx); -/* TODO */ + unsigned char *buf, size_t len, BN_CTX *ctx) + { + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y; + size_t field_len, i, skip; + + if ((form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + goto err; + } + + if (EC_POINT_is_at_infinity(group, point)) + { + /* encodes to a single 0 octet */ + if (buf != NULL) + { + if (len < 1) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + buf[0] = 0; + } + return 1; + } + + + /* ret := required output buffer length */ + field_len = BN_num_bytes(&group->field); + ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; + + /* if 'buf' is NULL, just return required length */ + if (buf != NULL) + { + if (len < ret) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + goto err; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + used_ctx = 1; + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + + if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_bit_set(y, 0)) + buf[0] = form + 1; + else + buf[0] = form; + + i = 1; + + skip = field_len - BN_num_bytes(x); + if (skip > field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) + { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(x, buf + i); + i += skip; + if (i != 1 + field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) + { + skip = field_len - BN_num_bytes(y); + if (skip > field_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + while (skip > 0) + { + buf[i++] = 0; + skip--; + } + skip = BN_bn2bin(y, buf + i); + i += skip; + } + + if (i != ret) + { + ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (used_ctx) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + + err: + if (used_ctx) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return 0; + } int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, - const unsigned char *buf, size_t len, BN_CTX *); -/* TODO */ + const unsigned char *buf, size_t len, BN_CTX *ctx) + { + point_conversion_form_t form; + int y_bit; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + size_t field_len, enc_len; + int ret = 0; + + if (len <= 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1; + if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (form == 0) + { + if (len != 1) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + return EC_POINT_set_to_infinity(group, point); + } + + field_len = BN_num_bytes(&group->field); + enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; + + if (len != enc_len) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; + + if (!BN_bin2bn(buf + 1, field_len, x)) goto err; + if (BN_ucmp(x, &group->field) >= 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + + if (form != POINT_CONVERSION_COMPRESSED) + { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; + if (BN_ucmp(y, &group->field) >= 0) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + if (form == POINT_CONVERSION_HYBRID) + { + if (y_bit != BN_is_bit_set(y, 0)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + } + + if (form == POINT_CONVERSION_COMPRESSED) + { + /* Recover y. We have a Weierstrass equation + * y^2 = x^3 + a*x + b, + * so y is one of the square roots of x^3 + a*x + b. + */ + + BIGNUM *tmp1, *tmp2; + + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + if (tmp2 == NULL) goto err; + + /* tmp1 := x^3 */ + if (!BN_mod_sqr(tmp2, x, &group->field, ctx)) goto err; + if (!BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) goto err; + + /* tmp1 := tmp1 + a*x */ + if (group->a_is_minus3) + { + if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err; + if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err; + if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err; + } + else + { + if (!BN_mod_mul(tmp2, &group->a, x, &group->field, ctx)) goto err; + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; + } + + /* tmp1 := tmp1 + b */ + if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err; + + if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, ERR_R_BN_LIB); + goto err; + } + + if (y_bit != BN_is_bit_set(y, 0)) + { + if (!BN_usub(y, &group->field, y)) goto err; + } + if (y_bit != BN_is_bit_set(y, 0)) + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; + + if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ + { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; + } int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) @@ -324,8 +714,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, con if (ctx == NULL) return 0; } - BN_CTX_start(ctx); + BN_CTX_start(ctx); n0 = BN_CTX_get(ctx); n1 = BN_CTX_get(ctx); n2 = BN_CTX_get(ctx); @@ -483,8 +873,8 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_ if (ctx == NULL) return 0; } - BN_CTX_start(ctx); + BN_CTX_start(ctx); n0 = BN_CTX_get(ctx); n1 = BN_CTX_get(ctx); n2 = BN_CTX_get(ctx); @@ -595,10 +985,10 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) - return 0; + return -1; } - BN_CTX_start(ctx); + BN_CTX_start(ctx); rh = BN_CTX_get(ctx); tmp1 = BN_CTX_get(ctx); tmp2 = BN_CTX_get(ctx); @@ -680,7 +1070,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; - BIGNUM *Z, *Z_1, *Z_2, *Z_3; + BIGNUM *x, *y; int ret = 0; if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) @@ -692,46 +1082,23 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ct if (ctx == NULL) return 0; } + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; - Z = BN_CTX_get(ctx); - Z_1 = BN_CTX_get(ctx); - Z_2 = BN_CTX_get(ctx); - Z_3 = BN_CTX_get(ctx); - if (Z_3 == NULL) goto end; - - /* transform (X, Y, Z) into (X/Z^2, Y/Z^3, 1) */ - - if (group->meth->field_decode) + 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) { - if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto end; + ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR); + goto err; } - else - Z = &point->Z; - if (BN_is_one(Z)) - { - point->Z_is_one = 1; - ret = 1; - goto end; - } - - if (!BN_mod_inverse(Z_1, Z, &group->field, ctx)) - { - ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_BN_LIB); - goto end; - } - if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto end; - if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto end; - - if (!BN_mod_mul(&point->X, &point->X, Z_2, &group->field, ctx)) goto end; - if (!BN_mod_mul(&point->Y, &point->Y, Z_2, &group->field, ctx)) goto end; - if (!BN_set_word(&point->Z, 1)) goto end; - point->Z_is_one = 1; - ret = 1; - end: + err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); diff --git a/util/mkerr.pl b/util/mkerr.pl index 33b904f9ee..b744c81d6b 100644 --- a/util/mkerr.pl +++ b/util/mkerr.pl @@ -288,7 +288,6 @@ EOF } #endif #endif - EOF close OUT;