Accumulative patch from commit 88c8bf311efa4eb64468bed9b41b3110ab9effff
88c8bf3 WPS NFC: Allow configuration token to be built from network block
e205401 WPS ER: Allow Enrollee to be specified with MAC address
c44a19c WPS ER: Document additional NFC command for ER operations
59307b3 WPS ER: Allow AP to be specified with BSSID
49e160a WPS: Fix use of pre-configured DH keys with multiple operations
5c9d63d WPS: Be more careful with pre-configured DH parameters
cd61936 hostapd: Show more helpful message for -g and -G errors
Change-Id: I7bfd1fa30214c54f2536679411ccd11bb4dd896d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/README-WPS b/wpa_supplicant/README-WPS
index 2a1dda5..3d07109 100644
--- a/wpa_supplicant/README-WPS
+++ b/wpa_supplicant/README-WPS
@@ -259,16 +259,16 @@
wps_er_stop
- stop WPS ER functionality
-wps_er_learn <UUID> <AP PIN>
+wps_er_learn <UUID|BSSID> <AP PIN>
- learn AP configuration
-wps_er_set_config <UUID> <network id>
+wps_er_set_config <UUID|BSSID> <network id>
- use AP configuration from a locally configured network (e.g., from
wps_reg command); this does not change the AP's configuration, but
only prepares a configuration to be used when enrolling a new device
to the AP
-wps_er_config <UUID> <AP PIN> <new SSID> <auth> <encr> <new key>
+wps_er_config <UUID|BSSID> <AP PIN> <new SSID> <auth> <encr> <new key>
- examples:
wps_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 testing WPA2PSK CCMP 12345678
wpa_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 clear OPEN NONE ""
@@ -277,10 +277,10 @@
<encr> must be one of the following: NONE WEP TKIP CCMP
-wps_er_pbc <Enrollee UUID>
+wps_er_pbc <Enrollee UUID|MAC address>
- accept an Enrollee PBC using External Registrar
-wps_er_pin <Enrollee UUID> <PIN> [Enrollee MAC address]
+wps_er_pin <Enrollee UUID|"any"|MAC address> <PIN> [Enrollee MAC address]
- add an Enrollee PIN to External Registrar
- if Enrollee UUID is not known, "any" can be used to add a wildcard PIN
- if the MAC address of the enrollee is known, it should be configured
@@ -346,6 +346,10 @@
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 <WPS/NDEF> <network id>" 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
@@ -368,12 +372,15 @@
argument selects which type of connection handover is requested (WPS =
Wi-Fi handover as specified in WSC 2.0).
-"nfc_get_handover_sel <NDEF> <WPS>" command can be used to build the
-contents of a Handover Select Message for connection handover when this
-does not depend on the contents of the Handover Request Message. The
-first argument selects the format of the output data and the second
-argument selects which type of connection handover is requested (WPS =
-Wi-Fi handover as specified in WSC 2.0).
+"nfc_get_handover_sel <NDEF> <WPS> [UUID|BSSID]" command can be used to
+build the contents of a Handover Select Message for connection handover
+when this does not depend on the contents of the Handover Request
+Message. The first argument selects the format of the output data and
+the second argument selects which type of connection handover is
+requested (WPS = Wi-Fi handover as specified in WSC 2.0). If the options
+UUID|BSSID argument is included, this is a request to build the handover
+message for the specified AP when wpa_supplicant is operating as a WPS
+ER.
"nfc_rx_handover_req <hexdump of payload>" is used to indicate receipt
of NFC connection handover request. The payload may include multiple
@@ -392,3 +399,13 @@
indicates whether the local device initiated or responded to the
connection handover and the carrier records are the selected carrier
from the handover request and select messages as a hexdump.
+
+The "wps_er_nfc_config_token <WPS/NDEF> <UUID|BSSID>" command can be
+used to build an NFC configuration token for the specified AP when
+wpa_supplicant is operating as a WPS ER. The output value from this
+command is a hexdump of the selected 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.
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 6d2b3b1..ad0392f 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -784,7 +784,11 @@
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 @@
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 86473cd..dbc143a 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -53,10 +53,12 @@
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 @@
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 @@
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 603ce91..9af6084 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant / WPS integration
- * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -1605,91 +1605,128 @@
const char *uuid, const char *pin)
{
u8 u[UUID_LEN];
- int any = 0;
+ const u8 *use_uuid = NULL;
+ u8 addr_buf[ETH_ALEN];
- if (os_strcmp(uuid, "any") == 0)
- any = 1;
- else if (uuid_str2bin(uuid, u))
+ if (os_strcmp(uuid, "any") == 0) {
+ } else if (uuid_str2bin(uuid, u) == 0) {
+ use_uuid = u;
+ } else if (hwaddr_aton(uuid, addr_buf) == 0) {
+ use_uuid = wps_er_get_sta_uuid(wpa_s->wps_er, addr_buf);
+ if (use_uuid == NULL)
+ return -1;
+ } else
return -1;
return wps_registrar_add_pin(wpa_s->wps->registrar, addr,
- any ? NULL : u,
+ use_uuid,
(const u8 *) pin, os_strlen(pin), 300);
}
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
{
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
- if (uuid_str2bin(uuid, u))
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
return -1;
- return wps_er_pbc(wpa_s->wps_er, u);
+ return wps_er_pbc(wpa_s->wps_er, use_uuid, use_addr);
}
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
const char *pin)
{
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
- if (uuid_str2bin(uuid, u))
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
return -1;
- return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin,
+
+ return wps_er_learn(wpa_s->wps_er, use_uuid, use_addr, (const u8 *) pin,
os_strlen(pin));
}
+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)
{
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
struct wpa_ssid *ssid;
struct wps_credential cred;
- if (uuid_str2bin(uuid, u))
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
return -1;
ssid = wpa_config_get_network(wpa_s->conf, id);
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, u, &cred);
+ return wps_er_set_config(wpa_s->wps_er, use_uuid, use_addr, &cred);
}
int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
const char *pin, struct wps_new_ap_settings *settings)
{
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
struct wps_credential cred;
size_t len;
- if (uuid_str2bin(uuid, u))
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
return -1;
if (settings->ssid_hex == NULL || settings->auth == NULL ||
settings->encr == NULL || settings->key_hex == NULL)
@@ -1728,8 +1765,8 @@
else
return -1;
- return wps_er_config(wpa_s->wps_er, u, (const u8 *) pin,
- os_strlen(pin), &cred);
+ return wps_er_config(wpa_s->wps_er, use_uuid, use_addr,
+ (const u8 *) pin, os_strlen(pin), &cred);
}
@@ -1738,15 +1775,20 @@
int ndef, const char *uuid)
{
struct wpabuf *ret;
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
if (!wpa_s->wps_er)
return NULL;
- if (uuid_str2bin(uuid, u))
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
return NULL;
- ret = wps_er_nfc_config_token(wpa_s->wps_er, u);
+ ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
@@ -1854,9 +1896,52 @@
#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);
@@ -1905,8 +1990,13 @@
return -1;
}
wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
- if (wps->dh_ctx == NULL)
+ if (wps->dh_ctx == NULL) {
+ wpabuf_free(wps->dh_pubkey);
+ wps->dh_pubkey = NULL;
+ wpabuf_free(wps->dh_privkey);
+ wps->dh_privkey = NULL;
return -1;
+ }
wpa_snprintf_hex_uppercase(pw, sizeof(pw),
wpabuf_head(wpa_s->conf->wps_nfc_dev_pw),
@@ -2033,19 +2123,26 @@
{
#ifdef CONFIG_WPS_ER
struct wpabuf *ret;
- u8 u[UUID_LEN];
+ u8 u[UUID_LEN], *use_uuid = NULL;
+ u8 addr[ETH_ALEN], *use_addr = NULL;
if (!wpa_s->wps_er)
return NULL;
- if (uuid == NULL || uuid_str2bin(uuid, u))
+ if (uuid == NULL)
+ return NULL;
+ if (uuid_str2bin(uuid, u) == 0)
+ use_uuid = u;
+ else if (hwaddr_aton(uuid, addr) == 0)
+ use_addr = addr;
+ else
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);
+ ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index 8bb9546..2a212ca 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -63,7 +63,7 @@
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,