BUG/MINOR: ssl: Encrypted keys could not be loaded when given alongside certificate

The SSL passphrase callback function was only called when loading
private keys from a dedicated file (separate from the corresponding
certificate) but not when both the certificate and the key were in the
same file.
We can now load them properly, regardless of how they are provided.
A flas had to be added in the 'passphrase_cb_data' structure because in
the 'ssl_sock_load_pem_into_ckch' function, when calling
'PEM_read_bio_PrivateKey' there might be no private key in the PEM file
which would mean that the callback never gets called (and cannot set the
'passphrase_idx' to -1).

This patch can be backported to 3.3.
This commit is contained in:
Remi Tricot-Le Breton 2026-01-26 11:54:45 +01:00 committed by William Lallemand
parent d2ccc19fde
commit 9b1faee4c9
3 changed files with 18 additions and 4 deletions

View file

@ -361,6 +361,7 @@ struct passphrase_cb_data {
const char *path;
struct ckch_data *ckch_data;
int passphrase_idx;
int callback_called;
};
#endif /* USE_OPENSSL */

View file

@ -593,7 +593,7 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d
BIO *in = NULL;
int ret = 1;
EVP_PKEY *key = NULL;
struct passphrase_cb_data cb_data = { path, data, 0 };
struct passphrase_cb_data cb_data = { path, data, 0, 0 };
if (buf) {
/* reading from a buffer */
@ -625,7 +625,7 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d
*/
do {
key = PEM_read_bio_PrivateKey(in, NULL, ssl_sock_passwd_cb, &cb_data);
} while (!key && cb_data.passphrase_idx != -1);
} while (!key && cb_data.passphrase_idx != -1 && cb_data.callback_called);
if (key == NULL) {
memprintf(err, "%sunable to load private key from file '%s'.\n",
@ -667,6 +667,7 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
HASSL_DH *dh = NULL;
STACK_OF(X509) *chain = NULL;
struct issuer_chain *issuer_chain = NULL;
struct passphrase_cb_data cb_data = { path, data, 0, 0 };
if (buf) {
/* reading from a buffer */
@ -691,8 +692,18 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
}
}
/* Read Private Key */
key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
/* Read Private Key
* Since multiple private keys might have different passphrases that are
* stored in a local cache, we want to try all the already known
* passphrases first before raising an error. The passphrase_idx field
* of the cb_data parameter will be modified in the callback and set to
* -1 after the external passphrase tool is called.
*/
/* We don't know yet if the private key requires a password. */
data->encrypted_privkey = 0;
do {
key = PEM_read_bio_PrivateKey(in, NULL, ssl_sock_passwd_cb, &cb_data);
} while (!key && cb_data.passphrase_idx != -1 && cb_data.callback_called);
/* no need to check for errors here, because the private key could be loaded later */
#ifndef OPENSSL_NO_DH

View file

@ -3813,6 +3813,8 @@ int ssl_sock_passwd_cb(char *buf, int size, int rwflag, void *userdata)
if (!data || data->passphrase_idx == -1)
return -1;
data->callback_called = 1;
ckch_data = data->ckch_data;
if (ckch_data)