]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS NFC: Process new style handover select
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 2 Apr 2013 15:30:58 +0000 (18:30 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2014 19:10:55 +0000 (21:10 +0200)
The new WPS connection handover select includes Registrar public key
hash instead of credential. Use the new information to start
abbreviated WPS handshake instead of configuring a new network directly
from the old Credential-from-NFC design.

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

src/eap_peer/eap_wsc.c
wpa_supplicant/wps_supplicant.c

index 27ce2e31cf4ee83dc1b8ae5cb7fcfed1868acfd5..6bdd341182943dca0b93f1bda99ed03d05ffa023 100644 (file)
@@ -210,6 +210,15 @@ static void * eap_wsc_init(struct eap_sm *sm)
                        cfg.pbc = 1;
        }
 
+       pos = os_strstr(phase1, "dev_pw_id=");
+       if (pos) {
+               u16 id = atoi(pos + 10);
+               if (id == DEV_PW_NFC_CONNECTION_HANDOVER)
+                       nfc = 1;
+               if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER)
+                       cfg.dev_pw_id = id;
+       }
+
        if (cfg.pin == NULL && !cfg.pbc && !nfc) {
                wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 "
                           "configuration data");
@@ -217,10 +226,6 @@ static void * eap_wsc_init(struct eap_sm *sm)
                return NULL;
        }
 
-       pos = os_strstr(phase1, "dev_pw_id=");
-       if (pos && cfg.pin)
-               cfg.dev_pw_id = atoi(pos + 10);
-
        pos = os_strstr(phase1, " pkhash=");
        if (pos) {
                size_t len;
index f6e6a5bad45df794bf41d8ccf61d70affa87cf05..c2de53d2f3c2273f5e589bcfebb691138c421878 100644 (file)
@@ -1120,13 +1120,18 @@ static int wpas_wps_start_dev_pw(struct wpa_supplicant *wpa_s, const u8 *bssid,
        if (pin)
                os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u%s\"",
                            pin, dev_pw_id, hash);
-       else {
+       else if (pin == NULL && dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
+               os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
+                           dev_pw_id, hash);
+       } else {
                rpin = wps_generate_pin();
                os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
                            rpin, dev_pw_id, hash);
        }
-       if (wpa_config_set(ssid, "phase1", val, 0) < 0)
+       if (wpa_config_set(ssid, "phase1", val, 0) < 0) {
+               wpa_printf(MSG_DEBUG, "WPS: Failed to set phase1 '%s'", val);
                return -1;
+       }
        if (wpa_s->wps_fragment_size)
                ssid->eap.fragment_size = wpa_s->wps_fragment_size;
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
@@ -2106,15 +2111,23 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid,
        struct wps_context *wps = wpa_s->wps;
        char pw[32 * 2 + 1];
 
-       if (dev_pw == NULL) {
+       if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
                dev_pw = wpa_s->conf->wps_nfc_dev_pw;
                dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
        }
 
        if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
-           wpa_s->conf->wps_nfc_dh_privkey == NULL ||
-           dev_pw == NULL)
+           wpa_s->conf->wps_nfc_dh_privkey == NULL) {
+               wpa_printf(MSG_DEBUG, "WPS: Missing DH params - "
+                          "cannot start NFC-triggered connection");
+               return -1;
+       }
+
+       if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && dev_pw == NULL) {
+               wpa_printf(MSG_DEBUG, "WPS: Missing Device Password (id=%u) - "
+                          "cannot start NFC-triggered connection", dev_pw_id);
                return -1;
+       }
 
        dh5_free(wps->dh_ctx);
        wpabuf_free(wps->dh_pubkey);
@@ -2127,6 +2140,7 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid,
                wps->dh_pubkey = NULL;
                wpabuf_free(wps->dh_privkey);
                wps->dh_privkey = NULL;
+               wpa_printf(MSG_DEBUG, "WPS: Failed to get DH priv/pub key");
                return -1;
        }
        wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
