FILS: Fix PMK and PMKID derivation from ERP

This adds helper functions for deriving PMK and PMKID from ERP exchange
in FILS shared key authentication as defined in IEEE Std 802.11ai-2016,
12.12.2.5.2 (PMKSA key derivation with FILS authentication). These
functions is used to fix PMK and PMKID derivation which were previously
using the rMSK directly as PMK instead of following the FILS protocol to
derive PMK with HMAC from nonces and rMSK.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-01-13 21:06:21 +02:00 committed by Jouni Malinen
parent ef495c78dd
commit fcd3d6ce32
5 changed files with 121 additions and 6 deletions

View file

@ -17,6 +17,7 @@
#include "crypto/aes_siv.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "eap_common/eap_defs.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "wpa.h"
#include "eloop.h"
@ -3302,12 +3303,19 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm)
wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
/* FILS Wrapped Data */
sm->fils_erp_pmkid_set = 0;
if (erp_msg) {
wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
/* Element ID Extension */
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA);
wpabuf_put_buf(buf, erp_msg);
/* Calculate pending PMKID here so that we do not need to
* maintain a copy of the EAP-Initiate/Reauth message. */
if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg),
wpabuf_len(erp_msg),
sm->fils_erp_pmkid) == 0)
sm->fils_erp_pmkid_set = 1;
}
wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
@ -3407,6 +3415,9 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len)
/* FILS Wrapped Data */
if (!sm->cur_pmksa && elems.fils_wrapped_data) {
u8 rmsk[ERP_MAX_KEY_LEN];
size_t rmsk_len;
wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
elems.fils_wrapped_data,
elems.fils_wrapped_data_len);
@ -3415,14 +3426,30 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len)
if (eapol_sm_failed(sm->eapol))
return -1;
res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
rmsk_len = ERP_MAX_KEY_LEN;
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
if (res == PMK_LEN) {
rmsk_len = PMK_LEN;
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
}
if (res)
return -1;
res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
sm->fils_nonce, sm->fils_anonce, NULL, 0,
sm->pmk, &sm->pmk_len);
os_memset(rmsk, 0, sizeof(rmsk));
if (!sm->fils_erp_pmkid_set) {
wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
return -1;
}
wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
PMKID_LEN);
wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result");
sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, PMK_LEN,
NULL, NULL, 0, sm->bssid,
sm->own_addr,
sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
sm->fils_erp_pmkid, NULL, 0,
sm->bssid, sm->own_addr,
sm->network_ctx, sm->key_mgmt);
}

View file

@ -147,6 +147,8 @@ struct wpa_sm {
u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN];
size_t fils_key_auth_len;
unsigned int fils_completed:1;
unsigned int fils_erp_pmkid_set:1;
u8 fils_erp_pmkid[PMKID_LEN];
#endif /* CONFIG_FILS */
};