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:
parent
9358878055
commit
db6ae69e6b
12 changed files with 531 additions and 11 deletions
102
src/p2p/p2p.c
102
src/p2p/p2p.c
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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(®->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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue