X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fec%2Fec_lib.c;h=0a182d4229e76cc11561930738162dba0b312e5b;hp=6abda2d4484ddde7d67e250933c3ae8301a42146;hb=4d3fa06fce52682bfbc503c7ded2d0289e3f8cde;hpb=80c808b90b79356c37ac41ee9bf748d39b4e53e3 diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 6abda2d448..0a182d4229 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -61,6 +61,8 @@ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ +#define OPENSSL_FIPSAPI + #include #include @@ -68,6 +70,7 @@ #include "ec_lcl.h" +__fips_constseg static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; @@ -79,7 +82,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) if (meth == NULL) { - ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER); + ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); return NULL; } if (meth->group_init == 0) @@ -98,6 +101,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) ret->meth = meth; ret->extra_data = NULL; + ret->mont_data = NULL; ret->generator = NULL; BN_init(&ret->order); @@ -127,7 +131,10 @@ void EC_GROUP_free(EC_GROUP *group) if (group->meth->group_finish != 0) group->meth->group_finish(group); - EC_GROUP_free_all_extra_data(group); + EC_EX_DATA_free_all_data(&group->extra_data); + + if (group->mont_data) + BN_MONT_CTX_free(group->mont_data); if (group->generator != NULL) EC_POINT_free(group->generator); @@ -147,10 +154,13 @@ void EC_GROUP_clear_free(EC_GROUP *group) if (group->meth->group_clear_finish != 0) group->meth->group_clear_finish(group); - else if (group->meth != NULL && group->meth->group_finish != 0) + else if (group->meth->group_finish != 0) group->meth->group_finish(group); - EC_GROUP_clear_free_all_extra_data(group); + EC_EX_DATA_clear_free_all_data(&group->extra_data); + + if (group->mont_data) + BN_MONT_CTX_free(group->mont_data); if (group->generator != NULL) EC_POINT_clear_free(group->generator); @@ -185,7 +195,7 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) if (dest == src) return 1; - EC_GROUP_free_all_extra_data(dest); + EC_EX_DATA_free_all_data(&dest->extra_data); for (d = src->extra_data; d != NULL; d = d->next) { @@ -193,10 +203,29 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) if (t == NULL) return 0; - if (!EC_GROUP_set_extra_data(dest, t, d->dup_func, d->free_func, d->clear_free_func)) + if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func)) return 0; } + if (src->mont_data != NULL) + { + if (dest->mont_data == NULL) + { + dest->mont_data = BN_MONT_CTX_new(); + if (dest->mont_data == NULL) return 0; + } + if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) return 0; + } + else + { + /* src->generator == NULL */ + if (dest->mont_data != NULL) + { + BN_MONT_CTX_free(dest->mont_data); + dest->mont_data = NULL; + } + } + if (src->generator != NULL) { if (dest->generator == NULL) @@ -306,15 +335,24 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG else BN_zero(&group->cofactor); + /* We ignore the return value because some groups have an order with + * factors of two, which makes the Montgomery setup fail. + * |group->mont_data| will be NULL in this case. */ + ec_precompute_mont_data(group); + return 1; } -EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) { return group->generator; } +BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) + { + return group->mont_data; + } int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { @@ -334,13 +372,13 @@ int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) } -void EC_GROUP_set_nid(EC_GROUP *group, int nid) +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) { group->curve_name = nid; } -int EC_GROUP_get_nid(const EC_GROUP *group) +int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; } @@ -425,7 +463,7 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM * return group->meth->group_get_curve(group, p, a, b, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { if (group->meth->group_set_curve == 0) @@ -446,7 +484,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM } return group->meth->group_get_curve(group, p, a, b, ctx); } - +#endif int EC_GROUP_get_degree(const EC_GROUP *group) { @@ -480,10 +518,10 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != EC_METHOD_get_field_type(EC_GROUP_method_of(b))) return 1; - /* compare the curve name (if present) */ - if (EC_GROUP_get_nid(a) && EC_GROUP_get_nid(b) && - EC_GROUP_get_nid(a) == EC_GROUP_get_nid(b)) - return 0; + /* compare the curve name (if present in both) */ + if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && + EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) + return 1; if (!ctx) ctx_new = ctx = BN_CTX_new(); @@ -546,19 +584,19 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) /* this has 'package' visibility */ -int EC_GROUP_set_extra_data(EC_GROUP *group, void *data, +int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { EC_EXTRA_DATA *d; - if (group == NULL) + if (ex_data == NULL) return 0; - for (d = group->extra_data; d != NULL; d = d->next) + for (d = *ex_data; d != NULL; d = d->next) { if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) { - ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL); + ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); return 0; } } @@ -576,22 +614,19 @@ int EC_GROUP_set_extra_data(EC_GROUP *group, void *data, d->free_func = free_func; d->clear_free_func = clear_free_func; - d->next = group->extra_data; - group->extra_data = d; + d->next = *ex_data; + *ex_data = d; return 1; } /* this has 'package' visibility */ -void *EC_GROUP_get_extra_data(const EC_GROUP *group, +void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { - EC_EXTRA_DATA *d; - - if (group == NULL) - return NULL; + const EC_EXTRA_DATA *d; - for (d = group->extra_data; d != NULL; d = d->next) + for (d = ex_data; d != NULL; d = d->next) { if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) return d->data; @@ -601,15 +636,15 @@ void *EC_GROUP_get_extra_data(const EC_GROUP *group, } /* this has 'package' visibility */ -void EC_GROUP_free_extra_data(EC_GROUP *group, +void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { EC_EXTRA_DATA **p; - if (group == NULL) + if (ex_data == NULL) return; - for (p = &group->extra_data; *p != NULL; p = &((*p)->next)) + for (p = ex_data; *p != NULL; p = &((*p)->next)) { if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) { @@ -625,15 +660,15 @@ void EC_GROUP_free_extra_data(EC_GROUP *group, } /* this has 'package' visibility */ -void EC_GROUP_clear_free_extra_data(EC_GROUP *group, +void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { EC_EXTRA_DATA **p; - if (group == NULL) + if (ex_data == NULL) return; - for (p = &group->extra_data; *p != NULL; p = &((*p)->next)) + for (p = ex_data; *p != NULL; p = &((*p)->next)) { if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) { @@ -649,14 +684,14 @@ void EC_GROUP_clear_free_extra_data(EC_GROUP *group, } /* this has 'package' visibility */ -void EC_GROUP_free_all_extra_data(EC_GROUP *group) +void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) { EC_EXTRA_DATA *d; - if (group == NULL) + if (ex_data == NULL) return; - d = group->extra_data; + d = *ex_data; while (d) { EC_EXTRA_DATA *next = d->next; @@ -666,18 +701,18 @@ void EC_GROUP_free_all_extra_data(EC_GROUP *group) d = next; } - group->extra_data = NULL; + *ex_data = NULL; } /* this has 'package' visibility */ -void EC_GROUP_clear_free_all_extra_data(EC_GROUP *group) +void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) { EC_EXTRA_DATA *d; - if (group == NULL) + if (ex_data == NULL) return; - d = group->extra_data; + d = *ex_data; while (d) { EC_EXTRA_DATA *next = d->next; @@ -687,7 +722,7 @@ void EC_GROUP_clear_free_all_extra_data(EC_GROUP *group) d = next; } - group->extra_data = NULL; + *ex_data = NULL; } @@ -743,7 +778,7 @@ void EC_POINT_clear_free(EC_POINT *point) if (point->meth->point_clear_finish != 0) point->meth->point_clear_finish(point); - else if (point->meth != NULL && point->meth->point_finish != 0) + else if (point->meth->point_finish != 0) point->meth->point_finish(point); OPENSSL_cleanse(point, sizeof *point); OPENSSL_free(point); @@ -859,7 +894,7 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { @@ -875,7 +910,7 @@ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, } return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); } - +#endif int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) @@ -893,7 +928,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *p return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); } - +#ifndef OPENSSL_NO_EC2M int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { @@ -909,75 +944,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT * } return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); } - - -int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, int y_bit, BN_CTX *ctx) - { - if (group->meth->point_set_compressed_coordinates == 0) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); - } - - -int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, int y_bit, BN_CTX *ctx) - { - if (group->meth->point_set_compressed_coordinates == 0) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); - } - - -size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx) - { - if (group->meth->point2oct == 0) - { - ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point2oct(group, point, form, buf, len, ctx); - } - - -int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, - const unsigned char *buf, size_t len, BN_CTX *ctx) - { - if (group->meth->oct2point == 0) - { - ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->oct2point(group, point, buf, len, ctx); - } - +#endif int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { @@ -1013,14 +980,14 @@ int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX * int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { - if (group->meth->dbl == 0) + if (group->meth->invert == 0) { - ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (group->meth != a->meth) { - ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); + ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->invert(group, a, ctx); @@ -1064,12 +1031,12 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN if (group->meth->point_cmp == 0) { ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; + return -1; } if ((group->meth != a->meth) || (a->meth != b->meth)) { ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); - return 0; + return -1; } return group->meth->point_cmp(group, a, b, ctx); } @@ -1165,3 +1132,39 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group) else return 0; /* cannot tell whether precomputation has been performed */ } + +/* ec_precompute_mont_data sets |group->mont_data| from |group->order| and + * returns one on success. On error it returns zero. */ +int ec_precompute_mont_data(EC_GROUP *group) + { + BN_CTX *ctx = BN_CTX_new(); + int ret = 0; + + if (group->mont_data) + { + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; + } + + if (ctx == NULL) + goto err; + + group->mont_data = BN_MONT_CTX_new(); + if (!group->mont_data) + goto err; + + if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) + { + BN_MONT_CTX_free(group->mont_data); + group->mont_data = NULL; + goto err; + } + + ret = 1; + +err: + + if (ctx) + BN_CTX_free(ctx); + return ret; + }