diff options
author | Jouni Malinen <jouni@qca.qualcomm.com> | 2013-02-15 15:07:28 (GMT) |
---|---|---|
committer | Jouni Malinen <j@w1.fi> | 2014-01-27 19:10:56 (GMT) |
commit | 93588780558074279f1603b2155d93bc76d71407 (patch) | |
tree | a131a09bf1b5485fdf7a16f5b0f0f3ec952c21e0 /wpa_supplicant | |
parent | c00ab85f7e45f8ab4b0039320146f339d3227a3c (diff) | |
download | hostap-93588780558074279f1603b2155d93bc76d71407.zip hostap-93588780558074279f1603b2155d93bc76d71407.tar.gz hostap-93588780558074279f1603b2155d93bc76d71407.tar.bz2 |
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>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r-- | wpa_supplicant/ctrl_iface.c | 63 | ||||
-rw-r--r-- | wpa_supplicant/p2p_supplicant.c | 103 | ||||
-rw-r--r-- | wpa_supplicant/p2p_supplicant.h | 4 |
3 files changed, 170 insertions, 0 deletions
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7ba17db..cde9c46 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 8ec70dc..e61d5ce 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -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 */ diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 7abfb12..17e7bae 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -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); |