]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Allow Device Password to be changed from M1 to M2
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 14 Feb 2013 18:41:14 +0000 (20:41 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 14 Feb 2013 18:41:14 +0000 (20:41 +0200)
Registrar is allowed to propose another Device Password ID in M2. Make
Enrollee validate Device Password ID in M2 to check if this happened.
This commit adds support for changing from NFC password token to default
PIN for the case where the AP is the Enrollee and has both the NFC
password token and AP PIN enabled at the same time.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/wps/wps.c
src/wps/wps_enrollee.c
src/wps/wps_i.h
src/wps/wps_registrar.c

index 2575705819cbf154f2b384e25543f231d85a901d..ff4b20d629a84570913326d7bd35b467178dbf2a 100644 (file)
@@ -53,12 +53,18 @@ struct wps_data * wps_init(const struct wps_config *cfg)
                }
                os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
                data->dev_password_len = cfg->pin_len;
+               wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
+                               data->dev_password, data->dev_password_len);
        }
 
 #ifdef CONFIG_WPS_NFC
        if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
+               /* Keep AP PIN as alternative Device Password */
+               data->alt_dev_pw_id = data->dev_pw_id;
+               data->alt_dev_password = data->dev_password;
+               data->alt_dev_password_len = data->dev_password_len;
+
                data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
-               os_free(data->dev_password);
                data->dev_password =
                        os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
                if (data->dev_password == NULL) {
@@ -69,6 +75,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
                          wpabuf_head(cfg->wps->ap_nfc_dev_pw),
                          wpabuf_len(cfg->wps->ap_nfc_dev_pw));
                data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
+               wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
+                           data->dev_password, data->dev_password_len);
        }
 #endif /* CONFIG_WPS_NFC */
 
@@ -155,6 +163,7 @@ void wps_deinit(struct wps_data *data)
        wpabuf_free(data->dh_pubkey_r);
        wpabuf_free(data->last_msg);
        os_free(data->dev_password);
+       os_free(data->alt_dev_password);
        os_free(data->new_psk);
        wps_device_data_free(&data->peer_dev);
        os_free(data->new_ap_settings);
index 837b9412e8ffb112ba6cc36311044a458320e849..9c0cebb75a8153f7c788f7a2bec62a1ce50698c2 100644 (file)
@@ -837,6 +837,39 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
 }
 
 
+static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id)
+{
+       u16 id;
+
+       if (dev_pw_id == NULL) {
+               wpa_printf(MSG_DEBUG, "WPS: Device Password ID");
+               return -1;
+       }
+
+       id = WPA_GET_BE16(dev_pw_id);
+       if (wps->dev_pw_id == id) {
+               wpa_printf(MSG_DEBUG, "WPS: Device Password ID %u", id);
+               return 0;
+       }
+
+       wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
+                  "ID from %u to %u", wps->dev_pw_id, id);
+
+       if (wps->alt_dev_password && wps->alt_dev_pw_id == id) {
+               wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password");
+               os_free(wps->dev_password);
+               wps->dev_pw_id = wps->alt_dev_pw_id;
+               wps->dev_password = wps->alt_dev_password;
+               wps->dev_password_len = wps->alt_dev_password_len;
+               wps->alt_dev_password = NULL;
+               wps->alt_dev_password_len = 0;
+               return 0;
+       }
+
+       return -1;
+}
+
+
 static enum wps_process_res wps_process_m2(struct wps_data *wps,
                                           const struct wpabuf *msg,
                                           struct wps_parse_attr *attr)
@@ -852,7 +885,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
 
        if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
            wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
-           wps_process_uuid_r(wps, attr->uuid_r)) {
+           wps_process_uuid_r(wps, attr->uuid_r) ||
+           wps_process_dev_pw_id(wps, attr->dev_password_id)) {
                wps->state = SEND_WSC_NACK;
                return WPS_CONTINUE;
        }
index 8110894e3af9d859a23a3a2e7081dd7bcdfb8f3b..6efc3bfea008fb46c556f7c275e5842f769b3249 100644 (file)
@@ -71,6 +71,9 @@ struct wps_data {
        size_t dev_password_len;
        u16 dev_pw_id;
        int pbc;
+       u8 *alt_dev_password;
+       size_t alt_dev_password_len;
+       u16 alt_dev_pw_id;
 
        /**
         * request_type - Request Type attribute from (Re)AssocReq
index b650a3c0ab361d392c94f350019c81c9398fa448..57344c56576963b16ba75da13b39064c035b1f18 100644 (file)
@@ -1358,6 +1358,14 @@ static int wps_get_dev_password(struct wps_data *wps)
        } else {
                pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
                                            &pin_len);
+               if (pin && wps->dev_pw_id >= 0x10) {
+                       wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device "
+                                  "Password ID, but PIN found");
+                       /*
+                        * See whether Enrollee is willing to use PIN instead.
+                        */
+                       wps->dev_pw_id = DEV_PW_DEFAULT;
+               }
        }
        if (pin == NULL) {
                wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "