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/hostapd/main.c b/hostapd/main.c
index 881a053..d2ec1a5 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -525,6 +525,8 @@
return -1;
pos = os_strrchr(interfaces->global_iface_path, '/');
if (pos == NULL) {
+ wpa_printf(MSG_ERROR, "No '/' in the global control interface "
+ "file");
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
return -1;
@@ -614,10 +616,12 @@
exit(1);
break;
case 'g':
- hostapd_get_global_ctrl_iface(&interfaces, optarg);
+ if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
+ return -1;
break;
case 'G':
- hostapd_get_ctrl_iface_group(&interfaces, optarg);
+ if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
+ return -1;
break;
default:
usage();
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 39fce56..cb03dbd 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup
- * Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -793,14 +793,19 @@
void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx);
void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
u16 sel_reg_config_methods);
-int wps_er_pbc(struct wps_er *er, const u8 *uuid);
-int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len);
-int wps_er_set_config(struct wps_er *er, const u8 *uuid,
+int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr);
+const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr);
+int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr,
+ const u8 *pin, size_t pin_len);
+int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
const struct wps_credential *cred);
-int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len, const struct wps_credential *cred);
-struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid);
+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);
int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]);
char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index 29aee8e..edcc18c 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -24,8 +24,15 @@
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
wpabuf_free(wps->dh_privkey);
- if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) {
+ wps->dh_privkey = NULL;
+ if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
+ wps->wps->dh_ctx) {
wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys");
+ if (wps->wps->dh_pubkey == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: wps->wps->dh_pubkey == NULL");
+ return -1;
+ }
wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
wps->dh_ctx = wps->wps->dh_ctx;
wps->wps->dh_ctx = NULL;
@@ -34,13 +41,22 @@
} else if (wps->dev_pw_id >= 0x10 && wps->wps->ap &&
wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) {
wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
+ if (wps->wps->ap_nfc_dh_privkey == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: wps->wps->ap_nfc_dh_privkey == NULL");
+ return -1;
+ }
+ if (wps->wps->ap_nfc_dh_pubkey == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: wps->wps->ap_nfc_dh_pubkey == NULL");
+ return -1;
+ }
wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey);
pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey);
wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey);
#endif /* CONFIG_WPS_NFC */
} else {
wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys");
- wps->dh_privkey = NULL;
dh5_free(wps->dh_ctx);
wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey);
pubkey = wpabuf_zeropad(pubkey, 192);
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 95a0dec..14c1b77 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup - External Registrar
- * Copyright (c) 2009-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -97,13 +97,16 @@
static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
- struct in_addr *addr, const u8 *uuid)
+ struct in_addr *addr, const u8 *uuid,
+ const u8 *mac_addr)
{
struct wps_er_ap *ap;
dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
if ((addr == NULL || ap->addr.s_addr == addr->s_addr) &&
(uuid == NULL ||
- os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0))
+ os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0) &&
+ (mac_addr == NULL ||
+ os_memcmp(mac_addr, ap->mac_addr, ETH_ALEN) == 0))
return ap;
}
return NULL;
@@ -290,7 +293,7 @@
struct wps_er_ap *ap;
struct wps_er_ap_settings *settings;
- ap = wps_er_ap_get(er, addr, NULL);
+ ap = wps_er_ap_get(er, addr, NULL, NULL);
if (ap == NULL || ap->ap_settings == NULL)
return -1;
@@ -636,7 +639,7 @@
{
struct wps_er_ap *ap;
- ap = wps_er_ap_get(er, addr, uuid);
+ ap = wps_er_ap_get(er, addr, uuid, NULL);
if (ap) {
/* Update advertisement timeout */
eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
@@ -1555,7 +1558,7 @@
}
-int wps_er_pbc(struct wps_er *er, const u8 *uuid)
+int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr)
{
int res;
struct wps_er_ap *ap;
@@ -1569,11 +1572,14 @@
return -2;
}
- ap = wps_er_ap_get(er, NULL, uuid);
+ if (uuid)
+ ap = wps_er_ap_get(er, NULL, uuid, NULL);
+ else
+ ap = NULL;
if (ap == NULL) {
struct wps_er_sta *sta = NULL;
dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
- sta = wps_er_sta_get(ap, NULL, uuid);
+ sta = wps_er_sta_get(ap, addr, uuid);
if (sta) {
uuid = ap->uuid;
break;
@@ -1619,6 +1625,19 @@
}
+const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr)
+{
+ struct wps_er_ap *ap;
+ dl_list_for_each(ap, &er->ap, struct wps_er_ap, list) {
+ struct wps_er_sta *sta;
+ sta = wps_er_sta_get(ap, addr, NULL);
+ if (sta)
+ return sta->uuid;
+ }
+ return NULL;
+}
+
+
static void wps_er_http_put_message_cb(void *ctx, struct http_client *c,
enum http_client_event event)
{
@@ -1877,20 +1896,22 @@
}
-int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len)
+int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr,
+ const u8 *pin, size_t pin_len)
{
struct wps_er_ap *ap;
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn "
"request");
return -1;
}
+ if (uuid == NULL)
+ uuid = ap->uuid;
if (ap->wps) {
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
"with the AP - cannot start learn");
@@ -1908,7 +1929,7 @@
}
-int wps_er_set_config(struct wps_er *er, const u8 *uuid,
+int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr,
const struct wps_credential *cred)
{
struct wps_er_ap *ap;
@@ -1916,7 +1937,7 @@
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for set config "
"request");
@@ -1960,20 +1981,23 @@
}
-int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin,
- size_t pin_len, const struct wps_credential *cred)
+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 wps_er_ap *ap;
if (er == NULL)
return -1;
- ap = wps_er_ap_get(er, NULL, uuid);
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
if (ap == NULL) {
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for config "
"request");
return -1;
}
+ if (uuid == NULL)
+ uuid = ap->uuid;
if (ap->wps) {
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
"with the AP - cannot start config");
@@ -1999,31 +2023,20 @@
#ifdef CONFIG_WPS_NFC
-struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid)
+
+struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps,
+ struct wps_credential *cred)
{
- struct wps_er_ap *ap;
struct wpabuf *ret;
struct wps_data data;
- if (er == NULL)
- return NULL;
-
- ap = wps_er_ap_get(er, NULL, uuid);
- if (ap == NULL)
- return NULL;
- if (ap->ap_settings == NULL) {
- wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the "
- "selected AP");
- 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;
+ 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)) {
@@ -2033,4 +2046,26 @@
return ret;
}
+
+
+struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
+ const u8 *addr)
+{
+ struct wps_er_ap *ap;
+
+ if (er == NULL)
+ return NULL;
+
+ ap = wps_er_ap_get(er, NULL, uuid, addr);
+ if (ap == NULL)
+ return NULL;
+ if (ap->ap_settings == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the "
+ "selected AP");
+ return NULL;
+ }
+
+ 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 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,