From a200a817add039d0515e6ecf94237b634819687d Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 28 Oct 2015 16:57:51 +0000 Subject: [PATCH] Top level ECDSA sign/verify redirection. Reviewed-by: Richard Levitte --- crypto/ec/ec_kmeth.c | 2 ++ crypto/ec/ec_lcl.h | 11 ++++++++++ crypto/ec/ecdsa_ossl.c | 48 ++++++++++++++++++++++++++++++++++++++++++ crypto/ec/ecdsa_sign.c | 18 ++++++---------- crypto/ec/ecdsa_vrf.c | 26 ++++++----------------- 5 files changed, 73 insertions(+), 32 deletions(-) diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c index a329e7adcb..596d8c02fd 100644 --- a/crypto/ec/ec_kmeth.c +++ b/crypto/ec/ec_kmeth.c @@ -66,8 +66,10 @@ static const EC_KEY_METHOD openssl_ec_key_method = { 0,0,0,0,0,0, ossl_ec_key_gen, ossl_ecdh_compute_key, + ossl_ecdsa_sign, ossl_ecdsa_sign_setup, ossl_ecdsa_sign_sig, + ossl_ecdsa_verify, ossl_ecdsa_verify_sig }; diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index b18e8821df..3cd2345695 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -572,11 +572,17 @@ struct ec_key_method_st { void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)); + int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char + *sig, unsigned int *siglen, const BIGNUM *kinv, + const BIGNUM *r, EC_KEY *eckey); int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey); + + int (*verify)(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); int (*verify_sig)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); } /* EC_KEY_METHOD */ ; @@ -596,8 +602,13 @@ struct ECDSA_SIG_st { int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); +int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey); ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey); +int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index 08e10f773f..40742bdf06 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -56,6 +56,7 @@ * */ +#include #include #include #include @@ -63,6 +64,22 @@ #include #include "ec_lcl.h" +int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) +{ + ECDSA_SIG *s; + RAND_seed(dgst, dlen); + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); + if (s == NULL) { + *siglen = 0; + return 0; + } + *siglen = i2d_ECDSA_SIG(s, &sig); + ECDSA_SIG_free(s); + return 1; +} + static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) @@ -326,6 +343,37 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, return ret; } +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) +{ + ECDSA_SIG *s; + const unsigned char *p = sigbuf; + unsigned char *der = NULL; + int derlen = -1; + int ret = -1; + + s = ECDSA_SIG_new(); + if (s == NULL) + return (ret); + if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) + goto err; + /* Ensure signature uses DER and doesn't have trailing garbage */ + derlen = i2d_ECDSA_SIG(s, &der); + if (derlen != sig_len || memcmp(sigbuf, der, derlen)) + goto err; + ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); + err: + OPENSSL_clear_free(der, derlen); + ECDSA_SIG_free(s); + return (ret); +} + int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { diff --git a/crypto/ec/ecdsa_sign.c b/crypto/ec/ecdsa_sign.c index f3c6d7871c..aeccda74a2 100644 --- a/crypto/ec/ecdsa_sign.c +++ b/crypto/ec/ecdsa_sign.c @@ -82,20 +82,14 @@ int ECDSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char return ECDSA_sign_ex(type, dgst, dlen, sig, siglen, NULL, NULL, eckey); } -int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char - *sig, unsigned int *siglen, const BIGNUM *kinv, +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { - ECDSA_SIG *s; - RAND_seed(dgst, dlen); - s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); - if (s == NULL) { - *siglen = 0; - return 0; - } - *siglen = i2d_ECDSA_SIG(s, &sig); - ECDSA_SIG_free(s); - return 1; + if (eckey->meth->sign) + return eckey->meth->sign(type, dgst, dlen, sig, siglen, kinv, r, eckey); + ECerr(EC_F_ECDSA_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED); + return 0; } int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, diff --git a/crypto/ec/ecdsa_vrf.c b/crypto/ec/ecdsa_vrf.c index a62b999bb9..f545cf6871 100644 --- a/crypto/ec/ecdsa_vrf.c +++ b/crypto/ec/ecdsa_vrf.c @@ -88,24 +88,10 @@ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) { - ECDSA_SIG *s; - const unsigned char *p = sigbuf; - unsigned char *der = NULL; - int derlen = -1; - int ret = -1; - - s = ECDSA_SIG_new(); - if (s == NULL) - return (ret); - if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) - goto err; - /* Ensure signature uses DER and doesn't have trailing garbage */ - derlen = i2d_ECDSA_SIG(s, &der); - if (derlen != sig_len || memcmp(sigbuf, der, derlen)) - goto err; - ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); - err: - OPENSSL_clear_free(der, derlen); - ECDSA_SIG_free(s); - return (ret); + if (eckey->meth->verify) + return eckey->meth->verify(type, dgst, dgst_len, sigbuf, sig_len, + eckey); + ECerr(EC_F_ECDSA_VERIFY, EC_R_OPERATION_NOT_SUPPORTED); + return 0; + return 0; } -- 2.25.1