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:
Vinay Gannevaram 2022-10-07 19:57:50 +05:30 committed by Jouni Malinen
parent 325236948a
commit 6be84343af
2 changed files with 103 additions and 59 deletions

View file

@ -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,

View file

@ -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;
} }