TLS client: Add support for disabling TLS versions
authorJouni Malinen <j@w1.fi>
Sun, 29 Nov 2015 18:03:11 +0000 (20:03 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 29 Nov 2015 18:03:11 +0000 (20:03 +0200)
The internal TLS client implementation in wpa_supplicant can now be used
with the phase2 parameters tls_disable_tlsv1_0=1, tls_disable_tlsv1_1=1,
and tls_disable_tlsv1_2=1 to disable the specified TLS version(s).

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

index 217c29b..eb9f3b7 100644 (file)
@@ -27,6 +27,17 @@ static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
                                         const u8 *in_data, size_t *in_len);
 
 
+static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
+{
+       return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
+                ver == TLS_VERSION_1) ||
+               ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
+                ver == TLS_VERSION_1_1) ||
+               ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
+                ver == TLS_VERSION_1_2));
+}
+
+
 static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
                                    const u8 *in_data, size_t *in_len)
 {
@@ -76,7 +87,8 @@ static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
        if (end - pos < 2)
                goto decode_error;
        tls_version = WPA_GET_BE16(pos);
-       if (!tls_version_ok(tls_version)) {
+       if (!tls_version_ok(tls_version) ||
+           tls_version_disabled(conn, tls_version)) {
                wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
                           "ServerHello %u.%u", pos[0], pos[1]);
                tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
index 6f1e052..1c835fe 100644 (file)
@@ -48,8 +48,27 @@ 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;
 
-       wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");
+       /* 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) {
+               wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
+               return NULL;
+       }
+
+       wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)",
+                  tls_version_str(tls_version));
        *out_len = 0;
 
        os_get_time(&now);
@@ -82,7 +101,7 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
        pos += 3;
        /* body - ClientHello */
        /* ProtocolVersion client_version */
-       WPA_PUT_BE16(pos, TLS_VERSION);
+       WPA_PUT_BE16(pos, tls_version);
        pos += 2;
        /* Random random: uint32 gmt_unix_time, opaque random_bytes */
        os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);