MLO: Validate MLO KDEs in EAPOL-Key msg 4/4
Verify that the MLD address in EAPOL-Key msg 4/4 is set correctly for MLO cases. Note that the mechanism used here for distinguishing between EAPOL-Key msg 2/4 and 4/4 is not exactly ideal and should be improved in the future. Signed-off-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
parent
856d99410f
commit
79212e93f7
1 changed files with 72 additions and 1 deletions
|
@ -1077,9 +1077,15 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
const u8 *key_data;
|
const u8 *key_data;
|
||||||
size_t keyhdrlen, mic_len;
|
size_t keyhdrlen, mic_len;
|
||||||
u8 *mic;
|
u8 *mic;
|
||||||
|
bool is_mld = false;
|
||||||
|
|
||||||
if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
|
if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
is_mld = sm->mld_assoc_link_id >= 0;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
|
wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
|
||||||
|
|
||||||
mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
|
mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
|
||||||
|
@ -1149,6 +1155,11 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Make this more robust for distinguising EAPOL-Key msg 2/4 from
|
||||||
|
* 4/4. Secure=1 is used in msg 2/4 when doing PTK rekeying, so the
|
||||||
|
* MLD mechanism here does not work without the somewhat undesired check
|
||||||
|
* on wpa_ptk_state.. Would likely need to decrypt Key Data first to be
|
||||||
|
* able to know which message this is in MLO cases.. */
|
||||||
if (key_info & WPA_KEY_INFO_REQUEST) {
|
if (key_info & WPA_KEY_INFO_REQUEST) {
|
||||||
msg = REQUEST;
|
msg = REQUEST;
|
||||||
msgtxt = "Request";
|
msgtxt = "Request";
|
||||||
|
@ -1157,7 +1168,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
msgtxt = "2/2 Group";
|
msgtxt = "2/2 Group";
|
||||||
} else if (key_data_length == 0 ||
|
} else if (key_data_length == 0 ||
|
||||||
(mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
|
(mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
|
||||||
key_data_length == AES_BLOCK_SIZE)) {
|
key_data_length == AES_BLOCK_SIZE) ||
|
||||||
|
(is_mld && (key_info & WPA_KEY_INFO_SECURE) &&
|
||||||
|
sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING)) {
|
||||||
msg = PAIRWISE_4;
|
msg = PAIRWISE_4;
|
||||||
msgtxt = "4/4 Pairwise";
|
msgtxt = "4/4 Pairwise";
|
||||||
} else {
|
} else {
|
||||||
|
@ -4317,10 +4330,68 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_auth_validate_ml_kdes_m4(struct wpa_state_machine *sm)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
const struct ieee802_1x_hdr *hdr;
|
||||||
|
const struct wpa_eapol_key *key;
|
||||||
|
struct wpa_eapol_ie_parse kde;
|
||||||
|
const u8 *key_data, *mic;
|
||||||
|
u16 key_data_length;
|
||||||
|
size_t mic_len;
|
||||||
|
|
||||||
|
if (sm->mld_assoc_link_id < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: last_rx_eapol_key length fields have already been validated in
|
||||||
|
* wpa_receive().
|
||||||
|
*/
|
||||||
|
mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
|
||||||
|
|
||||||
|
hdr = (const struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
|
||||||
|
key = (const struct wpa_eapol_key *) (hdr + 1);
|
||||||
|
mic = (const u8 *) (key + 1);
|
||||||
|
key_data = mic + mic_len + 2;
|
||||||
|
key_data_length = WPA_GET_BE16(mic + mic_len);
|
||||||
|
if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
|
||||||
|
sizeof(*key) - mic_len - 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
|
||||||
|
wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
|
||||||
|
LOGGER_INFO,
|
||||||
|
"received EAPOL-Key msg 4/4 with invalid Key Data contents");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MLD MAC address must be the same */
|
||||||
|
if (!kde.mac_addr ||
|
||||||
|
os_memcmp(kde.mac_addr, sm->peer_mld_addr, ETH_ALEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"MLD: Mismatching or missing MLD address in EAPOL-Key msg 4/4");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "MLD: MLD address in EAPOL-Key msg 4/4: " MACSTR,
|
||||||
|
MAC2STR(kde.mac_addr));
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SM_STATE(WPA_PTK, PTKINITDONE)
|
SM_STATE(WPA_PTK, PTKINITDONE)
|
||||||
{
|
{
|
||||||
SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
|
SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
|
||||||
sm->EAPOLKeyReceived = false;
|
sm->EAPOLKeyReceived = false;
|
||||||
|
|
||||||
|
if (wpa_auth_validate_ml_kdes_m4(sm) < 0) {
|
||||||
|
wpa_sta_disconnect(sm->wpa_auth, sm->addr,
|
||||||
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sm->Pair) {
|
if (sm->Pair) {
|
||||||
enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
|
enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
|
||||||
int klen = wpa_cipher_key_len(sm->pairwise);
|
int klen = wpa_cipher_key_len(sm->pairwise);
|
||||||
|
|
Loading…
Reference in a new issue