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 <quic_jouni@quicinc.com>
This commit is contained in:
Vinay Gannevaram 2022-07-08 02:47:08 +05:30 committed by Jouni Malinen
parent 9b62b61c68
commit 85e28a79ba
9 changed files with 278 additions and 21 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {