]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
GnuTLS: Suite B validation
authorJouni Malinen <j@w1.fi>
Thu, 28 Dec 2017 16:46:28 +0000 (18:46 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 28 Dec 2017 20:33:12 +0000 (22:33 +0200)
This allows OpenSSL-style configuration of Suite B parameters to be used
in the wpa_supplicant network profile. 128-bit and 192-bit level
requirements for ECDHE-ECDSA cases are supported. RSA >=3K case is
enforced using GnuTLS %PROFILE_HIGH special priority string keyword.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/crypto/tls_gnutls.c

index c223eafa336ebb3e711e71733a2c70b8c01da599..7ee3fa3a00a0a786e556c75c95d8030890ed0915 100644 (file)
@@ -346,6 +346,9 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
                              const struct tls_connection_params *params)
 {
        int ret;
+       const char *err;
+       char prio_buf[100];
+       const char *prio = NULL;
 
        if (conn == NULL || params == NULL)
                return -1;
@@ -400,16 +403,46 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
        if (params->flags & (TLS_CONN_DISABLE_TLSv1_0 |
                             TLS_CONN_DISABLE_TLSv1_1 |
                             TLS_CONN_DISABLE_TLSv1_2)) {
-               const char *err;
-               char prio[100];
-
-               os_snprintf(prio, sizeof(prio), "NORMAL:-VERS-SSL3.0%s%s%s",
+               os_snprintf(prio_buf, sizeof(prio_buf),
+                           "NORMAL:-VERS-SSL3.0%s%s%s",
                            params->flags & TLS_CONN_DISABLE_TLSv1_0 ?
                            ":-VERS-TLS1.0" : "",
                            params->flags & TLS_CONN_DISABLE_TLSv1_1 ?
                            ":-VERS-TLS1.1" : "",
                            params->flags & TLS_CONN_DISABLE_TLSv1_2 ?
                            ":-VERS-TLS1.2" : "");
+               prio = prio_buf;
+       }
+
+       if (params->openssl_ciphers) {
+               if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
+                       prio = "SUITEB128";
+               } else if (os_strcmp(params->openssl_ciphers,
+                                    "SUITEB192") == 0) {
+                       prio = "SUITEB192";
+               } else if ((params->flags & TLS_CONN_SUITEB) &&
+                          os_strcmp(params->openssl_ciphers,
+                                    "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
+                       prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
+               } else if (os_strcmp(params->openssl_ciphers,
+                                    "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
+                       prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
+               } else if (os_strcmp(params->openssl_ciphers,
+                                    "DHE-RSA-AES256-GCM-SHA384") == 0) {
+                       prio = "NONE:+VERS-TLS1.2:+AEAD:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
+               } else if (os_strcmp(params->openssl_ciphers,
+                                    "ECDHE-ECDSA-AES256-GCM-SHA384") == 0) {
+                       prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
+               } else {
+                       wpa_printf(MSG_INFO,
+                                  "GnuTLS: openssl_ciphers not supported");
+                       return -1;
+               }
+       } else if (params->flags & TLS_CONN_SUITEB) {
+               prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
+       }
+
+       if (prio) {
                wpa_printf(MSG_DEBUG, "GnuTLS: Set priority string: %s", prio);
                ret = gnutls_priority_set_direct(conn->session, prio, &err);
                if (ret < 0) {
@@ -420,11 +453,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
                }
        }
 
-       if (params->openssl_ciphers) {
-               wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
-               return -1;
-       }
-
        /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
         * to force peer validation(?) */
 
@@ -1375,6 +1403,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
        ret = gnutls_handshake(conn->session);
        if (ret < 0) {
                gnutls_alert_description_t alert;
+               union tls_event_data ev;
 
                switch (ret) {
                case GNUTLS_E_AGAIN:
@@ -1385,14 +1414,29 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
                                conn->push_buf = wpabuf_alloc(0);
                        }
                        break;
+               case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
+                       wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
+                       if (conn->global->event_cb) {
+                               os_memset(&ev, 0, sizeof(ev));
+                               ev.alert.is_local = 1;
+                               ev.alert.type = "fatal";
+                               ev.alert.description = "insufficient security";
+                               conn->global->event_cb(conn->global->cb_ctx,
+                                                      TLS_ALERT, &ev);
+                       }
+                       /*
+                        * Could send a TLS Alert to the server, but for now,
+                        * simply terminate handshake.
+                        */
+                       conn->failed++;
+                       conn->write_alerts++;
+                       break;
                case GNUTLS_E_FATAL_ALERT_RECEIVED:
                        alert = gnutls_alert_get(conn->session);
                        wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
                                   __func__, gnutls_alert_get_name(alert));
                        conn->read_alerts++;
                        if (conn->global->event_cb != NULL) {
-                               union tls_event_data ev;
-
                                os_memset(&ev, 0, sizeof(ev));
                                ev.alert.is_local = 0;
                                ev.alert.type = gnutls_alert_get_name(alert);