@@ -2135,13 +2149,18 @@ int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid,
                wps->dh_pubkey = NULL;
                wpabuf_free(wps->dh_privkey);
                wps->dh_privkey = NULL;
+               wpa_printf(MSG_DEBUG, "WPS: Failed to initialize DH context");
                return -1;
        }
 
-       wpa_snprintf_hex_uppercase(pw, sizeof(pw),
-                                  wpabuf_head(dev_pw), wpabuf_len(dev_pw));
-       return wpas_wps_start_dev_pw(wpa_s, bssid, pw, p2p_group, dev_pw_id,
-                                    peer_pubkey_hash, ssid, ssid_len);
+       if (dev_pw) {
+               wpa_snprintf_hex_uppercase(pw, sizeof(pw),
+                                          wpabuf_head(dev_pw),
+                                          wpabuf_len(dev_pw));
+       }
+       return wpas_wps_start_dev_pw(wpa_s, bssid, dev_pw ? pw : NULL,
+                                    p2p_group, dev_pw_id, peer_pubkey_hash,
+                                    ssid, ssid_len);
 }
 
 
@@ -2354,17 +2373,86 @@ int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
                                 const struct wpabuf *data)
 {
        struct wpabuf *wps;
-       int ret;
+       int ret = -1;
+       u16 wsc_len;
+       const u8 *pos;
+       struct wpabuf msg;
+       struct wps_parse_attr attr;
+       u16 dev_pw_id;
 
        wps = ndef_parse_wifi(data);
        if (wps == NULL)
                return -1;
        wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
                   "payload from NFC connection handover");
-       wpa_hexdump_buf_key(MSG_DEBUG, "WPS: NFC payload", wps);
-       ret = wpas_wps_nfc_tag_process(wpa_s, wps);
+       wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
+       if (wpabuf_len(wps) < 2) {
+               wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Select "
+                          "Message");
+               goto out;
+       }
+       pos = wpabuf_head(wps);
+       wsc_len = WPA_GET_BE16(pos);
+       if (wsc_len > wpabuf_len(wps) - 2) {
+               wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
+                          "in Wi-Fi Handover Select Message", wsc_len);
+               goto out;
+       }
+       pos += 2;
+
+       wpa_hexdump(MSG_DEBUG,
+                   "WPS: WSC attributes in Wi-Fi Handover Select Message",
+                   pos, wsc_len);
+       if (wsc_len < wpabuf_len(wps) - 2) {
+               wpa_hexdump(MSG_DEBUG,
+                           "WPS: Ignore extra data after WSC attributes",
+                           pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
+       }
+
+       wpabuf_set(&msg, pos, wsc_len);
+       ret = wps_parse_msg(&msg, &attr);
+       if (ret < 0) {
+               wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
+                          "Wi-Fi Handover Select Message");
+               goto out;
+       }
+
+       if (attr.oob_dev_password == NULL ||
+           attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
+               wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
+                          "included in Wi-Fi Handover Select Message");
+               ret = -1;
+               goto out;
+       }
+
+       if (attr.ssid == NULL) {
+               wpa_printf(MSG_DEBUG, "WPS: No SSID included in Wi-Fi Handover "
+                          "Select Message");
+               ret = -1;
+               goto out;
+       }
+
+       wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", attr.ssid, attr.ssid_len);
+
+       wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
+                   attr.oob_dev_password, attr.oob_dev_password_len);
+       dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
+                                WPS_OOB_PUBKEY_HASH_LEN);
+       if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
+               wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
+                          "%u in Wi-Fi Handover Select Message", dev_pw_id);
+               ret = -1;
+               goto out;
+       }
+       wpa_hexdump(MSG_DEBUG, "WPS: AP Public Key hash",
+                   attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
+
+       ret = wpas_wps_start_nfc(wpa_s, NULL, NULL, dev_pw_id, 0,
+                                attr.oob_dev_password,
+                                attr.ssid, attr.ssid_len);
+
+out:
        wpabuf_free(wps);
-
        return ret;
 }