From 85e28a79bab0df5e1ad9d4608e155f18762ee19b Mon Sep 17 00:00:00 2001 From: Vinay Gannevaram Date: Fri, 8 Jul 2022 02:47:08 +0530 Subject: [PATCH] PASN: Set secure ranging context to driver after association After the secure association and PTK derivation are completed, if the device supports LTF keyseed, generate the LTF keyseed using KDK and set the ranging context to the driver by using the command QCA_NL80211_VENDOR_SUBCMD_SECURE_RANGING_CONTEXT. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 131 +++++++++++++++++++++++++++++++++---- src/ap/wpa_auth.h | 4 ++ src/ap/wpa_auth_ft.c | 35 ++++++++++ src/ap/wpa_auth_glue.c | 18 +++++ src/rsn_supp/wpa.c | 46 +++++++++++-- src/rsn_supp/wpa.h | 5 ++ src/rsn_supp/wpa_ft.c | 30 +++++++-- src/rsn_supp/wpa_i.h | 12 ++++ wpa_supplicant/wpas_glue.c | 18 +++++ 9 files changed, 278 insertions(+), 21 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 53211f625..73feac429 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -149,6 +149,20 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, } +#ifdef CONFIG_PASN +static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth, + const u8 *peer_addr, + const u8 *ltf_keyseed, + size_t ltf_keyseed_len) +{ + if (!wpa_auth->cb->set_ltf_keyseed) + return -1; + return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr, + ltf_keyseed, ltf_keyseed_len); +} +#endif /* CONFIG_PASN */ + + static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, const u8 *addr, int idx, u8 *seq) { @@ -2311,6 +2325,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, const u8 *z = NULL; size_t z_len = 0, kdk_len; int akmp; + int ret; if (sm->wpa_auth->conf.force_kdk_derivation || (sm->wpa_auth->conf.secure_ltf && @@ -2324,16 +2339,33 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, if (sm->ft_completed) { u8 ptk_name[WPA_PMK_NAME_LEN]; - return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, - sm->SNonce, sm->ANonce, - sm->addr, sm->wpa_auth->addr, - sm->pmk_r1_name, - ptk, ptk_name, - sm->wpa_key_mgmt, - sm->pairwise, - kdk_len); + ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, + sm->SNonce, sm->ANonce, + sm->addr, sm->wpa_auth->addr, + sm->pmk_r1_name, ptk, + ptk_name, sm->wpa_key_mgmt, + sm->pairwise, kdk_len); + } else { + ret = wpa_auth_derive_ptk_ft(sm, ptk); } - return wpa_auth_derive_ptk_ft(sm, ptk); + if (ret) { + wpa_printf(MSG_ERROR, "FT: PTK derivation failed"); + return ret; + } + +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, + WLAN_RSNX_CAPAB_SECURE_LTF)) { + ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, + sm->pairwise); + if (ret) { + wpa_printf(MSG_ERROR, + "FT: LTF keyseed derivation failed"); + } + } +#endif /* CONFIG_PASN */ + return ret; } #endif /* CONFIG_IEEE80211R_AP */ @@ -2347,9 +2379,27 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, akmp = sm->wpa_key_mgmt; if (force_sha256) akmp |= WPA_KEY_MGMT_PSK_SHA256; - return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", - sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, - ptk, akmp, sm->pairwise, z, z_len, kdk_len); + ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", + sm->wpa_auth->addr, sm->addr, sm->ANonce, + snonce, ptk, akmp, sm->pairwise, z, z_len, + kdk_len); + if (ret) { + wpa_printf(MSG_DEBUG, + "WPA: PTK derivation failed"); + return ret; + } + +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) { + ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise); + if (ret) { + wpa_printf(MSG_DEBUG, + "WPA: LTF keyseed derivation failed"); + } + } +#endif /* CONFIG_PASN */ + return ret; } @@ -2380,6 +2430,19 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, fils_ft, &fils_ft_len, kdk_len); if (res < 0) return res; + +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) { + res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise); + if (res) { + wpa_printf(MSG_ERROR, + "FILS: LTF keyseed derivation failed"); + return res; + } + } +#endif /* CONFIG_PASN */ + sm->PTK_valid = true; sm->tk_already_set = false; @@ -2883,6 +2946,19 @@ int fils_set_tk(struct wpa_state_machine *sm) wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); return -1; } + +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr, + sm->PTK.ltf_keyseed, + sm->PTK.ltf_keyseed_len)) { + wpa_printf(MSG_ERROR, + "FILS: Failed to set LTF keyseed to driver"); + return -1; + } +#endif /* CONFIG_PASN */ + sm->pairwise_set = true; sm->tk_already_set = true; @@ -3481,6 +3557,21 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) return; } +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, + WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr, + sm->PTK.ltf_keyseed, + sm->PTK.ltf_keyseed_len)) { + wpa_printf(MSG_ERROR, + "WPA: Failed to set LTF keyseed to driver"); + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#endif /* CONFIG_PASN */ + /* WPA2 send GTK in the 4-way handshake */ secure = 1; gtk = gsm->GTK[gsm->GN - 1]; @@ -3692,6 +3783,22 @@ SM_STATE(WPA_PTK, PTKINITDONE) WLAN_REASON_PREV_AUTH_NOT_VALID); return; } + +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, + WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr, + sm->PTK.ltf_keyseed, + sm->PTK.ltf_keyseed_len)) { + wpa_printf(MSG_ERROR, + "WPA: Failed to set LTF keyseed to driver"); + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#endif /* CONFIG_PASN */ + /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = true; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index c6ba422f7..e8e6a8a6b 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -350,6 +350,10 @@ struct wpa_auth_callbacks { #ifdef CONFIG_MESH int (*start_ampe)(void *ctx, const u8 *sta_addr); #endif /* CONFIG_MESH */ +#ifdef CONFIG_PASN + int (*set_ltf_keyseed)(void *ctx, const u8 *addr, const u8 *ltf_keyseed, + size_t ltf_keyseed_len); +#endif /* CONFIG_PASN */ }; struct wpa_authenticator * wpa_init(const u8 *addr, diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 7a9761359..1b1324b8d 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2805,6 +2805,20 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, } +#ifdef CONFIG_PASN +static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth, + const u8 *peer_addr, + const u8 *ltf_keyseed, + size_t ltf_keyseed_len) +{ + if (!wpa_auth->cb->set_ltf_keyseed) + return -1; + return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr, + ltf_keyseed, ltf_keyseed_len); +} +#endif /* CONFIG_PASN */ + + static inline int wpa_auth_add_sta_ft(struct wpa_authenticator *wpa_auth, const u8 *addr) { @@ -2849,6 +2863,18 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry) sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) return; +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr, + sm->PTK.ltf_keyseed, + sm->PTK.ltf_keyseed_len)) { + wpa_printf(MSG_ERROR, + "FT: Failed to set LTF keyseed to driver"); + return; + } +#endif /* CONFIG_PASN */ + /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = true; sm->tk_already_set = true; @@ -3210,6 +3236,15 @@ pmk_r1_derived: pairwise, kdk_len) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; +#ifdef CONFIG_PASN + if (sm->wpa_auth->conf.secure_ltf && + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, pairwise)) { + wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } +#endif /* CONFIG_PASN */ + sm->pairwise = pairwise; sm->PTK_valid = true; sm->tk_already_set = false; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 1b4852cea..f388ffe9f 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1470,6 +1470,21 @@ static void hostapd_request_radius_psk(void *ctx, const u8 *addr, int key_mgmt, #endif /* CONFIG_NO_RADIUS */ +#ifdef CONFIG_PASN +static int hostapd_set_ltf_keyseed(void *ctx, const u8 *peer_addr, + const u8 *ltf_keyseed, + size_t ltf_keyseed_len) +{ + struct hostapd_data *hapd = ctx; + + return hostapd_drv_set_secure_ranging_ctx(hapd, hapd->own_addr, + peer_addr, 0, 0, NULL, + ltf_keyseed_len, + ltf_keyseed, 0); +} +#endif /* CONFIG_PASN */ + + int hostapd_setup_wpa(struct hostapd_data *hapd) { struct wpa_auth_config _conf; @@ -1516,6 +1531,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifndef CONFIG_NO_RADIUS .request_radius_psk = hostapd_request_radius_psk, #endif /* CONFIG_NO_RADIUS */ +#ifdef CONFIG_PASN + .set_ltf_keyseed = hostapd_set_ltf_keyseed, +#endif /* CONFIG_PASN */ }; const u8 *wpa_ie; size_t wpa_ie_len; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 3e39947a5..af7955140 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -585,6 +585,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { + int ret; const u8 *z = NULL; size_t z_len = 0, kdk_len; int akmp; @@ -618,11 +619,23 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, else kdk_len = 0; - return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, - key->key_nonce, ptk, akmp, - sm->pairwise_cipher, z, z_len, - kdk_len); + ret = wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", + sm->own_addr, sm->bssid, sm->snonce, + key->key_nonce, ptk, akmp, + sm->pairwise_cipher, z, z_len, + kdk_len); + if (ret) { + wpa_printf(MSG_ERROR, "WPA: PTK derivation failed"); + return ret; + } + +#ifdef CONFIG_PASN + if (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) + ret = wpa_ltf_keyseed(ptk, akmp, sm->pairwise_cipher); +#endif /* CONFIG_PASN */ + + return ret; } @@ -976,6 +989,20 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, return -1; } +#ifdef CONFIG_PASN + if (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_sm_set_ltf_keyseed(sm, sm->own_addr, sm->bssid, + sm->ptk.ltf_keyseed_len, + sm->ptk.ltf_keyseed) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to set LTF keyseed to the driver (keylen=%zu bssid=" + MACSTR ")", sm->ptk.ltf_keyseed_len, + MAC2STR(sm->bssid)); + return -1; + } +#endif /* CONFIG_PASN */ + wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher, sm->dot11RSNAConfigPMKLifetime, &sm->ptk); @@ -4452,6 +4479,15 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, goto fail; } +#ifdef CONFIG_PASN + if (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) { + wpa_printf(MSG_DEBUG, "FILS: Failed to derive LTF keyseed"); + goto fail; + } +#endif /* CONFIG_PASN */ + wpabuf_clear_free(dh_ss); dh_ss = NULL; diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index df32240c6..80262a23c 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -93,6 +93,11 @@ struct wpa_sm_ctx { void (*transition_disable)(void *ctx, u8 bitmap); void (*store_ptk)(void *ctx, u8 *addr, int cipher, u32 life_time, const struct wpa_ptk *ptk); +#ifdef CONFIG_PASN + int (*set_ltf_keyseed)(void *ctx, const u8 *own_addr, + const u8 *peer_addr, size_t ltf_keyseed_len, + const u8 *ltf_keyseed); +#endif /* CONFIG_PASN */ }; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 9d4044c14..c681a99df 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -41,6 +41,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); const u8 *mpmk; size_t mpmk_len, kdk_len; + int ret = 0; if (sm->xxkey_len > 0) { mpmk = sm->xxkey; @@ -75,10 +76,22 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, else kdk_len = 0; - return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce, - sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk, - ptk_name, sm->key_mgmt, sm->pairwise_cipher, - kdk_len); + ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, + anonce, sm->own_addr, sm->bssid, + sm->pmk_r1_name, ptk, ptk_name, sm->key_mgmt, + sm->pairwise_cipher, kdk_len); + if (ret) { + wpa_printf(MSG_ERROR, "FT: PTK derivation failed"); + return ret; + } + +#ifdef CONFIG_PASN + if (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) + ret = wpa_ltf_keyseed(ptk, sm->key_mgmt, sm->pairwise_cipher); +#endif /* CONFIG_PASN */ + + return ret; } @@ -688,6 +701,15 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, kdk_len) < 0) return -1; +#ifdef CONFIG_PASN + if (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) && + wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) { + wpa_printf(MSG_DEBUG, "FT: Failed to derive LTF keyseed"); + return -1; + } +#endif /* CONFIG_PASN */ + if (wpa_key_mgmt_fils(sm->key_mgmt)) { kck = sm->ptk.kck2; kck_len = sm->ptk.kck2_len; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index fabd6cb26..3811c3bc4 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -483,6 +483,18 @@ static inline void wpa_sm_store_ptk(struct wpa_sm *sm, ptk); } +#ifdef CONFIG_PASN +static inline int wpa_sm_set_ltf_keyseed(struct wpa_sm *sm, const u8 *own_addr, + const u8 *peer_addr, + size_t ltf_keyseed_len, + const u8 *ltf_keyseed) +{ + WPA_ASSERT(sm->ctx->set_ltf_keyseed); + return sm->ctx->set_ltf_keyseed(sm->ctx->ctx, own_addr, peer_addr, + ltf_keyseed_len, ltf_keyseed); +} +#endif /* CONFIG_PASN */ + int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic); diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 35ca12308..c5cfa92e5 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1385,6 +1385,21 @@ static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher, #endif /* CONFIG_NO_WPA */ +#ifdef CONFIG_PASN +static int wpa_supplicant_set_ltf_keyseed(void *_wpa_s, const u8 *own_addr, + const u8 *peer_addr, + size_t ltf_keyseed_len, + const u8 *ltf_keyseed) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + + return wpa_drv_set_secure_ranging_ctx(wpa_s, own_addr, peer_addr, 0, 0, + NULL, ltf_keyseed_len, + ltf_keyseed, 0); +} +#endif /* CONFIG_PASN */ + + int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) { #ifndef CONFIG_NO_WPA @@ -1447,6 +1462,9 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->channel_info = wpa_supplicant_channel_info; ctx->transition_disable = wpa_supplicant_transition_disable; ctx->store_ptk = wpa_supplicant_store_ptk; +#ifdef CONFIG_PASN + ctx->set_ltf_keyseed = wpa_supplicant_set_ltf_keyseed; +#endif /* CONFIG_PASN */ wpa_s->wpa = wpa_sm_init(ctx); if (wpa_s->wpa == NULL) {