diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index fa901b2742..ce24cc485f 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -294,7 +294,10 @@ OSSL_FUNC_keymgmt_has() should check whether the given I contains the s of data indicated by the I. A combination of several selector bits must consider all those subsets, not just one. An implementation is, however, free to consider an empty subset of data -to still be a valid subset. +to still be a valid subset. For algorithms where some selection is +not meaningful such as B for +RSA keys the function should just return 1 as the selected subset +is not really missing in the key. OSSL_FUNC_keymgmt_validate() should check if the I contains valid data subsets indicated by I. Some combined selections of @@ -307,7 +310,10 @@ performed on the subset of data. Two types of check are defined: B and B. The interpretation of how much checking is performed in a full check versus a quick check is key type specific. Some providers may have no distinction -between a full check and a quick check. +between a full check and a quick check. For algorithms where some selection is +not meaningful such as B for +RSA keys the function should just return 1 as there is nothing to validate for +that selection. OSSL_FUNC_keymgmt_match() should check if the data subset indicated by I in I and I match. It is assumed that 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; + int ok = 1; - if (ossl_prov_is_running() && dh != NULL) { - if ((selection & DH_POSSIBLE_SELECTIONS) != 0) - 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); - } + 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; + int ok = 1; - if (ossl_prov_is_running() && dsa != NULL) { - if ((selection & DSA_POSSIBLE_SELECTIONS) != 0) - 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); - } + 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; + int ok = 1; - if (ossl_prov_is_running() && ec != NULL) { - if ((selection & EC_POSSIBLE_SELECTIONS) != 0) - 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. - */ - } + 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 #include #include +#include #include #include #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) diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c index 18b62d4645..c89bb36628 100644 --- a/test/evp_pkey_provided_test.c +++ b/test/evp_pkey_provided_test.c @@ -344,7 +344,8 @@ static int test_fromdata_rsa(void) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), 32) || !TEST_int_eq(EVP_PKEY_security_bits(pk), 8) - || !TEST_int_eq(EVP_PKEY_size(pk), 4)) + || !TEST_int_eq(EVP_PKEY_size(pk), 4) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, ""))) @@ -509,7 +510,8 @@ static int test_fromdata_dh_named_group(void) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), 2048) || !TEST_int_eq(EVP_PKEY_security_bits(pk), 112) - || !TEST_int_eq(EVP_PKEY_size(pk), 256)) + || !TEST_int_eq(EVP_PKEY_size(pk), 256) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_true(EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_GROUP_NAME, @@ -654,7 +656,8 @@ static int test_fromdata_dh_fips186_4(void) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), 2048) || !TEST_int_eq(EVP_PKEY_security_bits(pk), 112) - || !TEST_int_eq(EVP_PKEY_size(pk), 256)) + || !TEST_int_eq(EVP_PKEY_size(pk), 256) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_true(EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_GROUP_NAME, @@ -926,7 +929,8 @@ static int test_fromdata_ecx(int tst) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), bits) || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits) - || !TEST_int_eq(EVP_PKEY_size(pk), size)) + || !TEST_int_eq(EVP_PKEY_size(pk), size) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_ptr(ctx2 = EVP_PKEY_CTX_new_from_pkey(NULL, pk, NULL))) @@ -1039,7 +1043,8 @@ static int test_fromdata_ec(void) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), 256) || !TEST_int_eq(EVP_PKEY_security_bits(pk), 128) - || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2)) + || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_ptr(copy_pk = EVP_PKEY_new()) @@ -1298,7 +1303,8 @@ static int test_fromdata_dsa_fips186_4(void) fromdata_params)) || !TEST_int_eq(EVP_PKEY_bits(pk), 2048) || !TEST_int_eq(EVP_PKEY_security_bits(pk), 112) - || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 2 * (3 + sizeof(q_data)))) + || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 2 * (3 + sizeof(q_data))) + || !TEST_false(EVP_PKEY_missing_parameters(pk))) goto err; if (!TEST_false(EVP_PKEY_get_utf8_string_param(pk, OSSL_PKEY_PARAM_GROUP_NAME,