From: Richard Levitte Date: Sat, 21 Mar 2020 05:03:39 +0000 (+0100) Subject: EVP: Clarify the states of an EVP_PKEY X-Git-Tag: openssl-3.0.0-alpha1~212 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=adc9f7312665f14ec5c73b60090a4df933e6556d;p=oweals%2Fopenssl.git EVP: Clarify the states of an EVP_PKEY EVP_PKEY is rather complex, even before provider side keys entered the stage. You could have untyped / unassigned keys (pk->type == EVP_PKEY_NONE), keys that had been assigned a type but no data (pk->pkey.ptr == NULL), and fully assigned keys (pk->type != EVP_PKEY_NONE && pk->pkey.ptr != NULL). For provider side keys, the corresponding states weren't well defined, and the code didn't quite account for all the possibilities. We also guard most of the legacy fields in EVP_PKEY with FIPS_MODE, so they don't exist at all in the FIPS module. Most of all, code needs to adapt to the case where an EVP_PKEY's |keymgmt| is non-NULL, but its |keydata| is NULL. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/11375) --- diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 94be3c2a9c..6e63c5ab2d 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -39,13 +39,26 @@ static int try_import(const OSSL_PARAM params[], void *arg) { struct import_data_st *data = arg; + /* + * It's fine if there was no data to transfer, we just end up with an + * empty destination key. + */ + if (params[0].key == NULL) + return 1; + + /* Just in time creation of keydata, if needed */ + if (data->keydata == NULL + && (data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return 0; + } + return evp_keymgmt_import(data->keymgmt, data->keydata, data->selection, params); } void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) { - void *keydata = NULL; struct import_data_st import_data; size_t i = 0; @@ -54,7 +67,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) return NULL; /* If we have an unassigned key, give up */ - if (pk->keymgmt == NULL) + if (pk->keydata == NULL) return NULL; /* If |keymgmt| matches the "origin" |keymgmt|, no more to do */ @@ -91,10 +104,6 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) if (!ossl_assert(match_type(pk->keymgmt, keymgmt))) return NULL; - /* Create space to import data into */ - if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL) - return NULL; - /* * We look at the already cached provider keys, and import from the * first that supports it (i.e. use its export function), and export @@ -102,7 +111,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) */ /* Setup for the export callback */ - import_data.keydata = keydata; + import_data.keydata = NULL; /* try_import will create it */ import_data.keymgmt = keymgmt; import_data.selection = OSSL_KEYMGMT_SELECT_ALL; @@ -113,17 +122,17 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt) if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, OSSL_KEYMGMT_SELECT_ALL, &try_import, &import_data)) { /* If there was an error, bail out */ - evp_keymgmt_freedata(keymgmt, keydata); + evp_keymgmt_freedata(keymgmt, import_data.keydata); return NULL; } /* Add the new export to the operation cache */ - if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, keydata)) { - evp_keymgmt_freedata(keymgmt, keydata); + if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, import_data.keydata)) { + evp_keymgmt_freedata(keymgmt, import_data.keydata); return NULL; } - return keydata; + return import_data.keydata; } void evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk) @@ -175,7 +184,7 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk) * * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc */ - if (pk->keymgmt != NULL) { + if (pk->keydata != NULL) { int bits = 0; int security_bits = 0; int size = 0; @@ -254,7 +263,17 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) keydata2 = pk2->keydata; if (keymgmt1 != keymgmt2) { - void *tmp_keydata = NULL; + /* + * The condition for a successful cross export is that the + * keydata to be exported is NULL (typed, but otherwise empty + * EVP_PKEY), or that it was possible to export it with + * evp_keymgmt_util_export_to_provider(). + * + * We use |ok| to determine if it's ok to cross export one way, + * but also to determine if we should attempt a cross export + * the other way. There's no point doing it both ways. + */ + int ok = 1; /* Complex case, where the keymgmt differ */ if (keymgmt1 != NULL @@ -270,17 +289,35 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) */ if (keymgmt2 != NULL && keymgmt2->match != NULL) { - tmp_keydata = evp_keymgmt_util_export_to_provider(pk1, keymgmt2); - if (tmp_keydata != NULL) { + void *tmp_keydata = NULL; + + ok = 1; + if (keydata1 != NULL) { + tmp_keydata = + evp_keymgmt_util_export_to_provider(pk1, keymgmt2); + ok = (tmp_keydata != NULL); + } + if (ok) { keymgmt1 = keymgmt2; keydata1 = tmp_keydata; } } - if (tmp_keydata == NULL + /* + * If we've successfully cross exported one way, there's not point + * doing it the other way, hence the |!ok| check. + */ + if (!ok && keymgmt1 != NULL && keymgmt1->match != NULL) { - tmp_keydata = evp_keymgmt_util_export_to_provider(pk2, keymgmt1); - if (tmp_keydata != NULL) { + void *tmp_keydata = NULL; + + ok = 1; + if (keydata2 != NULL) { + tmp_keydata = + evp_keymgmt_util_export_to_provider(pk2, keymgmt1); + ok = (tmp_keydata != NULL); + } + if (ok) { keymgmt2 = keymgmt1; keydata2 = tmp_keydata; } @@ -291,6 +328,13 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection) if (keymgmt1 != keymgmt2) return -2; + /* If both keydata are NULL, then they're the same key */ + if (keydata1 == NULL && keydata2 == NULL) + return 1; + /* If only one of the keydata is NULL, then they're different keys */ + if (keydata1 == NULL || keydata2 == NULL) + return 0; + /* If both keydata are non-NULL, we let the backend decide */ return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection); } @@ -301,23 +345,21 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) void *to_keydata = to->keydata, *alloc_keydata = NULL; /* An unassigned key can't be copied */ - if (from == NULL || from->keymgmt == NULL) - return 0; - - /* If |from| doesn't support copying, we fail */ - if (from->keymgmt->copy == NULL) + if (from == NULL || from->keydata == NULL) return 0; - /* If |to| doesn't have a provider side "origin" yet, create one */ - if (to_keymgmt == NULL) { - to_keydata = alloc_keydata = evp_keymgmt_newdata(from->keymgmt); - if (to_keydata == NULL) + if (to_keymgmt == from->keymgmt && to_keymgmt->copy != NULL) { + /* Make sure there's somewhere to copy to */ + if (to_keydata == NULL + && (to_keydata = evp_keymgmt_newdata(to_keymgmt)) == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return 0; - to_keymgmt = from->keymgmt; - } + } - if (to_keymgmt == from->keymgmt) { - /* |to| and |from| have the same keymgmt, just copy and be done */ + /* + * |to| and |from| have the same keymgmt, and the copy function is + * implemented, so just copy and be done + */ if (!evp_keymgmt_copy(to_keymgmt, to_keydata, from->keydata, selection)) return 0; @@ -333,6 +375,12 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) evp_keymgmt_freedata(to_keymgmt, alloc_keydata); return 0; } + + /* + * In this case to_keydata was previously unallocated, try_import() + * may have created it for us. + */ + to_keydata = import_data.keydata; } else { ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); return 0; diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index a2bb2b7190..1603f29b1a 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1069,13 +1069,16 @@ void EVP_PKEY_free(EVP_PKEY *x) int EVP_PKEY_size(const EVP_PKEY *pkey) { + int size = 0; + if (pkey != NULL) { - if (pkey->ameth == NULL) - return pkey->cache.size; - else if (pkey->ameth->pkey_size != NULL) - return pkey->ameth->pkey_size(pkey); + size = pkey->cache.size; +#ifndef FIPS_MODE + if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL) + size = pkey->ameth->pkey_size(pkey); +#endif } - return 0; + return size; } void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, @@ -1085,10 +1088,20 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, EVP_KEYMGMT *allocated_keymgmt = NULL; EVP_KEYMGMT *tmp_keymgmt = NULL; void *keydata = NULL; + int check; if (pk == NULL) return NULL; + /* No key data => nothing to export */ + check = 1; +#ifndef FIPS_MODE + check = check && pk->pkey.ptr == NULL; +#endif + check = check && pk->keydata == NULL; + if (check) + return NULL; + #ifndef FIPS_MODE if (pk->pkey.ptr != NULL) { /* diff --git a/crypto/evp/pmeth_check.c b/crypto/evp/pmeth_check.c index c02353d5ea..587e8ae12a 100644 --- a/crypto/evp/pmeth_check.c +++ b/crypto/evp/pmeth_check.c @@ -35,19 +35,24 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_PUBLIC_KEY); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE /* legacy */ /* call customized public key check function first */ if (ctx->pmeth->public_check != NULL) return ctx->pmeth->public_check(pkey); /* use default public key check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) + goto not_supported; return pkey->ameth->pkey_public_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) @@ -68,19 +73,24 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE + /* legacy */ /* call customized param check function first */ if (ctx->pmeth->param_check != NULL) return ctx->pmeth->param_check(pkey); - /* legacy */ /* use default param check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) + goto not_supported; return pkey->ameth->pkey_param_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) @@ -101,6 +111,7 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_PRIVATE_KEY); /* not supported for legacy keys */ + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; } @@ -121,6 +132,7 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx) if (key != NULL && keymgmt != NULL) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR); /* not supported for legacy keys */ + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; } @@ -141,18 +153,23 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx) if (key != NULL && keymgmt != NULL) return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL); + if (pkey->type == EVP_PKEY_NONE) + goto not_supported; + +#ifndef FIPS_MODE /* legacy */ /* call customized check function first */ if (ctx->pmeth->check != NULL) return ctx->pmeth->check(pkey); /* use default check function in ameth */ - if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) { - EVPerr(EVP_F_EVP_PKEY_CHECK, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) + goto not_supported; return pkey->ameth->pkey_check(pkey); +#endif + not_supported: + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index f5e1131f06..ecaaec41c7 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -157,7 +157,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * If the key doesn't contain anything legacy, then it must be provided, * so we extract the necessary information and use that. */ - if (pkey != NULL && pkey->ameth == NULL) { + if (pkey != NULL && pkey->type == EVP_PKEY_NONE) { /* If we have an engine, something went wrong somewhere... */ if (!ossl_assert(e == NULL)) return NULL; diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 2e0322fa98..e5f9aad010 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -502,14 +502,31 @@ const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; } cipher##_init_key, NULL, NULL, NULL, NULL) /* - * Type needs to be a bit field Sub-type needs to be for variations on the - * method, as in, can it do arbitrary encryption.... + * An EVP_PKEY can have the following states: + * + * untyped & empty: + * + * type == EVP_PKEY_NONE && keymgmt == NULL + * + * typed & empty: + * + * (type != EVP_PKEY_NONE && pkey.ptr == NULL) ## legacy (libcrypto only) + * || (keymgmt != NULL && keydata == NULL) ## provider side + * + * fully assigned: + * + * (type != EVP_PKEY_NONE && pkey.ptr != NULL) ## legacy (libcrypto only) + * || (keymgmt != NULL && keydata != NULL) ## provider side + * + * The easiest way to detect a legacy key is: type != EVP_PKEY_NONE + * The easiest way to detect a provider side key is: keymgmt != NULL */ struct evp_pkey_st { /* == Legacy attributes == */ int type; int save_type; +# ifndef FIPS_MODE /* * Legacy key "origin" is composed of a pointer to an EVP_PKEY_ASN1_METHOD, * a pointer to a low level key and possibly a pointer to an engine. @@ -519,20 +536,21 @@ struct evp_pkey_st { ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */ union { void *ptr; -# ifndef OPENSSL_NO_RSA +# ifndef OPENSSL_NO_RSA struct rsa_st *rsa; /* RSA */ -# endif -# ifndef OPENSSL_NO_DSA +# endif +# ifndef OPENSSL_NO_DSA struct dsa_st *dsa; /* DSA */ -# endif -# ifndef OPENSSL_NO_DH +# endif +# ifndef OPENSSL_NO_DH struct dh_st *dh; /* DH */ -# endif -# ifndef OPENSSL_NO_EC +# endif +# ifndef OPENSSL_NO_EC struct ec_key_st *ec; /* ECC */ ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */ -# endif +# endif } pkey; +# endif /* == Common attributes == */ CRYPTO_REF_COUNT references; diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c index 6a6a06cc86..c9aef88b16 100644 --- a/providers/implementations/keymgmt/dh_kmgmt.c +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -159,15 +159,17 @@ static int dh_has(void *keydata, int selection) DH *dh = keydata; int ok = 0; - 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); + if (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); + } return ok; } diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c index a4821f94c3..a8ef074153 100644 --- a/providers/implementations/keymgmt/dsa_kmgmt.c +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -164,15 +164,17 @@ static int dsa_has(void *keydata, int selection) DSA *dsa = keydata; int ok = 0; - 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); + if (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); + } return ok; } diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 47872553b3..4f8f44d527 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -432,21 +432,22 @@ int ec_has(void *keydata, int selection) EC_KEY *ec = keydata; int ok = 0; - 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. - */ - + if (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. + */ + } return ok; } diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index 6450fbb22e..121980e277 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -56,17 +56,18 @@ static void *ed448_new_key(void *provctx) static int ecx_has(void *keydata, int selection) { ECX_KEY *key = keydata; - int ok = 1; + int ok = 0; - if ((selection & ECX_POSSIBLE_SELECTIONS) == 0) - return 0; - - if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) - ok = ok && key->haspubkey; + if (key != NULL) { + if ((selection & ECX_POSSIBLE_SELECTIONS) != 0) + ok = 1; - if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) - ok = ok && key->privkey != NULL; + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = ok && key->haspubkey; + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ok = ok && key->privkey != NULL; + } return ok; } diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index 4e77f5c4a7..2826d337b4 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -198,14 +198,19 @@ static int rsa_has(void *keydata, int selection) RSA *rsa = keydata; int ok = 0; - if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) - ok = 1; - - 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 (rsa != NULL) { + if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) + ok = 1; + + if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) + ok = ok && 0; /* This will change with PSS and OAEP */ + 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; }