WPS NFC: Add AP mode connection handover report

The new NFC connection handover design requires the AP/Registrar to
process the connection handover request message received from the
Enrollee. Add control interface commands for handling this.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-04-02 18:30:58 +03:00 committed by Jouni Malinen
parent 41f9ffb635
commit 3189ca055d
3 changed files with 162 additions and 8 deletions

View file

@ -399,13 +399,70 @@ static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
char *cmd)
{
/*
* Since NFC connection handover provided full WPS Credential, there is
* no need for additional operations within hostapd. Just report this in
* debug log.
*/
wpa_printf(MSG_DEBUG, "NFC: Connection handover reported: %s", cmd);
return 0;
size_t len;
struct wpabuf *req, *sel;
int ret;
char *pos, *role, *type, *pos2;
role = cmd;
pos = os_strchr(role, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
type = pos;
pos = os_strchr(type, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
pos2 = os_strchr(pos, ' ');
if (pos2 == NULL)
return -1;
*pos2++ = '\0';
len = os_strlen(pos);
if (len & 0x01)
return -1;
len /= 2;
req = wpabuf_alloc(len);
if (req == NULL)
return -1;
if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
wpabuf_free(req);
return -1;
}
len = os_strlen(pos2);
if (len & 0x01) {
wpabuf_free(req);
return -1;
}
len /= 2;
sel = wpabuf_alloc(len);
if (sel == NULL) {
wpabuf_free(req);
return -1;
}
if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
wpabuf_free(req);
wpabuf_free(sel);
return -1;
}
if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
} else {
wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
"reported: role=%s type=%s", role, type);
ret = -1;
}
wpabuf_free(req);
wpabuf_free(sel);
return ret;
}
#endif /* CONFIG_WPS_NFC */
@ -1101,7 +1158,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
char buf[256];
char buf[4096];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);

View file

@ -1808,6 +1808,100 @@ struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef)
}
int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd,
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(hapd->wps->registrar,
attr.oob_dev_password,
DEV_PW_NFC_CONNECTION_HANDOVER,
NULL, 0, 1);
out:
wpabuf_free(wps);
return ret;
}
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef)
{
if (hapd->conf->wps_nfc_pw_from_config) {

View file

@ -37,6 +37,9 @@ int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd,
struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd,
int ndef);
struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef);
int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd,
const struct wpabuf *req,
const struct wpabuf *sel);
struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef);
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd);
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd);