FILS: Extend the fils_pmk_to_ptk() function to also derive KDK

Extend the fils_pmk_to_ptk() to also derive Key Derivation
Key (KDK) which can later be used for secure LTF measurements.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2020-12-16 13:00:19 +02:00 committed by Jouni Malinen
parent 6e834db74e
commit d87f4aea11
5 changed files with 37 additions and 10 deletions

View file

@ -2314,7 +2314,8 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
snonce, anonce, dhss, dhss_len, snonce, anonce, dhss, dhss_len,
&sm->PTK, ick, &ick_len, &sm->PTK, ick, &ick_len,
sm->wpa_key_mgmt, sm->pairwise, sm->wpa_key_mgmt, sm->pairwise,
fils_ft, &fils_ft_len); fils_ft, &fils_ft_len,
sm->wpa_auth->conf.kdk ? WPA_KDK_MAX_LEN : 0);
if (res < 0) if (res < 0)
return res; return res;
sm->PTK_valid = true; sm->PTK_valid = true;

View file

@ -592,15 +592,16 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
const u8 *snonce, const u8 *anonce, const u8 *dhss, const u8 *snonce, const u8 *anonce, const u8 *dhss,
size_t dhss_len, struct wpa_ptk *ptk, size_t dhss_len, struct wpa_ptk *ptk,
u8 *ick, size_t *ick_len, int akmp, int cipher, u8 *ick, size_t *ick_len, int akmp, int cipher,
u8 *fils_ft, size_t *fils_ft_len) u8 *fils_ft, size_t *fils_ft_len, size_t kdk_len)
{ {
u8 *data, *pos; u8 *data, *pos;
size_t data_len; size_t data_len;
u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN + u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
FILS_FT_MAX_LEN]; FILS_FT_MAX_LEN + WPA_KDK_MAX_LEN];
size_t key_data_len; size_t key_data_len;
const char *label = "FILS PTK Derivation"; const char *label = "FILS PTK Derivation";
int ret = -1; int ret = -1;
size_t offset;
/* /*
* FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation", * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
@ -611,6 +612,9 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
* If doing FT initial mobility domain association: * If doing FT initial mobility domain association:
* FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits, * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits,
* FILS-FT_bits) * FILS-FT_bits)
* When a KDK is derived:
* KDK = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits + FILS-FT_bits,
* KDK_bits)
*/ */
data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len; data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len;
data = os_malloc(data_len); data = os_malloc(data_len);
@ -639,6 +643,19 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
goto err; goto err;
key_data_len = *ick_len + ptk->kek_len + ptk->tk_len; key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
if (kdk_len) {
if (kdk_len > WPA_KDK_MAX_LEN) {
wpa_printf(MSG_ERROR, "FILS: KDK len=%zu too big",
kdk_len);
goto err;
}
ptk->kdk_len = kdk_len;
key_data_len += kdk_len;
} else {
ptk->kdk_len = 0;
}
if (fils_ft && fils_ft_len) { if (fils_ft && fils_ft_len) {
if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) { if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) {
*fils_ft_len = 32; *fils_ft_len = 32;
@ -673,19 +690,27 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len); wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len);
os_memcpy(ick, tmp, *ick_len); os_memcpy(ick, tmp, *ick_len);
offset = *ick_len;
wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len); wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len);
os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len); os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len); wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len);
offset += ptk->kek_len;
os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len); os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len); wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len);
offset += ptk->tk_len;
if (fils_ft && fils_ft_len) { if (fils_ft && fils_ft_len) {
os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len, os_memcpy(fils_ft, tmp + offset, *fils_ft_len);
*fils_ft_len);
wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT", wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT",
fils_ft, *fils_ft_len); fils_ft, *fils_ft_len);
offset += *fils_ft_len;
}
if (ptk->kdk_len) {
os_memcpy(ptk->kdk, tmp + offset, ptk->kdk_len);
wpa_hexdump_key(MSG_DEBUG, "FILS: KDK", ptk->kdk, ptk->kdk_len);
} }
ptk->kek2_len = 0; ptk->kek2_len = 0;

View file

@ -396,7 +396,7 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
const u8 *snonce, const u8 *anonce, const u8 *dhss, const u8 *snonce, const u8 *anonce, const u8 *dhss,
size_t dhss_len, struct wpa_ptk *ptk, size_t dhss_len, struct wpa_ptk *ptk,
u8 *ick, size_t *ick_len, int akmp, int cipher, u8 *ick, size_t *ick_len, int akmp, int cipher,
u8 *fils_ft, size_t *fils_ft_len); u8 *fils_ft, size_t *fils_ft_len, size_t kdk_len);
int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce, int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
const u8 *g_sta, size_t g_sta_len, const u8 *g_sta, size_t g_sta_len,

View file

@ -4350,7 +4350,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
dh_ss ? wpabuf_len(dh_ss) : 0, dh_ss ? wpabuf_len(dh_ss) : 0,
&sm->ptk, ick, &ick_len, &sm->ptk, ick, &ick_len,
sm->key_mgmt, sm->pairwise_cipher, sm->key_mgmt, sm->pairwise_cipher,
sm->fils_ft, &sm->fils_ft_len) < 0) { sm->fils_ft, &sm->fils_ft_len,
sm->kdk ? WPA_KDK_MAX_LEN : 0) < 0) {
wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
goto fail; goto fail;
} }

View file

@ -494,7 +494,7 @@ static int try_rmsk(struct wlantest *wt, struct wlantest_bss *bss,
sta->snonce, sta->anonce, NULL, 0, sta->snonce, sta->anonce, NULL, 0,
&ptk, ick, &ick_len, &ptk, ick, &ick_len,
sta->key_mgmt, sta->pairwise_cipher, sta->key_mgmt, sta->pairwise_cipher,
NULL, NULL) < 0) NULL, NULL, 0) < 0)
return -1; return -1;
/* Check AES-SIV decryption with the derived key */ /* Check AES-SIV decryption with the derived key */