X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fpmeth_lib.c;h=eca517812933b156212b86bb0535997dd4c4d00e;hp=534f857df1b7dce586784cea31a8d308761e41b5;hb=e25761b10d48abb36a5863b087152be81ea28466;hpb=390acbebfa90500c79c5014e6659eacda861550c diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 534f857df1..eca5178129 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1,6 +1,5 @@ - /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2020 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 @@ -8,6 +7,12 @@ * https://www.openssl.org/source/license.html */ +/* + * Low level key APIs (DH etc) are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include #include @@ -15,67 +20,79 @@ #include #include #include +#include #include "internal/cryptlib.h" -#include "internal/asn1_int.h" -#include "internal/evp_int.h" +#include "crypto/asn1.h" +#include "crypto/evp.h" +#include "crypto/dh.h" +#include "internal/ffc.h" #include "internal/numbers.h" #include "internal/provider.h" -#include "evp_locl.h" +#include "evp_local.h" +#ifndef FIPS_MODULE + +typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void); typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; /* This array needs to be in order of NIDs */ -static const EVP_PKEY_METHOD *standard_methods[] = { -#ifndef OPENSSL_NO_RSA - &rsa_pkey_meth, -#endif -#ifndef OPENSSL_NO_DH - &dh_pkey_meth, -#endif -#ifndef OPENSSL_NO_DSA - &dsa_pkey_meth, -#endif -#ifndef OPENSSL_NO_EC - &ec_pkey_meth, -#endif - &hmac_pkey_meth, -#ifndef OPENSSL_NO_CMAC - &cmac_pkey_meth, -#endif -#ifndef OPENSSL_NO_RSA - &rsa_pss_pkey_meth, -#endif -#ifndef OPENSSL_NO_DH - &dhx_pkey_meth, -#endif -#ifndef OPENSSL_NO_SCRYPT - &scrypt_pkey_meth, -#endif - &tls1_prf_pkey_meth, -#ifndef OPENSSL_NO_EC - &ecx25519_pkey_meth, - &ecx448_pkey_meth, -#endif - &hkdf_pkey_meth, -#ifndef OPENSSL_NO_POLY1305 - &poly1305_pkey_meth, -#endif -#ifndef OPENSSL_NO_SIPHASH - &siphash_pkey_meth, -#endif -#ifndef OPENSSL_NO_EC - &ed25519_pkey_meth, - &ed448_pkey_meth, -#endif -#ifndef OPENSSL_NO_SM2 - &sm2_pkey_meth, -#endif +static pmeth_fn standard_methods[] = { +# ifndef OPENSSL_NO_RSA + rsa_pkey_method, +# endif +# ifndef OPENSSL_NO_DH + dh_pkey_method, +# endif +# ifndef OPENSSL_NO_DSA + dsa_pkey_method, +# endif +# ifndef OPENSSL_NO_EC + ec_pkey_method, +# endif + hmac_pkey_method, +# ifndef OPENSSL_NO_CMAC + cmac_pkey_method, +# endif +# ifndef OPENSSL_NO_RSA + rsa_pss_pkey_method, +# endif +# ifndef OPENSSL_NO_DH + dhx_pkey_method, +# endif +# ifndef OPENSSL_NO_SCRYPT + scrypt_pkey_method, +# endif + tls1_prf_pkey_method, +# ifndef OPENSSL_NO_EC + ecx25519_pkey_method, + ecx448_pkey_method, +# endif + hkdf_pkey_method, +# ifndef OPENSSL_NO_POLY1305 + poly1305_pkey_method, +# endif +# ifndef OPENSSL_NO_SIPHASH + siphash_pkey_method, +# endif +# ifndef OPENSSL_NO_EC + ed25519_pkey_method, + ed448_pkey_method, +# endif +# ifndef OPENSSL_NO_SM2 + sm2_pkey_method, +# endif }; -DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, - pmeth); +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func); + +static int pmeth_func_cmp(const EVP_PKEY_METHOD *const *a, pmeth_fn const *b) +{ + return ((*a)->pkey_id - ((**b)())->pkey_id); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func); static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, const EVP_PKEY_METHOD *const *b) @@ -83,13 +100,12 @@ static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, return ((*a)->pkey_id - (*b)->pkey_id); } -IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, - pmeth); - const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) { + pmeth_fn *ret; EVP_PKEY_METHOD tmp; - const EVP_PKEY_METHOD *t = &tmp, **ret; + const EVP_PKEY_METHOD *t = &tmp; + tmp.pkey_id = type; if (app_pkey_methods) { int idx; @@ -97,18 +113,39 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) if (idx >= 0) return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); } - ret = OBJ_bsearch_pmeth(&t, standard_methods, - sizeof(standard_methods) / - sizeof(EVP_PKEY_METHOD *)); - if (!ret || !*ret) + ret = OBJ_bsearch_pmeth_func(&t, standard_methods, + sizeof(standard_methods) / + sizeof(pmeth_fn)); + if (ret == NULL || *ret == NULL) + return NULL; + 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; - return *ret; + } + + pmeth->pkey_id = id; + pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; + return pmeth; } +#endif /* FIPS_MODULE */ + +static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, + EVP_PKEY *pkey, ENGINE *e, + const char *keytype, const char *propquery, + int id) -static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) { EVP_PKEY_CTX *ret; const EVP_PKEY_METHOD *pmeth = NULL; + EVP_KEYMGMT *keymgmt = NULL; /* * When using providers, the context is bound to the algo implementation @@ -117,14 +154,43 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) if (pkey == NULL && e == NULL && id == -1) goto common; + /* + * 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->type == EVP_PKEY_NONE) { + /* If we have an engine, something went wrong somewhere... */ + if (!ossl_assert(e == NULL)) + return NULL; + keytype = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id); + goto common; + } +#ifndef FIPS_MODULE /* TODO(3.0) Legacy code should be removed when all is provider based */ /* BEGIN legacy */ if (id == -1) { if (pkey == NULL) - return 0; + return NULL; id = pkey->type; } -#ifndef OPENSSL_NO_ENGINE + + /* + * Here, we extract what information we can for the purpose of + * supporting usage with implementations from providers, to make + * for a smooth transition from legacy stuff to provider based stuff. + * + * If an engine is given, this is entirely legacy, and we should not + * pretend anything else, so we only set the name when no engine is + * given. If both are already given, someone made a mistake, and + * since that can only happen internally, it's safe to make an + * assertion. + */ + if (!ossl_assert(e == NULL || keytype == NULL)) + return NULL; + if (e == NULL) + keytype = OBJ_nid2sn(id); + +# 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 */ @@ -144,27 +210,43 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) 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_MODULE */ common: + /* + * If there's no engine and there's a name, we try fetching a provider + * implementation. + */ + if (e == NULL && keytype != NULL) { + /* This could fail so ignore errors */ + ERR_set_mark(); + keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery); + ERR_pop_to_mark(); + } + ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { -#ifndef OPENSSL_NO_ENGINE + EVP_KEYMGMT_free(keymgmt); +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) ENGINE_finish(e); #endif EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; + ret->propquery = propquery; + ret->keytype = keytype; + ret->keymgmt = keymgmt; ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; @@ -183,21 +265,71 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) return ret; } -EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) +/*- All methods below can also be used in FIPS_MODULE */ + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OPENSSL_CTX *libctx, + const char *name, + const char *propquery) { - EVP_PKEY_METHOD *pmeth; + return int_ctx_new(libctx, NULL, NULL, name, propquery, -1); +} - pmeth = OPENSSL_zalloc(sizeof(*pmeth)); - if (pmeth == NULL) { - EVPerr(EVP_F_EVP_PKEY_METH_NEW, ERR_R_MALLOC_FAILURE); - return NULL; +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OPENSSL_CTX *libctx, EVP_PKEY *pkey, + const char *propquery) +{ + return int_ctx_new(libctx, pkey, NULL, NULL, propquery, -1); +} + +void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *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; + } 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; + } +/* TODO(3.0): add dependancies and uncomment this when available for fips mode */ +#ifndef FIPS_MODULE + 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); + EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher); + ctx->op.ciph.ciphprovctx = NULL; + ctx->op.ciph.cipher = NULL; + } else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL) + evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx); } +#endif +} - pmeth->pkey_id = id; - pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; - return pmeth; +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) +{ + 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); +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) + ENGINE_finish(ctx->engine); +#endif + OPENSSL_free(ctx); } +#ifndef FIPS_MODULE + void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, const EVP_PKEY_METHOD *meth) { @@ -258,12 +390,12 @@ void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth) EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) { - return int_ctx_new(pkey, e, -1); + return int_ctx_new(NULL, pkey, e, NULL, NULL, -1); } EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) { - return int_ctx_new(NULL, e, id); + return int_ctx_new(NULL, NULL, e, NULL, NULL, id); } EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) @@ -271,15 +403,18 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) EVP_PKEY_CTX *rctx; if (((pctx->pmeth == NULL) || (pctx->pmeth->copy == NULL)) - && pctx->exchprovctx == NULL) + && ((EVP_PKEY_CTX_IS_DERIVE_OP(pctx) + && pctx->op.kex.exchprovctx == NULL) + || (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); @@ -290,28 +425,76 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) EVP_PKEY_up_ref(pctx->pkey); rctx->pkey = pctx->pkey; rctx->operation = pctx->operation; - - if (pctx->exchprovctx != NULL) { - if (!ossl_assert(pctx->exchange != NULL)) - return NULL; - rctx->exchange = pctx->exchange; - if (!EVP_KEYEXCH_up_ref(rctx->exchange)) { - OPENSSL_free(rctx); - return NULL; + rctx->libctx = pctx->libctx; + rctx->keytype = pctx->keytype; + rctx->propquery = pctx->propquery; + + if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) { + if (pctx->op.kex.exchange != NULL) { + rctx->op.kex.exchange = pctx->op.kex.exchange; + if (!EVP_KEYEXCH_up_ref(rctx->op.kex.exchange)) { + OPENSSL_free(rctx); + return NULL; + } } - rctx->exchprovctx = pctx->exchange->dupctx(pctx->exchprovctx); - if (rctx->exchprovctx == NULL) { - EVP_KEYEXCH_free(rctx->exchange); - OPENSSL_free(rctx); - return NULL; + if (pctx->op.kex.exchprovctx != NULL) { + if (!ossl_assert(pctx->op.kex.exchange != NULL)) + return NULL; + rctx->op.kex.exchprovctx + = pctx->op.kex.exchange->dupctx(pctx->op.kex.exchprovctx); + if (rctx->op.kex.exchprovctx == NULL) { + EVP_KEYEXCH_free(rctx->op.kex.exchange); + OPENSSL_free(rctx); + return NULL; + } + return rctx; + } + } else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) { + if (pctx->op.sig.signature != NULL) { + rctx->op.sig.signature = pctx->op.sig.signature; + if (!EVP_SIGNATURE_up_ref(rctx->op.sig.signature)) { + OPENSSL_free(rctx); + return NULL; + } + } + if (pctx->op.sig.sigprovctx != NULL) { + if (!ossl_assert(pctx->op.sig.signature != NULL)) + return NULL; + rctx->op.sig.sigprovctx + = pctx->op.sig.signature->dupctx(pctx->op.sig.sigprovctx); + if (rctx->op.sig.sigprovctx == NULL) { + EVP_SIGNATURE_free(rctx->op.sig.signature); + OPENSSL_free(rctx); + return NULL; + } + return rctx; + } + } else if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(pctx)) { + if (pctx->op.ciph.cipher != NULL) { + rctx->op.ciph.cipher = pctx->op.ciph.cipher; + if (!EVP_ASYM_CIPHER_up_ref(rctx->op.ciph.cipher)) { + OPENSSL_free(rctx); + return NULL; + } + } + if (pctx->op.ciph.ciphprovctx != NULL) { + if (!ossl_assert(pctx->op.ciph.cipher != NULL)) + return NULL; + rctx->op.ciph.ciphprovctx + = pctx->op.ciph.cipher->dupctx(pctx->op.ciph.ciphprovctx); + if (rctx->op.ciph.ciphprovctx == NULL) { + EVP_ASYM_CIPHER_free(rctx->op.ciph.cipher); + OPENSSL_free(rctx); + return NULL; + } + return rctx; } - return rctx; } 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); @@ -370,7 +553,7 @@ size_t EVP_PKEY_meth_get_count(void) const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx) { if (idx < OSSL_NELEM(standard_methods)) - return standard_methods[idx]; + return (standard_methods[idx])(); if (app_pkey_methods == NULL) return NULL; idx -= OSSL_NELEM(standard_methods); @@ -378,49 +561,159 @@ 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); + 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); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_set_params != NULL) + return evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx, + params); + return 0; +} - if (ctx->exchprovctx != NULL && ctx->exchange != NULL) - ctx->exchange->freectx(ctx->exchprovctx); +#ifndef FIPS_MODULE +int EVP_PKEY_CTX_get_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->get_ctx_params != NULL) + return ctx->op.kex.exchange->get_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->get_ctx_params != NULL) + return ctx->op.sig.signature->get_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->get_ctx_params != NULL) + return ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.ciphprovctx, + params); + return 0; +} - EVP_KEYEXCH_free(ctx->exchange); +const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx) +{ + if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) + && ctx->op.kex.exchange != NULL + && ctx->op.kex.exchange->gettable_ctx_params != NULL) + return ctx->op.kex.exchange->gettable_ctx_params(); + if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && ctx->op.sig.signature != NULL + && ctx->op.sig.signature->gettable_ctx_params != NULL) + return ctx->op.sig.signature->gettable_ctx_params(); + if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + && ctx->op.ciph.cipher != NULL + && ctx->op.ciph.cipher->gettable_ctx_params != NULL) + return ctx->op.ciph.cipher->gettable_ctx_params(); + return NULL; +} - if (ctx->sigprovctx != NULL && ctx->signature != NULL) - ctx->signature->freectx(ctx->sigprovctx); +const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) +{ + if (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) + && ctx->op.kex.exchange != NULL + && ctx->op.kex.exchange->settable_ctx_params != NULL) + return ctx->op.kex.exchange->settable_ctx_params(); + if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && ctx->op.sig.signature != NULL + && ctx->op.sig.signature->settable_ctx_params != NULL) + return ctx->op.sig.signature->settable_ctx_params(); + if (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + && ctx->op.ciph.cipher != NULL + && ctx->op.ciph.cipher->settable_ctx_params != NULL) + return ctx->op.ciph.cipher->settable_ctx_params(); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->keymgmt != NULL) + return evp_keymgmt_gen_settable_params(ctx->keymgmt); - EVP_SIGNATURE_free(ctx->signature); + return NULL; +} - EVP_PKEY_free(ctx->pkey); - EVP_PKEY_free(ctx->peerkey); -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(ctx->engine); -#endif - OPENSSL_free(ctx); +/* + * Internal helpers for stricter EVP_PKEY_CTX_{set,get}_params(). + * + * Return 1 on success, 0 or negative for errors. + * + * In particular they return -2 if any of the params is not supported. + * + * They are not available in FIPS_MODULE as they depend on + * - EVP_PKEY_CTX_{get,set}_params() + * - EVP_PKEY_CTX_{gettable,settable}_params() + * + */ +int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) +{ + const OSSL_PARAM *p; + + if (ctx == NULL || params == NULL) + return 0; + + for (p = params; p->key != NULL; p++) { + /* Check the ctx actually understands this parameter */ + if (OSSL_PARAM_locate_const(EVP_PKEY_CTX_settable_params(ctx), + p->key) == NULL ) + return -2; + } + + return EVP_PKEY_CTX_set_params(ctx, params); } -int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) +int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) { - if (ctx->exchprovctx != NULL && ctx->exchange != NULL) - return ctx->exchange->set_params(ctx->exchprovctx, params); - if (ctx->sigprovctx != NULL && ctx->signature != NULL) - return ctx->signature->set_params(ctx->sigprovctx, params); - return 0; + const OSSL_PARAM *p; + + if (ctx == NULL || params == NULL) + return 0; + + for (p = params; p->key != NULL; p++ ) { + /* Check the ctx actually understands this parameter */ + if (OSSL_PARAM_locate_const(EVP_PKEY_CTX_gettable_params(ctx), + p->key) == NULL ) + return -2; + } + + return EVP_PKEY_CTX_get_params(ctx, params); } -#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]; unsigned int upad = pad; + /* We use EVP_PKEY_CTX_ctrl return values */ + if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->exchprovctx == NULL) + if (ctx->op.kex.exchprovctx == NULL) return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_DH_PAD, pad, NULL); @@ -429,50 +722,205 @@ 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) +{ + OSSL_PARAM sig_md_params[3], *p = sig_md_params; + /* 80 should be big enough */ + char name[80] = ""; + const EVP_MD *tmp; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.sig.sigprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_GET_MD, 0, (void *)(md)); + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + name, + sizeof(name)); + *p++ = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params)) + return 0; + + tmp = evp_get_digestbyname_ex(ctx->libctx, name); + if (tmp == NULL) + return 0; + + *md = tmp; + + return 1; +} int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { - OSSL_PARAM sig_md_params[3]; - size_t mdsize; + OSSL_PARAM sig_md_params[2], *p = sig_md_params; const char *name; + if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + /* TODO(3.0): Remove this eventually when no more legacy */ - if (ctx->sigprovctx == NULL) + if (ctx->op.sig.sigprovctx == NULL) return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0, (void *)(md)); - if (md == NULL) - return 1; - - mdsize = EVP_MD_size(md); - name = EVP_MD_name(md); - sig_md_params[0] = OSSL_PARAM_construct_utf8_string( - OSSL_SIGNATURE_PARAM_DIGEST, - /* - * Cast away the const. This is read only so should - * be safe - */ - (char *)name, - strlen(name) + 1); - sig_md_params[1] = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, - &mdsize); - sig_md_params[2] = OSSL_PARAM_construct_end(); + if (md == NULL) { + name = ""; + } else { + name = EVP_MD_name(md); + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + /* + * Cast away the const. This is read + * only so should be safe + */ + (char *)name, 0); + *p++ = OSSL_PARAM_construct_end(); return EVP_PKEY_CTX_set_params(ctx, sig_md_params); - } 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 - case EVP_PKEY_CTRL_DH_PAD: - return EVP_PKEY_CTX_set_dh_pad(ctx, p1); -#endif - case EVP_PKEY_CTRL_MD: - return EVP_PKEY_CTX_set_signature_md(ctx, p2); + /* + * GOST CMS format is different for different cipher algorithms. + * Most of other algorithms don't have such a difference + * so this ctrl is just ignored. + */ + if (cmd == EVP_PKEY_CTRL_CIPHER) + return -2; + +# ifndef OPENSSL_NO_DH + if (keytype == EVP_PKEY_DH) { + switch (cmd) { + case EVP_PKEY_CTRL_DH_PAD: + return EVP_PKEY_CTX_set_dh_pad(ctx, p1); + case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: + return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, p1); + case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: + return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, p1); + case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: + return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, p1); + case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: + return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, p1); + case EVP_PKEY_CTRL_DH_RFC5114: + return EVP_PKEY_CTX_set_dh_rfc5114(ctx, p1); + } + } +# endif +# ifndef OPENSSL_NO_DSA + if (keytype == EVP_PKEY_DSA) { + switch (cmd) { + case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: + return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, p1); + case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: + return EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, p1); + case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: + return EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, p2); + } + } +# endif +# ifndef OPENSSL_NO_EC + if (keytype == EVP_PKEY_EC) { + switch (cmd) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, p1); + case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: + if (p1 == -2) { + return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx); + } else if (p1 < -1 || p1 > 1) { + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } else { + return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1); + } + case EVP_PKEY_CTRL_EC_KDF_TYPE: + if (p1 == -2) { + return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx); + } else { + return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1); + } + case EVP_PKEY_CTRL_GET_EC_KDF_MD: + return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_MD: + return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2); + case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: + return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_OUTLEN: + return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1); + case EVP_PKEY_CTRL_GET_EC_KDF_UKM: + return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2); + case EVP_PKEY_CTRL_EC_KDF_UKM: + return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1); + } + } +# endif + if (keytype == EVP_PKEY_RSA) { + switch (cmd) { + case EVP_PKEY_CTRL_RSA_OAEP_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_GET_RSA_OAEP_MD: + return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_MGF1_MD: + return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1); + case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL: + return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2); + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, p1); + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + return EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, p2); + case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES: + return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1); + } + } + /* + * keytype == -1 is used when several key types share the same structure, + * or for generic controls that are the same across multiple key types. + */ + if (keytype == -1) { + switch (cmd) { + case EVP_PKEY_CTRL_MD: + return EVP_PKEY_CTX_set_signature_md(ctx, p2); + case EVP_PKEY_CTRL_GET_MD: + return EVP_PKEY_CTX_get_signature_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_PADDING: + return EVP_PKEY_CTX_set_rsa_padding(ctx, p1); + case EVP_PKEY_CTRL_GET_RSA_PADDING: + return EVP_PKEY_CTX_get_rsa_padding(ctx, p2); + case EVP_PKEY_CTRL_GET_RSA_MGF1_MD: + return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2); + case EVP_PKEY_CTRL_RSA_PSS_SALTLEN: + return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1); + case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN: + return EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, p2); + case EVP_PKEY_CTRL_PKCS7_ENCRYPT: + case EVP_PKEY_CTRL_PKCS7_DECRYPT: +# ifndef OPENSSL_NO_CMS + case EVP_PKEY_CTRL_CMS_DECRYPT: + case EVP_PKEY_CTRL_CMS_ENCRYPT: +# endif + /* TODO (3.0) Temporary hack, this should probe */ + if (!EVP_PKEY_is_a(EVP_PKEY_CTX_get0_pkey(ctx), "RSASSA-PSS")) + return 1; + ERR_raise(ERR_LIB_EVP, + EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } } return 0; } @@ -487,7 +935,13 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, return -2; } - if (ctx->exchprovctx != NULL || ctx->sigprovctx != NULL) + if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL) + || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && ctx->op.sig.sigprovctx != NULL) + || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2); if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) { @@ -529,27 +983,106 @@ 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 - if (strcmp(name, "dh_pad") == 0) { - int pad; - pad = atoi(value); - return EVP_PKEY_CTX_set_dh_pad(ctx, pad); + /* Special cases that we intercept */ +# ifndef OPENSSL_NO_EC + /* + * We don't support encoding settings for providers, i.e. the only + * possible encoding is "named_curve", so we simply fail when something + * else is given, and otherwise just pretend all is fine. + */ + if (strcmp(name, "ec_param_enc") == 0) { + if (strcmp(value, "named_curve") == 0) { + return 1; + } else { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } } -#endif - if (strcmp(name, "digest") == 0) { - int ret; - EVP_MD *md - = EVP_MD_fetch(ossl_provider_library_context(ctx->signature->prov), - value, NULL); - if (md == NULL) +# endif + + if (strcmp(name, "rsa_padding_mode") == 0) + name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE; + else if (strcmp(name, "rsa_mgf1_md") == 0) + name = OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST; + else if (strcmp(name, "rsa_oaep_md") == 0) + name = OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST; + else if (strcmp(name, "rsa_oaep_label") == 0) + name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL; + else if (strcmp(name, "rsa_pss_saltlen") == 0) + name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN; + else if (strcmp(name, "rsa_keygen_bits") == 0) + name = OSSL_PKEY_PARAM_RSA_BITS; + else if (strcmp(name, "rsa_keygen_pubexp") == 0) + name = OSSL_PKEY_PARAM_RSA_E; + else if (strcmp(name, "rsa_keygen_primes") == 0) + name = OSSL_PKEY_PARAM_RSA_PRIMES; + else if (strcmp(name, "rsa_pss_keygen_md") == 0) + name = OSSL_PKEY_PARAM_RSA_DIGEST; + else if (strcmp(name, "rsa_pss_keygen_mgf1_md") == 0) + name = OSSL_PKEY_PARAM_RSA_MGF1_DIGEST; + else if (strcmp(name, "rsa_pss_keygen_saltlen") == 0) + name = OSSL_PKEY_PARAM_RSA_PSS_SALTLEN; +# ifndef OPENSSL_NO_DSA + else if (strcmp(name, "dsa_paramgen_bits") == 0) + name = OSSL_PKEY_PARAM_FFC_PBITS; + else if (strcmp(name, "dsa_paramgen_q_bits") == 0) + name = OSSL_PKEY_PARAM_FFC_QBITS; + else if (strcmp(name, "dsa_paramgen_md") == 0) + name = OSSL_PKEY_PARAM_FFC_DIGEST; +# endif +# ifndef OPENSSL_NO_DH + else if (strcmp(name, "dh_paramgen_generator") == 0) + name = OSSL_PKEY_PARAM_FFC_GENERATOR; + else if (strcmp(name, "dh_paramgen_prime_len") == 0) + name = OSSL_PKEY_PARAM_FFC_PBITS; + else if (strcmp(name, "dh_paramgen_subprime_len") == 0) + name = OSSL_PKEY_PARAM_FFC_QBITS; + else if (strcmp(name, "dh_paramgen_type") == 0) { + name = OSSL_PKEY_PARAM_FFC_TYPE; + value = dh_gen_type_id2name(atoi(value)); + } else if (strcmp(name, "dh_param") == 0) + name = OSSL_PKEY_PARAM_FFC_GROUP; + else if (strcmp(name, "dh_rfc5114") == 0) { + name = OSSL_PKEY_PARAM_FFC_GROUP; + value = ffc_named_group_from_uid(atoi(value)); + } else if (strcmp(name, "dh_pad") == 0) + name = OSSL_EXCHANGE_PARAM_PAD; +# endif +# ifndef OPENSSL_NO_EC + else if (strcmp(name, "ec_paramgen_curve") == 0) + name = OSSL_PKEY_PARAM_EC_NAME; + else if (strcmp(name, "ecdh_cofactor_mode") == 0) + name = OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE; + else if (strcmp(name, "ecdh_kdf_md") == 0) + name = OSSL_EXCHANGE_PARAM_KDF_DIGEST; +# endif + + { + /* + * TODO(3.0) reduce the code above to only translate known legacy + * string to the corresponding core name (see core_names.h), but + * otherwise leave it to this code block to do the actual work. + */ + const OSSL_PARAM *settable = EVP_PKEY_CTX_settable_params(ctx); + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + int rv = 0; + int exists = 0; + + if (!OSSL_PARAM_allocate_from_text(¶ms[0], settable, name, value, + strlen(value), &exists)) { + if (!exists) { + ERR_raise_data(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED, + "name=%s,value=%s", name, value); + return -2; + } return 0; - ret = EVP_PKEY_CTX_set_signature_md(ctx, md); - EVP_MD_meth_free(md); - return ret; + } + if (EVP_PKEY_CTX_set_params(ctx, params)) + rv = 1; + OPENSSL_free(params[0].data); + return rv; } - - return 0; } int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, @@ -560,7 +1093,13 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, return -2; } - if (ctx->exchprovctx != NULL || ctx->sigprovctx != NULL) + if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL) + || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && ctx->op.sig.sigprovctx != NULL) + || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_str_to_param(ctx, name, value); if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { @@ -798,6 +1337,21 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, pmeth->ctrl_str = ctrl_str; } +void EVP_PKEY_meth_set_digestsign(EVP_PKEY_METHOD *pmeth, + int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen)) +{ + pmeth->digestsign = digestsign; +} + +void EVP_PKEY_meth_set_digestverify(EVP_PKEY_METHOD *pmeth, + int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen)) +{ + pmeth->digestverify = digestverify; +} + void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, int (*check) (EVP_PKEY *pkey)) { @@ -990,6 +1544,23 @@ void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth, *pctrl_str = pmeth->ctrl_str; } +void EVP_PKEY_meth_get_digestsign(EVP_PKEY_METHOD *pmeth, + int (**digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen)) +{ + if (digestsign) + *digestsign = pmeth->digestsign; +} + +void EVP_PKEY_meth_get_digestverify(EVP_PKEY_METHOD *pmeth, + int (**digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen)) +{ + if (digestverify) + *digestverify = pmeth->digestverify; +} + void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth, int (**pcheck) (EVP_PKEY *pkey)) { @@ -1018,3 +1589,5 @@ void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, if (pdigest_custom != NULL) *pdigest_custom = pmeth->digest_custom; } + +#endif /* FIPS_MODULE */