This commit is contained in:
Amananas 2026-07-30 18:18:45 +08:00 committed by GitHub
commit 6780bf3e1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -825,7 +825,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"))
@ -1077,6 +1081,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 */
@ -1088,67 +1096,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;
@ -1233,6 +1232,10 @@ static int providerload(struct Curl_easy *data,
const char *cert_file)
{
#ifdef OPENSSL_HAS_PROVIDERS
X509 *cert = NULL;
STACK_OF(X509) *cert_chain = 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 */
@ -1244,55 +1247,74 @@ 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)));
}
while(!OSSL_STORE_eof(store)) {
OSSL_STORE_INFO *info = OSSL_STORE_load(store);
/* Not really an error, keep looping */
if(!info) {
continue;
}
if(OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_CERT) {
/* Only load the first cert hit: when using a cert chain,
first one should be the right one.*/
if(!cert) {
cert = OSSL_STORE_INFO_get1_CERT(info);
}
/* Load all certs found in the chain. */
if(!cert_chain) {
cert_chain = sk_X509_new_null();
}
X509_add_cert(cert_chain, OSSL_STORE_INFO_get1_CERT(info),
X509_ADD_FLAG_DEFAULT);
}
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)));
sk_X509_pop_free(cert_chain, X509_free);
return 0;
}
rc = (int) SSL_CTX_set1_chain(ctx, cert_chain);
sk_X509_pop_free(cert_chain, X509_free);
if(rc != 1) {
failf(data, "unable to set client certificate chain [%s]",
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)));
return 0;
}
return 1;