From b729fd8df9f618ed316677164feaaa4ab67bf31c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 3 Sep 2015 17:24:37 +0300 Subject: [PATCH] FILS: Use AEAD cipher to protect EAPOL-Key frames (AP) Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 96af41b68..e0c12e0bd 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -832,6 +832,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, const u8 *pmk = NULL; unsigned int pmk_len; + os_memset(&PTK, 0, sizeof(PTK)); for (;;) { if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, @@ -1430,6 +1431,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } len += key_data_len; + if (!mic_len && encr) + len += AES_BLOCK_SIZE; hdr = os_zalloc(len); if (hdr == NULL) @@ -1478,6 +1481,30 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (kde && !encr) { os_memcpy(key_data, kde, kde_len); WPA_PUT_BE16(key_mic + mic_len, kde_len); +#ifdef CONFIG_FILS + } else if (!mic_len) { + const u8 *aad[1]; + size_t aad_len[1]; + + WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len); + wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", + kde, kde_len); + + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", + sm->PTK.kek, sm->PTK.kek_len); + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = (u8 *) hdr; + aad_len[0] = key_mic + 2 - (u8 *) hdr; + if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len, + 1, aad, aad_len, key_mic + 2) < 0) { + wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed"); + return; + } + + wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV", + key_mic + 2, AES_BLOCK_SIZE + kde_len); +#endif /* CONFIG_FILS */ } else if (encr && kde) { buf = os_zalloc(key_data_len); if (buf == NULL) { @@ -1525,7 +1552,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } if (key_info & WPA_KEY_INFO_MIC) { - if (!sm->PTK_valid) { + if (!sm->PTK_valid || !mic_len) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "PTK not valid when sending EAPOL-Key " "frame"); @@ -2067,6 +2094,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); sm->EAPOLKeyReceived = FALSE; sm->update_snonce = FALSE; + os_memset(&PTK, 0, sizeof(PTK)); mic_len = wpa_mic_len(sm->wpa_key_mgmt); @@ -2470,7 +2498,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) #endif /* CONFIG_P2P */ wpa_send_eapol(sm->wpa_auth, sm, - (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | + (secure ? WPA_KEY_INFO_SECURE : 0) | + (wpa_mic_len(sm->wpa_key_mgmt) ? WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); @@ -2714,7 +2743,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) } wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | + WPA_KEY_INFO_SECURE | + (wpa_mic_len(sm->wpa_key_mgmt) ? WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1);