NFC: Update WPS ER to use the new connection handover design
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
d95079361b
commit
50d1f8901c
6 changed files with 169 additions and 7 deletions
|
@ -845,6 +845,9 @@ struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps,
|
||||||
struct wps_credential *cred);
|
struct wps_credential *cred);
|
||||||
struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
|
struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
|
||||||
const u8 *addr);
|
const u8 *addr);
|
||||||
|
struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er,
|
||||||
|
struct wps_context *wps, const u8 *uuid,
|
||||||
|
const u8 *addr, struct wpabuf *pubkey);
|
||||||
|
|
||||||
int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]);
|
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,
|
char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
|
||||||
|
|
|
@ -40,7 +40,11 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
|
||||||
#ifdef CONFIG_WPS_NFC
|
#ifdef CONFIG_WPS_NFC
|
||||||
} else if ((wps->dev_pw_id >= 0x10 ||
|
} else if ((wps->dev_pw_id >= 0x10 ||
|
||||||
wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
|
wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
|
||||||
wps->wps->ap &&
|
(wps->wps->ap ||
|
||||||
|
(wps->wps->ap_nfc_dh_pubkey &&
|
||||||
|
wps->wps->ap_nfc_dev_pw_id ==
|
||||||
|
DEV_PW_NFC_CONNECTION_HANDOVER &&
|
||||||
|
wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) &&
|
||||||
(wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
|
(wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
|
||||||
wps->wps->ap_nfc_dh_pubkey)) {
|
wps->wps->ap_nfc_dh_pubkey)) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
|
wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
|
||||||
|
|
|
@ -2070,4 +2070,29 @@ struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid,
|
||||||
return wps_er_config_token_from_cred(er->wps, ap->ap_settings);
|
return wps_er_config_token_from_cred(er->wps, ap->ap_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er,
|
||||||
|
struct wps_context *wps, const u8 *uuid,
|
||||||
|
const u8 *addr, struct wpabuf *pubkey)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len);
|
||||||
|
wps->ssid_len = ap->ap_settings->ssid_len;
|
||||||
|
|
||||||
|
return wps_build_nfc_handover_sel(wps, pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WPS_NFC */
|
#endif /* CONFIG_WPS_NFC */
|
||||||
|
|
|
@ -1128,6 +1128,8 @@ static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
|
} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0)
|
||||||
{
|
{
|
||||||
ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
|
ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel);
|
||||||
|
if (ret < 0)
|
||||||
|
ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel);
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
|
wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
|
||||||
"reported: role=%s type=%s", role, type);
|
"reported: role=%s type=%s", role, type);
|
||||||
|
|
|
@ -1444,6 +1444,20 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WPS_ER
|
||||||
|
static void wpas_wps_nfc_clear(struct wps_context *wps)
|
||||||
|
{
|
||||||
|
wps->ap_nfc_dev_pw_id = 0;
|
||||||
|
wpabuf_free(wps->ap_nfc_dh_pubkey);
|
||||||
|
wps->ap_nfc_dh_pubkey = NULL;
|
||||||
|
wpabuf_free(wps->ap_nfc_dh_privkey);
|
||||||
|
wps->ap_nfc_dh_privkey = NULL;
|
||||||
|
wpabuf_free(wps->ap_nfc_dev_pw);
|
||||||
|
wps->ap_nfc_dev_pw = NULL;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WPS_ER */
|
||||||
|
|
||||||
|
|
||||||
void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
|
||||||
|
@ -1457,6 +1471,7 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
|
||||||
#ifdef CONFIG_WPS_ER
|
#ifdef CONFIG_WPS_ER
|
||||||
wps_er_deinit(wpa_s->wps_er, NULL, NULL);
|
wps_er_deinit(wpa_s->wps_er, NULL, NULL);
|
||||||
wpa_s->wps_er = NULL;
|
wpa_s->wps_er = NULL;
|
||||||
|
wpas_wps_nfc_clear(wpa_s->wps);
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
|
|
||||||
wps_registrar_deinit(wpa_s->wps->registrar);
|
wps_registrar_deinit(wpa_s->wps->registrar);
|
||||||
|
@ -2305,6 +2320,7 @@ struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_NFC
|
#ifdef CONFIG_WPS_NFC
|
||||||
|
|
||||||
static struct wpabuf *
|
static struct wpabuf *
|
||||||
wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
|
wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
|
||||||
const char *uuid)
|
const char *uuid)
|
||||||
|
@ -2314,7 +2330,7 @@ wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
|
||||||
u8 u[UUID_LEN], *use_uuid = NULL;
|
u8 u[UUID_LEN], *use_uuid = NULL;
|
||||||
u8 addr[ETH_ALEN], *use_addr = NULL;
|
u8 addr[ETH_ALEN], *use_addr = NULL;
|
||||||
|
|
||||||
if (!wpa_s->wps_er)
|
if (wpa_s->wps == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (uuid == NULL)
|
if (uuid == NULL)
|
||||||
|
@ -2326,11 +2342,26 @@ wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
if (wpa_s->conf->wps_nfc_dh_pubkey == NULL) {
|
||||||
* Handover Select carrier record for WPS uses the same format as
|
struct wps_context *wps = wpa_s->wps;
|
||||||
* configuration token.
|
if (wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
|
||||||
*/
|
&wpa_s->conf->wps_nfc_dh_privkey) < 0)
|
||||||
ret = wps_er_nfc_config_token(wpa_s->wps_er, use_uuid, use_addr);
|
return NULL;
|
||||||
|
|
||||||
|
wpas_wps_nfc_clear(wps);
|
||||||
|
wps->ap_nfc_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
|
||||||
|
wps->ap_nfc_dh_pubkey =
|
||||||
|
wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
|
||||||
|
wps->ap_nfc_dh_privkey =
|
||||||
|
wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
|
||||||
|
if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey) {
|
||||||
|
wpas_wps_nfc_clear(wps);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wps_er_nfc_handover_sel(wpa_s->wps_er, wpa_s->wps, use_uuid,
|
||||||
|
use_addr, wpa_s->conf->wps_nfc_dh_pubkey);
|
||||||
if (ndef && ret) {
|
if (ndef && ret) {
|
||||||
struct wpabuf *tmp;
|
struct wpabuf *tmp;
|
||||||
tmp = ndef_build_wifi(ret);
|
tmp = ndef_build_wifi(ret);
|
||||||
|
@ -2467,6 +2498,100 @@ int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||||
return wpas_wps_nfc_rx_handover_sel(wpa_s, sel);
|
return wpas_wps_nfc_rx_handover_sel(wpa_s, sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct wpabuf *req,
|
||||||
|
const struct wpabuf *sel)
|
||||||
|
{
|
||||||
|
struct wpabuf *wps;
|
||||||
|
int ret = -1;
|
||||||
|
u16 wsc_len;
|
||||||
|
const u8 *pos;
|
||||||
|
struct wpabuf msg;
|
||||||
|
struct wps_parse_attr attr;
|
||||||
|
u16 dev_pw_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enrollee/station is always initiator of the NFC connection handover,
|
||||||
|
* so use the request message here to find Enrollee public key hash.
|
||||||
|
*/
|
||||||
|
wps = ndef_parse_wifi(req);
|
||||||
|
if (wps == NULL)
|
||||||
|
return -1;
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Received application/vnd.wfa.wsc "
|
||||||
|
"payload from NFC connection handover");
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "WPS: NFC payload", wps);
|
||||||
|
if (wpabuf_len(wps) < 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Too short Wi-Fi Handover Request "
|
||||||
|
"Message");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
pos = wpabuf_head(wps);
|
||||||
|
wsc_len = WPA_GET_BE16(pos);
|
||||||
|
if (wsc_len > wpabuf_len(wps) - 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Invalid WSC attribute length (%u) "
|
||||||
|
"in rt Wi-Fi Handover Request Message", wsc_len);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"WPS: WSC attributes in Wi-Fi Handover Request Message",
|
||||||
|
pos, wsc_len);
|
||||||
|
if (wsc_len < wpabuf_len(wps) - 2) {
|
||||||
|
wpa_hexdump(MSG_DEBUG,
|
||||||
|
"WPS: Ignore extra data after WSC attributes",
|
||||||
|
pos + wsc_len, wpabuf_len(wps) - 2 - wsc_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_set(&msg, pos, wsc_len);
|
||||||
|
ret = wps_parse_msg(&msg, &attr);
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Could not parse WSC attributes in "
|
||||||
|
"Wi-Fi Handover Request Message");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr.oob_dev_password == NULL ||
|
||||||
|
attr.oob_dev_password_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: No Out-of-Band Device Password "
|
||||||
|
"included in Wi-Fi Handover Request Message");
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr.uuid_e == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: No UUID-E included in Wi-Fi "
|
||||||
|
"Handover Request Message");
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", attr.uuid_e, WPS_UUID_LEN);
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: Out-of-Band Device Password",
|
||||||
|
attr.oob_dev_password, attr.oob_dev_password_len);
|
||||||
|
dev_pw_id = WPA_GET_BE16(attr.oob_dev_password +
|
||||||
|
WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Unexpected OOB Device Password ID "
|
||||||
|
"%u in Wi-Fi Handover Request Message", dev_pw_id);
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Public Key hash",
|
||||||
|
attr.oob_dev_password, WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
|
|
||||||
|
ret = wps_registrar_add_nfc_pw_token(wpa_s->wps->registrar,
|
||||||
|
attr.oob_dev_password,
|
||||||
|
DEV_PW_NFC_CONNECTION_HANDOVER,
|
||||||
|
NULL, 0, 1);
|
||||||
|
|
||||||
|
out:
|
||||||
|
wpabuf_free(wps);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WPS_NFC */
|
#endif /* CONFIG_WPS_NFC */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,9 @@ int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
|
||||||
int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||||
const struct wpabuf *req,
|
const struct wpabuf *req,
|
||||||
const struct wpabuf *sel);
|
const struct wpabuf *sel);
|
||||||
|
int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct wpabuf *req,
|
||||||
|
const struct wpabuf *sel);
|
||||||
void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
|
void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_scan_results *scan_res);
|
struct wpa_scan_results *scan_res);
|
||||||
void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid);
|
||||||
|
|
Loading…
Reference in a new issue