From 33e38bfa7159cef089d6ee0d904778e184c72c47 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 27 Feb 2013 12:56:00 -0800 Subject: [PATCH] Accumulative patch from commit f8361e3d681e55efead2aac79fedf4b232d533fb TDLS: Pass peer's VHT Capability information during sta_add WPS: Clear sent_carrier to avoid errors in python script WPS: Fix OOB Device Password use in PSK1,PSK1 derivation WPS: Add AP mode NFC connection handover with wpa_supplicant/nfcpy WPS NFC: Add connection handover support for ER WPS: Add wps-er-config command for writing config token from ER Change-Id: I8934dcffb9f66bd3a2f840b78d72c9dd6cecf61d Signed-off-by: Dmitry Shmidt --- hostapd/wps-ap-nfc.py | 1 + src/ap/wps_hostapd.c | 12 +++- src/eap_peer/eap_wsc.c | 9 --- src/rsn_supp/tdls.c | 46 ++++++++++++-- src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 5 +- src/rsn_supp/wpa_ie.c | 3 + src/rsn_supp/wpa_ie.h | 2 + src/wps/wps_registrar.c | 8 ++- wpa_supplicant/ctrl_iface.c | 11 ++-- wpa_supplicant/examples/wps-nfc.py | 126 +++++++++++++++++++++++++++++++++++-- wpa_supplicant/wpas_glue.c | 2 + wpa_supplicant/wps_supplicant.c | 40 +++++++++++- wpa_supplicant/wps_supplicant.h | 2 +- 14 files changed, 238 insertions(+), 30 deletions(-) diff --git a/hostapd/wps-ap-nfc.py b/hostapd/wps-ap-nfc.py index 32a0214..6ad0b43 100755 --- a/hostapd/wps-ap-nfc.py +++ b/hostapd/wps-ap-nfc.py @@ -120,6 +120,7 @@ def wps_handover_resp(peer): print "Trying to handle WPS handover" srv = HandoverServer() + srv.sent_carrier = None nfc.llcp.activate(peer); diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index dfe77ad..e017972 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -1612,6 +1612,7 @@ struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef) int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd) { struct wps_context *wps = hapd->wps; + struct wpabuf *pw; if (wps == NULL) return -1; @@ -1626,7 +1627,16 @@ int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd) wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id; wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey); wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey); - wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw); + pw = hapd->conf->wps_nfc_dev_pw; + wps->ap_nfc_dev_pw = wpabuf_alloc( + wpabuf_len(pw) * 2 + 1); + if (wps->ap_nfc_dev_pw) { + wpa_snprintf_hex_uppercase( + (char *) wpabuf_put(wps->ap_nfc_dev_pw, + wpabuf_len(pw) * 2), + wpabuf_len(pw) * 2 + 1, + wpabuf_head(pw), wpabuf_len(pw)); + } if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey || !wps->ap_nfc_dev_pw) { diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index f358156..81ad0ce 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -137,7 +137,6 @@ static void * eap_wsc_init(struct eap_sm *sm) struct wps_context *wps; struct wps_credential new_ap_settings; int res; - u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN]; int nfc = 0; wps = sm->wps; @@ -186,14 +185,6 @@ static void * eap_wsc_init(struct eap_sm *sm) while (*pos != '\0' && *pos != ' ') pos++; cfg.pin_len = pos - (const char *) cfg.pin; - if (cfg.pin_len >= WPS_OOB_DEVICE_PASSWORD_MIN_LEN * 2 && - cfg.pin_len <= WPS_OOB_DEVICE_PASSWORD_LEN * 2 && - hexstr2bin((const char *) cfg.pin, dev_pw, - cfg.pin_len / 2) == 0) { - /* Convert OOB Device Password to binary */ - cfg.pin = dev_pw; - cfg.pin_len /= 2; - } if (cfg.pin_len == 6 && os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) { cfg.pin = NULL; diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 09adc19..09abdbb 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -122,6 +122,7 @@ struct wpa_tdls_peer { size_t supp_rates_len; struct ieee80211_ht_capabilities *ht_capabilities; + struct ieee80211_vht_capabilities *vht_capabilities; u8 qos_info; @@ -620,6 +621,8 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) peer->sm_tmr.buf = NULL; os_free(peer->ht_capabilities); peer->ht_capabilities = NULL; + os_free(peer->vht_capabilities); + peer->vht_capabilities = NULL; os_free(peer->ext_capab); peer->ext_capab = NULL; peer->rsnie_i_len = peer->rsnie_p_len = 0; @@ -1370,6 +1373,34 @@ static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde, } +static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde, + struct wpa_tdls_peer *peer) +{ + if (!kde->vht_capabilities || + kde->vht_capabilities_len < + sizeof(struct ieee80211_vht_capabilities) ) { + wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities " + "received"); + return 0; + } + + if (!peer->vht_capabilities) { + peer->vht_capabilities = + os_zalloc(sizeof(struct ieee80211_vht_capabilities)); + if (peer->vht_capabilities == NULL) + return -1; + } + + os_memcpy(peer->vht_capabilities, kde->vht_capabilities, + sizeof(struct ieee80211_vht_capabilities)); + wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities", + (u8 *) peer->vht_capabilities, + sizeof(struct ieee80211_vht_capabilities)); + + return 0; +} + + static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde, struct wpa_tdls_peer *peer) { @@ -1466,6 +1497,9 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, if (copy_peer_ht_capab(&kde, peer) < 0) goto error; + if (copy_peer_vht_capab(&kde, peer) < 0) + goto error; + if (copy_peer_ext_capab(&kde, peer) < 0) goto error; @@ -1694,7 +1728,7 @@ skip_rsn: skip_rsn_check: /* add the peer to the driver as a "setup in progress" peer */ - wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0, + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0, NULL, 0); wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); @@ -1738,8 +1772,9 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) /* add supported rates, capabilities, and qos_info to the TDLS peer */ wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability, peer->supp_rates, peer->supp_rates_len, - peer->ht_capabilities, peer->qos_info, - peer->ext_capab, peer->ext_capab_len); + peer->ht_capabilities, peer->vht_capabilities, + peer->qos_info, peer->ext_capab, + peer->ext_capab_len); wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); } @@ -1838,6 +1873,9 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, if (copy_peer_ht_capab(&kde, peer) < 0) goto error; + if (copy_peer_vht_capab(&kde, peer) < 0) + goto error; + if (copy_peer_ext_capab(&kde, peer) < 0) goto error; @@ -2146,7 +2184,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) peer->initiator = 1; /* add the peer to the driver as a "setup in progress" peer */ - wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0, + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0, NULL, 0); if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 6679dda..dbb493e 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -60,6 +60,7 @@ struct wpa_sm_ctx { u16 capability, const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len); #endif /* CONFIG_TDLS */ diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 5dae5de..877e6de 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -285,14 +285,15 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, u16 capability, const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) { if (sm->ctx->tdls_peer_addset) return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add, capability, supp_rates, supp_rates_len, ht_capab, - qosinfo, ext_capab, - ext_capab_len); + vht_capab, qosinfo, + ext_capab, ext_capab_len); return -1; } #endif /* CONFIG_TDLS */ diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 252737f..652197f 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -430,6 +430,9 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len, } else if (*pos == WLAN_EID_HT_CAP) { ie->ht_capabilities = pos + 2; ie->ht_capabilities_len = pos[1]; + } else if (*pos == WLAN_EID_VHT_CAP) { + ie->vht_capabilities = pos + 2; + ie->vht_capabilities_len = pos[1]; } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) { ie->qosinfo = pos[2]; } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index b212711..82a5c08 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -51,6 +51,8 @@ struct wpa_eapol_ie_parse { size_t ext_supp_rates_len; const u8 *ht_capabilities; size_t ht_capabilities_len; + const u8 *vht_capabilities; + size_t vht_capabilities_len; u8 qosinfo; }; diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index f01e3b3..86ef022 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -32,7 +32,7 @@ struct wps_nfc_pw_token { struct dl_list list; u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; u16 pw_id; - u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN]; + u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1]; size_t dev_pw_len; }; @@ -3503,8 +3503,10 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); token->pw_id = pw_id; - os_memcpy(token->dev_pw, dev_pw, dev_pw_len); - token->dev_pw_len = dev_pw_len; + wpa_snprintf_hex_uppercase((char *) token->dev_pw, + sizeof(token->dev_pw), + dev_pw, dev_pw_len); + token->dev_pw_len = dev_pw_len * 2; dl_list_add(®->nfc_pw_tokens, &token->list); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index dbe9153..940cd74 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -910,12 +910,12 @@ static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, char *reply, size_t max_len, - int ndef, int cr) + int ndef, int cr, char *uuid) { struct wpabuf *buf; int res; - buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr); + buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid); if (buf == NULL) return -1; @@ -934,7 +934,7 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) { - char *pos; + char *pos, *pos2; int ndef; pos = os_strchr(cmd, ' '); @@ -949,10 +949,13 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, else return -1; + pos2 = os_strchr(pos, ' '); + if (pos2) + *pos2++ = '\0'; if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { return wpas_ctrl_nfc_get_handover_sel_wps( wpa_s, reply, max_len, ndef, - os_strcmp(pos, "WPS-CR") == 0); + os_strcmp(pos, "WPS-CR") == 0, pos2); } return -1; diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py index 14acc5b..9a6da5f 100755 --- a/wpa_supplicant/examples/wps-nfc.py +++ b/wpa_supplicant/examples/wps-nfc.py @@ -61,6 +61,13 @@ def wpas_get_config_token(): return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex") +def wpas_get_er_config_token(uuid): + wpas = wpas_connect() + if (wpas == None): + return None + return wpas.request("WPS_ER_NFC_CONFIG_TOKEN NDEF " + uuid).rstrip().decode("hex") + + def wpas_get_password_token(): wpas = wpas_connect() if (wpas == None): @@ -75,15 +82,91 @@ def wpas_get_handover_req(): return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex") -def wpas_report_handover(req, sel): +def wpas_get_handover_sel(uuid): wpas = wpas_connect() if (wpas == None): return None - return wpas.request("NFC_REPORT_HANDOVER INIT WPS " + + if uuid is None: + return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip().decode("hex") + return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip().decode("hex") + + +def wpas_report_handover(req, sel, type): + wpas = wpas_connect() + if (wpas == None): + return None + return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " + str(req).encode("hex") + " " + str(sel).encode("hex")) +class HandoverServer(nfc.handover.HandoverServer): + def __init__(self): + super(HandoverServer, self).__init__() + + def process_request(self, request): + print "HandoverServer - request received" + print "Parsed handover request: " + request.pretty() + + sel = nfc.ndef.HandoverSelectMessage(version="1.2") + + for carrier in request.carriers: + print "Remote carrier type: " + carrier.type + if carrier.type == "application/vnd.wfa.wsc": + print "WPS carrier type match - add WPS carrier record" + self.received_carrier = carrier.record + data = wpas_get_handover_sel(self.uuid) + if data is None: + print "Could not get handover select carrier record from wpa_supplicant" + continue + print "Handover select carrier record from wpa_supplicant:" + print data.encode("hex") + self.sent_carrier = data + + message = nfc.ndef.Message(data); + sel.add_carrier(message[0], "active", message[1:]) + + print "Handover select:" + print sel.pretty() + print str(sel).encode("hex") + + print "Sending handover select" + return sel + + +def wps_handover_resp(peer, uuid): + if uuid is None: + print "Trying to handle WPS handover" + else: + print "Trying to handle WPS handover with AP " + uuid + + srv = HandoverServer() + srv.sent_carrier = None + srv.uuid = uuid + + nfc.llcp.activate(peer); + + try: + print "Trying handover"; + srv.start() + print "Wait for disconnect" + while nfc.llcp.connected(): + time.sleep(0.1) + print "Disconnected after handover" + except nfc.llcp.ConnectRefused: + print "Handover connection refused" + nfc.llcp.shutdown() + return + + if srv.sent_carrier: + wpas_report_handover(srv.received_carrier, srv.sent_carrier, "RESP") + + print "Remove peer" + nfc.llcp.shutdown() + print "Done with handover" + time.sleep(1) + + def wps_handover_init(peer): print "Trying to initiate WPS handover" @@ -147,7 +230,7 @@ def wps_handover_init(peer): print "Remote carrier type: " + carrier.type if carrier.type == "application/vnd.wfa.wsc": print "WPS carrier type match - send to wpa_supplicant" - wpas_report_handover(data, carrier.record) + wpas_report_handover(data, carrier.record, "INIT") wifi = nfc.ndef.WifiConfigRecord(carrier.record) print wifi.pretty() @@ -198,6 +281,28 @@ def wps_write_config_tag(clf): time.sleep(0.1) +def wps_write_er_config_tag(clf, uuid): + print "Write WPS ER config token" + data = wpas_get_er_config_token(uuid) + if (data == None): + print "Could not get WPS config token from wpa_supplicant" + return + + print "Touch an NFC tag" + while True: + tag = clf.poll() + if tag == None: + time.sleep(0.1) + continue + break + + print "Tag found - writing" + tag.ndef.message = data + print "Done - remove tag" + while tag.is_present: + time.sleep(0.1) + + def wps_write_password_tag(clf): print "Write WPS password token" data = wpas_get_password_token() @@ -252,10 +357,18 @@ def main(): clf = nfc.ContactlessFrontend() try: + arg_uuid = None + if len(sys.argv) > 1: + arg_uuid = sys.argv[1] + if len(sys.argv) > 1 and sys.argv[1] == "write-config": wps_write_config_tag(clf) raise SystemExit + if len(sys.argv) > 2 and sys.argv[1] == "write-er-config": + wps_write_er_config_tag(clf, sys.argv[2]) + raise SystemExit + if len(sys.argv) > 1 and sys.argv[1] == "write-password": wps_write_password_tag(clf) raise SystemExit @@ -265,7 +378,12 @@ def main(): tag = find_peer(clf) if isinstance(tag, nfc.DEP): - wps_handover_init(tag) + if arg_uuid is None: + wps_handover_init(tag) + elif arg_uuid is "ap": + wps_handover_resp(tag, None) + else: + wps_handover_resp(tag, arg_uuid) continue if tag.ndef: diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index dfc3b76..7585b86 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -554,6 +554,7 @@ static int wpa_supplicant_tdls_peer_addset( void *ctx, const u8 *peer, int add, u16 capability, const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) { struct wpa_supplicant *wpa_s = ctx; @@ -574,6 +575,7 @@ static int wpa_supplicant_tdls_peer_addset( params.flags |= WPA_STA_WMM; params.ht_capabilities = ht_capab; + params.vht_capabilities = vht_capab; params.qosinfo = qosinfo; params.listen_interval = 0; params.supp_rates = supp_rates; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index c89479f..509a7c0 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -2003,12 +2003,48 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr) } +#ifdef CONFIG_WPS_NFC +struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, + int ndef, const char *uuid) +{ + struct wpabuf *ret; + u8 u[UUID_LEN]; + + if (!wpa_s->wps_er) + return NULL; + + if (uuid == NULL || uuid_str2bin(uuid, u)) + return NULL; + + /* + * Handover Select carrier record for WPS uses the same format as + * configuration token. + */ + ret = wps_er_nfc_config_token(wpa_s->wps_er, u); + if (ndef && ret) { + struct wpabuf *tmp; + tmp = ndef_build_wifi(ret); + wpabuf_free(ret); + if (tmp == NULL) + return NULL; + ret = tmp; + } + + return ret; +} +#endif /* CONFIG_WPS_NFC */ + + struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, - int ndef, int cr) + int ndef, int cr, const char *uuid) { + struct wpabuf *ret; if (!cr) return NULL; - return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef); + ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef); + if (ret) + return ret; + return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid); } diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index 5bc5ffa..8bb9546 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -70,7 +70,7 @@ int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s, const struct wpabuf *data); struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr); struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, - int ndef, int cr); + int ndef, int cr, const char *uuid); int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s, const struct wpabuf *data); int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s, -- 2.11.0