diff options
author | Matt Caswell <matt@openssl.org> | 2019-09-04 12:46:02 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2019-09-09 14:00:00 +0100 |
commit | 9c45222ddc36124b8826d98dc0794f3eef1e5f0b (patch) | |
tree | ab9140d515d73f044944d4998244b047282ada0d /crypto | |
parent | 21fb7067228e39633755aeba251e925634e64870 (diff) |
Revise EVP_PKEY param handling
We add new functions for getting parameters and discovering the gettable
and settable parameters. We also make EVP_PKEY_CTX_get_signature_md() a
function and implement it in terms of the new functions.
This enables applications to discover the set of parameters that are
supported for a given algorithm implementation.
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9753)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/evp/evp_locl.h | 8 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 23 | ||||
-rw-r--r-- | crypto/evp/pmeth_fn.c | 41 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 120 |
4 files changed, 155 insertions, 37 deletions
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index 722eecfe43..b338823f84 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -110,7 +110,8 @@ struct evp_keyexch_st { OSSL_OP_keyexch_derive_fn *derive; OSSL_OP_keyexch_freectx_fn *freectx; OSSL_OP_keyexch_dupctx_fn *dupctx; - OSSL_OP_keyexch_set_params_fn *set_params; + OSSL_OP_keyexch_set_ctx_params_fn *set_ctx_params; + OSSL_OP_keyexch_settable_ctx_params_fn *settable_ctx_params; } /* EVP_KEYEXCH */; struct evp_signature_st { @@ -130,7 +131,10 @@ struct evp_signature_st { OSSL_OP_signature_verify_recover_fn *verify_recover; OSSL_OP_signature_freectx_fn *freectx; OSSL_OP_signature_dupctx_fn *dupctx; - OSSL_OP_signature_set_params_fn *set_params; + OSSL_OP_signature_get_ctx_params_fn *get_ctx_params; + OSSL_OP_signature_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_OP_signature_set_ctx_params_fn *set_ctx_params; + OSSL_OP_signature_settable_ctx_params_fn *settable_ctx_params; } /* EVP_SIGNATURE */; int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index e9b7259cd1..1f14a368a2 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -50,7 +50,7 @@ static void *evp_keyexch_from_dispatch(const char *name, EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(keymgmt_data->ctx, name, keymgmt_data->properties); EVP_KEYEXCH *exchange = NULL; - int fncnt = 0; + int fncnt = 0, paramfncnt = 0; if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) { ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE); @@ -102,19 +102,28 @@ static void *evp_keyexch_from_dispatch(const char *name, break; exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns); break; - case OSSL_FUNC_KEYEXCH_SET_PARAMS: - if (exchange->set_params != NULL) + case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS: + if (exchange->set_ctx_params != NULL) break; - exchange->set_params = OSSL_get_OP_keyexch_set_params(fns); + exchange->set_ctx_params = OSSL_get_OP_keyexch_set_ctx_params(fns); + paramfncnt++; + break; + case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS: + if (exchange->settable_ctx_params != NULL) + break; + exchange->settable_ctx_params + = OSSL_get_OP_keyexch_settable_ctx_params(fns); + paramfncnt++; break; } } - if (fncnt != 4) { + if (fncnt != 4 || (paramfncnt != 0 && paramfncnt != 2)) { /* * In order to be a consistent set of functions we must have at least * a complete set of "exchange" functions: init, derive, newctx, - * and freectx. The dupctx, set_peer and set_params functions are - * optional. + * and freectx. The set_ctx_params and settable_ctx_params functions are + * optional, but if one of them is present then the other one must also + * be present. The dupctx and set_peer functions are optional. */ EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS); diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c index 8fdb31c218..dfdc85f1d5 100644 --- a/crypto/evp/pmeth_fn.c +++ b/crypto/evp/pmeth_fn.c @@ -51,6 +51,7 @@ static void *evp_signature_from_dispatch(const char *name, keymgmt_data->properties); EVP_SIGNATURE *signature = NULL; int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0; + int gparamfncnt = 0, sparamfncnt = 0; if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) { ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE); @@ -123,21 +124,49 @@ static void *evp_signature_from_dispatch(const char *name, break; signature->dupctx = OSSL_get_OP_signature_dupctx(fns); break; - case OSSL_FUNC_SIGNATURE_SET_PARAMS: - if (signature->set_params != NULL) + case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS: + if (signature->get_ctx_params != NULL) break; - signature->set_params = OSSL_get_OP_signature_set_params(fns); + 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; } } if (ctxfncnt != 2 - || (signfncnt != 2 && verifyfncnt != 2 && verifyrecfncnt != 2)) { + || (signfncnt != 2 && verifyfncnt != 2 && verifyrecfncnt != 2) + || (gparamfncnt != 0 && gparamfncnt != 2) + || (sparamfncnt != 0 && sparamfncnt != 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 pair of * "signature" functions: (sign_init, sign) or (verify_init verify) or - * (verify_recover_init, verify_recover). The dupctx and set_params - * functions are optional. + * (verify_recover_init, verify_recover). 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 dupctx function is + * optional. */ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); goto err; diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 534f857df1..4c98212c6a 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -404,15 +404,49 @@ 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 (ctx->sigprovctx != NULL + && ctx->signature != NULL + && ctx->signature->get_ctx_params != NULL) + return ctx->signature->get_ctx_params(ctx->sigprovctx, params); + return 0; +} + +const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(EVP_PKEY_CTX *ctx) +{ + if (ctx->signature != NULL + && ctx->signature->gettable_ctx_params != NULL) + return ctx->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 (ctx->sigprovctx != NULL && ctx->signature != NULL) - return ctx->signature->set_params(ctx->sigprovctx, params); + if (ctx->exchprovctx != NULL + && ctx->exchange != NULL + && ctx->exchange->set_ctx_params != NULL) + return ctx->exchange->set_ctx_params(ctx->exchprovctx, params); + if (ctx->sigprovctx != NULL + && ctx->signature != NULL + && ctx->signature->set_ctx_params != NULL) + return ctx->signature->set_ctx_params(ctx->sigprovctx, params); return 0; } +const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) +{ + if (ctx->exchange != NULL + && ctx->exchange->settable_ctx_params != NULL) + return ctx->exchange->settable_ctx_params(); + if (ctx->signature != NULL + && ctx->signature->settable_ctx_params != NULL) + return ctx->signature->settable_ctx_params(); + + return NULL; +} + #ifndef OPENSSL_NO_DH int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) { @@ -431,36 +465,78 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) } #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) { + 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) + 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]; + OSSL_PARAM sig_md_params[3], *p = sig_md_params; size_t mdsize; const char *name; + if (ctx == NULL) { + 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) 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 = ""; + mdsize = 0; + } else { + mdsize = EVP_MD_size(md); + name = EVP_MD_name(md); + } - return EVP_PKEY_CTX_set_params(ctx, sig_md_params); + *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, |