PASN: Add pairing verification wrapper function for Wi-Fi Aware
Wi-Fi Aware uses PASN handshake to authenticate peer devices. Devices can simply verify each other for subsequent sessions as long as the keys remain valid after authentication has been successful and pairing has been established. In pairing verification, Wi-Fi Aware devices uses PASN Authentication frames with custom PMKID and Wi-Fi Aware R4 specific verification IEs. It does not use wrapped data in the Authentication frames. This function provides support to construct PASN Authentication frames for pairing verification. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
325236948a
commit
6be84343af
2 changed files with 103 additions and 59 deletions
|
@ -152,6 +152,11 @@ int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
const struct wpabuf *comeback);
|
const struct wpabuf *comeback);
|
||||||
|
int wpa_pasn_verify(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
|
const u8 *bssid, int akmp, int cipher, u16 group,
|
||||||
|
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
|
const struct wpabuf *comeback);
|
||||||
int wpa_pasn_auth_rx(struct wpas_pasn *pasn, const u8 *data, size_t len,
|
int wpa_pasn_auth_rx(struct wpas_pasn *pasn, const u8 *data, size_t len,
|
||||||
struct wpa_pasn_params_data *pasn_params);
|
struct wpa_pasn_params_data *pasn_params);
|
||||||
int wpa_pasn_auth_tx_status(struct wpas_pasn *pasn,
|
int wpa_pasn_auth_tx_status(struct wpas_pasn *pasn,
|
||||||
|
|
|
@ -511,7 +511,8 @@ static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
|
||||||
|
|
||||||
|
|
||||||
static struct wpabuf * wpas_pasn_build_auth_1(struct wpas_pasn *pasn,
|
static struct wpabuf * wpas_pasn_build_auth_1(struct wpas_pasn *pasn,
|
||||||
const struct wpabuf *comeback)
|
const struct wpabuf *comeback,
|
||||||
|
bool verify)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
|
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
|
||||||
const u8 *pmkid;
|
const u8 *pmkid;
|
||||||
|
@ -562,7 +563,8 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpas_pasn *pasn,
|
||||||
* Note: Even when PMKSA is available, also add wrapped data as
|
* Note: Even when PMKSA is available, also add wrapped data as
|
||||||
* it is possible that the PMKID is no longer valid at the AP.
|
* it is possible that the PMKID is no longer valid at the AP.
|
||||||
*/
|
*/
|
||||||
wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn);
|
if (!verify)
|
||||||
|
wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0)
|
if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0)
|
||||||
|
@ -855,15 +857,80 @@ static int wpas_pasn_set_pmk(struct wpas_pasn *pasn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_pasn_send_auth_1(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
|
const u8 *bssid, int akmp, int cipher,
|
||||||
|
u16 group, int freq,
|
||||||
|
const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
|
const struct wpabuf *comeback, bool verify)
|
||||||
|
{
|
||||||
|
struct wpabuf *frame;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pasn->ecdh = crypto_ecdh_init(group);
|
||||||
|
if (!pasn->ecdh) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beacon_rsne && beacon_rsne_len) {
|
||||||
|
pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
|
||||||
|
beacon_rsnxe_len);
|
||||||
|
if (!pasn->beacon_rsne_rsnxe) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Failed storing beacon RSNE/RSNXE");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne,
|
||||||
|
beacon_rsne_len);
|
||||||
|
if (beacon_rsnxe && beacon_rsnxe_len)
|
||||||
|
wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
|
||||||
|
beacon_rsnxe_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
pasn->akmp = akmp;
|
||||||
|
pasn->cipher = cipher;
|
||||||
|
pasn->group = group;
|
||||||
|
pasn->freq = freq;
|
||||||
|
|
||||||
|
os_memcpy(pasn->own_addr, own_addr, ETH_ALEN);
|
||||||
|
os_memcpy(pasn->bssid, bssid, ETH_ALEN);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Init%s: " MACSTR " akmp=0x%x, cipher=0x%x, group=%u",
|
||||||
|
verify ? " (verify)" : "",
|
||||||
|
MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher, pasn->group);
|
||||||
|
|
||||||
|
frame = wpas_pasn_build_auth_1(pasn, comeback, verify);
|
||||||
|
if (!frame) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pasn->send_mgmt(pasn->cb_ctx,
|
||||||
|
wpabuf_head(frame), wpabuf_len(frame), 0,
|
||||||
|
pasn->freq, 1000);
|
||||||
|
|
||||||
|
wpabuf_free(frame);
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
|
int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
const u8 *bssid, int akmp, int cipher, u16 group,
|
const u8 *bssid, int akmp, int cipher, u16 group,
|
||||||
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
const struct wpabuf *comeback)
|
const struct wpabuf *comeback)
|
||||||
{
|
{
|
||||||
struct wpabuf *frame;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* TODO: Currently support only ECC groups */
|
/* TODO: Currently support only ECC groups */
|
||||||
if (!dragonfly_suitable_group(group, 1)) {
|
if (!dragonfly_suitable_group(group, 1)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -905,61 +972,33 @@ int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pasn->ecdh = crypto_ecdh_init(group);
|
return wpas_pasn_send_auth_1(pasn, own_addr, bssid, akmp, cipher, group,
|
||||||
if (!pasn->ecdh) {
|
freq, beacon_rsne, beacon_rsne_len,
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
|
beacon_rsnxe, beacon_rsnxe_len, comeback,
|
||||||
goto fail;
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beacon_rsne && beacon_rsne_len) {
|
/*
|
||||||
pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
|
* Wi-Fi Aware uses PASN handshake to authenticate peer devices.
|
||||||
beacon_rsnxe_len);
|
* Devices can simply verify each other for subsequent sessions using
|
||||||
if (!pasn->beacon_rsne_rsnxe) {
|
* pairing verification procedure.
|
||||||
wpa_printf(MSG_DEBUG,
|
*
|
||||||
"PASN: Failed storing beacon RSNE/RSNXE");
|
* In pairing verification, Wi-Fi aware devices use PASN authentication
|
||||||
goto fail;
|
* frames with a custom PMKID and Wi-Fi Aware R4 specific verification IEs.
|
||||||
}
|
* It does not use wrapped data in the Authentication frames. This function
|
||||||
|
* provides support to construct PASN Authentication frames for pairing
|
||||||
wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne,
|
* verification.
|
||||||
beacon_rsne_len);
|
*/
|
||||||
if (beacon_rsnxe && beacon_rsnxe_len)
|
int wpa_pasn_verify(struct wpas_pasn *pasn, const u8 *own_addr,
|
||||||
wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
|
const u8 *bssid, int akmp, int cipher, u16 group,
|
||||||
beacon_rsnxe_len);
|
int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
}
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
|
const struct wpabuf *comeback)
|
||||||
pasn->akmp = akmp;
|
{
|
||||||
pasn->cipher = cipher;
|
return wpas_pasn_send_auth_1(pasn, own_addr, bssid, akmp, cipher, group,
|
||||||
pasn->group = group;
|
freq, beacon_rsne, beacon_rsne_len,
|
||||||
pasn->freq = freq;
|
beacon_rsnxe, beacon_rsnxe_len, comeback,
|
||||||
|
true);
|
||||||
os_memcpy(pasn->own_addr, own_addr, ETH_ALEN);
|
|
||||||
os_memcpy(pasn->bssid, bssid, ETH_ALEN);
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"PASN: Init: " MACSTR " akmp=0x%x, cipher=0x%x, group=%u",
|
|
||||||
MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
|
|
||||||
pasn->group);
|
|
||||||
|
|
||||||
frame = wpas_pasn_build_auth_1(pasn, comeback);
|
|
||||||
if (!frame) {
|
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pasn->send_mgmt(pasn->cb_ctx,
|
|
||||||
wpabuf_head(frame), wpabuf_len(frame), 0,
|
|
||||||
pasn->freq, 1000);
|
|
||||||
|
|
||||||
wpabuf_free(frame);
|
|
||||||
if (ret) {
|
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue