diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 213e2162f6..f292dcadd9 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1135,15 +1135,14 @@ int EVP_PKEY_can_sign(const EVP_PKEY *pkey) } else { const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt); OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); - const char *supported_sig = - pkey->keymgmt->query_operation_name != NULL - ? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE) - : EVP_KEYMGMT_get0_name(pkey->keymgmt); - EVP_SIGNATURE *signature = NULL; + EVP_SIGNATURE *sig; + const char *name; - signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL); - if (signature != NULL) { - EVP_SIGNATURE_free(signature); + name = evp_keymgmt_util_query_operation_name(pkey->keymgmt, + OSSL_OP_SIGNATURE); + sig = EVP_SIGNATURE_fetch(libctx, name, NULL); + if (sig != NULL) { + EVP_SIGNATURE_free(sig); return 1; } } diff --git a/test/fake_rsaprov.c b/test/fake_rsaprov.c index 9948c381e8..26b56831f6 100644 --- a/test/fake_rsaprov.c +++ b/test/fake_rsaprov.c @@ -35,6 +35,8 @@ static int exptypes_selection; static int query_id; static int key_deleted; +unsigned fake_rsa_query_operation_name = 0; + typedef struct { OSSL_LIB_CTX *libctx; } PROV_FAKE_RSA_CTX; @@ -90,7 +92,7 @@ static const char *fake_rsa_keymgmt_query(int id) /* record global for checking */ query_id = id; - return "RSA"; + return fake_rsa_query_operation_name ? NULL: "RSA"; } static int fake_rsa_keymgmt_import(void *keydata, int selection, diff --git a/test/fake_rsaprov.h b/test/fake_rsaprov.h index cb2e66eb68..b2bc5d9ab5 100644 --- a/test/fake_rsaprov.h +++ b/test/fake_rsaprov.h @@ -14,5 +14,14 @@ /* Fake RSA provider implementation */ OSSL_PROVIDER *fake_rsa_start(OSSL_LIB_CTX *libctx); void fake_rsa_finish(OSSL_PROVIDER *p); + OSSL_PARAM *fake_rsa_key_params(int priv); void fake_rsa_restore_store_state(void); + +/* + * When fake_rsa_query_operation_name is set to a non-zero value, + * query_operation_name() will return NULL. + * + * By default, it is 0, in which case query_operation_name() will return "RSA". + */ +extern unsigned fake_rsa_query_operation_name; diff --git a/test/provider_pkey_test.c b/test/provider_pkey_test.c index 128f2138ff..77c165e590 100644 --- a/test/provider_pkey_test.c +++ b/test/provider_pkey_test.c @@ -239,6 +239,77 @@ end: return ret; } +static int test_pkey_can_sign(void) +{ + OSSL_PROVIDER *fake_rsa = NULL; + EVP_PKEY *pkey_fake = NULL; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM *params = NULL; + int ret = 0; + + if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx))) + return 0; + + /* + * Ensure other tests did not forget to reset fake_rsa_query_operation_name + * to its default value: 0 + */ + if (!TEST_int_eq(fake_rsa_query_operation_name, 0)) + goto end; + + if (!TEST_ptr(params = fake_rsa_key_params(0)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", + "provider=fake-rsa")) + || !TEST_true(EVP_PKEY_fromdata_init(ctx)) + || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY, + params)) + || !TEST_true(EVP_PKEY_can_sign(pkey_fake)) + || !TEST_ptr(pkey_fake)) + goto end; + + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + EVP_PKEY_free(pkey_fake); + pkey_fake = NULL; + OSSL_PARAM_free(params); + params = NULL; + + /* + * Documented behavior for OSSL_FUNC_keymgmt_query_operation_name() + * allows it to return NULL, in which case the fallback should be to use + * EVP_KEYMGMT_get0_name(). That is exactly the thing we are testing here. + */ + fake_rsa_query_operation_name = 1; + + if (!TEST_ptr(params = fake_rsa_key_params(0)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", + "provider=fake-rsa")) + || !TEST_true(EVP_PKEY_fromdata_init(ctx)) + || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY, + params)) + || !TEST_true(EVP_PKEY_can_sign(pkey_fake)) + || !TEST_ptr(pkey_fake)) + goto end; + + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + EVP_PKEY_free(pkey_fake); + pkey_fake = NULL; + OSSL_PARAM_free(params); + params = NULL; + + ret = 1; +end: + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey_fake); + OSSL_PARAM_free(params); + fake_rsa_query_operation_name = 0; + + fake_rsa_finish(fake_rsa); + return ret; +} + static int test_pkey_store(int idx) { OSSL_PROVIDER *deflt = NULL; @@ -719,6 +790,7 @@ int setup_tests(void) ADD_TEST(test_pkey_sig); ADD_TEST(test_alternative_keygen_init); ADD_TEST(test_pkey_eq); + ADD_TEST(test_pkey_can_sign); ADD_ALL_TESTS(test_pkey_store, 2); ADD_TEST(test_pkey_delete); ADD_TEST(test_pkey_store_open_ex);