diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index 27ce2e31c..6bdd34118 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -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; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index f6e6a5bad..c2de53d2f 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -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); - wpabuf_free(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; }