WPS: Do not build Credential with unsupported encr combination on AP
authorJouni Malinen <j@w1.fi>
Fri, 1 Jan 2016 09:59:20 +0000 (11:59 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 1 Jan 2016 11:42:04 +0000 (13:42 +0200)
It was possible for the Registrar code to generate a Credential with
auth type WPAPSK (i.e., WPA v1) with encr type AES if the Enrollee
claimed support for WPAPSK and not WPA2PSK while the AP was configured
in mixed mode WPAPSK+WPA2PSK regardless of how wpa_pairwise (vs.
rsn_pairwise) was set since encr type was selected from the union of
wpa_pairwise and rsn_pairwise. This could result in the Enrollee
receiving a Credential that it could then not use with the AP.

Fix this by masking the encryption types separately on AP based on the
wpa_pairwise/rsn_pairwise configuration. In the example case described
above, the Credential would get auth=WPAPSK encr=TKIP instead of
auth=WPAPSK encr=AES.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/ap/wps_hostapd.c
src/wps/wps.h
src/wps/wps_registrar.c

index 66a43eb..ba58f3e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / WPS integration
- * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -445,6 +445,8 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
        os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
        hapd->wps->ssid_len = cred->ssid_len;
        hapd->wps->encr_types = cred->encr_type;
+       hapd->wps->encr_types_rsn = cred->encr_type;
+       hapd->wps->encr_types_wpa = cred->encr_type;
        hapd->wps->auth_types = cred->auth_type;
        hapd->wps->ap_encr_type = cred->encr_type;
        hapd->wps->ap_auth_type = cred->auth_type;
@@ -1068,10 +1070,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
                if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
                        wps->auth_types |= WPS_AUTH_WPA2;
 
-               if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))
+               if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) {
                        wps->encr_types |= WPS_ENCR_AES;
-               if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
+                       wps->encr_types_rsn |= WPS_ENCR_AES;
+               }
+               if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
                        wps->encr_types |= WPS_ENCR_TKIP;
+                       wps->encr_types_rsn |= WPS_ENCR_TKIP;
+               }
        }
 
        if (conf->wpa & WPA_PROTO_WPA) {
@@ -1080,10 +1086,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
                if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
                        wps->auth_types |= WPS_AUTH_WPA;
 
-               if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+               if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
                        wps->encr_types |= WPS_ENCR_AES;
-               if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+                       wps->encr_types_wpa |= WPS_ENCR_AES;
+               }
+               if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
                        wps->encr_types |= WPS_ENCR_TKIP;
+                       wps->encr_types_wpa |= WPS_ENCR_TKIP;
+               }
        }
 
        if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
@@ -1123,6 +1133,8 @@ int hostapd_init_wps(struct hostapd_data *hapd,
                /* Override parameters to enable security by default */
                wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
                wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
+               wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP;
+               wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
        }
 
        wps->ap_settings = conf->ap_settings;
index 2c91d16..ff4dd10 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup
- * Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -664,6 +664,16 @@ struct wps_context {
        u16 encr_types;
 
        /**
+        * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
+        */
+       u16 encr_types_rsn;
+
+       /**
+        * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
+        */
+       u16 encr_types_wpa;
+
+       /**
         * auth_types - Authentication types (bit field of WPS_AUTH_*)
         */
        u16 auth_types;
index 4ca3a42..22b68af 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Wi-Fi Protected Setup - Registrar
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -1606,6 +1606,9 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
        wps->cred.ssid_len = wps->wps->ssid_len;
 
        /* Select the best authentication and encryption type */
+       wpa_printf(MSG_DEBUG,
+                  "WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x",
+                  wps->wps->auth_types, wps->auth_type);
        if (wps->auth_type & WPS_AUTH_WPA2PSK)
                wps->auth_type = WPS_AUTH_WPA2PSK;
        else if (wps->auth_type & WPS_AUTH_WPAPSK)
@@ -1619,6 +1622,14 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
        }
        wps->cred.auth_type = wps->auth_type;
 
+       wpa_printf(MSG_DEBUG,
+                  "WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x",
+                  wps->wps->encr_types, wps->wps->encr_types_rsn,
+                  wps->wps->encr_types_wpa, wps->encr_type);
+       if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK)
+               wps->encr_type &= wps->wps->encr_types_rsn;
+       else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK)
+               wps->encr_type &= wps->wps->encr_types_wpa;
        if (wps->auth_type == WPS_AUTH_WPA2PSK ||
            wps->auth_type == WPS_AUTH_WPAPSK) {
                if (wps->encr_type & WPS_ENCR_AES)