]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Use tls_connection_prf() for all EAP TLS-based key derivation
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 31 Mar 2015 12:47:32 +0000 (15:47 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 31 Mar 2015 12:47:32 +0000 (15:47 +0300)
tls_openssl.c is the only remaining TLS/crypto wrapper that needs the
internal PRF implementation for EAP-FAST (since
SSL_export_keying_material() is not available in older versions and does
not support server-random-before-client case). As such, it is cleaner to
assume that TLS libraries support tls_connection_prf() and move the
additional support code for the otherwise unsupported cases into
tls_openssl.c.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/crypto/tls_openssl.c
src/eap_common/eap_fast_common.c
src/eap_peer/eap_tls_common.c
src/eap_server/eap_server_tls_common.c

index 52db8fc076ac988da1968bb9ad1a28fde5ffed27..8f9bea6a1af509a1982a568af12ba44907dcde49 100644 (file)
@@ -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)
@@ -2644,6 +2645,60 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
 }
 
 
+static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
+                          const char *label, int server_random_first,
+                          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;
+
+       /*
+        * 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;
+
+       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, out_len) == 0)
+               ret = 0;
+       os_free(rnd);
+
+       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)
@@ -2653,7 +2708,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
        if (conn == NULL)
                return -1;
        if (server_random_first)
-               return -1;
+               return openssl_tls_prf(tls_ctx, conn, label,
+                                      server_random_first, 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 +2717,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
                return 0;
        }
 #endif
-       return -1;
+       return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
+                              out, out_len);
 }
 
 
index fceb1b0adc1c22ec6eced6b8ee06ae09a60ea8a1..5b4118935bdcd197c7b861edd29a722b2f623c13 100644 (file)
@@ -96,8 +96,7 @@ void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
 u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
                         const char *label, size_t len)
 {
-       struct tls_keys keys;
-       u8 *rnd = NULL, *out;
+       u8 *out;
        int block_size;
 
        block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
@@ -108,37 +107,15 @@ u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
        if (out == NULL)
                return NULL;
 
-       if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
-           == 0) {
-               os_memmove(out, out + block_size, len);
-               return out;
+       if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len))
+       {
+               os_free(out);
+               return NULL;
        }
 
-       if (tls_connection_get_keys(ssl_ctx, conn, &keys))
-               goto fail;
-
-       rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-       if (rnd == NULL)
-               goto fail;
-
-       os_memcpy(rnd, keys.server_random, keys.server_random_len);
-       os_memcpy(rnd + keys.server_random_len, keys.client_random,
-                 keys.client_random_len);
-
-       wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
-                       "expansion", keys.master_key, keys.master_key_len);
-       if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
-                            label, rnd, keys.client_random_len +
-                            keys.server_random_len, out, block_size + len))
-               goto fail;
-       os_free(rnd);
        os_memmove(out, out + block_size, len);
+       os_memset(out + len, 0, block_size);
        return out;
-
-fail:
-       os_free(rnd);
-       os_free(out);
-       return NULL;
 }
 
 
index 8710781618effb7cf655047a3ccb2fddf9dc8c69..e5a6ee5e4ed2894f6cf3dc2f6f2e4e3d74aff468 100644 (file)
@@ -313,53 +313,18 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
                             const char *label, size_t len)
 {
-#ifndef CONFIG_FIPS
-       struct tls_keys keys;
-#endif /* CONFIG_FIPS */
-       u8 *rnd = NULL, *out;
+       u8 *out;
 
        out = os_malloc(len);
        if (out == NULL)
                return NULL;
 
-       /* First, try to use TLS library function for PRF, if available. */
-       if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
-           == 0)
-               return out;
-
-#ifndef CONFIG_FIPS
-       /*
-        * 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 (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
-               goto fail;
-
-       if (keys.client_random == NULL || keys.server_random == NULL ||
-           keys.master_key == NULL)
-               goto fail;
-
-       rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-       if (rnd == NULL)
-               goto fail;
-       os_memcpy(rnd, keys.client_random, keys.client_random_len);
-       os_memcpy(rnd + keys.client_random_len, keys.server_random,
-                 keys.server_random_len);
-
-       if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
-                            label, rnd, keys.client_random_len +
-                            keys.server_random_len, out, len))
-               goto fail;
+       if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)) {
+               os_free(out);
+               return NULL;
+       }
 
-       os_free(rnd);
        return out;
-
-fail:
-#endif /* CONFIG_FIPS */
-       os_free(out);
-       os_free(rnd);
-       return NULL;
 }
 
 
index 56916c45ac69a000749564b258266d9eddbc5a7f..09f2a82d01e3cf8d755d8be5b6211469fc26235b 100644 (file)
@@ -100,43 +100,18 @@ void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
                               char *label, size_t len)
 {
-       struct tls_keys keys;
-       u8 *rnd = NULL, *out;
+       u8 *out;
 
        out = os_malloc(len);
        if (out == NULL)
                return NULL;
 
-       if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
-           0)
-               return out;
-
-       if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
-               goto fail;
-
-       if (keys.client_random == NULL || keys.server_random == NULL ||
-           keys.master_key == NULL)
-               goto fail;
-
-       rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-       if (rnd == NULL)
-               goto fail;
-       os_memcpy(rnd, keys.client_random, keys.client_random_len);
-       os_memcpy(rnd + keys.client_random_len, keys.server_random,
-                 keys.server_random_len);
-
-       if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
-                            label, rnd, keys.client_random_len +
-                            keys.server_random_len, out, len))
-               goto fail;
+       if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len)) {
+               os_free(out);
+               return NULL;
+       }
 
-       os_free(rnd);
        return out;
-
-fail:
-       os_free(out);
-       os_free(rnd);
-       return NULL;
 }