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
|
#ifdef PKCS12_FUNCS
|
||||||
static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
|
static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
|
||||||
const char *passwd)
|
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
|
if (!password)
|
||||||
#ifndef LIBRESSL_VERSION_NUMBER
|
return 0;
|
||||||
#ifndef OPENSSL_IS_BORINGSSL
|
os_strlcpy(buf, (const char *) password, size);
|
||||||
if (ssl) {
|
return os_strlen(buf);
|
||||||
SSL_set_default_passwd_cb(ssl, NULL);
|
}
|
||||||
SSL_set_default_passwd_cb_userdata(ssl, NULL);
|
#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 */
|
if (ssl)
|
||||||
#endif /* >= 1.1.0f */
|
ret = SSL_use_PrivateKey(ssl, pkey);
|
||||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
|
else
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL);
|
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,
|
const u8 *private_key_blob,
|
||||||
size_t private_key_blob_len)
|
size_t private_key_blob_len)
|
||||||
{
|
{
|
||||||
SSL_CTX *ssl_ctx = data->ssl;
|
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
if (private_key == NULL && private_key_blob == NULL)
|
if (private_key == NULL && private_key_blob == NULL)
|
||||||
return 0;
|
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;
|
ok = 0;
|
||||||
while (private_key_blob) {
|
while (private_key_blob) {
|
||||||
if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
|
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) {
|
while (!ok && private_key) {
|
||||||
#ifndef OPENSSL_NO_STDIO
|
if (tls_use_private_key_file(data, conn->ssl, private_key,
|
||||||
if (SSL_use_PrivateKey_file(conn->ssl, private_key,
|
private_key_passwd) == 0) {
|
||||||
SSL_FILETYPE_ASN1) == 1) {
|
|
||||||
wpa_printf(MSG_DEBUG, "OpenSSL: "
|
|
||||||
"SSL_use_PrivateKey_File (DER) --> OK");
|
|
||||||
ok = 1;
|
ok = 1;
|
||||||
break;
|
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,
|
if (tls_read_pkcs12(data, conn->ssl, private_key,
|
||||||
private_key_passwd) == 0) {
|
private_key_passwd) == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
|
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) {
|
if (!ok) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Failed to load private key");
|
"Failed to load private key");
|
||||||
tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
tls_clear_default_passwd_cb(ssl_ctx, conn->ssl);
|
|
||||||
|
|
||||||
if (!SSL_check_private_key(conn->ssl)) {
|
if (!SSL_check_private_key(conn->ssl)) {
|
||||||
tls_show_errors(MSG_INFO, __func__, "Private key failed "
|
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)
|
if (private_key == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
|
if (tls_use_private_key_file(data, NULL, private_key,
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx,
|
private_key_passwd) &&
|
||||||
(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 */
|
|
||||||
tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
|
tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
|
||||||
tls_show_errors(MSG_INFO, __func__,
|
tls_show_errors(MSG_INFO, __func__,
|
||||||
"Failed to load private key");
|
"Failed to load private key");
|
||||||
tls_clear_default_passwd_cb(ssl_ctx, NULL);
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tls_clear_default_passwd_cb(ssl_ctx, NULL);
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
if (!SSL_CTX_check_private_key(ssl_ctx)) {
|
if (!SSL_CTX_check_private_key(ssl_ctx)) {
|
||||||
|
|
Loading…
Reference in a new issue