P2P NFC: Build connection handover messages
"NFC_GET_HANDOVER_{REQ,SEL} NDEF P2P-CR" can now be used to build P2P alternative carrier record for NFC connection handover request/select messages. Static connection handover case can be enabled by configuring the DH parameters (either with wps_nfc_* configuration parameters or with WPS_NFC_TOKEN command at run time. The NFC Tag contents can be generated with "NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG" after having configured Listen channel (p2p_listen_reg_class/p2p_listen_channel). Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
c00ab85f7e
commit
9358878055
7 changed files with 233 additions and 0 deletions
|
@ -4370,3 +4370,55 @@ void p2p_err(struct p2p_data *p2p, const char *fmt, ...)
|
|||
va_end(ap);
|
||||
p2p->cfg->debug_print(p2p->cfg->cb_ctx, MSG_ERROR, buf);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
|
||||
static struct wpabuf * p2p_build_nfc_handover(struct p2p_data *p2p)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
u8 op_class, channel;
|
||||
enum p2p_role_indication role = P2P_DEVICE_NOT_IN_GROUP;
|
||||
|
||||
buf = wpabuf_alloc(1000);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
op_class = p2p->cfg->reg_class;
|
||||
channel = p2p->cfg->channel;
|
||||
|
||||
p2p_buf_add_capability(buf, p2p->dev_capab &
|
||||
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
|
||||
p2p_buf_add_device_info(buf, p2p, NULL);
|
||||
|
||||
if (p2p->num_groups > 0) {
|
||||
role = P2P_GO_IN_A_GROUP;
|
||||
p2p_freq_to_channel(p2p_group_get_freq(p2p->groups[0]),
|
||||
&op_class, &channel);
|
||||
}
|
||||
|
||||
p2p_buf_add_oob_go_neg_channel(buf, p2p->cfg->country, op_class,
|
||||
channel, role);
|
||||
|
||||
if (p2p->num_groups > 0) {
|
||||
/* Limit number of clients to avoid very long message */
|
||||
p2p_buf_add_group_info(p2p->groups[0], buf, 5);
|
||||
p2p_group_buf_add_id(p2p->groups[0], buf);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * p2p_build_nfc_handover_req(struct p2p_data *p2p)
|
||||
{
|
||||
return p2p_build_nfc_handover(p2p);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * p2p_build_nfc_handover_sel(struct p2p_data *p2p)
|
||||
{
|
||||
return p2p_build_nfc_handover(p2p);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
|
|
@ -1897,4 +1897,7 @@ int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
|
|||
*/
|
||||
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);
|
||||
|
||||
#endif /* P2P_H */
|
||||
|
|
|
@ -419,6 +419,13 @@ void p2p_buf_add_group_info(struct p2p_group *group, struct wpabuf *buf,
|
|||
}
|
||||
|
||||
|
||||
void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf)
|
||||
{
|
||||
p2p_buf_add_group_id(buf, group->p2p->cfg->dev_addr, group->cfg->ssid,
|
||||
group->cfg->ssid_len);
|
||||
}
|
||||
|
||||
|
||||
static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group)
|
||||
{
|
||||
struct wpabuf *p2p_subelems, *ie;
|
||||
|
|
|
@ -613,6 +613,7 @@ void p2p_group_force_beacon_update_ies(struct p2p_group *group);
|
|||
struct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g);
|
||||
void p2p_buf_add_group_info(struct p2p_group *group, struct wpabuf *buf,
|
||||
int max_clients);
|
||||
void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf);
|
||||
int p2p_group_get_freq(struct p2p_group *group);
|
||||
|
||||
|
||||
|
|
|
@ -928,6 +928,30 @@ static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s,
|
||||
char *reply, size_t max_len,
|
||||
int ndef)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
|
||||
buf = wpas_p2p_nfc_handover_req(wpa_s, ndef);
|
||||
if (buf == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
|
||||
wpabuf_len(buf));
|
||||
reply[res++] = '\n';
|
||||
reply[res] = '\0';
|
||||
|
||||
wpabuf_free(buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
|
||||
char *cmd, char *reply,
|
||||
size_t max_len)
|
||||
|
@ -954,6 +978,11 @@ static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
|
|||
wpa_s, reply, max_len, ndef);
|
||||
}
|
||||
|
||||
if (os_strcmp(pos, "P2P-CR") == 0) {
|
||||
return wpas_ctrl_nfc_get_handover_req_p2p(
|
||||
wpa_s, reply, max_len, ndef);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -980,6 +1009,28 @@ static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s,
|
||||
char *reply, size_t max_len,
|
||||
int ndef, int tag)
|
||||
{
|
||||
struct wpabuf *buf;
|
||||
int res;
|
||||
|
||||
buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
|
||||
wpabuf_len(buf));
|
||||
reply[res++] = '\n';
|
||||
reply[res] = '\0';
|
||||
|
||||
wpabuf_free(buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
|
||||
char *cmd, char *reply,
|
||||
size_t max_len)
|
||||
|
@ -1003,11 +1054,23 @@ static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
|
|||
if (pos2)
|
||||
*pos2++ = '\0';
|
||||
if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
|
||||
if (!ndef)
|
||||
return -1;
|
||||
return wpas_ctrl_nfc_get_handover_sel_wps(
|
||||
wpa_s, reply, max_len, ndef,
|
||||
os_strcmp(pos, "WPS-CR") == 0, pos2);
|
||||
}
|
||||
|
||||
if (os_strcmp(pos, "P2P-CR") == 0) {
|
||||
return wpas_ctrl_nfc_get_handover_sel_p2p(
|
||||
wpa_s, reply, max_len, ndef, 0);
|
||||
}
|
||||
|
||||
if (os_strcmp(pos, "P2P-CR-TAG") == 0) {
|
||||
return wpas_ctrl_nfc_get_handover_sel_p2p(
|
||||
wpa_s, reply, max_len, ndef, 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -6923,3 +6923,106 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->p2p_last_4way_hs_fail = ssid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS_NFC
|
||||
|
||||
static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
|
||||
struct wpabuf *p2p)
|
||||
{
|
||||
struct wpabuf *ret;
|
||||
|
||||
if (wsc == NULL) {
|
||||
wpabuf_free(p2p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p2p == NULL) {
|
||||
wpabuf_free(wsc);
|
||||
wpa_printf(MSG_DEBUG, "P2P: No p2p buffer for handover");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = wpabuf_alloc(2 + wpabuf_len(wsc) + 2 + wpabuf_len(p2p));
|
||||
if (ret == NULL) {
|
||||
wpabuf_free(wsc);
|
||||
wpabuf_free(p2p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpabuf_put_be16(ret, wpabuf_len(wsc));
|
||||
wpabuf_put_buf(ret, wsc);
|
||||
wpabuf_put_be16(ret, wpabuf_len(p2p));
|
||||
wpabuf_put_buf(ret, p2p);
|
||||
|
||||
wpabuf_free(wsc);
|
||||
wpabuf_free(p2p);
|
||||
wpa_hexdump_buf(MSG_DEBUG,
|
||||
"P2P: Generated NFC connection handover message", ret);
|
||||
|
||||
if (ndef && ret) {
|
||||
struct wpabuf *tmp;
|
||||
tmp = ndef_build_p2p(ret);
|
||||
wpabuf_free(ret);
|
||||
if (tmp == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Failed to NDEF encapsulate handover request");
|
||||
return NULL;
|
||||
}
|
||||
ret = tmp;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
|
||||
int ndef)
|
||||
{
|
||||
struct wpabuf *wsc, *p2p;
|
||||
|
||||
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No DH key available for handover request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsc = wps_build_nfc_handover_req_p2p(wpa_s->parent->wps,
|
||||
wpa_s->conf->wps_nfc_dh_pubkey);
|
||||
p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p);
|
||||
|
||||
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
|
||||
int ndef, int tag)
|
||||
{
|
||||
struct wpabuf *wsc, *p2p;
|
||||
|
||||
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!tag && 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 NULL;
|
||||
|
||||
wsc = wps_build_nfc_handover_sel_p2p(wpa_s->parent->wps,
|
||||
tag ?
|
||||
wpa_s->conf->wps_nfc_dev_pw_id :
|
||||
DEV_PW_NFC_CONNECTION_HANDOVER,
|
||||
wpa_s->conf->wps_nfc_dh_pubkey,
|
||||
tag ? wpa_s->conf->wps_nfc_dev_pw :
|
||||
NULL);
|
||||
p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p);
|
||||
|
||||
return wpas_p2p_nfc_handover(ndef, wsc, p2p);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
|
|
|
@ -148,6 +148,10 @@ void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
|
|||
const u8 *psk, size_t psk_len);
|
||||
void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
|
||||
int iface_addr);
|
||||
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);
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
|
||||
|
|
Loading…
Reference in a new issue