From bbf41865c90c2e16510712fa32290729c194422d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 Feb 2013 11:45:29 +0200 Subject: [PATCH] WPS: Add support for config token generation with wpa_supplicant When wpa_supplicant is controlling an AP mode interface, it can generate the NFC configuration token similarly to the way this is done in hostapd. Signed-hostap: Jouni Malinen --- wpa_supplicant/README-WPS | 10 +++++++++ wpa_supplicant/ap.c | 12 +++++++++++ wpa_supplicant/ap.h | 2 ++ wpa_supplicant/ctrl_iface.c | 32 +++++++++++++++++++++++++++++ wpa_supplicant/examples/wps-nfc.py | 33 ++++++++++++++++++++++++++++++ wpa_supplicant/wpa_cli.c | 10 +++++++++ wpa_supplicant/wps_supplicant.c | 11 ++++++++++ wpa_supplicant/wps_supplicant.h | 2 ++ 8 files changed, 112 insertions(+) diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS index 1ea98432f..a024ac894 100644 --- a/wpa_supplicant/README-WPS +++ b/wpa_supplicant/README-WPS @@ -336,6 +336,16 @@ wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with tokens during manufacturing (each station needs to have its own random keys). +The "wps_nfc_config_token " command can be used to build an +NFC configuration token when wpa_supplicant is controlling an AP +interface (AP or P2P GO). The output value from this command is a +hexdump of the current AP configuration (WPS parameter requests this to +include only the WPS attributes; NDEF parameter requests additional NDEF +encapsulation to be included). This data needs to be written to an NFC +tag with an external program. Once written, the NFC configuration token +can be used to touch an NFC interface on a station to provision the +credentials needed to access the network. + If the station includes NFC interface and reads an NFC tag with a MIME media type "application/vnd.wfa.wsc", the NDEF message payload (with or without NDEF encapsulation) can be delivered to wpa_supplicant using the diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 85ee6cb24..df0bba07b 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -848,6 +848,18 @@ void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s) hapd->conf->ap_pin = NULL; } + +struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef) +{ + struct hostapd_data *hapd; + + if (wpa_s->ap_iface == NULL) + return NULL; + hapd = wpa_s->ap_iface->bss[0]; + return hostapd_wps_nfc_config_token(hapd, ndef); +} + #endif /* CONFIG_WPS */ diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index 536064f7c..a997937ee 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -52,5 +52,7 @@ int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s, void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s); void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, int offset); +struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef); #endif /* AP_H */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index de6c450e2..1163c2453 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -778,6 +778,35 @@ static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, } +static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( + struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) +{ + int ndef; + struct wpabuf *buf; + int res; + + if (os_strcmp(cmd, "WPS") == 0) + ndef = 0; + else if (os_strcmp(cmd, "NDEF") == 0) + ndef = 1; + else + return -1; + + buf = wpas_wps_nfc_config_token(wpa_s, ndef); + if (buf == NULL) + return -1; + + res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), + wpabuf_len(buf)); + reply[res++] = '\n'; + reply[res] = '\0'; + + wpabuf_free(buf); + + return res; +} + + static int wpa_supplicant_ctrl_iface_wps_nfc_token( struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) { @@ -4958,6 +4987,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) reply_len = -1; + } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { + reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( + wpa_s, buf + 21, reply, reply_size); } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( wpa_s, buf + 14, reply, reply_size); diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py index 4d00a3a4e..14acc5b26 100755 --- a/wpa_supplicant/examples/wps-nfc.py +++ b/wpa_supplicant/examples/wps-nfc.py @@ -54,6 +54,13 @@ def wpas_tag_read(message): print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")) +def wpas_get_config_token(): + wpas = wpas_connect() + if (wpas == None): + return None + return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex") + + def wpas_get_password_token(): wpas = wpas_connect() if (wpas == None): @@ -169,6 +176,28 @@ def wps_tag_read(tag): time.sleep(0.1) +def wps_write_config_tag(clf): + print "Write WPS config token" + data = wpas_get_config_token() + 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() @@ -223,6 +252,10 @@ def main(): clf = nfc.ContactlessFrontend() try: + if len(sys.argv) > 1 and sys.argv[1] == "write-config": + wps_write_config_tag(clf) + raise SystemExit + if len(sys.argv) > 1 and sys.argv[1] == "write-password": wps_write_password_tag(clf) raise SystemExit diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 3034e1538..861f9c966 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -744,6 +744,13 @@ static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv); +} + + static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2488,6 +2495,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss, cli_cmd_flag_none, "[BSSID] = start Wi-Fi Protected Setup: NFC" }, + { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL, + cli_cmd_flag_none, + " = build configuration token" }, { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL, cli_cmd_flag_none, " = create password token" }, diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 281fef707..a38972b5c 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1830,6 +1830,17 @@ void wpas_wps_update_config(struct wpa_supplicant *wpa_s) #ifdef CONFIG_WPS_NFC +struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef) +{ +#ifdef CONFIG_AP + if (wpa_s->ap_iface) + return wpas_ap_wps_nfc_config_token(wpa_s, ndef); +#endif /* CONFIG_AP */ + return NULL; +} + + struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef) { if (wpa_s->conf->wps_nfc_pw_from_config) { diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index 465e6f227..c3816f457 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -62,6 +62,8 @@ struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s, int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s); int wpas_wps_in_progress(struct wpa_supplicant *wpa_s); void wpas_wps_update_config(struct wpa_supplicant *wpa_s); +struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef); struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef); int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s,