WPS: Add support for config token generation with wpa_supplicant
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 15 Feb 2013 09:45:29 +0000 (11:45 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 15 Feb 2013 09:47:52 +0000 (11:47 +0200)
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 <jouni@qca.qualcomm.com>

wpa_supplicant/README-WPS
wpa_supplicant/ap.c
wpa_supplicant/ap.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/examples/wps-nfc.py
wpa_supplicant/wpa_cli.c
wpa_supplicant/wps_supplicant.c
wpa_supplicant/wps_supplicant.h

index 1ea9843..a024ac8 100644 (file)
@@ -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 <WPS/NDEF>" 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
index 85ee6cb..df0bba0 100644 (file)
@@ -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 */
 
 
index 536064f..a997937 100644 (file)
@@ -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 */
index de6c450..1163c24 100644 (file)
@@ -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);
index 4d00a3a..14acc5b 100755 (executable)
@@ -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
index 3034e15..861f9c9 100644 (file)
@@ -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,
+         "<WPS|NDEF> = build configuration token" },
        { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
          cli_cmd_flag_none,
          "<WPS|NDEF> = create password token" },
index 281fef7..a38972b 100644 (file)
@@ -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) {
index 465e6f2..c3816f4 100644 (file)
@@ -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,