X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=crypto%2Fevp%2Fpmeth_lib.c;h=1ae22a7df4b50f33099266c98a38b8a6a1d3399d;hb=12a765a5235f181c2f4992b615eb5f892c368e88;hp=cc26f06d9b5b9a420cf02f17c4ca68e028b3fce3;hpb=d0ea49a820e02713bbe8892a333f2552da633b16;p=thirdparty%2Fopenssl.git diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index cc26f06d9b..1ae22a7df4 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -16,65 +16,73 @@ #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 "internal/numbers.h" -#include "evp_locl.h" +#include "internal/provider.h" +#include "evp_local.h" +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[] = { +static pmeth_fn standard_methods[] = { #ifndef OPENSSL_NO_RSA - &rsa_pkey_meth, + rsa_pkey_method, #endif #ifndef OPENSSL_NO_DH - &dh_pkey_meth, + dh_pkey_method, #endif #ifndef OPENSSL_NO_DSA - &dsa_pkey_meth, + dsa_pkey_method, #endif #ifndef OPENSSL_NO_EC - &ec_pkey_meth, + ec_pkey_method, #endif - &hmac_pkey_meth, + hmac_pkey_method, #ifndef OPENSSL_NO_CMAC - &cmac_pkey_meth, + cmac_pkey_method, #endif #ifndef OPENSSL_NO_RSA - &rsa_pss_pkey_meth, + rsa_pss_pkey_method, #endif #ifndef OPENSSL_NO_DH - &dhx_pkey_meth, + dhx_pkey_method, #endif #ifndef OPENSSL_NO_SCRYPT - &scrypt_pkey_meth, + scrypt_pkey_method, #endif - &tls1_prf_pkey_meth, + tls1_prf_pkey_method, #ifndef OPENSSL_NO_EC - &ecx25519_pkey_meth, - &ecx448_pkey_meth, + ecx25519_pkey_method, + ecx448_pkey_method, #endif - &hkdf_pkey_meth, + hkdf_pkey_method, #ifndef OPENSSL_NO_POLY1305 - &poly1305_pkey_meth, + poly1305_pkey_method, #endif #ifndef OPENSSL_NO_SIPHASH - &siphash_pkey_meth, + siphash_pkey_method, #endif #ifndef OPENSSL_NO_EC - &ed25519_pkey_meth, - &ed448_pkey_meth, + ed25519_pkey_method, + ed448_pkey_method, #endif #ifndef OPENSSL_NO_SM2 - &sm2_pkey_meth, + 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) @@ -82,13 +90,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; @@ -96,12 +103,12 @@ 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; + return (**ret)(); } static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) @@ -171,7 +178,7 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) if (pkey != NULL) EVP_PKEY_up_ref(pkey); - if (pmeth != NULL && pmeth->init) { + if (pmeth != NULL && pmeth->init != NULL) { if (pmeth->init(ret) <= 0) { ret->pmeth = NULL; EVP_PKEY_CTX_free(ret); @@ -182,6 +189,19 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) return ret; } +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); + } else 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); + } +} + EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) { EVP_PKEY_METHOD *pmeth; @@ -270,7 +290,10 @@ 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 /* Make sure it's safe to copy a pkey context using an ENGINE */ @@ -290,21 +313,46 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) 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; + 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; } - return rctx; } rctx->pmeth = pctx->pmeth; @@ -369,7 +417,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); @@ -385,10 +433,7 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) if (ctx->pmeth && ctx->pmeth->cleanup) ctx->pmeth->cleanup(ctx); - if (ctx->exchprovctx != NULL && ctx->exchange != NULL) - ctx->exchange->freectx(ctx->exchprovctx); - - EVP_KEYEXCH_free(ctx->exchange); + evp_pkey_ctx_free_old_ops(ctx); EVP_PKEY_free(ctx->pkey); EVP_PKEY_free(ctx->peerkey); @@ -398,30 +443,156 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) OPENSSL_free(ctx); } +int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *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); + return 0; +} + +const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx) +{ + 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(); + + return NULL; +} + int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) { - if (ctx->exchprovctx != NULL && ctx->exchange != NULL) - return ctx->exchange->set_params(ctx->exchprovctx, 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); return 0; } +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(); + + return NULL; +} + #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); - dh_pad_params[0] = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_PAD, &pad); + dh_pad_params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &upad); dh_pad_params[1] = OSSL_PARAM_construct_end(); return EVP_PKEY_CTX_set_params(ctx, dh_pad_params); } #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(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], *p = sig_md_params; + size_t mdsize; + 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->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) { + name = ""; + mdsize = 0; + } else { + mdsize = EVP_MD_size(md); + 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, + strlen(name) + 1); + *p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, + &mdsize); + *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) { @@ -430,6 +601,10 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, 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); + case EVP_PKEY_CTRL_GET_MD: + return EVP_PKEY_CTX_get_signature_md(ctx, p2); } return 0; } @@ -444,7 +619,9 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, return -2; } - if (ctx->exchprovctx != NULL) + if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL) + || (EVP_PKEY_CTX_IS_DERIVE_OP(ctx) + && ctx->op.sig.sigprovctx != NULL)) return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2); if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) { @@ -494,6 +671,21 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, return EVP_PKEY_CTX_set_dh_pad(ctx, pad); } #endif + if (strcmp(name, "digest") == 0) { + int ret; + EVP_MD *md; + + if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) || ctx->op.sig.signature == NULL) + return 0; + md = EVP_MD_fetch(ossl_provider_library_context(ctx->op.sig.signature->prov), + value, NULL); + if (md == NULL) + return 0; + ret = EVP_PKEY_CTX_set_signature_md(ctx, md); + EVP_MD_meth_free(md); + return ret; + } + return 0; } @@ -505,7 +697,9 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, return -2; } - if (ctx->exchprovctx != 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)) return legacy_ctrl_str_to_param(ctx, name, value); if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {