P2P NFC: Report connection handover as trigger for P2P

"NFC_REPORT_HANDOVER {INIT,RESP} P2P <req> <sel>" can now be used to
report completed NFC negotiated connection handover in which the P2P
alternative carrier was selected.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-04-27 18:50:14 +03:00 committed by Jouni Malinen
parent 9358878055
commit db6ae69e6b
12 changed files with 531 additions and 11 deletions

View file

@ -4421,4 +4421,106 @@ struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p)
return p2p_build_nfc_handover(p2p);
}
int p2p_process_nfc_connection_handover(struct p2p_data *p2p,
struct p2p_nfc_params *params)
{
struct p2p_message msg;
struct p2p_device *dev;
const u8 *p2p_dev_addr;
int peer_go = 0;
params->next_step = NO_ACTION;
if (p2p_parse_ies_separate(params->wsc_attr, params->wsc_len,
params->p2p_attr, params->p2p_len, &msg)) {
p2p_dbg(p2p, "Failed to parse WSC/P2P attributes from NFC");
p2p_parse_free(&msg);
return -1;
}
if (msg.p2p_device_addr)
p2p_dev_addr = msg.p2p_device_addr;
else if (msg.device_id)
p2p_dev_addr = msg.device_id;
else {
p2p_dbg(p2p, "Ignore scan data without P2P Device Info or P2P Device Id");
p2p_parse_free(&msg);
return -1;
}
if (msg.oob_dev_password) {
os_memcpy(params->oob_dev_pw, msg.oob_dev_password,
msg.oob_dev_password_len);
params->oob_dev_pw_len = msg.oob_dev_password_len;
}
dev = p2p_create_device(p2p, p2p_dev_addr);
if (dev == NULL) {
p2p_parse_free(&msg);
return -1;
}
params->peer = &dev->info;
os_get_reltime(&dev->last_seen);
dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
p2p_copy_wps_info(p2p, dev, 0, &msg);
if (msg.oob_go_neg_channel) {
int freq;
if (msg.oob_go_neg_channel[3] == 0 &&
msg.oob_go_neg_channel[4] == 0)
freq = 0;
else
freq = p2p_channel_to_freq(msg.oob_go_neg_channel[3],
msg.oob_go_neg_channel[4]);
if (freq < 0) {
p2p_dbg(p2p, "Unknown peer OOB GO Neg channel");
} else {
p2p_dbg(p2p, "Peer OOB GO Neg channel: %u MHz", freq);
dev->oob_go_neg_freq = freq;
}
if (!params->sel) {
freq = p2p_channel_to_freq(p2p->cfg->reg_class,
p2p->cfg->channel);
if (freq < 0) {
p2p_dbg(p2p, "Own listen channel not known");
return -1;
}
p2p_dbg(p2p, "Use own Listen channel as OOB GO Neg channel: %u MHz",
freq);
dev->oob_go_neg_freq = freq;
}
if (msg.oob_go_neg_channel[5] == P2P_GO_IN_A_GROUP)
peer_go = 1;
}
p2p_parse_free(&msg);
if (dev->flags & P2P_DEV_USER_REJECTED) {
p2p_dbg(p2p, "Do not report rejected device");
return 0;
}
if (!(dev->flags & P2P_DEV_REPORTED)) {
p2p->cfg->dev_found(p2p->cfg->cb_ctx, p2p_dev_addr, &dev->info,
!(dev->flags & P2P_DEV_REPORTED_ONCE));
dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
}
if (peer_go)
params->next_step = JOIN_GROUP;
else if (p2p->num_groups > 0)
params->next_step = AUTH_JOIN;
else if (params->sel)
params->next_step = INIT_GO_NEG;
else
params->next_step = RESP_GO_NEG;
return 0;
}
#endif /* CONFIG_WPS_NFC */

View file

