summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2019-09-04 12:46:02 +0100
committerMatt Caswell <matt@openssl.org>2019-09-09 14:00:00 +0100
commit9c45222ddc36124b8826d98dc0794f3eef1e5f0b (patch)
treeab9140d515d73f044944d4998244b047282ada0d /crypto
parent21fb7067228e39633755aeba251e925634e64870 (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.h8
-rw-r--r--crypto/evp/exchange.c23
-rw-r--r--crypto/evp/pmeth_fn.c41
-rw-r--r--crypto/evp/pmeth_lib.c120
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,