From a27665b872ef1ec5d4ec8fe75933cf2a9215b33c Mon Sep 17 00:00:00 2001 From: Alexandre Besnard Date: Mon, 23 Mar 2026 11:10:36 +0100 Subject: [PATCH] openssl: change default file type to provider Openssl 3+ encourages using providers for all data storages. This commit sets it as the default file type when supported, when the file type is not explicitly defined (instead of PEM by default). This change also removes the explicit check on a provider being loaded, before trying to open the matching store: openssl should raise an explicit error when opening it, and an explicit check in libcurl breaks the possibility of a default provider in Openssl. This change should not have any impact on behavior, since openssl default implementation embeds a provider for PEM file types. This change full leverages the Openssl store providers: with this, the end user does not need to maintain the actual storage type in calls to libcurl, and can freely ignore storage types by changing the URI (or file path). --- lib/vtls/openssl.c | 204 ++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 105 deletions(-) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 3af360b731..fc71a630d7 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -861,7 +861,11 @@ static CURLcode ossl_seed(struct Curl_easy *data) static int ossl_do_file_type(const char *type) { if(!type || !type[0]) +#ifdef OPENSSL_HAS_PROVIDERS + return SSL_FILETYPE_PROVIDER; +#else return SSL_FILETYPE_PEM; +#endif if(curl_strequal(type, "PEM")) return SSL_FILETYPE_PEM; if(curl_strequal(type, "DER")) @@ -1113,6 +1117,10 @@ static int providercheck(struct Curl_easy *data, const char *key_file) { #ifdef OPENSSL_HAS_PROVIDERS + EVP_PKEY *priv_key = NULL; + OSSL_STORE_CTX *store = NULL; + OSSL_STORE_INFO *info = NULL; + UI_METHOD *ui_method = NULL; char error_buffer[256]; /* Implicitly use pkcs11 provider if none was provided and the * key_file is a PKCS#11 URI */ @@ -1124,67 +1132,58 @@ static int providercheck(struct Curl_easy *data, } } - if(data->state.provider_loaded) { - /* Load the private key from the provider */ - EVP_PKEY *priv_key = NULL; - OSSL_STORE_CTX *store = NULL; - OSSL_STORE_INFO *info = NULL; - UI_METHOD *ui_method = UI_create_method("curl user interface"); - if(!ui_method) { - failf(data, "unable to create " OSSL_PACKAGE " user-interface method"); - return 0; - } - UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); - UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); - UI_method_set_reader(ui_method, ssl_ui_reader); - UI_method_set_writer(ui_method, ssl_ui_writer); - - store = OSSL_STORE_open_ex(key_file, data->state.libctx, - data->state.propq, ui_method, NULL, NULL, - NULL, NULL); - if(!store) { - failf(data, "Failed to open OpenSSL store: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - UI_destroy_method(ui_method); - return 0; - } - if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) { - failf(data, "Failed to set store preference. Ignoring the error: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - } - - info = OSSL_STORE_load(store); - if(info) { - int ossl_type = OSSL_STORE_INFO_get_type(info); - - if(ossl_type == OSSL_STORE_INFO_PKEY) - priv_key = OSSL_STORE_INFO_get1_PKEY(info); - OSSL_STORE_INFO_free(info); - } - OSSL_STORE_close(store); - UI_destroy_method(ui_method); - if(!priv_key) { - failf(data, "No private key found in the openssl store: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return 0; - } - - if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { - failf(data, "unable to set private key [%s]", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - EVP_PKEY_free(priv_key); - return 0; - } - EVP_PKEY_free(priv_key); /* we do not need the handle any more... */ - } - else { - failf(data, "crypto provider not set, cannot load private key"); + /* Load the private key from the provider */ + ui_method = UI_create_method("curl user interface"); + if(!ui_method) { + failf(data, "unable to create " OSSL_PACKAGE " user-interface method"); return 0; } + UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); + UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); + UI_method_set_reader(ui_method, ssl_ui_reader); + UI_method_set_writer(ui_method, ssl_ui_writer); + + store = OSSL_STORE_open_ex(key_file, data->state.libctx, + data->state.propq, ui_method, NULL, NULL, + NULL, NULL); + if(!store) { + failf(data, "Failed to open OpenSSL store: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + UI_destroy_method(ui_method); + return 0; + } + if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) { + failf(data, "Failed to set store preference. Ignoring the error: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + } + + info = OSSL_STORE_load(store); + if(info) { + int ossl_type = OSSL_STORE_INFO_get_type(info); + + if(ossl_type == OSSL_STORE_INFO_PKEY) + priv_key = OSSL_STORE_INFO_get1_PKEY(info); + OSSL_STORE_INFO_free(info); + } + OSSL_STORE_close(store); + UI_destroy_method(ui_method); + if(!priv_key) { + failf(data, "No private key found in the openssl store: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return 0; + } + + if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { + failf(data, "unable to set private key [%s]", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + EVP_PKEY_free(priv_key); + return 0; + } + EVP_PKEY_free(priv_key); /* we do not need the handle any more... */ return 1; #else (void)ctx; @@ -1269,6 +1268,10 @@ static int providerload(struct Curl_easy *data, const char *cert_file) { #ifdef OPENSSL_HAS_PROVIDERS + OSSL_STORE_INFO *info = NULL; + X509 *cert = NULL; + OSSL_STORE_CTX *store = NULL; + int rc; char error_buffer[256]; /* Implicitly use pkcs11 provider if none was provided and the * cert_file is a PKCS#11 URI */ @@ -1280,55 +1283,46 @@ static int providerload(struct Curl_easy *data, } } - if(data->state.provider_loaded) { - /* Load the certificate from the provider */ - OSSL_STORE_INFO *info = NULL; - X509 *cert = NULL; - OSSL_STORE_CTX *store = - OSSL_STORE_open_ex(cert_file, data->state.libctx, - NULL, NULL, NULL, NULL, NULL, NULL); - int rc; + /* Load the certificate from the provider */ - if(!store) { - failf(data, "Failed to open OpenSSL store: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return 0; - } - if(OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) != 1) { - failf(data, "Failed to set store preference. Ignoring the error: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - } + store = OSSL_STORE_open_ex(cert_file, data->state.libctx, + NULL, NULL, NULL, NULL, NULL, NULL); - info = OSSL_STORE_load(store); - if(info) { - int ossl_type = OSSL_STORE_INFO_get_type(info); - - if(ossl_type == OSSL_STORE_INFO_CERT) - cert = OSSL_STORE_INFO_get1_CERT(info); - OSSL_STORE_INFO_free(info); - } - OSSL_STORE_close(store); - if(!cert) { - failf(data, "No cert found in the openssl store: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return 0; - } - - rc = SSL_CTX_use_certificate(ctx, cert); - X509_free(cert); /* we do not need the handle any more... */ - - if(rc != 1) { - failf(data, "unable to set client certificate [%s]", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); - return 0; - } + if(!store) { + failf(data, "Failed to open OpenSSL store: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return 0; } - else { - failf(data, "crypto provider not set, cannot load certificate"); + if(OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) != 1) { + failf(data, "Failed to set store preference. Ignoring the error: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + } + + info = OSSL_STORE_load(store); + if(info) { + int ossl_type = OSSL_STORE_INFO_get_type(info); + + if(ossl_type == OSSL_STORE_INFO_CERT) + cert = OSSL_STORE_INFO_get1_CERT(info); + OSSL_STORE_INFO_free(info); + } + OSSL_STORE_close(store); + if(!cert) { + failf(data, "No cert found in the openssl store: %s", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); + return 0; + } + + rc = SSL_CTX_use_certificate(ctx, cert); + X509_free(cert); /* we do not need the handle any more... */ + + if(rc != 1) { + failf(data, "unable to set client certificate [%s]", + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); return 0; } return 1;