@ -9,6 +9,8 @@
#ifndef P2P_H
#define P2P_H
#include "wps/wps_defs.h"
/**
* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
*/
@ -1900,4 +1902,23 @@ const char * p2p_get_state_txt(struct p2p_data *p2p);
struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p);
struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p);
struct p2p_nfc_params {
int sel;
const u8 *wsc_attr;
size_t wsc_len;
const u8 *p2p_attr;
size_t p2p_len;
enum {
NO_ACTION, JOIN_GROUP, AUTH_JOIN, INIT_GO_NEG, RESP_GO_NEG
} next_step;
struct p2p_peer_info *peer;
u8 oob_dev_pw[WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_LEN];
size_t oob_dev_pw_len;
};
int p2p_process_nfc_connection_handover(struct p2p_data *p2p,
struct p2p_nfc_params *params);
#endif /* P2P_H */

View file

@ -217,6 +217,8 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
}
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
if (dev->oob_go_neg_freq > 0)
freq = dev->oob_go_neg_freq;
if (freq <= 0) {
p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
MACSTR " to send GO Negotiation Request",
@ -614,7 +616,11 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
if (dev && dev->flags & P2P_DEV_USER_REJECTED) {
p2p_dbg(p2p, "User has rejected this peer");
status = P2P_SC_FAIL_REJECTED_BY_USER;
} else if (dev == NULL || dev->wps_method == WPS_NOT_READY) {
} else if (dev == NULL ||
(dev->wps_method == WPS_NOT_READY &&
(p2p->authorized_oob_dev_pw_id == 0 ||
p2p->authorized_oob_dev_pw_id !=
msg.dev_password_id))) {
p2p_dbg(p2p, "Not ready for GO negotiation with " MACSTR,
MAC2STR(sa));
status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
@ -701,6 +707,28 @@ void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa,
}
break;
default:
if (msg.dev_password_id &&
msg.dev_password_id == dev->oob_pw_id) {
p2p_dbg(p2p, "Peer using NFC");
if (dev->wps_method != WPS_NFC) {
p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(
dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
}
#ifdef CONFIG_WPS_NFC
if (p2p->authorized_oob_dev_pw_id &&
msg.dev_password_id ==
p2p->authorized_oob_dev_pw_id) {
p2p_dbg(p2p, "Using static handover with our device password from NFC Tag");
dev->wps_method = WPS_NFC;
dev->oob_pw_id = p2p->authorized_oob_dev_pw_id;
break;
}
#endif /* CONFIG_WPS_NFC */
p2p_dbg(p2p, "Unsupported Device Password ID %d",
msg.dev_password_id);
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
@ -1026,6 +1054,17 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
}
break;
default:
if (msg.dev_password_id &&
msg.dev_password_id == dev->oob_pw_id) {
p2p_dbg(p2p, "Peer using NFC");
if (dev->wps_method != WPS_NFC) {
p2p_dbg(p2p, "We have wps_method=%s -> incompatible",
p2p_wps_method_str(dev->wps_method));
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;
goto fail;
}
break;
}
p2p_dbg(p2p, "Unsupported Device Password ID %d",
msg.dev_password_id);
status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD;

View file

@ -27,6 +27,7 @@ struct p2p_device {
struct dl_list list;
struct os_reltime last_seen;
int listen_freq;
int oob_go_neg_freq;
enum p2p_wps_method wps_method;
u16 oob_pw_id;
@ -465,6 +466,8 @@ struct p2p_data {
struct wpabuf *wfd_assoc_bssid;
struct wpabuf *wfd_coupled_sink_info;
#endif /* CONFIG_WIFI_DISPLAY */
u16 authorized_oob_dev_pw_id;
};
/**

View file

@ -178,7 +178,6 @@ void wps_deinit(struct wps_data *data)
wps_device_data_free(&data->peer_dev);
os_free(data->new_ap_settings);
dh5_free(data->dh_ctx);
os_free(data->nfc_pw_token);
os_free(data);
}

View file

@ -31,6 +31,7 @@
struct wps_nfc_pw_token {
struct dl_list list;
u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
unsigned int peer_pk_hash_known:1;
u16 pw_id;
u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
size_t dev_pw_len;
@ -1822,7 +1823,8 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
}
#ifdef CONFIG_WPS_NFC
if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob) {
if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob &&
wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
/*
* Use abbreviated handshake since public key hash allowed
* Enrollee to validate our public key similarly to how Enrollee
@ -2585,7 +2587,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
wps->dev_pw_id, wps->wps, wps->wps->registrar);
token = wps_get_nfc_pw_token(
&wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
if (token) {
if (token && token->peer_pk_hash_known) {
wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
"Password Token");
dl_list_del(&token->list);
@ -2602,6 +2604,10 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
WPS_CFG_PUBLIC_KEY_HASH_MISMATCH;
return WPS_CONTINUE;
}
} else if (token) {
wpa_printf(MSG_DEBUG, "WPS: Found matching NFC "
"Password Token (no peer PK hash)");
wps->nfc_pw_token = token;
}
}
#endif /* CONFIG_WPS_NFC */
@ -3543,13 +3549,23 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN)
return -1;
if (pw_id == DEV_PW_NFC_CONNECTION_HANDOVER &&
(pubkey_hash == NULL || !pk_hash_provided_oob)) {
wpa_printf(MSG_DEBUG, "WPS: Unexpected NFC Password Token "
"addition - missing public key hash");
return -1;
}
wps_free_nfc_pw_tokens(&reg->nfc_pw_tokens, pw_id);
token = os_zalloc(sizeof(*token));
if (token == NULL)
return -1;
os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
token->peer_pk_hash_known = pubkey_hash != NULL;
if (pubkey_hash)
os_memcpy(token->pubkey_hash, pubkey_hash,
WPS_OOB_PUBKEY_HASH_LEN);
token->pw_id = pw_id;
token->pk_hash_provided_oob = pk_hash_provided_oob;
if (dev_pw) {
@ -3615,6 +3631,14 @@ void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg,
wps_registrar_remove_authorized_mac(reg,
(u8 *) "\xff\xff\xff\xff\xff\xff");
wps_registrar_selected_registrar_changed(reg, 0);
/*
* Free the NFC password token if it was used only for a single protocol
* run. The static handover case uses the same password token multiple
* times, so do not free that case here.
*/
if (token->peer_pk_hash_known)
os_free(token);
}
#endif /* CONFIG_WPS_NFC */

View file

@ -15,6 +15,7 @@
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "crypto/dh_group5.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
@ -1152,3 +1153,48 @@ int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
return 0;
}
#ifdef CONFIG_WPS_NFC
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
const struct wpabuf *pw, const u8 *pubkey_hash)
{
struct hostapd_data *hapd;
struct wps_context *wps;
if (!wpa_s->ap_iface)
return -1;
hapd = wpa_s->ap_iface->bss[0];
wps = hapd->wps;
if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL ||
wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) {
wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
return -1;
}
dh5_free(wps->dh_ctx);
wpabuf_free(wps->dh_pubkey);
wpabuf_free(wps->dh_privkey);
wps->dh_privkey = wpabuf_dup(
wpa_s->parent->conf->wps_nfc_dh_privkey);
wps->dh_pubkey = wpabuf_dup(
wpa_s->parent->conf->wps_nfc_dh_pubkey);
if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
wps->dh_ctx = NULL;
wpabuf_free(wps->dh_pubkey);
wps->dh_pubkey = NULL;
wpabuf_free(wps->dh_privkey);
wps->dh_privkey = NULL;
return -1;
}
wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, wps->dh_pubkey);
if (wps->dh_ctx == NULL)
return -1;
return wps_registrar_add_nfc_pw_token(hapd->wps->registrar, pubkey_hash,
pw_id,
pw ? wpabuf_head(pw) : NULL,
pw ? wpabuf_len(pw) : 0, 1);
}
#endif /* CONFIG_WPS_NFC */

