]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Fix highest TLS version disabling with internal TLS client
authorJouni Malinen <j@w1.fi>
Sun, 14 Mar 2021 10:48:19 +0000 (12:48 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 14 Mar 2021 11:08:04 +0000 (13:08 +0200)
The highest supported TLS version for pre_master_secret needs to be
limited based on the local configuration for the case where the highest
version number is being explicitly disabled. Without this, the server
would likely detect a downgrade attack.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/tls/tlsv1_client.c
src/tls/tlsv1_client_i.h
src/tls/tlsv1_client_write.c

index a147a54a3d10622dfad1dafadaf6f173b0f4d862..486da16fd3c9556e30709984f4053e81e7001a4b 100644 (file)
@@ -38,9 +38,33 @@ void tlsv1_client_free_dh(struct tlsv1_client *conn)
 }
 
 
-int tls_derive_pre_master_secret(u8 *pre_master_secret)
+u16 tls_client_highest_ver(struct tlsv1_client *conn)
 {
-       WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
+       u16 tls_version = TLS_VERSION;
+
+       /* Pick the highest locally enabled TLS version */
+#ifdef CONFIG_TLSV12
+       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
+           tls_version == TLS_VERSION_1_2)
+               tls_version = TLS_VERSION_1_1;
+#endif /* CONFIG_TLSV12 */
+#ifdef CONFIG_TLSV11
+       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
+           tls_version == TLS_VERSION_1_1)
+               tls_version = TLS_VERSION_1;
+#endif /* CONFIG_TLSV11 */
+       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
+           tls_version == TLS_VERSION_1)
+               return 0;
+
+       return tls_version;
+}
+
+
+int tls_derive_pre_master_secret(struct tlsv1_client *conn,
+                                u8 *pre_master_secret)
+{
+       WPA_PUT_BE16(pre_master_secret, tls_client_highest_ver(conn));
        if (os_get_random(pre_master_secret + 2,
                          TLS_PRE_MASTER_SECRET_LEN - 2))
                return -1;
@@ -844,6 +868,7 @@ int tlsv1_client_set_cred(struct tlsv1_client *conn,
 void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
 {
        conn->flags = flags;
+       conn->rl.tls_version = tls_client_highest_ver(conn);
 }
 
 
index 12ec8df6c3ac1f02b1bb7de5f01abe5e6f03c57f..ccb2e1580849545bd9a0e170cf952619cfc6a1d2 100644 (file)
@@ -78,7 +78,9 @@ struct tlsv1_client {
 
 void tls_alert(struct tlsv1_client *conn, u8 level, u8 description);
 void tlsv1_client_free_dh(struct tlsv1_client *conn);
-int tls_derive_pre_master_secret(u8 *pre_master_secret);
+u16 tls_client_highest_ver(struct tlsv1_client *conn);
+int tls_derive_pre_master_secret(struct tlsv1_client *conn,
+                                u8 *pre_master_secret);
 int tls_derive_keys(struct tlsv1_client *conn,
                    const u8 *pre_master_secret, size_t pre_master_secret_len);
 u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len);
index 4a1147b69e7616a3e0431a662b65bf55c42df153..9b12618aaf06cd01ad12e93c1eec9abec255cc27 100644 (file)
@@ -48,21 +48,9 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
        struct os_time now;
        size_t len, i;
        u8 *ext_start;
-       u16 tls_version = TLS_VERSION;
+       u16 tls_version = tls_client_highest_ver(conn);
 
-       /* Pick the highest locally enabled TLS version */
-#ifdef CONFIG_TLSV12
-       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
-           tls_version == TLS_VERSION_1_2)
-               tls_version = TLS_VERSION_1_1;
-#endif /* CONFIG_TLSV12 */
-#ifdef CONFIG_TLSV11
-       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
-           tls_version == TLS_VERSION_1_1)
-               tls_version = TLS_VERSION_1;
-#endif /* CONFIG_TLSV11 */
-       if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
-           tls_version == TLS_VERSION_1) {
+       if (!tls_version) {
                wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
                return NULL;
        }
@@ -474,7 +462,7 @@ static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end)
        size_t clen;
        int res;
 
-       if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
+       if (tls_derive_pre_master_secret(conn, pre_master_secret) < 0 ||
            tls_derive_keys(conn, pre_master_secret,
                            TLS_PRE_MASTER_SECRET_LEN)) {
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");