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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(¶ms, 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, ¶ms);
|
||||
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, ¶ms);
|
||||
case AUTH_JOIN:
|
||||
return wpas_p2p_nfc_auth_join(wpa_s, ¶ms);
|
||||
case INIT_GO_NEG:
|
||||
return wpas_p2p_nfc_init_go_neg(wpa_s, ¶ms);
|
||||
case RESP_GO_NEG:
|
||||
/* TODO: use own OOB Dev Pw */
|
||||
return wpas_p2p_nfc_resp_go_neg(wpa_s, ¶ms);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue