From c089bc5725037a619190e8e38a94bfa689ba04bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 8 Sep 2015 00:58:11 +0300 Subject: [PATCH] FILS: PMK-to-PTK key derivation for FILS authentication This is the PTKSA key derivation used as part of the FILS authentication exchange. See P802.11ai/D11.0 12.12.2.5.3. Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 67 +++++++++++++++++++++++++++++++++++++++++ src/common/wpa_common.h | 4 +++ 2 files changed, 71 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index e909c3375..fa3e173ef 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -229,6 +229,73 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, return 0; } +#ifdef CONFIG_FILS +int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa, + const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk, + u8 *ick, size_t *ick_len, int akmp, int cipher) +{ + u8 data[2 * ETH_ALEN + 2 * FILS_NONCE_LEN]; + u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; + size_t key_data_len; + const char *label = "FILS PTK Derivation"; + + /* + * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation", + * SPA || AA || SNonce || ANonce) + * ICK = L(FILS-Key-Data, 0, ICK_bits) + * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits) + * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits) + * If doing FT initial mobility domain association: + * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits, + * FILS-FT_bits) + */ + os_memcpy(data, spa, ETH_ALEN); + os_memcpy(data + ETH_ALEN, aa, ETH_ALEN); + os_memcpy(data + 2 * ETH_ALEN, snonce, FILS_NONCE_LEN); + os_memcpy(data + 2 * ETH_ALEN + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN); + + ptk->kck_len = 0; + ptk->kek_len = wpa_kek_len(akmp); + ptk->tk_len = wpa_cipher_key_len(cipher); + if (wpa_key_mgmt_sha384(akmp)) + *ick_len = 48; + else if (wpa_key_mgmt_sha256(akmp)) + *ick_len = 32; + else + return -1; + key_data_len = *ick_len + ptk->kek_len + ptk->tk_len; + + if (wpa_key_mgmt_sha384(akmp)) + sha384_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, key_data_len); + else if (sha256_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, key_data_len) < 0) + return -1; + + wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR + " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa)); + wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN); + wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len); + + os_memcpy(ick, tmp, *ick_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len); + + os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len); + + os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len); + + /* TODO: FILS-FT */ + + os_memset(tmp, 0, sizeof(tmp)); + return 0; +} + +#endif /* CONFIG_FILS */ + #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index cff404fde..d55ecad42 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -192,6 +192,7 @@ struct wpa_eapol_key { #define WPA_KCK_MAX_LEN 24 #define WPA_KEK_MAX_LEN 64 #define WPA_TK_MAX_LEN 32 +#define FILS_ICK_MAX_LEN 48 /** * struct wpa_ptk - WPA Pairwise Transient Key @@ -329,6 +330,9 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, struct wpa_ptk *ptk, int akmp, int cipher); +int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa, + const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk, + u8 *ick, size_t *ick_len, int akmp, int cipher); #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,