From 81bedf428302cd9f95bd5c033a2543ecf8223045 Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Wed, 10 Apr 2024 08:50:29 +0200 Subject: [PATCH] Do not cache operations when provider status is uninitialized OpenSSL calls p11prov_query_operation() to query which operations the provider supports. With the 'no_cache' function argument, the provider can tell OpenSSL if it is OK to cache the query results or not. As soon as the PKCS#11 provider has fully initialized, it is OK to cache the operations, since they won't change during the lifetime of the provider. However, when the provider has not yet fully initialized, only the KEYMGMT, DECODER, and STORE operations are fully set up (they are static), but the other operations have not been set up, and may change when the operations are eventually initialized. Thus, these operations can not be cached as long as the provider status is still in 'uninitialized' state. Operations that the provider does not support at all can always be cached. Allowing to cache operations that have not been set up may cause various errors with applications that fetch algorithms before the PKCS#11 provider is fully initialized. Unless 'pkcs11-module-load-behavior = early' is set, the provider will only initialize the operations when a PKCS#11 operation is used the first time, i.e. when a key is generated with the provider, or a PKCS#11 key or certificate is loaded through the store or via URI-PEM. When an operation has been queried and is cached before the provider was fully initialized, then it can happen that OpenSSL remembers that the provider would not support that algorithm, and will not query the provider again. So even though that algorithm would be supported by the provider (after full initialization), OpenSSL would never query the provider again for that algorithm, but only use the cached information. This can lead to various failures of the application, e.g. after loading a PKCS#11 key via URI or URI-PEM, an operation using that key fails, because it won't find the operation with that key (e.g. SIGNATURE) being supported by the PKCS#11 provider. Signed-off-by: Ingo Franzki --- src/provider.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/provider.c b/src/provider.c index bf334e0f..d54c6dae 100644 --- a/src/provider.c +++ b/src/provider.c @@ -1158,29 +1158,39 @@ static const OSSL_ALGORITHM * p11prov_query_operation(void *provctx, int operation_id, int *no_cache) { P11PROV_CTX *ctx = (P11PROV_CTX *)provctx; - *no_cache = 0; switch (operation_id) { case OSSL_OP_DIGEST: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_digest; case OSSL_OP_KDF: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_kdf; case OSSL_OP_RAND: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_random; case OSSL_OP_KEYMGMT: + *no_cache = 0; return p11prov_keymgmt; case OSSL_OP_KEYEXCH: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_exchange; case OSSL_OP_SIGNATURE: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_signature; case OSSL_OP_ASYM_CIPHER: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_asym_cipher; case OSSL_OP_ENCODER: + *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_encoder; case OSSL_OP_DECODER: + *no_cache = 0; return p11prov_decoders; case OSSL_OP_STORE: + *no_cache = 0; return p11prov_store; } + *no_cache = 0; return NULL; }