View file

@ -72,5 +72,7 @@ wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
const struct wpabuf *req,
const struct wpabuf *sel);
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
const struct wpabuf *pw, const u8 *pubkey_hash);
#endif /* AP_H */

View file

@ -1193,6 +1193,12 @@ static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s,
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 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0)
{
ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel);
} else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0)
{
ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel);
} else {
wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
"reported: role=%s type=%s", role, type);

View file

@ -1107,9 +1107,20 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
res->ssid, res->ssid_len);
wpa_supplicant_ap_deinit(wpa_s);
wpas_copy_go_neg_results(wpa_s, res);
if (res->wps_method == WPS_PBC)
if (res->wps_method == WPS_PBC) {
wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1);
else {
#ifdef CONFIG_WPS_NFC
} else if (res->wps_method == WPS_NFC) {
wpas_wps_start_nfc(wpa_s, res->peer_interface_addr,
wpa_s->parent->p2p_oob_dev_pw,
wpa_s->parent->p2p_oob_dev_pw_id, 1,
wpa_s->parent->p2p_oob_dev_pw_id ==
DEV_PW_NFC_CONNECTION_HANDOVER ?
wpa_s->parent->p2p_peer_oob_pubkey_hash :
NULL,
NULL, 0);
#endif /* CONFIG_WPS_NFC */
} else {
u16 dev_pw_id = DEV_PW_DEFAULT;
if (wpa_s->p2p_wps_method == WPS_PIN_KEYPAD)
dev_pw_id = DEV_PW_REGISTRAR_SPECIFIED;
@ -1233,10 +1244,24 @@ static void p2p_go_configured(void *ctx, void *data)
"filtering");
return;
}
if (params->wps_method == WPS_PBC)
if (params->wps_method == WPS_PBC) {
wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
params->peer_device_addr);
else if (wpa_s->p2p_pin[0])
#ifdef CONFIG_WPS_NFC
} else if (params->wps_method == WPS_NFC) {
if (wpa_s->parent->p2p_oob_dev_pw_id !=
DEV_PW_NFC_CONNECTION_HANDOVER &&
!wpa_s->parent->p2p_oob_dev_pw) {
wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
return;
}
wpas_ap_wps_add_nfc_pw(
wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
wpa_s->parent->p2p_oob_dev_pw,
wpa_s->parent->p2p_peer_oob_pk_hash_known ?
wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
#endif /* CONFIG_WPS_NFC */
} else if (wpa_s->p2p_pin[0])
wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
wpa_s->p2p_pin, NULL, 0, 0);
os_free(wpa_s->go_params);
@ -3848,6 +3873,9 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
}
eloop_cancel_timeout(wpas_p2p_send_action_work_timeout, wpa_s, NULL);
wpabuf_free(wpa_s->p2p_oob_dev_pw);
wpa_s->p2p_oob_dev_pw = NULL;
/* TODO: remove group interface from the driver if this wpa_s instance
* is on top of a P2P group interface */
}
@ -3942,7 +3970,9 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
go_intent, own_interface_addr, force_freq,
persistent_group, ssid ? ssid->ssid : NULL,
ssid ? ssid->ssid_len : 0,
wpa_s->p2p_pd_before_go_neg, pref_freq, 0);
wpa_s->p2p_pd_before_go_neg, pref_freq,
wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
0);
}
@ -3959,7 +3989,9 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
go_intent, own_interface_addr, force_freq,
persistent_group, ssid ? ssid->ssid : NULL,
ssid ? ssid->ssid_len : 0, pref_freq, 0);
ssid ? ssid->ssid_len : 0, pref_freq,
wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
0);
}
@ -7025,4 +7057,240 @@ struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
}
static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
struct p2p_nfc_params *params)
{
wpa_printf(MSG_DEBUG, "P2P: Initiate join-group based on NFC "
"connection handover");
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
0, -1, 0, 1, 1);
}
static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
struct p2p_nfc_params *params)
{
wpa_printf(MSG_DEBUG, "P2P: Authorize join-group based on NFC "
"connection handover");
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
if (ssid == NULL)
continue;
if (ssid->mode != WPAS_MODE_P2P_GO)
continue;
if (wpa_s->ap_iface == NULL)
continue;
break;
}
if (wpa_s == NULL) {
wpa_printf(MSG_DEBUG, "P2P: Could not find GO interface");
return -1;
}
if (wpa_s->parent->p2p_oob_dev_pw_id !=
DEV_PW_NFC_CONNECTION_HANDOVER &&
!wpa_s->parent->p2p_oob_dev_pw) {
wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
return -1;
}
return wpas_ap_wps_add_nfc_pw(
wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
wpa_s->parent->p2p_oob_dev_pw,
wpa_s->parent->p2p_peer_oob_pk_hash_known ?
wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
}
static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
struct p2p_nfc_params *params)
{
wpa_printf(MSG_DEBUG, "P2P: Initiate GO Negotiation based on NFC "
"connection handover");
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
0, -1, 0, 1, 1);
}
static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
struct p2p_nfc_params *params)
{
int res;
wpa_printf(MSG_DEBUG, "P2P: Authorize GO Negotiation based on NFC "
"connection handover");
res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
0, -1, 0, 1, 1);
if (res)
return res;
res = wpas_p2p_listen(wpa_s, 60);
if (res) {
p2p_unauthorize(wpa_s->global->p2p,
params->peer->p2p_device_addr);
}
return res;
}
static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
const struct wpabuf *data,
int sel, int tag)
{
const u8 *pos, *end;
u16 len, id;
struct p2p_nfc_params params;
int res;
os_memset(&params, 0, sizeof(params));
params.sel = sel;
wpa_hexdump_buf(MSG_DEBUG, "P2P: Received NFC tag payload", data);
pos = wpabuf_head(data);
end = pos + wpabuf_len(data);
if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "P2P: Not enough data for Length of WSC "
"attributes");
return -1;
}
len = WPA_GET_BE16(pos);
pos += 2;
if (pos + len > end) {
wpa_printf(MSG_DEBUG, "P2P: Not enough data for WSC "
"attributes");
return -1;
}
params.wsc_attr = pos;
params.wsc_len = len;
pos += len;
if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "P2P: Not enough data for Length of P2P "
"attributes");
return -1;
}
len = WPA_GET_BE16(pos);
pos += 2;
if (pos + len > end) {
wpa_printf(MSG_DEBUG, "P2P: Not enough data for P2P "
"attributes");
return -1;
}
params.p2p_attr = pos;
params.p2p_len = len;
pos += len;
wpa_hexdump(MSG_DEBUG, "P2P: WSC attributes",
params.wsc_attr, params.wsc_len);
wpa_hexdump(MSG_DEBUG, "P2P: P2P attributes",
params.p2p_attr, params.p2p_len);
if (pos < end) {
wpa_hexdump(MSG_DEBUG,
"P2P: Ignored extra data after P2P attributes",
pos, end - pos);
}
res = p2p_process_nfc_connection_handover(wpa_s->global->p2p, &params);
if (res)
return res;
wpabuf_free(wpa_s->p2p_oob_dev_pw);
wpa_s->p2p_oob_dev_pw = NULL;
if (params.oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
wpa_printf(MSG_DEBUG, "P2P: No peer OOB Dev Pw "
"received");
return -1;
}
id = WPA_GET_BE16(params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN);
wpa_printf(MSG_DEBUG, "P2P: Peer OOB Dev Pw %u", id);
wpa_hexdump(MSG_DEBUG, "P2P: Peer OOB Public Key hash",
params.oob_dev_pw, WPS_OOB_PUBKEY_HASH_LEN);
os_memcpy(wpa_s->p2p_peer_oob_pubkey_hash,
params.oob_dev_pw, WPS_OOB_PUBKEY_HASH_LEN);
wpa_s->p2p_peer_oob_pk_hash_known = 1;
if (tag) {
if (id < 0x10) {
wpa_printf(MSG_DEBUG, "P2P: Static handover - invalid "
"peer OOB Device Password Id %u", id);
return -1;
}
wpa_printf(MSG_DEBUG, "P2P: Static handover - use peer OOB "
"Device Password Id %u", id);
wpa_hexdump_key(MSG_DEBUG, "P2P: Peer OOB Device Password",
params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN + 2,
params.oob_dev_pw_len -
WPS_OOB_PUBKEY_HASH_LEN - 2);
wpa_s->p2p_oob_dev_pw_id = id;
wpa_s->p2p_oob_dev_pw = wpabuf_alloc_copy(
params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN + 2,
params.oob_dev_pw_len -
WPS_OOB_PUBKEY_HASH_LEN - 2);
if (wpa_s->p2p_oob_dev_pw == NULL)
return -1;
if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
&wpa_s->conf->wps_nfc_dh_privkey) < 0)
return -1;
} else {
wpa_printf(MSG_DEBUG, "P2P: Using abbreviated WPS handshake "
"without Device Password");
wpa_s->p2p_oob_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
}
switch (params.next_step) {
case NO_ACTION:
return 0;
case JOIN_GROUP:
return wpas_p2p_nfc_join_group(wpa_s, &params);
case AUTH_JOIN:
return wpas_p2p_nfc_auth_join(wpa_s, &params);
case INIT_GO_NEG:
return wpas_p2p_nfc_init_go_neg(wpa_s, &params);
case RESP_GO_NEG:
/* TODO: use own OOB Dev Pw */
return wpas_p2p_nfc_resp_go_neg(wpa_s, &params);
}
return -1;
}
int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init,
const struct wpabuf *req,
const struct wpabuf *sel)
{
struct wpabuf *tmp;
int ret;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
wpa_printf(MSG_DEBUG, "NFC: P2P connection handover reported");
wpa_hexdump_ascii(MSG_DEBUG, "NFC: Req",
wpabuf_head(req), wpabuf_len(req));
wpa_hexdump_ascii(MSG_DEBUG, "NFC: Sel",
wpabuf_head(sel), wpabuf_len(sel));
tmp = ndef_parse_p2p(init ? sel : req);
if (tmp == NULL) {
wpa_printf(MSG_DEBUG, "P2P: Could not parse NDEF");
return -1;
}
ret = wpas_p2p_nfc_connection_handover(wpa_s, tmp, init, 0);
wpabuf_free(tmp);
return ret;
}
#endif /* CONFIG_WPS_NFC */

View file

@ -152,6 +152,9 @@ struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
int ndef);
struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef, int tag);
int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init,
const struct wpabuf *req,
const struct wpabuf *sel);
#ifdef CONFIG_P2P
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);

View file

@ -12,6 +12,7 @@
#include "utils/list.h"
#include "common/defs.h"
#include "common/sae.h"
#include "wps/wps_defs.h"
#include "config_ssid.h"
extern const char *wpa_supplicant_version;
@ -713,6 +714,7 @@ struct wpa_supplicant {
unsigned int p2p_go_group_formation_completed:1;
unsigned int waiting_presence_resp;
int p2p_first_connection_timeout;
unsigned int p2p_peer_oob_pk_hash_known:1;
int p2p_persistent_go_freq;
int p2p_persistent_id;
int p2p_go_intent;
@ -722,6 +724,11 @@ struct wpa_supplicant {
struct wpa_radio_work *p2p_scan_work;
struct wpa_radio_work *p2p_listen_work;
struct wpa_radio_work *p2p_send_action_work;
u16 p2p_oob_dev_pw_id; /* OOB Device Password Id for group formation */
struct wpabuf *p2p_oob_dev_pw; /* OOB Device Password for group
* formation */
u8 p2p_peer_oob_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
#endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid;