OpenSSL: Avoid SSL*_use_default_passwd_cb()
These functions are a bit awkward to use for one-off file loads, as suggested by the tls_clear_default_passwd_cb() logic. There was also some historical mess with OpenSSL versions and either not having per-SSL settings, having per-SSL settings but ignoring them, and requiring the per-SSL settings. Instead, loading the key with the lower-level functions seems a bit tidier and also allows abstracting away trying both formats, one after another. Signed-off-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
149143e31d
commit
63942cf0f3
1 changed files with 57 additions and 72 deletions
|
@ -2686,16 +2686,6 @@ static int tls_global_client_cert(struct tls_data *data,
|
|||
}
|
||||
|
||||
|
||||
static int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
|
||||
{
|
||||
if (password == NULL) {
|
||||
return 0;
|
||||
}
|
||||
os_strlcpy(buf, (char *) password, size);
|
||||
return os_strlen(buf);
|
||||
}
|
||||
|
||||
|
||||
#ifdef PKCS12_FUNCS
|
||||
static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
|
||||
const char *passwd)
|
||||
|
@ -3014,20 +3004,61 @@ static int tls_connection_engine_private_key(struct tls_connection *conn)
|
|||
}
|
||||
|
||||
|
||||
static void tls_clear_default_passwd_cb(SSL_CTX *ssl_ctx, SSL *ssl)
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
static int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
#ifndef LIBRESSL_VERSION_NUMBER
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
if (ssl) {
|
||||
SSL_set_default_passwd_cb(ssl, NULL);
|
||||
SSL_set_default_passwd_cb_userdata(ssl, NULL);
|
||||
if (!password)
|
||||
return 0;
|
||||
os_strlcpy(buf, (const char *) password, size);
|
||||
return os_strlen(buf);
|
||||
}
|
||||
#endif /* OPENSSL_NO_STDIO */
|
||||
|
||||
|
||||
static int tls_use_private_key_file(struct tls_data *data, SSL *ssl,
|
||||
const char *private_key,
|
||||
const char *private_key_passwd)
|
||||
{
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
BIO *bio;
|
||||
EVP_PKEY *pkey;
|
||||
int ret;
|
||||
|
||||
/* First try ASN.1 (DER). */
|
||||
bio = BIO_new_file(private_key, "r");
|
||||
if (!bio)
|
||||
return -1;
|
||||
pkey = d2i_PrivateKey_bio(bio, NULL);
|
||||
BIO_free(bio);
|
||||
|
||||
if (pkey) {
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: %s (DER) --> loaded", __func__);
|
||||
} else {
|
||||
/* Try PEM with the provided password. */
|
||||
bio = BIO_new_file(private_key, "r");
|
||||
if (!bio)
|
||||
return -1;
|
||||
pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_passwd_cb,
|
||||
(void *) private_key_passwd);
|
||||
BIO_free(bio);
|
||||
if (!pkey)
|
||||
return -1;
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: %s (PEM) --> loaded", __func__);
|
||||
/* Clear errors from the previous failed load. */
|
||||
ERR_clear_error();
|
||||
}
|
||||
#endif /* !BoringSSL */
|
||||
#endif /* !LibreSSL */
|
||||
#endif /* >= 1.1.0f */
|
||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
|
||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL);
|
||||
|
||||
if (ssl)
|
||||
ret = SSL_use_PrivateKey(ssl, pkey);
|
||||
else
|
||||
ret = SSL_CTX_use_PrivateKey(data->ssl, pkey);
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret == 1 ? 0 : -1;
|
||||
#else /* OPENSSL_NO_STDIO */
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
|
||||
return -1;
|
||||
#endif /* OPENSSL_NO_STDIO */
|
||||
}
|
||||
|
||||
|
||||
|
@ -3038,30 +3069,11 @@ static int tls_connection_private_key(struct tls_data *data,
|
|||
const u8 *private_key_blob,
|
||||
size_t private_key_blob_len)
|
||||
{
|
||||
SSL_CTX *ssl_ctx = data->ssl;
|
||||
int ok;
|
||||
|
||||
if (private_key == NULL && private_key_blob == NULL)
|
||||
return 0;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
#ifndef LIBRESSL_VERSION_NUMBER
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
/*
|
||||
* In OpenSSL >= 1.1.0f SSL_use_PrivateKey_file() uses the callback
|
||||
* from the SSL object. See OpenSSL commit d61461a75253.
|
||||
*/
|
||||
SSL_set_default_passwd_cb(conn->ssl, tls_passwd_cb);
|
||||
SSL_set_default_passwd_cb_userdata(conn->ssl,
|
||||
(void *) private_key_passwd);
|
||||
#endif /* !BoringSSL */
|
||||
#endif /* !LibreSSL */
|
||||
#endif /* >= 1.1.0f && */
|
||||
/* Keep these for OpenSSL < 1.1.0f */
|
||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
|
||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx,
|
||||
(void *) private_key_passwd);
|
||||
|
||||
ok = 0;
|
||||
while (private_key_blob) {
|
||||
if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
|
||||
|
@ -3104,27 +3116,12 @@ static int tls_connection_private_key(struct tls_data *data,
|
|||
}
|
||||
|
||||
while (!ok && private_key) {
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
|
||||
SSL_FILETYPE_ASN1) == 1) {
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: "
|
||||
"SSL_use_PrivateKey_File (DER) --> OK");
|
||||
if (tls_use_private_key_file(data, conn->ssl, private_key,
|
||||
private_key_passwd) == 0) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
|
||||
SSL_FILETYPE_PEM) == 1) {
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: "
|
||||
"SSL_use_PrivateKey_File (PEM) --> OK");
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
#else /* OPENSSL_NO_STDIO */
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
|
||||
__func__);
|
||||
#endif /* OPENSSL_NO_STDIO */
|
||||
|
||||
if (tls_read_pkcs12(data, conn->ssl, private_key,
|
||||
private_key_passwd) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
|
||||
|
@ -3146,11 +3143,9 @@ static int tls_connection_private_key(struct tls_data *data,
|
|||
if (!ok) {
|
||||
tls_show_errors(MSG_INFO, __func__,
|
||||
"Failed to load private key");
|
||||
tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
|
||||
return -1;
|
||||
}
|
||||
ERR_clear_error();
|
||||
tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
|
||||
|
||||
if (!SSL_check_private_key(conn->ssl)) {
|
||||
tls_show_errors(MSG_INFO, __func__, "Private key failed "
|
||||
|
@ -3172,24 +3167,14 @@ static int tls_global_private_key(struct tls_data *data,
|
|||
if (private_key == NULL)
|
||||
return 0;
|
||||
|
||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
|
||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx,
|
||||
(void *) private_key_passwd);
|
||||
if (
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
|
||||
SSL_FILETYPE_ASN1) != 1 &&
|
||||
SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
|
||||
SSL_FILETYPE_PEM) != 1 &&
|
||||
#endif /* OPENSSL_NO_STDIO */
|
||||
if (tls_use_private_key_file(data, NULL, private_key,
|
||||
private_key_passwd) &&
|
||||
tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
|
||||
tls_show_errors(MSG_INFO, __func__,
|
||||
"Failed to load private key");
|
||||
tls_clear_default_passwd_cb(ssl_ctx, NULL);
|
||||
ERR_clear_error();
|
||||
return -1;
|
||||
}
|
||||
tls_clear_default_passwd_cb(ssl_ctx, NULL);
|
||||
ERR_clear_error();
|
||||
|
||||
if (!SSL_CTX_check_private_key(ssl_ctx)) {
|
||||
|
|
Loading…
Reference in a new issue