summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-03-11 13:31:13 +0100
committerTomas Mraz <tomas@openssl.org>2021-03-17 14:57:47 +0100
commit9a4854405869158bd87ee90345b933815882a24d (patch)
tree3bad42c70a66232ac69c0d9e2adcc41ed7b27c17 /providers
parente08993eab65cdc67a3f2078e99f366c155eed49d (diff)
Make EVP_PKEY_missing_parameters work properly on provided RSA keys
This requires changing semantics of the keymgmt_has() function a little in the sense that it now returns 1 if the selection has no meaning for the key type. It was already doing so for ECX keys for example. The keymgmt_validate function semantics is changed similarly to allow passing validation on the same selection that the key returns 1 for. Fixes #14509 Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14511)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/keymgmt/dh_kmgmt.c32
-rw-r--r--providers/implementations/keymgmt/dsa_kmgmt.c32
-rw-r--r--providers/implementations/keymgmt/ec_kmgmt.c48
-rw-r--r--providers/implementations/keymgmt/ecx_kmgmt.c20
-rw-r--r--providers/implementations/keymgmt/kdf_legacy_kmgmt.c2
-rw-r--r--providers/implementations/keymgmt/rsa_kmgmt.c48
6 files changed, 87 insertions, 95 deletions
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index da111c2cd7..abaf6c9ce8 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -128,19 +128,19 @@ static void dh_freedata(void *keydata)
static int dh_has(const void *keydata, int selection)
{
const DH *dh = keydata;
- int ok = 0;
-
- if (ossl_prov_is_running() && dh != NULL) {
- if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
-
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
- ok = ok && (DH_get0_pub_key(dh) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
- ok = ok && (DH_get0_priv_key(dh) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
- ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
- }
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dh == NULL)
+ return 0;
+ if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (DH_get0_pub_key(dh) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (DH_get0_priv_key(dh) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
return ok;
}
@@ -376,13 +376,13 @@ static int dh_validate_private(const DH *dh)
static int dh_validate(const void *keydata, int selection, int checktype)
{
const DH *dh = keydata;
- int ok = 0;
+ int ok = 1;
if (!ossl_prov_is_running())
return 0;
- if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
+ if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
/*
diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c
index f37982c278..02ad9ecb7d 100644
--- a/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -128,19 +128,19 @@ static void dsa_freedata(void *keydata)
static int dsa_has(const void *keydata, int selection)
{
const DSA *dsa = keydata;
- int ok = 0;
-
- if (ossl_prov_is_running() && dsa != NULL) {
- if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
-
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
- ok = ok && (DSA_get0_pub_key(dsa) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
- ok = ok && (DSA_get0_priv_key(dsa) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
- ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
- }
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || dsa == NULL)
+ return 0;
+ if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (DSA_get0_pub_key(dsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (DSA_get0_priv_key(dsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
return ok;
}
@@ -341,13 +341,13 @@ static int dsa_validate_private(const DSA *dsa)
static int dsa_validate(const void *keydata, int selection, int checktype)
{
const DSA *dsa = keydata;
- int ok = 0;
+ int ok = 1;
if (!ossl_prov_is_running())
return 0;
- if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
+ if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && dsa_validate_domparams(dsa, checktype);
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 01e5983236..2ba21dfb39 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -281,24 +281,24 @@ static
int ec_has(const void *keydata, int selection)
{
const EC_KEY *ec = keydata;
- int ok = 0;
-
- if (ossl_prov_is_running() && ec != NULL) {
- if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
-
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
- ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
- ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
- ok = ok && (EC_KEY_get0_group(ec) != NULL);
- /*
- * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
- * available, so no extra check is needed other than the previous one
- * against EC_POSSIBLE_SELECTIONS.
- */
- }
+ int ok = 1;
+
+ if (!ossl_prov_is_running() || ec == NULL)
+ return 0;
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+ ok = ok && (EC_KEY_get0_group(ec) != NULL);
+ /*
+ * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
+ * available, so no extra check is needed other than the previous one
+ * against EC_POSSIBLE_SELECTIONS.
+ */
return ok;
}
@@ -841,7 +841,7 @@ static
int sm2_validate(const void *keydata, int selection, int checktype)
{
const EC_KEY *eck = keydata;
- int ok = 0;
+ int ok = 1;
BN_CTX *ctx = NULL;
if (!ossl_prov_is_running())
@@ -851,8 +851,8 @@ int sm2_validate(const void *keydata, int selection, int checktype)
if (ctx == NULL)
return 0;
- if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
@@ -880,7 +880,7 @@ static
int ec_validate(const void *keydata, int selection, int checktype)
{
const EC_KEY *eck = keydata;
- int ok = 0;
+ int ok = 1;
BN_CTX *ctx = NULL;
if (!ossl_prov_is_running())
@@ -890,8 +890,8 @@ int ec_validate(const void *keydata, int selection, int checktype)
if (ctx == NULL)
return 0;
- if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
+ if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
int flags = EC_KEY_get_flags(eck);
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 9b23c2f0ec..6aa947827c 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -15,6 +15,7 @@
#include <openssl/core_names.h>
#include <openssl/params.h>
#include <openssl/err.h>
+#include <openssl/proverr.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "internal/param_build_set.h"
@@ -71,6 +72,8 @@ static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
static OSSL_FUNC_keymgmt_export_fn ecx_export;
static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
+#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
+
struct ecx_gen_ctx {
OSSL_LIB_CTX *libctx;
char *propq;
@@ -718,21 +721,18 @@ static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
{
const ECX_KEY *ecx = keydata;
- int ok = 0;
+ int ok = keylen == ecx->keylen;
if (!ossl_prov_is_running())
return 0;
- assert(keylen == ecx->keylen);
+ if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
- /*
- * ECX keys have no parameters. But if EVP_PKEY_param_check() is called then
- * we should return true.
- */
- if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
- | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)) != 0)
- ok = 1;
+ if (!ok) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
+ return 0;
+ }
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && ecx->haspubkey;
diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
index 7d788343fe..16d5f971cc 100644
--- a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
+++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
@@ -93,7 +93,7 @@ static void kdf_freedata(void *kdfdata)
static int kdf_has(const void *keydata, int selection)
{
- return 0;
+ return 1; /* nothing is missing */
}
const OSSL_DISPATCH ossl_kdf_keymgmt_functions[] = {
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index 7869b2dddc..46962c7ab8 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -112,22 +112,22 @@ static void rsa_freedata(void *keydata)
static int rsa_has(const void *keydata, int selection)
{
const RSA *rsa = keydata;
- int ok = 0;
+ int ok = 1;
- if (rsa != NULL && ossl_prov_is_running()) {
- if ((selection & RSA_POSSIBLE_SELECTIONS) != 0)
- ok = 1;
+ if (rsa == NULL || !ossl_prov_is_running())
+ return 0;
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* the selection is not missing */
- if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
- /* This will change with OAEP */
- ok = ok && (RSA_test_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS) != 0);
- if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
- ok = ok && (RSA_get0_e(rsa) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
- ok = ok && (RSA_get0_n(rsa) != NULL);
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
- ok = ok && (RSA_get0_d(rsa) != NULL);
- }
+ if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
+ /* This will change with OAEP */
+ ok = ok && (RSA_test_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS) != 0);
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
+ ok = ok && (RSA_get0_e(rsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && (RSA_get0_n(rsa) != NULL);
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && (RSA_get0_d(rsa) != NULL);
return ok;
}
@@ -187,6 +187,9 @@ static int rsa_export(void *keydata, int selection,
if (!ossl_prov_is_running() || rsa == NULL)
return 0;
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 0;
+
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
@@ -358,24 +361,13 @@ static const OSSL_PARAM *rsa_gettable_params(void *provctx)
static int rsa_validate(const void *keydata, int selection, int checktype)
{
const RSA *rsa = keydata;
- int ok = 0;
+ int ok = 1;
if (!ossl_prov_is_running())
return 0;
- /*
- * Although an RSA key has no domain parameters, validating them should
- * return true.
- *
- * RSA_POSSIBLE_SELECTIONS already includes
- * OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS. We explicitly add
- * OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS here as well for completeness. In
- * practice this makes little difference since EVP_PKEY_param_check() always
- * checks the combination of "other" and "domain" parameters anyway.
- */
- if ((selection & (RSA_POSSIBLE_SELECTIONS
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) != 0)
- ok = 1;
+ if ((selection & RSA_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
/* If the whole key is selected, we do a pairwise validation */
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)