From 88c8bf311efa4eb64468bed9b41b3110ab9effff Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 1 Apr 2013 21:28:57 +0300 Subject: [PATCH] WPS NFC: Allow configuration token to be built from network block "WPS_NFC_CONFIG_TOKEN " can now be used to build an NFC configuration token from a locally configured network. Signed-hostap: Jouni Malinen --- src/wps/wps.h | 2 + src/wps/wps_er.c | 44 +++++++----- wpa_supplicant/README-WPS | 4 ++ wpa_supplicant/ctrl_iface.c | 6 +- wpa_supplicant/examples/wps-nfc.py | 12 +++- wpa_supplicant/wps_supplicant.c | 107 +++++++++++++++++++++-------- wpa_supplicant/wps_supplicant.h | 2 +- 7 files changed, 128 insertions(+), 49 deletions(-) diff --git a/src/wps/wps.h b/src/wps/wps.h index 6e74a4109..cb03dbdcd 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -802,6 +802,8 @@ int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, const u8 *pin, size_t pin_len, const struct wps_credential *cred); +struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, + struct wps_credential *cred); struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, const u8 *addr); diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 31ba450e1..14c1b779d 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -2023,12 +2023,35 @@ int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, #ifdef CONFIG_WPS_NFC + +struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, + struct wps_credential *cred) +{ + struct wpabuf *ret; + struct wps_data data; + + ret = wpabuf_alloc(500); + if (ret == NULL) + return NULL; + + os_memset(&data, 0, sizeof(data)); + data.wps = wps; + data.use_cred = cred; + if (wps_build_version(ret) || + wps_build_cred(&data, ret) || + wps_build_wfa_ext(ret, 0, NULL, 0)) { + wpabuf_free(ret); + return NULL; + } + + return ret; +} + + struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, const u8 *addr) { struct wps_er_ap *ap; - struct wpabuf *ret; - struct wps_data data; if (er == NULL) return NULL; @@ -2042,20 +2065,7 @@ struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, return NULL; } - ret = wpabuf_alloc(500); - if (ret == NULL) - return NULL; - - os_memset(&data, 0, sizeof(data)); - data.wps = er->wps; - data.use_cred = ap->ap_settings; - if (wps_build_version(ret) || - wps_build_cred(&data, ret) || - wps_build_wfa_ext(ret, 0, NULL, 0)) { - wpabuf_free(ret); - return NULL; - } - - return ret; + return wps_er_config_token_from_cred(er->wps, ap->ap_settings); } + #endif /* CONFIG_WPS_NFC */ diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS index 06154666a..3d0710937 100644 --- a/wpa_supplicant/README-WPS +++ b/wpa_supplicant/README-WPS @@ -346,6 +346,10 @@ 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. +The "wps_nfc_config_token " command can be used +to build an NFC configuration token based on a locally configured +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/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 49497718a..27220a935 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -784,7 +784,11 @@ static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( int ndef; struct wpabuf *buf; int res; + char *pos; + pos = os_strchr(cmd, ' '); + if (pos) + *pos++ = '\0'; if (os_strcmp(cmd, "WPS") == 0) ndef = 0; else if (os_strcmp(cmd, "NDEF") == 0) @@ -792,7 +796,7 @@ static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( else return -1; - buf = wpas_wps_nfc_config_token(wpa_s, ndef); + buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos); if (buf == NULL) return -1; diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py index 86473cd62..dbc143ad6 100755 --- a/wpa_supplicant/examples/wps-nfc.py +++ b/wpa_supplicant/examples/wps-nfc.py @@ -53,10 +53,12 @@ def wpas_tag_read(message): print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")) -def wpas_get_config_token(): +def wpas_get_config_token(id=None): wpas = wpas_connect() if (wpas == None): return None + if id: + return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id).rstrip().decode("hex") return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex") @@ -258,9 +260,9 @@ def wps_tag_read(tag): time.sleep(0.1) -def wps_write_config_tag(clf): +def wps_write_config_tag(clf, id=None): print "Write WPS config token" - data = wpas_get_config_token() + data = wpas_get_config_token(id) if (data == None): print "Could not get WPS config token from wpa_supplicant" return @@ -364,6 +366,10 @@ def main(): wps_write_config_tag(clf) raise SystemExit + if len(sys.argv) > 2 and sys.argv[1] == "write-config-id": + wps_write_config_tag(clf, sys.argv[2]) + 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 diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index d9b1b297e..9af608494 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1656,6 +1656,40 @@ int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid, } +static int wpas_wps_network_to_cred(struct wpa_ssid *ssid, + struct wps_credential *cred) +{ + os_memset(cred, 0, sizeof(*cred)); + if (ssid->ssid_len > 32) + return -1; + os_memcpy(cred->ssid, ssid->ssid, ssid->ssid_len); + cred->ssid_len = ssid->ssid_len; + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { + cred->auth_type = (ssid->proto & WPA_PROTO_RSN) ? + WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK; + if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) + cred->encr_type = WPS_ENCR_AES; + else + cred->encr_type = WPS_ENCR_TKIP; + if (ssid->passphrase) { + cred->key_len = os_strlen(ssid->passphrase); + if (cred->key_len >= 64) + return -1; + os_memcpy(cred->key, ssid->passphrase, cred->key_len); + } else if (ssid->psk_set) { + cred->key_len = 32; + os_memcpy(cred->key, ssid->psk, 32); + } else + return -1; + } else { + cred->auth_type = WPS_AUTH_OPEN; + cred->encr_type = WPS_ENCR_NONE; + } + + return 0; +} + + int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, int id) { @@ -1674,32 +1708,8 @@ int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, if (ssid == NULL || ssid->ssid == NULL) return -1; - os_memset(&cred, 0, sizeof(cred)); - if (ssid->ssid_len > 32) + if (wpas_wps_network_to_cred(ssid, &cred) < 0) return -1; - os_memcpy(cred.ssid, ssid->ssid, ssid->ssid_len); - cred.ssid_len = ssid->ssid_len; - if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { - cred.auth_type = (ssid->proto & WPA_PROTO_RSN) ? - WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK; - if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) - cred.encr_type = WPS_ENCR_AES; - else - cred.encr_type = WPS_ENCR_TKIP; - if (ssid->passphrase) { - cred.key_len = os_strlen(ssid->passphrase); - if (cred.key_len >= 64) - return -1; - os_memcpy(cred.key, ssid->passphrase, cred.key_len); - } else if (ssid->psk_set) { - cred.key_len = 32; - os_memcpy(cred.key, ssid->psk, 32); - } else - return -1; - } else { - cred.auth_type = WPS_AUTH_OPEN; - cred.encr_type = WPS_ENCR_NONE; - } return wps_er_set_config(wpa_s->wps_er, use_uuid, use_addr, &cred); } @@ -1886,9 +1896,52 @@ 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_WPS_ER +static struct wpabuf * +wpas_wps_network_config_token(struct wpa_supplicant *wpa_s, int ndef, + struct wpa_ssid *ssid) { + struct wpabuf *ret; + struct wps_credential cred; + + if (wpas_wps_network_to_cred(ssid, &cred) < 0) + return NULL; + + ret = wps_er_config_token_from_cred(wpa_s->wps, &cred); + + 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_ER */ + + +struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef, const char *id_str) +{ +#ifdef CONFIG_WPS_ER + if (id_str) { + int id; + char *end = NULL; + struct wpa_ssid *ssid; + + id = strtol(id_str, &end, 10); + if (end && *end) + return NULL; + + ssid = wpa_config_get_network(wpa_s->conf, id); + if (ssid == NULL) + return NULL; + return wpas_wps_network_config_token(wpa_s, ndef, ssid); + } +#endif /* CONFIG_WPS_ER */ #ifdef CONFIG_AP if (wpa_s->ap_iface) return wpas_ap_wps_nfc_config_token(wpa_s, ndef); diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h index 8bb9546e1..2a212caba 100644 --- a/wpa_supplicant/wps_supplicant.h +++ b/wpa_supplicant/wps_supplicant.h @@ -63,7 +63,7 @@ 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); + int ndef, const char *id_str); 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,