aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/eap_peer/eap_wsc.c13
-rw-r--r--wpa_supplicant/wps_supplicant.c114
2 files changed, 110 insertions, 17 deletions
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index 27ce2e3..6bdd341 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 f6e6a5b..c2de53d 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);
+ 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;
}