Cumulative patch from commit 681278246232029c334117bd6dc7e74c6b179f96
6812782 hlr_auc_gw: Allow Milenage RES length to be reduced
4839f7c wpa_cli: Fix a typo in usage text
a20a361 wpa_supplicant: Clear blacklist on connect
0144ecb Android: wpa_ctrl missing include for sys/stat.h
0bb20ef HS 2.0R2: Allow user to specify spp.xsd file location
97c9991 HS 2.0R2: Add more debugging messages to hs20-osu-client
93c2e60 HS 2.0R2 CA: Improve setup.sh and .conf for more flexibility
02e122a Reschedule scan from wpas_stop_pno if it was postponed
80fd9c3 EAP-PEAP server: Add support for negotiating vendor for Phase 2
a867082 EAP peer: Use 32-bit EAP method type for Phase 2 processing
56dfc49 Fix a typo in configuration parameter documentation
c4b45c6 TLS: Fix memory leaks on tls_connection_set_params() error paths
af85191 Make tls_connection_get_keyblock_size() internal to tls_*.c
94f1fe6 Remove master key extraction from tls_connection_get_keys()
fa0e715 Use tls_connection_prf() for all EAP TLS-based key derivation
df8191d Rename HT 20/40 coex variable to be more descriptive
1d0f42a EAP server: Add debug prints to help asleap testing
2c1cf90 Add wpa_snprintf_hex_sep()
5955cfa ms_funcs: Make challenge_hash() non-static
Change-Id: I0f3e5e5170a61e458949a675641946d95598dc5d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 52db8fc..935add5 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -26,6 +26,7 @@
#include "common.h"
#include "crypto.h"
+#include "sha1.h"
#include "tls.h"
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
@@ -2632,8 +2633,6 @@
return -1;
os_memset(keys, 0, sizeof(*keys));
- keys->master_key = ssl->session->master_key;
- keys->master_key_len = ssl->session->master_key_length;
keys->client_random = ssl->s3->client_random;
keys->client_random_len = SSL3_RANDOM_SIZE;
keys->server_random = ssl->s3->server_random;
@@ -2644,16 +2643,122 @@
}
+static int openssl_get_keyblock_size(SSL *ssl)
+{
+ const EVP_CIPHER *c;
+ const EVP_MD *h;
+ int md_size;
+
+ if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
+ ssl->read_hash == NULL)
+ return -1;
+
+ c = ssl->enc_read_ctx->cipher;
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ h = EVP_MD_CTX_md(ssl->read_hash);
+#else
+ h = conn->ssl->read_hash;
+#endif
+ if (h)
+ md_size = EVP_MD_size(h);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ else if (ssl->s3)
+ md_size = ssl->s3->tmp.new_mac_secret_size;
+#endif
+ else
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
+ "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
+ EVP_CIPHER_iv_length(c));
+ return 2 * (EVP_CIPHER_key_length(c) +
+ md_size +
+ EVP_CIPHER_iv_length(c));
+}
+
+
+static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
+{
+#ifdef CONFIG_FIPS
+ wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
+ "mode");
+ return -1;
+#else /* CONFIG_FIPS */
+ SSL *ssl;
+ u8 *rnd;
+ int ret = -1;
+ int skip = 0;
+ u8 *tmp_out = NULL;
+ u8 *_out = out;
+
+ /*
+ * TLS library did not support key generation, so get the needed TLS
+ * session parameters and use an internal implementation of TLS PRF to
+ * derive the key.
+ */
+
+ if (conn == NULL)
+ return -1;
+ ssl = conn->ssl;
+ if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
+ ssl->s3->client_random == NULL || ssl->s3->server_random == NULL ||
+ ssl->session->master_key == NULL)
+ return -1;
+
+ if (skip_keyblock) {
+ skip = openssl_get_keyblock_size(ssl);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
+ }
+
+ rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
+ if (rnd == NULL)
+ return -1;
+ if (server_random_first) {
+ os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE);
+ } else {
+ os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE);
+ }
+
+ /* TODO: TLSv1.2 may need another PRF. This could use something closer
+ * to SSL_export_keying_material() design. */
+ if (tls_prf_sha1_md5(ssl->session->master_key,
+ ssl->session->master_key_length,
+ label, rnd, 2 * SSL3_RANDOM_SIZE,
+ _out, skip + out_len) == 0)
+ ret = 0;
+ os_free(rnd);
+ if (ret == 0 && skip_keyblock)
+ os_memcpy(out, _out + skip, out_len);
+ bin_clear_free(tmp_out, skip);
+
+ return ret;
+#endif /* CONFIG_FIPS */
+}
+
+
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
SSL *ssl;
if (conn == NULL)
return -1;
- if (server_random_first)
- return -1;
+ if (server_random_first || skip_keyblock)
+ return openssl_tls_prf(tls_ctx, conn, label,
+ server_random_first, skip_keyblock,
+ out, out_len);
ssl = conn->ssl;
if (SSL_export_keying_material(ssl, out, out_len, label,
os_strlen(label), NULL, 0, 0) == 1) {
@@ -2661,7 +2766,8 @@
return 0;
}
#endif
- return -1;
+ return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
+ skip_keyblock, out, out_len);
}
@@ -3514,43 +3620,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- const EVP_CIPHER *c;
- const EVP_MD *h;
- int md_size;
-
- if (conn == NULL || conn->ssl == NULL ||
- conn->ssl->enc_read_ctx == NULL ||
- conn->ssl->enc_read_ctx->cipher == NULL ||
- conn->ssl->read_hash == NULL)
- return -1;
-
- c = conn->ssl->enc_read_ctx->cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
- h = EVP_MD_CTX_md(conn->ssl->read_hash);
-#else
- h = conn->ssl->read_hash;
-#endif
- if (h)
- md_size = EVP_MD_size(h);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- else if (conn->ssl->s3)
- md_size = conn->ssl->s3->tmp.new_mac_secret_size;
-#endif
- else
- return -1;
-
- wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
- "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
- EVP_CIPHER_iv_length(c));
- return 2 * (EVP_CIPHER_key_length(c) +
- md_size +
- EVP_CIPHER_iv_length(c));
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;