diff options
Diffstat (limited to 'crypto/ec/ecp_smpl.c')
-rw-r--r-- | crypto/ec/ecp_smpl.c | 109 |
1 files changed, 108 insertions, 1 deletions
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 4666a052bf..8e062dc951 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -2,7 +2,7 @@ /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> * for the OpenSSL project. */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2002 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 @@ -73,6 +73,7 @@ const EC_METHOD *EC_GFp_simple_method(void) ec_GFp_simple_group_get0_generator, ec_GFp_simple_group_get_order, ec_GFp_simple_group_get_cofactor, + ec_GFp_simple_group_check, ec_GFp_simple_point_init, ec_GFp_simple_point_finish, ec_GFp_simple_point_clear_finish, @@ -338,6 +339,112 @@ int ec_GFp_simple_group_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN } +int ec_GFp_simple_group_check(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; + EC_POINT *point = NULL; + + if (ctx == NULL) + { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, ERR_R_MALLOC_FAILURE); + goto err; + } + } + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + tmp_1 = BN_CTX_get(ctx); + tmp_2 = BN_CTX_get(ctx); + order = BN_CTX_get(ctx); + if (order == 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)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); + 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)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); + goto err; + } + } + + /* check the generator */ + if (group->generator == NULL) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); + goto err; + } + if (!ec_GFp_simple_is_on_curve(group, group->generator, ctx)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, 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)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, 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)) + { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); + goto err; + } + + ret = 1; + +err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (point) + EC_POINT_free(point); + return ret; + } + + int ec_GFp_simple_point_init(EC_POINT *point) { BN_init(&point->X); |