From: Shane Lontis Date: Sun, 12 Jan 2020 01:32:12 +0000 (+1000) Subject: Add dsa signature alg to fips provider X-Git-Tag: openssl-3.0.0-alpha1~710 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=e683582bf37de45a9512aea7ff33b9a3ebdf07f4 Add dsa signature alg to fips provider Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10615) --- diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c index 3b19ef15a8..739df23d44 100644 --- a/apps/fipsinstall.c +++ b/apps/fipsinstall.c @@ -170,7 +170,7 @@ static CONF *generate_config_and_load(const char *prov_name, if (conf == NULL) goto end; - if (!CONF_modules_load(conf, NULL, 0)) + if (CONF_modules_load(conf, NULL, 0) <= 0) goto end; BIO_free(mem_bio); return conf; diff --git a/crypto/dsa/build.info b/crypto/dsa/build.info index 2e759853a2..309fda323e 100644 --- a/crypto/dsa/build.info +++ b/crypto/dsa/build.info @@ -1,5 +1,9 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - dsa_gen.c dsa_key.c dsa_lib.c dsa_asn1.c dsa_vrf.c dsa_sign.c \ - dsa_err.c dsa_ossl.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \ + +$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c + +SOURCE[../../libcrypto]=$COMMON\ + dsa_gen.c dsa_key.c dsa_asn1.c \ + dsa_err.c dsa_depr.c dsa_ameth.c dsa_pmeth.c dsa_prn.c \ dsa_meth.c +SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c index bf16e282d5..20bf2518c8 100644 --- a/crypto/dsa/dsa_asn1.c +++ b/crypto/dsa/dsa_asn1.c @@ -15,110 +15,6 @@ #include #include "crypto/asn1_dsa.h" -DSA_SIG *DSA_SIG_new(void) -{ - DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); - if (sig == NULL) - DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE); - return sig; -} - -void DSA_SIG_free(DSA_SIG *sig) -{ - if (sig == NULL) - return; - BN_clear_free(sig->r); - BN_clear_free(sig->s); - OPENSSL_free(sig); -} - -DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len) -{ - DSA_SIG *sig; - - if (len < 0) - return NULL; - if (psig != NULL && *psig != NULL) { - sig = *psig; - } else { - sig = DSA_SIG_new(); - if (sig == NULL) - return NULL; - } - if (sig->r == NULL) - sig->r = BN_new(); - if (sig->s == NULL) - sig->s = BN_new(); - if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) { - if (psig == NULL || *psig == NULL) - DSA_SIG_free(sig); - return NULL; - } - if (psig != NULL && *psig == NULL) - *psig = sig; - return sig; -} - -int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout) -{ - BUF_MEM *buf = NULL; - size_t encoded_len; - WPACKET pkt; - - if (ppout == NULL) { - if (!WPACKET_init_null(&pkt, 0)) - return -1; - } else if (*ppout == NULL) { - if ((buf = BUF_MEM_new()) == NULL - || !WPACKET_init_len(&pkt, buf, 0)) { - BUF_MEM_free(buf); - return -1; - } - } else { - if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0)) - return -1; - } - - if (!encode_der_dsa_sig(&pkt, sig->r, sig->s) - || !WPACKET_get_total_written(&pkt, &encoded_len) - || !WPACKET_finish(&pkt)) { - BUF_MEM_free(buf); - WPACKET_cleanup(&pkt); - return -1; - } - - if (ppout != NULL) { - if (*ppout == NULL) { - *ppout = (unsigned char *)buf->data; - buf->data = NULL; - BUF_MEM_free(buf); - } else { - *ppout += encoded_len; - } - } - - return (int)encoded_len; -} - -void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) -{ - if (pr != NULL) - *pr = sig->r; - if (ps != NULL) - *ps = sig->s; -} - -int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) -{ - if (r == NULL || s == NULL) - return 0; - BN_clear_free(sig->r); - BN_clear_free(sig->s); - sig->r = r; - sig->s = s; - return 1; -} - /* Override the default free and new methods */ static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) @@ -168,50 +64,3 @@ DSA *DSAparams_dup(const DSA *dsa) { return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), dsa); } - -int DSA_sign(int type, const unsigned char *dgst, int dlen, - unsigned char *sig, unsigned int *siglen, DSA *dsa) -{ - DSA_SIG *s; - - s = DSA_do_sign(dgst, dlen, dsa); - if (s == NULL) { - *siglen = 0; - return 0; - } - *siglen = i2d_DSA_SIG(s, &sig); - DSA_SIG_free(s); - return 1; -} - -/* data has already been hashed (probably with SHA or SHA-1). */ -/*- - * returns - * 1: correct signature - * 0: incorrect signature - * -1: error - */ -int DSA_verify(int type, const unsigned char *dgst, int dgst_len, - const unsigned char *sigbuf, int siglen, DSA *dsa) -{ - DSA_SIG *s; - const unsigned char *p = sigbuf; - unsigned char *der = NULL; - int derlen = -1; - int ret = -1; - - s = DSA_SIG_new(); - if (s == NULL) - return ret; - if (d2i_DSA_SIG(&s, &p, siglen) == NULL) - goto err; - /* Ensure signature uses DER and doesn't have trailing garbage */ - derlen = i2d_DSA_SIG(s, &der); - if (derlen != siglen || memcmp(sigbuf, der, derlen)) - goto err; - ret = DSA_do_verify(dgst, dgst_len, s, dsa); - err: - OPENSSL_clear_free(der, derlen); - DSA_SIG_free(s); - return ret; -} diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 4670c433c5..2a97c0852c 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -15,12 +15,140 @@ #include #include #include +#include "crypto/dsa.h" + +#ifndef FIPS_MODE DSA *DSA_new(void) { return DSA_new_method(NULL); } +int DSA_set_ex_data(DSA *d, int idx, void *arg) +{ + return CRYPTO_set_ex_data(&d->ex_data, idx, arg); +} + +void *DSA_get_ex_data(DSA *d, int idx) +{ + return CRYPTO_get_ex_data(&d->ex_data, idx); +} + +int DSA_security_bits(const DSA *d) +{ + if (d->p && d->q) + return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); + return -1; +} + +#ifndef OPENSSL_NO_DH +DH *DSA_dup_DH(const DSA *r) +{ + /* + * DSA has p, q, g, optional pub_key, optional priv_key. DH has p, + * optional length, g, optional pub_key, optional priv_key, optional q. + */ + + DH *ret = NULL; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; + + if (r == NULL) + goto err; + ret = DH_new(); + if (ret == NULL) + goto err; + if (r->p != NULL || r->g != NULL || r->q != NULL) { + if (r->p == NULL || r->g == NULL || r->q == NULL) { + /* Shouldn't happen */ + goto err; + } + p = BN_dup(r->p); + g = BN_dup(r->g); + q = BN_dup(r->q); + if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g)) + goto err; + p = g = q = NULL; + } + + if (r->pub_key != NULL) { + pub_key = BN_dup(r->pub_key); + if (pub_key == NULL) + goto err; + if (r->priv_key != NULL) { + priv_key = BN_dup(r->priv_key); + if (priv_key == NULL) + goto err; + } + if (!DH_set0_key(ret, pub_key, priv_key)) + goto err; + } else if (r->priv_key != NULL) { + /* Shouldn't happen */ + goto err; + } + + return ret; + + err: + BN_free(p); + BN_free(g); + BN_free(q); + BN_free(pub_key); + BN_free(priv_key); + DH_free(ret); + return NULL; +} +#endif + +const BIGNUM *DSA_get0_p(const DSA *d) +{ + return d->p; +} + +const BIGNUM *DSA_get0_q(const DSA *d) +{ + return d->q; +} + +const BIGNUM *DSA_get0_g(const DSA *d) +{ + return d->g; +} + +const BIGNUM *DSA_get0_pub_key(const DSA *d) +{ + return d->pub_key; +} + +const BIGNUM *DSA_get0_priv_key(const DSA *d) +{ + return d->priv_key; +} + +void DSA_clear_flags(DSA *d, int flags) +{ + d->flags &= ~flags; +} + +int DSA_test_flags(const DSA *d, int flags) +{ + return d->flags & flags; +} + +void DSA_set_flags(DSA *d, int flags) +{ + d->flags |= flags; +} + +ENGINE *DSA_get0_engine(DSA *d) +{ + return d->engine; +} + +int DSA_bits(const DSA *dsa) +{ + return BN_num_bits(dsa->p); +} + int DSA_set_method(DSA *dsa, const DSA_METHOD *meth) { /* @@ -40,13 +168,15 @@ int DSA_set_method(DSA *dsa, const DSA_METHOD *meth) meth->init(dsa); return 1; } +#endif /* FIPS_MODE */ + const DSA_METHOD *DSA_get_method(DSA *d) { return d->meth; } -DSA *DSA_new_method(ENGINE *engine) +static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine) { DSA *ret = OPENSSL_zalloc(sizeof(*ret)); @@ -64,7 +194,7 @@ DSA *DSA_new_method(ENGINE *engine) } ret->meth = DSA_get_default_method(); -#ifndef OPENSSL_NO_ENGINE +#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE) ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */ if (engine) { if (!ENGINE_init(engine)) { @@ -85,7 +215,7 @@ DSA *DSA_new_method(ENGINE *engine) ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; - if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data)) + if (!crypto_new_ex_data_ex(libctx, CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data)) goto err; if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { @@ -100,6 +230,16 @@ DSA *DSA_new_method(ENGINE *engine) return NULL; } +DSA *DSA_new_method(ENGINE *engine) +{ + return dsa_new_method(NULL, engine); +} + +DSA *dsa_new(OPENSSL_CTX *libctx) +{ + return dsa_new_method(libctx, NULL); +} + void DSA_free(DSA *r) { int i; @@ -115,7 +255,7 @@ void DSA_free(DSA *r) if (r->meth != NULL && r->meth->finish != NULL) r->meth->finish(r); -#ifndef OPENSSL_NO_ENGINE +#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE) ENGINE_finish(r->engine); #endif @@ -143,103 +283,6 @@ int DSA_up_ref(DSA *r) return ((i > 1) ? 1 : 0); } -int DSA_size(const DSA *r) -{ - int ret, i; - ASN1_INTEGER bs; - unsigned char buf[4]; /* 4 bytes looks really small. However, - * i2d_ASN1_INTEGER() will not look beyond - * the first byte, as long as the second - * parameter is NULL. */ - - i = BN_num_bits(r->q); - bs.length = (i + 7) / 8; - bs.data = buf; - bs.type = V_ASN1_INTEGER; - /* If the top bit is set the asn1 encoding is 1 larger. */ - buf[0] = 0xff; - - i = i2d_ASN1_INTEGER(&bs, NULL); - i += i; /* r and s */ - ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); - return ret; -} - -int DSA_set_ex_data(DSA *d, int idx, void *arg) -{ - return CRYPTO_set_ex_data(&d->ex_data, idx, arg); -} - -void *DSA_get_ex_data(DSA *d, int idx) -{ - return CRYPTO_get_ex_data(&d->ex_data, idx); -} - -int DSA_security_bits(const DSA *d) -{ - if (d->p && d->q) - return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q)); - return -1; -} - -#ifndef OPENSSL_NO_DH -DH *DSA_dup_DH(const DSA *r) -{ - /* - * DSA has p, q, g, optional pub_key, optional priv_key. DH has p, - * optional length, g, optional pub_key, optional priv_key, optional q. - */ - - DH *ret = NULL; - BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; - - if (r == NULL) - goto err; - ret = DH_new(); - if (ret == NULL) - goto err; - if (r->p != NULL || r->g != NULL || r->q != NULL) { - if (r->p == NULL || r->g == NULL || r->q == NULL) { - /* Shouldn't happen */ - goto err; - } - p = BN_dup(r->p); - g = BN_dup(r->g); - q = BN_dup(r->q); - if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g)) - goto err; - p = g = q = NULL; - } - - if (r->pub_key != NULL) { - pub_key = BN_dup(r->pub_key); - if (pub_key == NULL) - goto err; - if (r->priv_key != NULL) { - priv_key = BN_dup(r->priv_key); - if (priv_key == NULL) - goto err; - } - if (!DH_set0_key(ret, pub_key, priv_key)) - goto err; - } else if (r->priv_key != NULL) { - /* Shouldn't happen */ - goto err; - } - - return ret; - - err: - BN_free(p); - BN_free(g); - BN_free(q); - BN_free(pub_key); - BN_free(priv_key); - DH_free(ret); - return NULL; -} -#endif - void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { @@ -309,52 +352,3 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) return 1; } -const BIGNUM *DSA_get0_p(const DSA *d) -{ - return d->p; -} - -const BIGNUM *DSA_get0_q(const DSA *d) -{ - return d->q; -} - -const BIGNUM *DSA_get0_g(const DSA *d) -{ - return d->g; -} - -const BIGNUM *DSA_get0_pub_key(const DSA *d) -{ - return d->pub_key; -} - -const BIGNUM *DSA_get0_priv_key(const DSA *d) -{ - return d->priv_key; -} - -void DSA_clear_flags(DSA *d, int flags) -{ - d->flags &= ~flags; -} - -int DSA_test_flags(const DSA *d, int flags) -{ - return d->flags & flags; -} - -void DSA_set_flags(DSA *d, int flags) -{ - d->flags |= flags; -} - -ENGINE *DSA_get0_engine(DSA *d) -{ - return d->engine; -} - -int DSA_bits(const DSA *dsa) -{ - return BN_num_bits(dsa->p); -} diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h index e56ff06977..13a3007ff0 100644 --- a/crypto/dsa/dsa_local.h +++ b/crypto/dsa/dsa_local.h @@ -78,3 +78,6 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, size_t seed_len, int idx, unsigned char *seed_out, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); + +DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, + int dlen, DSA *dsa); diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 5e34fc5586..af0fa6b566 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -44,10 +44,12 @@ static DSA_METHOD openssl_dsa_meth = { static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth; +#ifndef FIPS_MODE void DSA_set_default_method(const DSA_METHOD *meth) { default_DSA_method = meth; } +#endif /* FIPS_MODE */ const DSA_METHOD *DSA_get_default_method(void) { @@ -59,7 +61,8 @@ const DSA_METHOD *DSA_OpenSSL(void) return &openssl_dsa_meth; } -static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) +DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst, + int dlen, DSA *dsa) { BIGNUM *kinv = NULL; BIGNUM *m, *blind, *blindm, *tmp; @@ -85,7 +88,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) if (ret->r == NULL || ret->s == NULL) goto err; - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(libctx); if (ctx == NULL) goto err; m = BN_CTX_get(ctx); @@ -121,8 +124,8 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) /* Generate a blinding value */ do { - if (!BN_priv_rand(blind, BN_num_bits(dsa->q) - 1, - BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + if (!BN_priv_rand_ex(blind, BN_num_bits(dsa->q) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, ctx)) goto err; } while (BN_is_zero(blind)); BN_set_flags(blind, BN_FLG_CONSTTIME); @@ -164,7 +167,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) err: if (rv == 0) { - DSAerr(DSA_F_DSA_DO_SIGN, reason); + DSAerr(0, reason); DSA_SIG_free(ret); ret = NULL; } @@ -173,6 +176,11 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) return ret; } +static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) +{ + return dsa_do_sign_int(NULL, dgst, dlen, dsa); +} + static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { @@ -210,7 +218,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, goto err; if (ctx_in == NULL) { - if ((ctx = BN_CTX_new()) == NULL) + /* if you don't pass in ctx_in you get a default libctx */ + if ((ctx = BN_CTX_new_ex(NULL)) == NULL) goto err; } else ctx = ctx_in; @@ -232,7 +241,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst, dlen, ctx)) goto err; - } else if (!BN_priv_rand_range(k, dsa->q)) + } else if (!BN_priv_rand_range_ex(k, dsa->q, ctx)) goto err; } while (BN_is_zero(k)); @@ -323,7 +332,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, u1 = BN_new(); u2 = BN_new(); t1 = BN_new(); - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(NULL); /* verify does not need a libctx */ if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL) goto err; diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 99ef0043eb..d09aaea6db 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -7,9 +7,11 @@ * https://www.openssl.org/source/license.html */ +#include #include "internal/cryptlib.h" #include "dsa_local.h" -#include +#include "crypto/asn1_dsa.h" +#include "crypto/dsa.h" DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { @@ -22,3 +24,178 @@ int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp); } #endif + +DSA_SIG *DSA_SIG_new(void) +{ + DSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); + if (sig == NULL) + DSAerr(DSA_F_DSA_SIG_NEW, ERR_R_MALLOC_FAILURE); + return sig; +} + +void DSA_SIG_free(DSA_SIG *sig) +{ + if (sig == NULL) + return; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + OPENSSL_free(sig); +} + +DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len) +{ + DSA_SIG *sig; + + if (len < 0) + return NULL; + if (psig != NULL && *psig != NULL) { + sig = *psig; + } else { + sig = DSA_SIG_new(); + if (sig == NULL) + return NULL; + } + if (sig->r == NULL) + sig->r = BN_new(); + if (sig->s == NULL) + sig->s = BN_new(); + if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) { + if (psig == NULL || *psig == NULL) + DSA_SIG_free(sig); + return NULL; + } + if (psig != NULL && *psig == NULL) + *psig = sig; + return sig; +} + +int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout) +{ + BUF_MEM *buf = NULL; + size_t encoded_len; + WPACKET pkt; + + if (ppout == NULL) { + if (!WPACKET_init_null(&pkt, 0)) + return -1; + } else if (*ppout == NULL) { + if ((buf = BUF_MEM_new()) == NULL + || !WPACKET_init_len(&pkt, buf, 0)) { + BUF_MEM_free(buf); + return -1; + } + } else { + if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0)) + return -1; + } + + if (!encode_der_dsa_sig(&pkt, sig->r, sig->s) + || !WPACKET_get_total_written(&pkt, &encoded_len) + || !WPACKET_finish(&pkt)) { + BUF_MEM_free(buf); + WPACKET_cleanup(&pkt); + return -1; + } + + if (ppout != NULL) { + if (*ppout == NULL) { + *ppout = (unsigned char *)buf->data; + buf->data = NULL; + BUF_MEM_free(buf); + } else { + *ppout += encoded_len; + } + } + + return (int)encoded_len; +} + +int DSA_size(const DSA *dsa) +{ + int ret; + DSA_SIG sig; + + sig.r = sig.s = dsa->q; + ret = i2d_DSA_SIG(&sig, NULL); + + if (ret < 0) + ret = 0; + return ret; +} + +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst, + int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa) +{ + DSA_SIG *s; + + /* legacy case uses the method table */ + if (libctx == NULL || dsa->meth != DSA_get_default_method()) + s = DSA_do_sign(dgst, dlen, dsa); + else + s = dsa_do_sign_int(libctx, dgst, dlen, dsa); + if (s == NULL) { + *siglen = 0; + return 0; + } + *siglen = i2d_DSA_SIG(s, &sig); + DSA_SIG_free(s); + return 1; +} + +int DSA_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa) +{ + return dsa_sign_int(NULL, type, dgst, dlen, sig, siglen, dsa); +} + +/* data has already been hashed (probably with SHA or SHA-1). */ +/*- + * returns + * 1: correct signature + * 0: incorrect signature + * -1: error + */ +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa) +{ + DSA_SIG *s; + const unsigned char *p = sigbuf; + unsigned char *der = NULL; + int derlen = -1; + int ret = -1; + + s = DSA_SIG_new(); + if (s == NULL) + return ret; + if (d2i_DSA_SIG(&s, &p, siglen) == NULL) + goto err; + /* Ensure signature uses DER and doesn't have trailing garbage */ + derlen = i2d_DSA_SIG(s, &der); + if (derlen != siglen || memcmp(sigbuf, der, derlen)) + goto err; + ret = DSA_do_verify(dgst, dgst_len, s, dsa); + err: + OPENSSL_clear_free(der, derlen); + DSA_SIG_free(s); + return ret; +} + diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 156b26050b..71e0ebaf44 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -1,19 +1,18 @@ LIBS=../../libcrypto $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \ mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \ - m_sigver.c + m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c + SOURCE[../../libcrypto]=$COMMON\ encode.c evp_key.c evp_cnf.c \ e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ e_rc4.c e_aes.c names.c e_seed.c e_aria.c e_sm4.c \ - e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \ - m_null.c \ - p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ + e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c m_null.c \ + p_open.c p_seal.c p_sign.c p_verify.c p_enc.c p_dec.c \ bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \ c_allc.c c_alld.c bio_ok.c \ evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ - pkey_kdf.c \ - e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c \ + pkey_kdf.c e_old.c pmeth_fn.c\ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ e_chacha20_poly1305.c \ pkey_mac.c exchange.c \ diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 59cadb4aad..5c11ce1b6a 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -28,7 +28,9 @@ #include "crypto/evp.h" #include "internal/provider.h" -static void EVP_PKEY_free_it(EVP_PKEY *x); +static void evp_pkey_free_it(EVP_PKEY *key); + +#ifndef FIPS_MODE int EVP_PKEY_bits(const EVP_PKEY *pkey) { @@ -46,16 +48,9 @@ int EVP_PKEY_security_bits(const EVP_PKEY *pkey) return pkey->ameth->pkey_security_bits(pkey); } -int EVP_PKEY_size(const EVP_PKEY *pkey) -{ - if (pkey && pkey->ameth && pkey->ameth->pkey_size) - return pkey->ameth->pkey_size(pkey); - return 0; -} - int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) { -#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { int ret = pkey->save_parameters; @@ -63,8 +58,8 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) pkey->save_parameters = mode; return ret; } -#endif -#ifndef OPENSSL_NO_EC +# endif +# ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { int ret = pkey->save_parameters; @@ -72,7 +67,7 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) pkey->save_parameters = mode; return ret; } -#endif +# endif return 0; } @@ -141,38 +136,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -EVP_PKEY *EVP_PKEY_new(void) -{ - EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); - - if (ret == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - return NULL; - } - ret->type = EVP_PKEY_NONE; - ret->save_type = EVP_PKEY_NONE; - ret->references = 1; - ret->save_parameters = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - OPENSSL_free(ret); - return NULL; - } - return ret; -} - -int EVP_PKEY_up_ref(EVP_PKEY *pkey) -{ - int i; - - if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) - return 0; - - REF_PRINT_COUNT("EVP_PKEY", pkey); - REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); -} /* * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey @@ -187,29 +150,29 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, if (pkey) { if (pkey->pkey.ptr) - EVP_PKEY_free_it(pkey); + evp_pkey_free_it(pkey); /* * If key type matches and a method exists then this lookup has * succeeded once so just indicate success. */ if ((type == pkey->save_type) && pkey->ameth) return 1; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE /* If we have ENGINEs release them */ ENGINE_finish(pkey->engine); pkey->engine = NULL; ENGINE_finish(pkey->pmeth_engine); pkey->pmeth_engine = NULL; -#endif +# endif } if (str) ameth = EVP_PKEY_asn1_find_str(eptr, str, len); else ameth = EVP_PKEY_asn1_find(eptr, type); -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE if (pkey == NULL && eptr != NULL) ENGINE_finish(e); -#endif +# endif if (ameth == NULL) { EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); return 0; @@ -321,10 +284,10 @@ int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, size_t len, const EVP_CIPHER *cipher) { -#ifndef OPENSSL_NO_CMAC -# ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_CMAC +# ifndef OPENSSL_NO_ENGINE const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL; -# endif +# endif const char *cipher_name = EVP_CIPHER_name(cipher); const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher); OPENSSL_CTX *libctx = @@ -342,11 +305,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, goto err; } -# ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE if (engine_id != NULL) params[paramsn++] = OSSL_PARAM_construct_utf8_string("engine", (char *)engine_id, 0); -# endif +# endif params[paramsn++] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, @@ -369,11 +332,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, EVP_MAC_CTX_free(cmctx); EVP_MAC_free(cmac); return NULL; -#else +# else EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return NULL; -#endif +# endif } int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) @@ -405,7 +368,7 @@ int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) return 1; } -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) { if (e != NULL) { @@ -428,7 +391,7 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey) { return pkey->engine; } -#endif +# endif int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) @@ -454,7 +417,7 @@ const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len) return os->data; } -#ifndef OPENSSL_NO_POLY1305 +# ifndef OPENSSL_NO_POLY1305 const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) { ASN1_OCTET_STRING *os = NULL; @@ -466,9 +429,9 @@ const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) *len = os->length; return os->data; } -#endif +# endif -#ifndef OPENSSL_NO_SIPHASH +# ifndef OPENSSL_NO_SIPHASH const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) { ASN1_OCTET_STRING *os = NULL; @@ -481,9 +444,9 @@ const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) *len = os->length; return os->data; } -#endif +# endif -#ifndef OPENSSL_NO_RSA +# ifndef OPENSSL_NO_RSA int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { int ret = EVP_PKEY_assign_RSA(pkey, key); @@ -508,9 +471,9 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) RSA_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { int ret = EVP_PKEY_assign_DSA(pkey, key); @@ -535,9 +498,9 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) DSA_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { @@ -563,9 +526,9 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) EC_KEY_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) { @@ -593,7 +556,7 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) DH_up_ref(ret); return ret; } -#endif +# endif int EVP_PKEY_type(int type) { @@ -605,9 +568,9 @@ int EVP_PKEY_type(int type) ret = ameth->pkey_id; else ret = NID_undef; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE ENGINE_finish(e); -#endif +# endif return ret; } @@ -621,41 +584,6 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey) return EVP_PKEY_type(pkey->type); } -void EVP_PKEY_free(EVP_PKEY *x) -{ - int i; - - if (x == NULL) - return; - - CRYPTO_DOWN_REF(&x->references, &i, x->lock); - REF_PRINT_COUNT("EVP_PKEY", x); - if (i > 0) - return; - REF_ASSERT_ISNT(i < 0); - EVP_PKEY_free_it(x); - CRYPTO_THREAD_lock_free(x->lock); - sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); - OPENSSL_free(x); -} - -static void EVP_PKEY_free_it(EVP_PKEY *x) -{ - /* internal function; x is never NULL */ - - evp_keymgmt_clear_pkey_cache(x); - - if (x->ameth && x->ameth->pkey_free) { - x->ameth->pkey_free(x); - x->pkey.ptr = NULL; - } -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(x->engine); - x->engine = NULL; - ENGINE_finish(x->pmeth_engine); - x->pmeth_engine = NULL; -#endif -} static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent) { @@ -807,3 +735,87 @@ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) return 0; return rv; } + +#endif /* FIPS_MODE */ + +/*- All methods below can also be used in FIPS_MODE */ + +EVP_PKEY *EVP_PKEY_new(void) +{ + EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = EVP_PKEY_NONE; + ret->save_type = EVP_PKEY_NONE; + ret->references = 1; + ret->save_parameters = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ + int i; + + if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) + return 0; + + REF_PRINT_COUNT("EVP_PKEY", pkey); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +static void evp_pkey_free_it(EVP_PKEY *x) +{ + /* internal function; x is never NULL */ + + evp_keymgmt_clear_pkey_cache(x); + + if (x->ameth && x->ameth->pkey_free) { + x->ameth->pkey_free(x); + x->pkey.ptr = NULL; + } +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) + ENGINE_finish(x->engine); + x->engine = NULL; + ENGINE_finish(x->pmeth_engine); + x->pmeth_engine = NULL; +#endif +} + +void EVP_PKEY_free(EVP_PKEY *x) +{ + int i; + + if (x == NULL) + return; + + CRYPTO_DOWN_REF(&x->references, &i, x->lock); + REF_PRINT_COUNT("EVP_PKEY", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + evp_pkey_free_it(x); + CRYPTO_THREAD_lock_free(x->lock); +#ifndef FIPS_MODE + sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); +#endif + OPENSSL_free(x); +} + +/* TODO (3.0) : Needs to call getparams fo non legacy case */ +int EVP_PKEY_size(const EVP_PKEY *pkey) +{ + if (pkey && pkey->ameth && pkey->ameth->pkey_size) + return pkey->ameth->pkey_size(pkey); + return 0; +} + diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c index 3d0ee2e646..31422baa4c 100644 --- a/crypto/evp/pmeth_fn.c +++ b/crypto/evp/pmeth_fn.c @@ -16,569 +16,6 @@ #include "internal/provider.h" #include "evp_local.h" -static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov) -{ - EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE)); - - if (signature == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - return NULL; - } - - signature->lock = CRYPTO_THREAD_lock_new(); - if (signature->lock == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - OPENSSL_free(signature); - return NULL; - } - signature->prov = prov; - ossl_provider_up_ref(prov); - signature->refcnt = 1; - - return signature; -} - -static void *evp_signature_from_dispatch(int name_id, - const OSSL_DISPATCH *fns, - OSSL_PROVIDER *prov) -{ - EVP_SIGNATURE *signature = NULL; - int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0; - int digsignfncnt = 0, digverifyfncnt = 0; - int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0; - - if ((signature = evp_signature_new(prov)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - goto err; - } - - signature->name_id = name_id; - - for (; fns->function_id != 0; fns++) { - switch (fns->function_id) { - case OSSL_FUNC_SIGNATURE_NEWCTX: - if (signature->newctx != NULL) - break; - signature->newctx = OSSL_get_OP_signature_newctx(fns); - ctxfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SIGN_INIT: - if (signature->sign_init != NULL) - break; - signature->sign_init = OSSL_get_OP_signature_sign_init(fns); - signfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SIGN: - if (signature->sign != NULL) - break; - signature->sign = OSSL_get_OP_signature_sign(fns); - signfncnt++; - break; - case OSSL_FUNC_SIGNATURE_VERIFY_INIT: - if (signature->verify_init != NULL) - break; - signature->verify_init = OSSL_get_OP_signature_verify_init(fns); - verifyfncnt++; - break; - case OSSL_FUNC_SIGNATURE_VERIFY: - if (signature->verify != NULL) - break; - signature->verify = OSSL_get_OP_signature_verify(fns); - verifyfncnt++; - break; - case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT: - if (signature->verify_recover_init != NULL) - break; - signature->verify_recover_init - = OSSL_get_OP_signature_verify_recover_init(fns); - verifyrecfncnt++; - break; - case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER: - if (signature->verify_recover != NULL) - break; - signature->verify_recover - = OSSL_get_OP_signature_verify_recover(fns); - verifyrecfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT: - if (signature->digest_sign_init != NULL) - break; - signature->digest_sign_init - = OSSL_get_OP_signature_digest_sign_init(fns); - digsignfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: - if (signature->digest_sign_update != NULL) - break; - signature->digest_sign_update - = OSSL_get_OP_signature_digest_sign_update(fns); - digsignfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL: - if (signature->digest_sign_final != NULL) - break; - signature->digest_sign_final - = OSSL_get_OP_signature_digest_sign_final(fns); - digsignfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT: - if (signature->digest_verify_init != NULL) - break; - signature->digest_verify_init - = OSSL_get_OP_signature_digest_verify_init(fns); - digverifyfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: - if (signature->digest_verify_update != NULL) - break; - signature->digest_verify_update - = OSSL_get_OP_signature_digest_verify_update(fns); - digverifyfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL: - if (signature->digest_verify_final != NULL) - break; - signature->digest_verify_final - = OSSL_get_OP_signature_digest_verify_final(fns); - digverifyfncnt++; - break; - case OSSL_FUNC_SIGNATURE_FREECTX: - if (signature->freectx != NULL) - break; - signature->freectx = OSSL_get_OP_signature_freectx(fns); - ctxfncnt++; - break; - case OSSL_FUNC_SIGNATURE_DUPCTX: - if (signature->dupctx != NULL) - break; - signature->dupctx = OSSL_get_OP_signature_dupctx(fns); - break; - case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS: - if (signature->get_ctx_params != NULL) - break; - signature->get_ctx_params - = OSSL_get_OP_signature_get_ctx_params(fns); - gparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS: - if (signature->gettable_ctx_params != NULL) - break; - signature->gettable_ctx_params - = OSSL_get_OP_signature_gettable_ctx_params(fns); - gparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS: - if (signature->set_ctx_params != NULL) - break; - signature->set_ctx_params - = OSSL_get_OP_signature_set_ctx_params(fns); - sparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS: - if (signature->settable_ctx_params != NULL) - break; - signature->settable_ctx_params - = OSSL_get_OP_signature_settable_ctx_params(fns); - sparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS: - if (signature->get_ctx_md_params != NULL) - break; - signature->get_ctx_md_params - = OSSL_get_OP_signature_get_ctx_md_params(fns); - gmdparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS: - if (signature->gettable_ctx_md_params != NULL) - break; - signature->gettable_ctx_md_params - = OSSL_get_OP_signature_gettable_ctx_md_params(fns); - gmdparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS: - if (signature->set_ctx_md_params != NULL) - break; - signature->set_ctx_md_params - = OSSL_get_OP_signature_set_ctx_md_params(fns); - smdparamfncnt++; - break; - case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS: - if (signature->settable_ctx_md_params != NULL) - break; - signature->settable_ctx_md_params - = OSSL_get_OP_signature_settable_ctx_md_params(fns); - smdparamfncnt++; - break; - } - } - if (ctxfncnt != 2 - || (signfncnt == 0 - && verifyfncnt == 0 - && verifyrecfncnt == 0 - && digsignfncnt == 0 - && digverifyfncnt == 0) - || (signfncnt != 0 && signfncnt != 2) - || (verifyfncnt != 0 && verifyfncnt != 2) - || (verifyrecfncnt != 0 && verifyrecfncnt != 2) - || (digsignfncnt != 0 && digsignfncnt != 3) - || (digverifyfncnt != 0 && digverifyfncnt != 3) - || (gparamfncnt != 0 && gparamfncnt != 2) - || (sparamfncnt != 0 && sparamfncnt != 2) - || (gmdparamfncnt != 0 && gmdparamfncnt != 2) - || (smdparamfncnt != 0 && smdparamfncnt != 2)) { - /* - * In order to be a consistent set of functions we must have at least - * a set of context functions (newctx and freectx) as well as a set of - * "signature" functions: - * (sign_init, sign) or - * (verify_init verify) or - * (verify_recover_init, verify_recover) or - * (digest_sign_init, digest_sign_update, digest_sign_final) or - * (digest_verify_init, digest_verify_update, digest_verify_final). - * - * set_ctx_params and settable_ctx_params are optional, but if one of - * them is present then the other one must also be present. The same - * applies to get_ctx_params and gettable_ctx_params. The same rules - * apply to the "md_params" functions. The dupctx function is optional. - */ - ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); - goto err; - } - - return signature; - err: - EVP_SIGNATURE_free(signature); - return NULL; -} - -void EVP_SIGNATURE_free(EVP_SIGNATURE *signature) -{ - if (signature != NULL) { - int i; - - CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock); - if (i > 0) - return; - ossl_provider_free(signature->prov); - CRYPTO_THREAD_lock_free(signature->lock); - OPENSSL_free(signature); - } -} - -int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature) -{ - int ref = 0; - - CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock); - return 1; -} - -OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature) -{ - return signature->prov; -} - -EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm, - const char *properties) -{ - return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties, - evp_signature_from_dispatch, - (int (*)(void *))EVP_SIGNATURE_up_ref, - (void (*)(void *))EVP_SIGNATURE_free); -} - -int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name) -{ - return evp_is_a(signature->prov, signature->name_id, name); -} - -int EVP_SIGNATURE_number(const EVP_SIGNATURE *signature) -{ - return signature->name_id; -} - -void EVP_SIGNATURE_do_all_provided(OPENSSL_CTX *libctx, - void (*fn)(EVP_SIGNATURE *signature, - void *arg), - void *arg) -{ - evp_generic_do_all(libctx, OSSL_OP_SIGNATURE, - (void (*)(void *, void *))fn, arg, - evp_signature_from_dispatch, - (void (*)(void *))EVP_SIGNATURE_free); -} - - -void EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature, - void (*fn)(const char *name, void *data), - void *data) -{ - if (signature->prov != NULL) - evp_names_do_all(signature->prov, signature->name_id, fn, data); -} - -static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation) -{ - int ret = 0; - void *provkey = NULL; - EVP_SIGNATURE *signature = NULL; - - if (ctx == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - evp_pkey_ctx_free_old_ops(ctx); - ctx->operation = operation; - - if (ctx->keytype == NULL) - goto legacy; - - if (ctx->keymgmt == NULL) - ctx->keymgmt = - EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery); - if (ctx->keymgmt != NULL) { - const char *supported_sig = NULL; - - if (ctx->keymgmt->query_operation_name != NULL) - supported_sig = - ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE); - - /* - * If we didn't get a supported sig, assume there is one with the - * same name as the key type. - */ - if (supported_sig == NULL) - supported_sig = ctx->keytype; - - /* - * Because we cleared out old ops, we shouldn't need to worry about - * checking if signature is already there. - */ - signature = - EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery); - } - - if (ctx->keymgmt == NULL - || signature == NULL - || (EVP_KEYMGMT_provider(ctx->keymgmt) - != EVP_SIGNATURE_provider(signature))) { - /* - * We don't have the full support we need with provided methods, - * let's go see if legacy does. Also, we don't need to free - * ctx->keymgmt here, as it's not necessarily tied to this - * operation. It will be freed by EVP_PKEY_CTX_free(). - */ - EVP_SIGNATURE_free(signature); - goto legacy; - } - - ctx->op.sig.signature = signature; - - if (ctx->pkey != NULL) { - provkey = - evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0); - /* If export failed, legacy may be able to pick it up */ - if (provkey == NULL) - goto legacy; - } - ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov)); - if (ctx->op.sig.sigprovctx == NULL) { - /* The provider key can stay in the cache */ - EVPerr(0, EVP_R_INITIALIZATION_ERROR); - goto err; - } - - switch (operation) { - case EVP_PKEY_OP_SIGN: - if (signature->sign_init == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - ret = -2; - goto err; - } - ret = signature->sign_init(ctx->op.sig.sigprovctx, provkey); - break; - case EVP_PKEY_OP_VERIFY: - if (signature->verify_init == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - ret = -2; - goto err; - } - ret = signature->verify_init(ctx->op.sig.sigprovctx, provkey); - break; - case EVP_PKEY_OP_VERIFYRECOVER: - if (signature->verify_recover_init == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - ret = -2; - goto err; - } - ret = signature->verify_recover_init(ctx->op.sig.sigprovctx, provkey); - break; - default: - EVPerr(0, EVP_R_INITIALIZATION_ERROR); - goto err; - } - - if (ret <= 0) { - signature->freectx(ctx->op.sig.sigprovctx); - ctx->op.sig.sigprovctx = NULL; - goto err; - } - return 1; - - legacy: - if (ctx->pmeth == NULL - || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL) - || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL) - || (operation == EVP_PKEY_OP_VERIFYRECOVER - && ctx->pmeth->verify_recover == NULL)) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - switch (operation) { - case EVP_PKEY_OP_SIGN: - if (ctx->pmeth->sign_init == NULL) - return 1; - ret = ctx->pmeth->sign_init(ctx); - break; - case EVP_PKEY_OP_VERIFY: - if (ctx->pmeth->verify_init == NULL) - return 1; - ret = ctx->pmeth->verify_init(ctx); - break; - case EVP_PKEY_OP_VERIFYRECOVER: - if (ctx->pmeth->verify_recover_init == NULL) - return 1; - ret = ctx->pmeth->verify_recover_init(ctx); - break; - default: - EVPerr(0, EVP_R_INITIALIZATION_ERROR); - goto err; - } - if (ret <= 0) - goto err; - return ret; - - err: - ctx->operation = EVP_PKEY_OP_UNDEFINED; - return ret; -} - -int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) -{ - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN); -} - -int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, - unsigned char *sig, size_t *siglen, - const unsigned char *tbs, size_t tbslen) -{ - int ret; - - if (ctx == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - if (ctx->operation != EVP_PKEY_OP_SIGN) { - EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } - - if (ctx->op.sig.sigprovctx == NULL) - goto legacy; - - ret = ctx->op.sig.signature->sign(ctx->op.sig.sigprovctx, sig, siglen, - SIZE_MAX, tbs, tbslen); - - return ret; - legacy: - - if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) - return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); -} - -int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) -{ - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY); -} - -int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, - const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) -{ - int ret; - - if (ctx == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - if (ctx->operation != EVP_PKEY_OP_VERIFY) { - EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } - - if (ctx->op.sig.sigprovctx == NULL) - goto legacy; - - ret = ctx->op.sig.signature->verify(ctx->op.sig.sigprovctx, sig, siglen, - tbs, tbslen); - - return ret; - legacy: - if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); -} - -int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) -{ - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER); -} - -int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, - unsigned char *rout, size_t *routlen, - const unsigned char *sig, size_t siglen) -{ - int ret; - - if (ctx == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { - EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } - - if (ctx->op.sig.sigprovctx == NULL) - goto legacy; - - ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.sigprovctx, rout, - routlen, - (rout == NULL ? 0 : *routlen), - sig, siglen); - return ret; - legacy: - if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) { - EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) - return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); -} - static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation) { int ret = 0; diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 100931cda7..14c5fd4b99 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -17,89 +17,7 @@ #include "crypto/evp.h" #include "evp_local.h" -static int fromdata_init(EVP_PKEY_CTX *ctx, int operation) -{ - if (ctx == NULL || ctx->keytype == NULL) - goto not_supported; - - evp_pkey_ctx_free_old_ops(ctx); - ctx->operation = operation; - if (ctx->keymgmt == NULL) - ctx->keymgmt = EVP_KEYMGMT_fetch(NULL, ctx->keytype, ctx->propquery); - if (ctx->keymgmt == NULL) - goto not_supported; - - return 1; - - not_supported: - ctx->operation = EVP_PKEY_OP_UNDEFINED; - ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; -} - -int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx) -{ - return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA); -} - -int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx) -{ - return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA); -} - -int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[]) -{ - void *provdata = NULL; - - if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) { - ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } - - if (ppkey == NULL) - return -1; - - if (*ppkey == NULL) - *ppkey = EVP_PKEY_new(); - - if (*ppkey == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - return -1; - } - - provdata = - evp_keymgmt_fromdata(*ppkey, ctx->keymgmt, params, - ctx->operation == EVP_PKEY_OP_PARAMFROMDATA); - - if (provdata == NULL) - return 0; - /* provdata is cached in *ppkey, so we need not bother with it further */ - return 1; -} - -/* - * TODO(3.0) Re-evaluate the names, it's possible that we find these to be - * better: - * - * EVP_PKEY_param_settable() - * EVP_PKEY_param_gettable() - */ -const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx) -{ - /* We call fromdata_init to get ctx->keymgmt populated */ - if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED)) - return evp_keymgmt_importdomparam_types(ctx->keymgmt); - return NULL; -} - -const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx) -{ - /* We call fromdata_init to get ctx->keymgmt populated */ - if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED)) - return evp_keymgmt_importdomparam_types(ctx->keymgmt); - return NULL; -} - +#ifndef FIPS_MODE int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) { int ret; @@ -321,3 +239,93 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) return pkey->ameth->pkey_param_check(pkey); } + +#endif /* FIPS_MODE */ + +/*- All methods below can also be used in FIPS_MODE */ + +static int fromdata_init(EVP_PKEY_CTX *ctx, int operation) +{ + if (ctx == NULL || ctx->keytype == NULL) + goto not_supported; + + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = operation; + if (ctx->keymgmt == NULL) + ctx->keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, + ctx->propquery); + if (ctx->keymgmt == NULL) + goto not_supported; + + return 1; + + not_supported: + ctx->operation = EVP_PKEY_OP_UNDEFINED; + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; +} + +int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx) +{ + return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA); +} + +int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx) +{ + return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA); +} + +int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[]) +{ + void *provdata = NULL; + + if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (ppkey == NULL) + return -1; + + if (*ppkey == NULL) + *ppkey = EVP_PKEY_new(); + + if (*ppkey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return -1; + } + + provdata = + evp_keymgmt_fromdata(*ppkey, ctx->keymgmt, params, + ctx->operation == EVP_PKEY_OP_PARAMFROMDATA); + + if (provdata == NULL) + return 0; + /* provdata is cached in *ppkey, so we need not bother with it further */ + return 1; +} + +/* + * TODO(3.0) Re-evaluate the names, it's possible that we find these to be + * better: + * + * EVP_PKEY_param_settable() + * EVP_PKEY_param_gettable() + */ +const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx) +{ + /* We call fromdata_init to get ctx->keymgmt populated */ + if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED)) + return evp_keymgmt_importdomparam_types(ctx->keymgmt); + return NULL; +} + +const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx) +{ + /* We call fromdata_init to get ctx->keymgmt populated */ + if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED)) + return evp_keymgmt_importdomparam_types(ctx->keymgmt); + return NULL; +} + + diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 2ecc17734e..428b97b7b5 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -23,6 +23,8 @@ #include "internal/provider.h" #include "evp_local.h" +#ifndef FIPS_MODE + typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void); typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); @@ -30,50 +32,50 @@ static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; /* This array needs to be in order of NIDs */ static pmeth_fn standard_methods[] = { -#ifndef OPENSSL_NO_RSA +# ifndef OPENSSL_NO_RSA rsa_pkey_method, -#endif -#ifndef OPENSSL_NO_DH +# endif +# ifndef OPENSSL_NO_DH dh_pkey_method, -#endif -#ifndef OPENSSL_NO_DSA +# endif +# ifndef OPENSSL_NO_DSA dsa_pkey_method, -#endif -#ifndef OPENSSL_NO_EC +# endif +# ifndef OPENSSL_NO_EC ec_pkey_method, -#endif +# endif hmac_pkey_method, -#ifndef OPENSSL_NO_CMAC +# ifndef OPENSSL_NO_CMAC cmac_pkey_method, -#endif -#ifndef OPENSSL_NO_RSA +# endif +# ifndef OPENSSL_NO_RSA rsa_pss_pkey_method, -#endif -#ifndef OPENSSL_NO_DH +# endif +# ifndef OPENSSL_NO_DH dhx_pkey_method, -#endif -#ifndef OPENSSL_NO_SCRYPT +# endif +# ifndef OPENSSL_NO_SCRYPT scrypt_pkey_method, -#endif +# endif tls1_prf_pkey_method, -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC ecx25519_pkey_method, ecx448_pkey_method, -#endif +# endif hkdf_pkey_method, -#ifndef OPENSSL_NO_POLY1305 +# ifndef OPENSSL_NO_POLY1305 poly1305_pkey_method, -#endif -#ifndef OPENSSL_NO_SIPHASH +# endif +# ifndef OPENSSL_NO_SIPHASH siphash_pkey_method, -#endif -#ifndef OPENSSL_NO_EC +# endif +# ifndef OPENSSL_NO_EC ed25519_pkey_method, ed448_pkey_method, -#endif -#ifndef OPENSSL_NO_SM2 +# endif +# ifndef OPENSSL_NO_SM2 sm2_pkey_method, -#endif +# endif }; DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func); @@ -112,10 +114,27 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) return (**ret)(); } +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) +{ + EVP_PKEY_METHOD *pmeth; + + pmeth = OPENSSL_zalloc(sizeof(*pmeth)); + if (pmeth == NULL) { + EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + + pmeth->pkey_id = id; + pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; + return pmeth; +} +#endif /* FIPS_MODE */ + static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, EVP_PKEY *pkey, ENGINE *e, const char *name, const char *propquery, int id) + { EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth = NULL; @@ -131,7 +150,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * If the key doesn't contain anything legacy, then it must be provided, * so we extract the necessary information and use that. */ - if (pkey != NULL && pkey->ameth == NULL) { + if (pkey != NULL && pkey->pkey.ptr == NULL) { /* If we have an engine, something went wrong somewhere... */ if (!ossl_assert(e == NULL)) return NULL; @@ -143,7 +162,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, */ goto common; } - +#ifndef FIPS_MODE /* TODO(3.0) Legacy code should be removed when all is provider based */ /* BEGIN legacy */ if (id == -1) { @@ -179,7 +198,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, */ libctx = NULL; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE if (e == NULL && pkey != NULL) e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine; /* Try to find an ENGINE which implements this method */ @@ -199,22 +218,22 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, if (e) pmeth = ENGINE_get_pkey_meth(e, id); else -#endif +# endif pmeth = EVP_PKEY_meth_find(id); if (pmeth == NULL) { -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE ENGINE_finish(e); -#endif +# endif EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM); return NULL; } /* END legacy */ - +#endif /* FIPS_MODE */ common: ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) ENGINE_finish(e); #endif EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); @@ -241,20 +260,37 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, return ret; } +/*- All methods below can also be used in FIPS_MODE */ + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx, + const char *name, + const char *propquery) +{ + return int_ctx_new(libctx, NULL, NULL, name, propquery, -1); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx, EVP_PKEY *pkey) +{ + return int_ctx_new(libctx, pkey, NULL, NULL, NULL, -1); +} + void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) { - if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { - if (ctx->op.kex.exchprovctx != NULL && ctx->op.kex.exchange != NULL) - ctx->op.kex.exchange->freectx(ctx->op.kex.exchprovctx); - EVP_KEYEXCH_free(ctx->op.kex.exchange); - ctx->op.kex.exchprovctx = NULL; - ctx->op.kex.exchange = NULL; - } else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { + if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { if (ctx->op.sig.sigprovctx != NULL && ctx->op.sig.signature != NULL) ctx->op.sig.signature->freectx(ctx->op.sig.sigprovctx); EVP_SIGNATURE_free(ctx->op.sig.signature); ctx->op.sig.sigprovctx = NULL; ctx->op.sig.signature = NULL; + } +/* TODO(3.0): add dependancies and uncomment this when available for fips mode */ +#ifndef FIPS_MODE + else if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + if (ctx->op.kex.exchprovctx != NULL && ctx->op.kex.exchange != NULL) + ctx->op.kex.exchange->freectx(ctx->op.kex.exchprovctx); + EVP_KEYEXCH_free(ctx->op.kex.exchange); + ctx->op.kex.exchprovctx = NULL; + ctx->op.kex.exchange = NULL; } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) { if (ctx->op.ciph.ciphprovctx != NULL && ctx->op.ciph.cipher != NULL) ctx->op.ciph.cipher->freectx(ctx->op.ciph.ciphprovctx); @@ -262,23 +298,29 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) ctx->op.ciph.ciphprovctx = NULL; ctx->op.ciph.cipher = NULL; } +#endif } -EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) { - EVP_PKEY_METHOD *pmeth; + if (ctx == NULL) + return; + if (ctx->pmeth && ctx->pmeth->cleanup) + ctx->pmeth->cleanup(ctx); - pmeth = OPENSSL_zalloc(sizeof(*pmeth)); - if (pmeth == NULL) { - EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE); - return NULL; - } + evp_pkey_ctx_free_old_ops(ctx); + EVP_KEYMGMT_free(ctx->keymgmt); - pmeth->pkey_id = id; - pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; - return pmeth; + EVP_PKEY_free(ctx->pkey); + EVP_PKEY_free(ctx->peerkey); +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) + ENGINE_finish(ctx->engine); +#endif + OPENSSL_free(ctx); } +#ifndef FIPS_MODE + void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, const EVP_PKEY_METHOD *meth) { @@ -347,12 +389,6 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) return int_ctx_new(NULL, NULL, e, NULL, NULL, id); } -EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx, - const char *name, - const char *propquery) -{ - return int_ctx_new(libctx, NULL, NULL, name, propquery, -1); -} EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) { @@ -364,13 +400,13 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) || (EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx) && pctx->op.sig.sigprovctx == NULL))) return NULL; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE /* Make sure it's safe to copy a pkey context using an ENGINE */ if (pctx->engine && !ENGINE_init(pctx->engine)) { EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB); return 0; } -#endif +# endif rctx = OPENSSL_zalloc(sizeof(*rctx)); if (rctx == NULL) { EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_MALLOC_FAILURE); @@ -448,9 +484,9 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) } rctx->pmeth = pctx->pmeth; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE rctx->engine = pctx->engine; -#endif +# endif if (pctx->peerkey) EVP_PKEY_up_ref(pctx->peerkey); @@ -517,25 +553,32 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx) return NULL; return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); } +#endif -void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) +int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) { - if (ctx == NULL) - return; - if (ctx->pmeth && ctx->pmeth->cleanup) - ctx->pmeth->cleanup(ctx); - - evp_pkey_ctx_free_old_ops(ctx); - EVP_KEYMGMT_free(ctx->keymgmt); - - EVP_PKEY_free(ctx->pkey); - EVP_PKEY_free(ctx->peerkey); -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(ctx->engine); -#endif - OPENSSL_free(ctx); + if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) + && ctx->op.kex.exchprovctx != NULL + && ctx->op.kex.exchange != NULL + && ctx->op.kex.exchange->set_ctx_params != NULL) + return ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.exchprovctx, + params); + if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && ctx->op.sig.sigprovctx != NULL + && ctx->op.sig.signature != NULL + && ctx->op.sig.signature->set_ctx_params != NULL) + return ctx->op.sig.signature->set_ctx_params(ctx->op.sig.sigprovctx, + params); + if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + && ctx->op.ciph.ciphprovctx != NULL + && ctx->op.ciph.cipher != NULL + && ctx->op.ciph.cipher->set_ctx_params != NULL) + return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx, + params); + return 0; } +#ifndef FIPS_MODE int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) { if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) @@ -568,29 +611,6 @@ const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx) return NULL; } -int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) -{ - if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) - && ctx->op.kex.exchprovctx != NULL - && ctx->op.kex.exchange != NULL - && ctx->op.kex.exchange->set_ctx_params != NULL) - return ctx->op.kex.exchange->set_ctx_params(ctx->op.kex.exchprovctx, - params); - if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) - && ctx->op.sig.sigprovctx != NULL - && ctx->op.sig.signature != NULL - && ctx->op.sig.signature->set_ctx_params != NULL) - return ctx->op.sig.signature->set_ctx_params(ctx->op.sig.sigprovctx, - params); - if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx != NULL - && ctx->op.ciph.cipher != NULL - && ctx->op.ciph.cipher->set_ctx_params != NULL) - return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx, - params); - return 0; -} - const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) { if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) @@ -609,7 +629,7 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) return NULL; } -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) { OSSL_PARAM dh_pad_params[2]; @@ -631,7 +651,7 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) return EVP_PKEY_CTX_set_params(ctx, dh_pad_params); } -#endif +# endif int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md) { @@ -711,10 +731,10 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2) { switch (cmd) { -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH case EVP_PKEY_CTRL_DH_PAD: return EVP_PKEY_CTX_set_dh_pad(ctx, p1); -#endif +# endif case EVP_PKEY_CTRL_MD: return EVP_PKEY_CTX_set_signature_md(ctx, p2); case EVP_PKEY_CTRL_GET_MD: @@ -737,10 +757,10 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: -#ifndef OPENSSL_NO_CMS +# ifndef OPENSSL_NO_CMS case EVP_PKEY_CTRL_CMS_DECRYPT: case EVP_PKEY_CTRL_CMS_ENCRYPT: -#endif +# endif if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS) return 1; ERR_raise(ERR_LIB_EVP, @@ -806,14 +826,14 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, const char *value) { -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH if (strcmp(name, "dh_pad") == 0) { int pad; pad = atoi(value); return EVP_PKEY_CTX_set_dh_pad(ctx, pad); } -#endif +# endif if (strcmp(name, "digest") == 0) { int ret; EVP_MD *md; @@ -1380,3 +1400,5 @@ void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, if (pdigest_custom != NULL) *pdigest_custom = pmeth->digest_custom; } + +#endif /* FIPS_MODE */ diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c new file mode 100644 index 0000000000..119cd322a3 --- /dev/null +++ b/crypto/evp/signature.c @@ -0,0 +1,580 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "crypto/evp.h" +#include "internal/provider.h" +#include "evp_local.h" + +static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov) +{ + EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE)); + + if (signature == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + signature->lock = CRYPTO_THREAD_lock_new(); + if (signature->lock == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(signature); + return NULL; + } + signature->prov = prov; + ossl_provider_up_ref(prov); + signature->refcnt = 1; + + return signature; +} + +static void *evp_signature_from_dispatch(int name_id, + const OSSL_DISPATCH *fns, + OSSL_PROVIDER *prov) +{ + EVP_SIGNATURE *signature = NULL; + int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0; + int digsignfncnt = 0, digverifyfncnt = 0; + int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0; + + if ((signature = evp_signature_new(prov)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + goto err; + } + + signature->name_id = name_id; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_SIGNATURE_NEWCTX: + if (signature->newctx != NULL) + break; + signature->newctx = OSSL_get_OP_signature_newctx(fns); + ctxfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SIGN_INIT: + if (signature->sign_init != NULL) + break; + signature->sign_init = OSSL_get_OP_signature_sign_init(fns); + signfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SIGN: + if (signature->sign != NULL) + break; + signature->sign = OSSL_get_OP_signature_sign(fns); + signfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY_INIT: + if (signature->verify_init != NULL) + break; + signature->verify_init = OSSL_get_OP_signature_verify_init(fns); + verifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY: + if (signature->verify != NULL) + break; + signature->verify = OSSL_get_OP_signature_verify(fns); + verifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT: + if (signature->verify_recover_init != NULL) + break; + signature->verify_recover_init + = OSSL_get_OP_signature_verify_recover_init(fns); + verifyrecfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER: + if (signature->verify_recover != NULL) + break; + signature->verify_recover + = OSSL_get_OP_signature_verify_recover(fns); + verifyrecfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT: + if (signature->digest_sign_init != NULL) + break; + signature->digest_sign_init + = OSSL_get_OP_signature_digest_sign_init(fns); + digsignfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: + if (signature->digest_sign_update != NULL) + break; + signature->digest_sign_update + = OSSL_get_OP_signature_digest_sign_update(fns); + digsignfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL: + if (signature->digest_sign_final != NULL) + break; + signature->digest_sign_final + = OSSL_get_OP_signature_digest_sign_final(fns); + digsignfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT: + if (signature->digest_verify_init != NULL) + break; + signature->digest_verify_init + = OSSL_get_OP_signature_digest_verify_init(fns); + digverifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: + if (signature->digest_verify_update != NULL) + break; + signature->digest_verify_update + = OSSL_get_OP_signature_digest_verify_update(fns); + digverifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL: + if (signature->digest_verify_final != NULL) + break; + signature->digest_verify_final + = OSSL_get_OP_signature_digest_verify_final(fns); + digverifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_FREECTX: + if (signature->freectx != NULL) + break; + signature->freectx = OSSL_get_OP_signature_freectx(fns); + ctxfncnt++; + break; + case OSSL_FUNC_SIGNATURE_DUPCTX: + if (signature->dupctx != NULL) + break; + signature->dupctx = OSSL_get_OP_signature_dupctx(fns); + break; + case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS: + if (signature->get_ctx_params != NULL) + break; + signature->get_ctx_params + = OSSL_get_OP_signature_get_ctx_params(fns); + gparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS: + if (signature->gettable_ctx_params != NULL) + break; + signature->gettable_ctx_params + = OSSL_get_OP_signature_gettable_ctx_params(fns); + gparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS: + if (signature->set_ctx_params != NULL) + break; + signature->set_ctx_params + = OSSL_get_OP_signature_set_ctx_params(fns); + sparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS: + if (signature->settable_ctx_params != NULL) + break; + signature->settable_ctx_params + = OSSL_get_OP_signature_settable_ctx_params(fns); + sparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS: + if (signature->get_ctx_md_params != NULL) + break; + signature->get_ctx_md_params + = OSSL_get_OP_signature_get_ctx_md_params(fns); + gmdparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS: + if (signature->gettable_ctx_md_params != NULL) + break; + signature->gettable_ctx_md_params + = OSSL_get_OP_signature_gettable_ctx_md_params(fns); + gmdparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS: + if (signature->set_ctx_md_params != NULL) + break; + signature->set_ctx_md_params + = OSSL_get_OP_signature_set_ctx_md_params(fns); + smdparamfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS: + if (signature->settable_ctx_md_params != NULL) + break; + signature->settable_ctx_md_params + = OSSL_get_OP_signature_settable_ctx_md_params(fns); + smdparamfncnt++; + break; + } + } + if (ctxfncnt != 2 + || (signfncnt == 0 + && verifyfncnt == 0 + && verifyrecfncnt == 0 + && digsignfncnt == 0 + && digverifyfncnt == 0) + || (signfncnt != 0 && signfncnt != 2) + || (verifyfncnt != 0 && verifyfncnt != 2) + || (verifyrecfncnt != 0 && verifyrecfncnt != 2) + || (digsignfncnt != 0 && digsignfncnt != 3) + || (digverifyfncnt != 0 && digverifyfncnt != 3) + || (gparamfncnt != 0 && gparamfncnt != 2) + || (sparamfncnt != 0 && sparamfncnt != 2) + || (gmdparamfncnt != 0 && gmdparamfncnt != 2) + || (smdparamfncnt != 0 && smdparamfncnt != 2)) { + /* + * In order to be a consistent set of functions we must have at least + * a set of context functions (newctx and freectx) as well as a set of + * "signature" functions: + * (sign_init, sign) or + * (verify_init verify) or + * (verify_recover_init, verify_recover) or + * (digest_sign_init, digest_sign_update, digest_sign_final) or + * (digest_verify_init, digest_verify_update, digest_verify_final). + * + * set_ctx_params and settable_ctx_params are optional, but if one of + * them is present then the other one must also be present. The same + * applies to get_ctx_params and gettable_ctx_params. The same rules + * apply to the "md_params" functions. The dupctx function is optional. + */ + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); + goto err; + } + + return signature; + err: + EVP_SIGNATURE_free(signature); + return NULL; +} + +void EVP_SIGNATURE_free(EVP_SIGNATURE *signature) +{ + if (signature != NULL) { + int i; + + CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock); + if (i > 0) + return; + ossl_provider_free(signature->prov); + CRYPTO_THREAD_lock_free(signature->lock); + OPENSSL_free(signature); + } +} + +int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature) +{ + int ref = 0; + + CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock); + return 1; +} + +OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature) +{ + return signature->prov; +} + +EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm, + const char *properties) +{ + return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties, + evp_signature_from_dispatch, + (int (*)(void *))EVP_SIGNATURE_up_ref, + (void (*)(void *))EVP_SIGNATURE_free); +} + +int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name) +{ + return evp_is_a(signature->prov, signature->name_id, name); +} + +int EVP_SIGNATURE_number(const EVP_SIGNATURE *signature) +{ + return signature->name_id; +} + +void EVP_SIGNATURE_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(EVP_SIGNATURE *signature, + void *arg), + void *arg) +{ + evp_generic_do_all(libctx, OSSL_OP_SIGNATURE, + (void (*)(void *, void *))fn, arg, + evp_signature_from_dispatch, + (void (*)(void *))EVP_SIGNATURE_free); +} + + +void EVP_SIGNATURE_names_do_all(const EVP_SIGNATURE *signature, + void (*fn)(const char *name, void *data), + void *data) +{ + if (signature->prov != NULL) + evp_names_do_all(signature->prov, signature->name_id, fn, data); +} + +static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation) +{ + int ret = 0; + void *provkey = NULL; + EVP_SIGNATURE *signature = NULL; + + if (ctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = operation; + + if (ctx->keytype == NULL) + goto legacy; + + if (ctx->keymgmt == NULL) + ctx->keymgmt = + EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery); + if (ctx->keymgmt != NULL) { + const char *supported_sig = NULL; + + if (ctx->keymgmt->query_operation_name != NULL) + supported_sig = + ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE); + + /* + * If we didn't get a supported sig, assume there is one with the + * same name as the key type. + */ + if (supported_sig == NULL) + supported_sig = ctx->keytype; + + /* + * Because we cleared out old ops, we shouldn't need to worry about + * checking if signature is already there. + */ + signature = + EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery); + } + + if (ctx->keymgmt == NULL + || signature == NULL + || (EVP_KEYMGMT_provider(ctx->keymgmt) + != EVP_SIGNATURE_provider(signature))) { + /* + * We don't have the full support we need with provided methods, + * let's go see if legacy does. Also, we don't need to free + * ctx->keymgmt here, as it's not necessarily tied to this + * operation. It will be freed by EVP_PKEY_CTX_free(). + */ + EVP_SIGNATURE_free(signature); + goto legacy; + } + + ctx->op.sig.signature = signature; + + if (ctx->pkey != NULL) { + provkey = + evp_keymgmt_export_to_provider(ctx->pkey, ctx->keymgmt, 0); + /* If export failed, legacy may be able to pick it up */ + if (provkey == NULL) + goto legacy; + } + ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov)); + if (ctx->op.sig.sigprovctx == NULL) { + /* The provider key can stay in the cache */ + EVPerr(0, EVP_R_INITIALIZATION_ERROR); + goto err; + } + + switch (operation) { + case EVP_PKEY_OP_SIGN: + if (signature->sign_init == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = signature->sign_init(ctx->op.sig.sigprovctx, provkey); + break; + case EVP_PKEY_OP_VERIFY: + if (signature->verify_init == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = signature->verify_init(ctx->op.sig.sigprovctx, provkey); + break; + case EVP_PKEY_OP_VERIFYRECOVER: + if (signature->verify_recover_init == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = signature->verify_recover_init(ctx->op.sig.sigprovctx, provkey); + break; + default: + EVPerr(0, EVP_R_INITIALIZATION_ERROR); + goto err; + } + + if (ret <= 0) { + signature->freectx(ctx->op.sig.sigprovctx); + ctx->op.sig.sigprovctx = NULL; + goto err; + } + return 1; + + legacy: + if (ctx->pmeth == NULL + || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL) + || (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL) + || (operation == EVP_PKEY_OP_VERIFYRECOVER + && ctx->pmeth->verify_recover == NULL)) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + switch (operation) { + case EVP_PKEY_OP_SIGN: + if (ctx->pmeth->sign_init == NULL) + return 1; + ret = ctx->pmeth->sign_init(ctx); + break; + case EVP_PKEY_OP_VERIFY: + if (ctx->pmeth->verify_init == NULL) + return 1; + ret = ctx->pmeth->verify_init(ctx); + break; + case EVP_PKEY_OP_VERIFYRECOVER: + if (ctx->pmeth->verify_recover_init == NULL) + return 1; + ret = ctx->pmeth->verify_recover_init(ctx); + break; + default: + EVPerr(0, EVP_R_INITIALIZATION_ERROR); + goto err; + } + if (ret <= 0) + goto err; + return ret; + + err: + ctx->operation = EVP_PKEY_OP_UNDEFINED; + return ret; +} + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) +{ + return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN); +} + +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret; + + if (ctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (ctx->operation != EVP_PKEY_OP_SIGN) { + EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.sigprovctx == NULL) + goto legacy; + + ret = ctx->op.sig.signature->sign(ctx->op.sig.sigprovctx, sig, siglen, + SIZE_MAX, tbs, tbslen); + + return ret; + legacy: + + if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) + return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) +{ + return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY); +} + +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret; + + if (ctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (ctx->operation != EVP_PKEY_OP_VERIFY) { + EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.sigprovctx == NULL) + goto legacy; + + ret = ctx->op.sig.signature->verify(ctx->op.sig.sigprovctx, sig, siglen, + tbs, tbslen); + + return ret; + legacy: + if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) +{ + return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER); +} + +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen) +{ + int ret; + + if (ctx == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { + EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.sigprovctx == NULL) + goto legacy; + + ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.sigprovctx, rout, + routlen, + (rout == NULL ? 0 : *routlen), + sig, siglen); + return ret; + legacy: + if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) + return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); +} diff --git a/doc/man3/EVP_PKEY_CTX_new.pod b/doc/man3/EVP_PKEY_CTX_new.pod index 90486ae0dc..b08f7e4d78 100644 --- a/doc/man3/EVP_PKEY_CTX_new.pod +++ b/doc/man3/EVP_PKEY_CTX_new.pod @@ -2,8 +2,8 @@ =head1 NAME -EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_provided, -EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free +EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_from_name, +EVP_PKEY_CTX_new_from_pkey, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free - public key algorithm context functions =head1 SYNOPSIS @@ -12,9 +12,11 @@ EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); - EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx, - const char *name, - const char *propquery); + EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx, + const char *name, + const char *propquery); + EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx, + EVP_PKEY *pkey); EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); @@ -26,13 +28,19 @@ the I key type and ENGINE I. The EVP_PKEY_CTX_new_id() function allocates public key algorithm context using the key type specified by I and ENGINE I. -The EVP_PKEY_CTX_new_provided() function allocates a public key algorithm +The EVP_PKEY_CTX_new_from_name() function allocates a public key algorithm context using the library context I (see L), the key type specified by I and the property query I. None of the arguments are duplicated, so they must remain unchanged for the lifetime of the returned B or of any of its duplicates. -EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_provided() are normally +The EVP_PKEY_CTX_new_from_pkey() function allocates a public key algorithm +context using the library context I (see L) and the +algorithm specified by I . None of the arguments are duplicated, so they +must remain unchanged for the lifetime of the returned B or of +any of its duplicates. + +EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_from_name() are normally used when no B structure is associated with the operations, for example during parameter generation or key generation for some algorithms. @@ -76,7 +84,11 @@ L =head1 HISTORY -These functions were added in OpenSSL 1.0.0. +The EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id(), EVP_PKEY_CTX_dup() and +EVP_PKEY_CTX_free() functions were added in OpenSSL 1.0.0. + +The EVP_PKEY_CTX_new_from_name() and EVP_PKEY_CTX_new_from_pkey() functions were +added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/include/crypto/dsa.h b/include/crypto/dsa.h new file mode 100644 index 0000000000..efd4acf6fc --- /dev/null +++ b/include/crypto/dsa.h @@ -0,0 +1,14 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +DSA *dsa_new(OPENSSL_CTX *libctx); +int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst, + int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa); diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 973ef203ba..91f535093d 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -638,3 +638,4 @@ void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags); const EVP_CIPHER *evp_get_cipherbyname_ex(OPENSSL_CTX *libctx, const char *name); const EVP_MD *evp_get_digestbyname_ex(OPENSSL_CTX *libctx, const char *name); + diff --git a/include/openssl/evp.h b/include/openssl/evp.h index e661053225..57a73382e8 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1466,9 +1466,11 @@ void EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt, EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); -EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(OPENSSL_CTX *libctx, - const char *name, - const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx, + const char *name, + const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx, + EVP_PKEY *pkey); EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 7afab78063..788963911b 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -121,6 +121,49 @@ static OSSL_PARAM core_params[] = OSSL_PARAM_END }; +/* + * This routine is currently necessary as bn params are currently processed + * using BN_native2bn when raw data is received. This means we need to do + * magic to reverse the order of the bytes to match native format. + * The array of hexdata is to get around compilers that dont like + * strings longer than 509 bytes, + */ +static int rawnative_fromhex(const char *hex_data[], + unsigned char **native, size_t *nativelen) +{ + int ret = 0; + unsigned char *data = NULL; + BIGNUM *bn = NULL; + int i, slen, datalen, sz; + char *str = NULL; + + for (slen = 0, i = 0; hex_data[i] != NULL; ++i) + slen += strlen(hex_data[i]); + str = OPENSSL_zalloc(slen + 1); + if (str == NULL) + return 0; + for (i = 0; hex_data[i] != NULL; ++i) + strcat(str, hex_data[i]); + + if (BN_hex2bn(&bn, str) <= 0) + return 0; + + datalen = slen / 2; + data = (unsigned char *)str; /* reuse the str buffer */ + + sz = BN_bn2nativepad(bn, data, datalen); + if (sz <= 0) + goto err; + ret = 1; + *native = data; + *nativelen = datalen; + data = NULL; /* so it does not get freed */ +err: + BN_free(bn); + OPENSSL_free(data); + return ret; +} + /* TODO(3.0): To be removed */ static int dummy_evp_call(void *provctx) { @@ -128,6 +171,58 @@ static int dummy_evp_call(void *provctx) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL); EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF2, NULL); + EVP_PKEY_CTX *sctx = NULL, *kctx = NULL; + EVP_PKEY *pkey = NULL; + OSSL_PARAM *p; + OSSL_PARAM params[16]; + unsigned char sig[64]; + size_t siglen, sigdgstlen; + unsigned char *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; + unsigned char *dsa_pub = NULL, *dsa_priv = NULL; + size_t dsa_p_len, dsa_q_len, dsa_g_len, dsa_pub_len, dsa_priv_len; + + /* dsa 2048 */ + static const char *dsa_p_hex[] = { + "a29b8872ce8b8423b7d5d21d4b02f57e03e9e6b8a258dc16611ba098ab543415" + "e415f156997a3ee236658fa093260de3ad422e05e046f9ec29161a375f0eb4ef" + "fcef58285c5d39ed425d7a62ca12896c4a92cb1946f2952a48133f07da364d1b" + "df6b0f7139983e693c80059b0eacd1479ba9f2857754ede75f112b07ebbf3534", + "8bbf3e01e02f2d473de39453f99dd2367541caca3ba01166343d7b5b58a37bd1" + "b7521db2f13b86707132fe09f4cd09dc1618fa3401ebf9cc7b19fa94aa472088" + "133d6cb2d35c1179c8c8ff368758d507d9f9a17d46c110fe3144ce9b022b42e4" + "19eb4f5388613bfc3e26241a432e8706bc58ef76117278deab6cf692618291b7", + NULL + }; + static const char *dsa_q_hex[] = { + "a3bfd9ab7884794e383450d5891dc18b65157bdcfcdac51518902867", + NULL + }; + static const char *dsa_g_hex[] = { + "6819278869c7fd3d2d7b77f77e8150d9ad433bea3ba85efc80415aa3545f78f7" + "2296f06cb19ceda06c94b0551cfe6e6f863e31d1de6eed7dab8b0c9df231e084" + "34d1184f91d033696bb382f8455e9888f5d31d4784ec40120246f4bea61794bb" + "a5866f09746463bdf8e9e108cd9529c3d0f6df80316e2e70aaeb1b26cdb8ad97", + "bc3d287e0b8d616c42e65b87db20deb7005bc416747a6470147a68a7820388eb" + "f44d52e0628af9cf1b7166d03465f35acc31b6110c43dabc7c5d591e671eaf7c" + "252c1c145336a1a4ddf13244d55e835680cab2533b82df2efe55ec18c1e6cd00" + "7bb089758bb17c2cbe14441bd093ae66e5976d53733f4fa3269701d31d23d467", + NULL + }; + static const char *dsa_pub_hex[] = { + "a012b3b170b307227957b7ca2061a816ac7a2b3d9ae995a5119c385b603bf6f6" + "c5de4dc5ecb5dfa4a41c68662eb25b638b7e2620ba898d07da6c4991e76cc0ec" + "d1ad3421077067e47c18f58a92a72ad43199ecb7bd84e7d3afb9019f0e9dd0fb" + "aa487300b13081e33c902876436f7b03c345528481d362815e24fe59dac5ac34", + "660d4c8a76cb99a7c7de93eb956cd6bc88e58d901034944a094b01803a43c672" + "b9688c0e01d8f4fc91c62a3f88021f7bd6a651b1a88f43aa4ef27653d12bf8b7" + "099fdf6b461082f8e939107bfd2f7210087d326c375200f1f51e7e74a3413190" + "1bcd0863521ff8d676c48581868736c5e51b16a4e39215ea0b17c4735974c516", + NULL + }; + static const char *dsa_priv_hex[] = { + "6ccaeef6d73b4e80f11c17b8e9627c036635bac39423505e407e5cb7", + NULL + }; char msg[] = "Hello World!"; const unsigned char exptd[] = { 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, @@ -186,7 +281,54 @@ static int dummy_evp_call(void *provctx) if (!EC_KEY_generate_key(key)) goto err; #endif + if (!rawnative_fromhex(dsa_p_hex, &dsa_p, &dsa_p_len) + || !rawnative_fromhex(dsa_q_hex, &dsa_q, &dsa_q_len) + || !rawnative_fromhex(dsa_g_hex, &dsa_g, &dsa_g_len) + || !rawnative_fromhex(dsa_pub_hex, &dsa_pub, &dsa_pub_len) + || !rawnative_fromhex(dsa_priv_hex, &dsa_priv, &dsa_priv_len)) + goto err; + + p = params; + *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, dsa_p, dsa_p_len); + *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, dsa_q, dsa_q_len); + *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, dsa_g, dsa_g_len); + *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PUB_KEY, + dsa_pub, dsa_pub_len); + *p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PRIV_KEY, + dsa_priv, dsa_priv_len); + *p = OSSL_PARAM_construct_end(); + + kctx = EVP_PKEY_CTX_new_from_name(libctx, SN_dsa, ""); + if (kctx == NULL) + goto err; + if (EVP_PKEY_key_fromdata_init(kctx) <= 0 + || EVP_PKEY_fromdata(kctx, &pkey, params) <= 0) + goto err; + + sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey); + if (sctx == NULL) + goto err;; + if (EVP_PKEY_sign_init(sctx) <= 0) + goto err; + + /* set signature parameters */ + sigdgstlen = SHA256_DIGEST_LENGTH; + p = params; + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + SN_sha256, + strlen(SN_sha256) + 1); + + *p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, + &sigdgstlen); + *p = OSSL_PARAM_construct_end(); + if (EVP_PKEY_CTX_set_params(sctx, params) <= 0) + goto err; + + if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0 + || EVP_PKEY_verify_init(sctx) <= 0 + || EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0) + goto err; ret = 1; err: BN_CTX_end(bnctx); @@ -199,6 +341,14 @@ static int dummy_evp_call(void *provctx) #ifndef OPENSSL_NO_EC EC_KEY_free(key); #endif + OPENSSL_free(dsa_p); + OPENSSL_free(dsa_q); + OPENSSL_free(dsa_g); + OPENSSL_free(dsa_pub); + OPENSSL_free(dsa_priv); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(sctx); return ret; } @@ -435,6 +585,19 @@ static const OSSL_ALGORITHM fips_kdfs[] = { { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM fips_signature[] = { +#ifndef OPENSSL_NO_DSA + { "DSA:dsaEncryption", "fips=yes", dsa_signature_functions }, +#endif + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM fips_keymgmt[] = { +#ifndef OPENSSL_NO_DSA + { "DSA", "fips=yes", dsa_keymgmt_functions }, +#endif + { NULL, NULL, NULL } +}; static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov, int operation_id, @@ -451,6 +614,10 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov, return fips_macs; case OSSL_OP_KDF: return fips_kdfs; + case OSSL_OP_KEYMGMT: + return fips_keymgmt; + case OSSL_OP_SIGNATURE: + return fips_signature; } return NULL; } @@ -574,19 +741,18 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider, return 0; } - *out = fips_dispatch_table; - *provctx = ctx; - /* * TODO(3.0): Remove me. This is just a dummy call to demonstrate making * EVP calls from within the FIPS module. */ - if (!dummy_evp_call(*provctx)) { - OPENSSL_CTX_free(*provctx); - *provctx = NULL; + if (!dummy_evp_call(ctx)) { + OPENSSL_CTX_free(ctx); return 0; } + *out = fips_dispatch_table; + *provctx = ctx; + return 1; } diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index ca4354af59..c3ab48b4eb 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -10,11 +10,12 @@ #include #include #include -#include #include #include "internal/param_build.h" #include "prov/implementations.h" #include "prov/providercommon.h" +#include "prov/provider_ctx.h" +#include "crypto/dsa.h" static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams; static OSSL_OP_keymgmt_exportdomparams_fn dsa_exportdomparams; @@ -134,8 +135,9 @@ static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl) static void *dsa_importdomparams(void *provctx, const OSSL_PARAM params[]) { DSA *dsa; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); - if ((dsa = DSA_new()) == NULL + if ((dsa = dsa_new(libctx)) == NULL || !params_to_domparams(dsa, params)) { DSA_free(dsa); dsa = NULL; @@ -164,8 +166,9 @@ static int dsa_exportdomparams(void *domparams, static void *dsa_importkey(void *provctx, const OSSL_PARAM params[]) { DSA *dsa; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); - if ((dsa = DSA_new()) == NULL + if ((dsa = dsa_new(libctx)) == NULL || !params_to_key(dsa, params)) { DSA_free(dsa); dsa = NULL; diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index 1eef3c9165..c656a45fd7 100644 --- a/providers/implementations/signature/dsa.c +++ b/providers/implementations/signature/dsa.c @@ -15,6 +15,7 @@ #include #include "prov/implementations.h" #include "prov/provider_ctx.h" +#include "crypto/dsa.h" static OSSL_OP_signature_newctx_fn dsa_newctx; static OSSL_OP_signature_sign_init_fn dsa_signature_init; @@ -95,8 +96,8 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) return 0; - ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa); - + ret = dsa_sign_int(pdsactx->libctx, 0, tbs, tbslen, sig, &sltmp, + pdsactx->dsa); if (ret <= 0) return 0; diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c index c38f79ce79..029a8e425a 100644 --- a/test/evp_pkey_provided_test.c +++ b/test/evp_pkey_provided_test.c @@ -122,7 +122,7 @@ static int test_fromdata_rsa(void) OSSL_PARAM_END }; - if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_provided(NULL, "RSA", NULL))) + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL))) goto err; if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx)) @@ -172,7 +172,7 @@ static int test_fromdata_dh(void) OSSL_PARAM_END }; - if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_provided(NULL, "DH", NULL))) + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL))) goto err; if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx)) diff --git a/util/libcrypto.num b/util/libcrypto.num index 1fbd264047..e2729895d9 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4819,7 +4819,6 @@ EVP_DigestSignUpdate ? 3_0_0 EXIST::FUNCTION: EVP_DigestVerifyInit_ex ? 3_0_0 EXIST::FUNCTION: EVP_DigestVerifyUpdate ? 3_0_0 EXIST::FUNCTION: BN_check_prime ? 3_0_0 EXIST::FUNCTION: -EVP_PKEY_CTX_new_provided ? 3_0_0 EXIST::FUNCTION: EVP_KEYMGMT_is_a ? 3_0_0 EXIST::FUNCTION: EVP_KEYMGMT_do_all_provided ? 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_is_a ? 3_0_0 EXIST::FUNCTION: @@ -4912,3 +4911,5 @@ RSA_get0_pss_params ? 3_0_0 EXIST::FUNCTION:RSA X509_cmp_timeframe ? 3_0_0 EXIST::FUNCTION: OSSL_CMP_MSG_get0_header ? 3_0_0 EXIST::FUNCTION:CMP BIO_f_prefix ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_name ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_pkey ? 3_0_0 EXIST::FUNCTION: