From 98cd3d1c3b2f2081539a95be26b37aae88b2b0f5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 25 Jan 2015 16:49:18 +0200 Subject: [PATCH] Preparations for variable length KCK and KEK This modifies struct wpa_ptk to allow the length of KCK and KEK to be stored. This is needed to allow longer keys to be used, e.g., with Suite B 192-bit level. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 45 ++++++++------- src/ap/wpa_auth_ft.c | 52 ++++++++--------- src/ap/wpa_auth_i.h | 4 +- src/common/wpa_common.c | 107 ++++++++++++++++++++++++++-------- src/common/wpa_common.h | 50 ++++++++-------- src/drivers/driver.h | 7 ++- src/drivers/driver_nl80211.c | 9 +-- src/rsn_supp/peerkey.c | 87 +++++++++++++--------------- src/rsn_supp/peerkey.h | 4 +- src/rsn_supp/wpa.c | 106 +++++++++++++++++----------------- src/rsn_supp/wpa.h | 10 ++-- src/rsn_supp/wpa_ft.c | 54 ++++++++---------- src/rsn_supp/wpa_i.h | 12 ++-- wlantest/inject.c | 6 +- wlantest/rx_data.c | 18 +++--- wlantest/rx_eapol.c | 108 +++++++++++++++++++---------------- wlantest/rx_mgmt.c | 4 +- wlantest/wlantest.c | 12 +++- wpa_supplicant/driver_i.h | 8 ++- wpa_supplicant/events.c | 6 +- wpa_supplicant/wpas_glue.c | 9 +-- 21 files changed, 401 insertions(+), 317 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index b46b2439f..ece949a1c 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1,6 +1,6 @@ /* * IEEE 802.11 RSN / WPA Authenticator - * Copyright (c) 2004-2013, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1487,7 +1487,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - if (aes_wrap(sm->PTK.kek, 16, + if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, (key_data_len - 8) / 8, buf, (u8 *) (key + 1))) { os_free(hdr); @@ -1495,16 +1495,20 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, return; } WPA_PUT_BE16(key->key_data_length, key_data_len); - } else { + } else if (sm->PTK.kek_len == 16) { u8 ek[32]; os_memcpy(key->key_iv, sm->group->Counter + WPA_NONCE_LEN - 16, 16); inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->PTK.kek, 16); + os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); os_memcpy(key + 1, buf, key_data_len); rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); WPA_PUT_BE16(key->key_data_length, key_data_len); + } else { + os_free(hdr); + os_free(buf); + return; } os_free(buf); } @@ -1517,7 +1521,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, os_free(hdr); return; } - wpa_eapol_key_mic(sm->PTK.kck, sm->wpa_key_mgmt, version, + wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_key_mgmt, version, (u8 *) hdr, len, key->key_mic); #ifdef CONFIG_TESTING_OPTIONS if (!pairwise && @@ -1577,7 +1582,8 @@ static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, struct wpa_eapol_key *key; u16 key_info; int ret = 0; - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; if (data_len < sizeof(*hdr) + sizeof(*key)) return -1; @@ -1585,13 +1591,14 @@ static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); key_info = WPA_GET_BE16(key->key_info); - os_memcpy(mic, key->key_mic, 16); - os_memset(key->key_mic, 0, 16); - if (wpa_eapol_key_mic(PTK->kck, akmp, key_info & WPA_KEY_INFO_TYPE_MASK, + os_memcpy(mic, key->key_mic, mic_len); + os_memset(key->key_mic, 0, mic_len); + if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, + key_info & WPA_KEY_INFO_TYPE_MASK, data, data_len, key->key_mic) || - os_memcmp_const(mic, key->key_mic, 16) != 0) + os_memcmp_const(mic, key->key_mic, mic_len) != 0) ret = -1; - os_memcpy(key->key_mic, mic, 16); + os_memcpy(key->key_mic, mic, mic_len); return ret; } @@ -1928,18 +1935,14 @@ SM_STATE(WPA_PTK, PTKSTART) static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, const u8 *pmk, struct wpa_ptk *ptk) { - size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32; #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); + return wpa_auth_derive_ptk_ft(sm, pmk, ptk); #endif /* CONFIG_IEEE80211R */ - wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", - sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - - return 0; + return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", + sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, + ptk, sm->wpa_key_mgmt, sm->pairwise); } @@ -2271,7 +2274,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) { + sm->PTK.tk, klen)) { wpa_sta_disconnect(sm->wpa_auth, sm->addr); return; } @@ -3171,7 +3174,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, return -1; if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, - sm->PTK.kck, sizeof(sm->PTK.kck), + sm->PTK.kck, sm->PTK.kck_len, sm->wpa_auth->addr, sm->addr, session_timeout, eapol, sm->wpa_key_mgmt)) return 0; diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index e061b5e1e..ef3249a3e 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2014, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -362,7 +362,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len) + struct wpa_ptk *ptk) { u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; u8 pmk_r1[PMK_LEN]; @@ -374,7 +374,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, const u8 *ssid = sm->wpa_auth->conf.ssid; size_t ssid_len = sm->wpa_auth->conf.ssid_len; - if (sm->xxkey_len == 0) { wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " "derivation"); @@ -396,13 +395,9 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name, sm->pairwise); - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, sm->pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; + return wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, + sm->wpa_auth->addr, sm->pmk_r1_name, + ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise); } @@ -461,7 +456,8 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); subelem[4] = gsm->GTK_len; wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5); - if (aes_wrap(sm->PTK.kek, 16, key_len / 8, key, subelem + 13)) { + if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, key_len / 8, key, + subelem + 13)) { os_free(subelem); return NULL; } @@ -493,7 +489,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; *pos++ = WPA_IGTK_LEN; - if (aes_wrap(sm->PTK.kek, 16, WPA_IGTK_LEN / 8, + if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, WPA_IGTK_LEN / 8, gsm->IGTK[gsm->GN_igtk - 4], pos)) { os_free(subelem); return NULL; @@ -745,7 +741,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, ric_start = NULL; if (auth_alg == WLAN_AUTH_FT && - wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, + wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr, + sm->wpa_auth->addr, 6, mdie, mdie_len, ftie, ftie_len, rsnie, rsnie_len, ric_start, ric_start ? pos - ric_start : 0, @@ -789,7 +786,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) * optimized by adding the STA entry earlier. */ if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) + sm->PTK.tk, klen)) return; /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ @@ -807,7 +804,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, u8 ptk_name[WPA_PMK_NAME_LEN]; struct wpa_auth_config *conf; struct wpa_ft_ies parse; - size_t buflen, ptk_len; + size_t buflen; int ret; u8 *pos, *end; int pairwise; @@ -892,13 +889,11 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); - ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48; - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, - (u8 *) &sm->PTK, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->PTK, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); + if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, + sm->wpa_auth->addr, pmk_r1_name, + &sm->PTK, ptk_name, sm->wpa_key_mgmt, + pairwise) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; sm->pairwise = pairwise; sm->PTK_valid = TRUE; @@ -993,7 +988,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, struct wpa_ft_ies parse; struct rsn_mdie *mdie; struct rsn_ftie *ftie; - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; unsigned int count; if (sm == NULL) @@ -1108,7 +1104,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return -1; } - if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5, + if (wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr, + sm->wpa_auth->addr, 5, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, @@ -1118,12 +1115,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_UNSPECIFIED_FAILURE; } - if (os_memcmp_const(mic, ftie->mic, 16) != 0) { + if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR, MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr)); - wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16); - wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", + ftie->mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "FT: MDIE", parse.mdie - 2, parse.mdie_len + 2); wpa_hexdump(MSG_MSGDUMP, "FT: FTIE", diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 478bc9552..7b2cd3ea8 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -248,7 +248,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len); + struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); void wpa_ft_install_ptk(struct wpa_state_machine *sm); diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index a573e11eb..d4a17a121 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1,6 +1,6 @@ /* * WPA/RSN - Shared functions for supplicant and authenticator - * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2002-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -19,9 +19,22 @@ #include "wpa_common.h" +static unsigned int wpa_kck_len(int akmp) +{ + return 16; +} + + +static unsigned int wpa_kek_len(int akmp) +{ + return 16; +} + + /** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) + * @key_len: KCK length in octets * @akmp: WPA_KEY_MGMT_* used in key derivation * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) @@ -38,18 +51,18 @@ * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */ -int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf, - size_t len, u8 *mic) +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic) { u8 hash[SHA256_MAC_LEN]; switch (ver) { #ifndef CONFIG_FIPS case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - return hmac_md5(key, 16, buf, len, mic); + return hmac_md5(key, key_len, buf, len, mic); #endif /* CONFIG_FIPS */ case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - if (hmac_sha1(key, 16, buf, len, hash)) + if (hmac_sha1(key, key_len, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; @@ -65,7 +78,7 @@ int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf, #endif /* CONFIG_HS20 */ #ifdef CONFIG_SUITEB case WPA_KEY_MGMT_IEEE8021X_SUITE_B: - if (hmac_sha256(key, 16, buf, len, hash)) + if (hmac_sha256(key, key_len, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; @@ -92,8 +105,9 @@ int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf, * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key - * @ptk_len: Length of PTK - * @use_sha256: Whether to use SHA256-based KDF + * @akmp: Negotiated AKM + * @cipher: Negotiated pairwise cipher + * Returns: 0 on success, -1 on failure * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", @@ -104,12 +118,14 @@ int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf, * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ -void 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, - u8 *ptk, size_t ptk_len, int use_sha256) +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) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; + u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; + size_t ptk_len; if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); @@ -129,27 +145,44 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } + ptk->kck_len = wpa_kck_len(akmp); + ptk->kek_len = wpa_kek_len(akmp); + ptk->tk_len = wpa_cipher_key_len(cipher); + ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; + #ifdef CONFIG_IEEE80211W - if (use_sha256) + if (wpa_key_mgmt_sha256(akmp)) sha256_prf(pmk, pmk_len, label, data, sizeof(data), - ptk, ptk_len); + tmp, ptk_len); else #endif /* CONFIG_IEEE80211W */ - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, - ptk_len); + sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); - wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); + + os_memcpy(ptk->kck, tmp, ptk->kck_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len); + + os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); + + os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); + + os_memset(tmp, 0, sizeof(tmp)); + return 0; } #ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, +int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, + const u8 *ap_addr, u8 transaction_seqnum, + const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic) @@ -157,6 +190,12 @@ int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, u8 *buf, *pos; size_t buf_len; + if (kck_len != 16) { + wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u", + (unsigned int) kck_len); + return -1; + } + buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; buf = os_malloc(buf_len); if (buf == NULL) @@ -858,15 +897,17 @@ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name) +int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, + const u8 *sta_addr, const u8 *bssid, + const u8 *pmk_r1_name, + struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher) { u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; + u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; + size_t ptk_len; /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || @@ -882,7 +923,12 @@ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; - sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); + ptk->kck_len = wpa_kck_len(akmp); + ptk->kek_len = wpa_kek_len(akmp); + ptk->tk_len = wpa_cipher_key_len(cipher); + ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; + + sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || @@ -903,6 +949,19 @@ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, sha256_vector(6, addr, len, hash); os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); + + os_memcpy(ptk->kck, tmp, ptk->kck_len); + os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); + os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); + + wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len); + wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); + wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); + + os_memset(tmp, 0, sizeof(tmp)); + + return 0; } #endif /* CONFIG_IEEE80211R */ diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 17bed34a5..ddb4a090f 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -1,6 +1,6 @@ /* * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2002-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -191,22 +191,23 @@ struct wpa_eapol_key { /* followed by key_data_length bytes of key_data */ } STRUCT_PACKED; +#define WPA_EAPOL_KEY_MIC_MAX_LEN 16 +#define WPA_KCK_MAX_LEN 16 +#define WPA_KEK_MAX_LEN 16 +#define WPA_TK_MAX_LEN 32 + /** * struct wpa_ptk - WPA Pairwise Transient Key * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy */ struct wpa_ptk { - u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ - u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ - u8 tk1[16]; /* Temporal Key 1 (TK1) */ - union { - u8 tk2[16]; /* Temporal Key 2 (TK2) */ - struct { - u8 tx_mic_key[8]; - u8 rx_mic_key[8]; - } auth; - } u; -} STRUCT_PACKED; + u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */ + u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */ + size_t kck_len; + size_t kek_len; + size_t tk_len; +}; /* WPA IE version 1 @@ -327,16 +328,17 @@ struct rsn_rdie { #endif /* _MSC_VER */ -int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf, - size_t len, u8 *mic); -void 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, - u8 *ptk, size_t ptk_len, int use_sha256); +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic); +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); #ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, +int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, + const u8 *ap_addr, u8 transaction_seqnum, + const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic); @@ -349,10 +351,10 @@ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name); -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name); +int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, + const u8 *sta_addr, const u8 *bssid, + const u8 *pmk_r1_name, + struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher); #endif /* CONFIG_IEEE80211R */ struct wpa_ie_data { diff --git a/src/drivers/driver.h b/src/drivers/driver.h index b8a7c5190..1d93cc07a 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1,6 +1,6 @@ /* * Driver interface definition - * Copyright (c) 2003-2014, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -2859,14 +2859,17 @@ struct wpa_driver_ops { * set_rekey_info - Set rekey information * @priv: Private driver interface data * @kek: Current KEK + * @kek_len: KEK length in octets * @kck: Current KCK + * @kck_len: KCK length in octets * @replay_ctr: Current EAPOL-Key Replay Counter * * This optional function can be used to provide information for the * driver/firmware to process EAPOL-Key frames in Group Key Handshake * while the host (including wpa_supplicant) is sleeping. */ - void (*set_rekey_info)(void *priv, const u8 *kek, const u8 *kck, + void (*set_rekey_info)(void *priv, const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, const u8 *replay_ctr); /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index f955ee4f0..ea525759e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1,6 +1,6 @@ /* * Driver interaction with Linux nl80211/cfg80211 - * Copyright (c) 2002-2014, Jouni Malinen + * Copyright (c) 2002-2015, Jouni Malinen * Copyright (c) 2003-2004, Instant802 Networks, Inc. * Copyright (c) 2005-2006, Devicescape Software, Inc. * Copyright (c) 2007, Johannes Berg @@ -6781,7 +6781,8 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) } -static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck, +static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, const u8 *replay_ctr) { struct i802_bss *bss = priv; @@ -6796,8 +6797,8 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck, wpa_printf(MSG_DEBUG, "nl80211: Set rekey offload"); if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_REKEY_OFFLOAD)) || !(replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA)) || - nla_put(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek) || - nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) || + nla_put(msg, NL80211_REKEY_DATA_KEK, kek_len, kek) || + nla_put(msg, NL80211_REKEY_DATA_KCK, kck_len, kck) || nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN, replay_ctr)) { nl80211_nlmsg_clear(msg); diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index aca8f540c..43d3af6b7 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen + * Copyright (c) 2006-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -112,8 +112,8 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, "(mui %d error_type %d)", mui, error_type); } - wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, err->key_mic); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst, + ETH_P_EAPOL, rbuf, rlen, err->key_mic); return 0; } @@ -164,8 +164,8 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr, + ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; } @@ -240,12 +240,7 @@ static int wpa_supplicant_process_smk_m2( os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); peerkey->rsnie_i_len = kde.rsn_ie_len; peerkey->cipher = cipher; -#ifdef CONFIG_IEEE80211W - if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_PSK_SHA256 | - WPA_KEY_MGMT_IEEE8021X_SUITE_B)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ + peerkey->akmp = ie.key_mgmt; if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -289,14 +284,14 @@ static int wpa_supplicant_process_smk_m2( * @mac_p: Peer MAC address * @inonce: Initiator Nonce * @mac_i: Initiator MAC address - * @use_sha256: Whether to use SHA256-based KDF + * @akmp: Negotiated AKM * * 8.5.1.4 Station to station (STK) key hierarchy * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) */ static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, const u8 *inonce, const u8 *mac_i, u8 *smkid, - int use_sha256) + int akmp) { char *title = "SMK Name"; const u8 *addr[5]; @@ -311,7 +306,7 @@ static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, addr[4] = mac_i; #ifdef CONFIG_IEEE80211W - if (use_sha256) + if (wpa_key_mgmt_sha256(akmp)) hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); else #endif /* CONFIG_IEEE80211W */ @@ -372,7 +367,7 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, + wpa_eapol_key_send(sm, NULL, 0, ver, peerkey->addr, ETH_P_EAPOL, mbuf, mlen, NULL); } @@ -427,8 +422,9 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, - ETH_P_EAPOL, mbuf, mlen, msg->key_mic); + wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver, + peerkey->addr, ETH_P_EAPOL, mbuf, mlen, + msg->key_mic); } @@ -576,12 +572,12 @@ static int wpa_supplicant_process_smk_m45( if (peerkey->initiator) { rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, peerkey->inonce, sm->own_addr, peerkey->smkid, - peerkey->use_sha256); + peerkey->akmp); wpa_supplicant_send_stk_1_of_4(sm, peerkey); } else { rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, peerkey->inonce, peerkey->addr, peerkey->smkid, - peerkey->use_sha256); + peerkey->akmp); } wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); @@ -695,12 +691,11 @@ static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", sm->own_addr, peerkey->addr, peerkey->pnonce, key->key_nonce, - (u8 *) stk, sizeof(*stk), - peerkey->use_sha256); + stk, peerkey->akmp, peerkey->cipher); /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, stk->u.auth.tx_mic_key, 8); - os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); - os_memcpy(stk->u.auth.rx_mic_key, buf, 8); + os_memcpy(buf, &stk->tk[16], 8); + os_memcpy(&stk->tk[16], &stk->tk[24], 8); + os_memcpy(&stk->tk[24], buf, 8); peerkey->tstk_set = 1; kde_buf_len = peerkey->rsnie_p_len + @@ -856,12 +851,12 @@ static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, &peerkey->stk)) return; - _key = (u8 *) peerkey->stk.tk1; + _key = peerkey->stk.tk; if (peerkey->cipher == WPA_CIPHER_TKIP) { /* Swap Tx/Rx keys for Michael MIC */ os_memcpy(key_buf, _key, 16); - os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); - os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8); + os_memcpy(key_buf + 16, _key + 24, 8); + os_memcpy(key_buf + 24, _key + 16, 8); _key = key_buf; key_len = 32; } else @@ -870,10 +865,12 @@ static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, os_memset(rsc, 0, 6); if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, rsc, sizeof(rsc), _key, key_len) < 0) { + os_memset(key_buf, 0, sizeof(key_buf)); wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " "driver."); return; } + os_memset(key_buf, 0, sizeof(key_buf)); } @@ -889,7 +886,7 @@ static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, os_memset(rsc, 0, 6); if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, - rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1, + rsc, sizeof(rsc), peerkey->stk.tk, peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " "driver."); @@ -913,24 +910,24 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; int ok = 0; if (peerkey->initiator && !peerkey->stk_set) { wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", sm->own_addr, peerkey->addr, peerkey->inonce, key->key_nonce, - (u8 *) &peerkey->stk, sizeof(peerkey->stk), - peerkey->use_sha256); + &peerkey->stk, peerkey->akmp, peerkey->cipher); peerkey->stk_set = 1; } - os_memcpy(mic, key->key_mic, 16); + os_memcpy(mic, key->key_mic, mic_len); if (peerkey->tstk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->tstk.kck, sm->key_mgmt, ver, buf, - len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len, + sm->key_mgmt, ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "when using TSTK - ignoring TSTK"); } else { @@ -939,14 +936,15 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, peerkey->stk_set = 1; os_memcpy(&peerkey->stk, &peerkey->tstk, sizeof(peerkey->stk)); + os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk)); } } if (!ok && peerkey->stk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->stk.kck, sm->key_mgmt, ver, buf, len, - key->key_mic); - if (os_memcmp_const(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len, + sm->key_mgmt, ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "- dropping packet"); return -1; @@ -1015,10 +1013,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) return -1; peerkey->initiator = 1; os_memcpy(peerkey->addr, peer, ETH_ALEN); -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->key_mgmt)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ + peerkey->akmp = sm->key_mgmt; /* SMK M1: * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, @@ -1085,8 +1080,8 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " MACSTR ")", MAC2STR(peer)); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, req->key_mic); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, + ETH_P_EAPOL, rbuf, rlen, req->key_mic); peerkey->next = sm->peerkey; sm->peerkey = peerkey; diff --git a/src/rsn_supp/peerkey.h b/src/rsn_supp/peerkey.h index 4c17eae0c..f3d07f3d3 100644 --- a/src/rsn_supp/peerkey.h +++ b/src/rsn_supp/peerkey.h @@ -1,6 +1,6 @@ /* * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen + * Copyright (c) 2006-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -27,7 +27,7 @@ struct wpa_peerkey { int cipher; /* Selected cipher (WPA_CIPHER_*) */ u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; int replay_counter_set; - int use_sha256; /* whether AKMP indicate SHA256-based derivations */ + int akmp; struct wpa_ptk stk, tstk; int stk_set, tstk_set; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 8ea54bbab..078e9a050 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - WPA state machine and EAPOL-Key processing - * Copyright (c) 2003-2012, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -27,6 +27,7 @@ * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() * @kck: Key Confirmation Key (KCK, part of PTK) + * @kck_len: KCK length in octets * @ver: Version field from Key Info * @dest: Destination address for the frame * @proto: Ethertype (usually ETH_P_EAPOL) @@ -34,10 +35,12 @@ * @msg_len: Length of message * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written */ -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, +void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { + size_t mic_len = 16; + if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { /* * Association event was not yet received; try to fetch @@ -56,14 +59,15 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, } } if (key_mic && - wpa_eapol_key_mic(kck, sm->key_mgmt, ver, msg, msg_len, key_mic)) { + wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len, + key_mic)) { wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC", ver, sm->key_mgmt); goto out; } - wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16); - wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16); + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len); + wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); wpa_sm_ether_send(sm, dest, proto, msg, msg_len); eapol_sm_notify_tx_eapol_key(sm->eapol); @@ -133,9 +137,9 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) "WPA: Sending EAPOL-Key Request (error=%d " "pairwise=%d ptk_set=%d len=%lu)", error, pairwise, sm->ptk_set, (unsigned long) rlen); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? - reply->key_mic : NULL); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, + ETH_P_EAPOL, rbuf, rlen, + key_info & WPA_KEY_INFO_MIC ? reply->key_mic : NULL); } @@ -374,7 +378,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, + wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; @@ -382,20 +386,17 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk) + const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { - size_t ptk_len = wpa_cipher_key_len(sm->pairwise_cipher) + 32; #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) - return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); + return wpa_derive_ptk_ft(sm, src_addr, key, ptk); #endif /* CONFIG_IEEE80211R */ - wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->key_mgmt)); - return 0; + return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", + sm->own_addr, sm->bssid, sm->snonce, + key->key_nonce, ptk, sm->key_mgmt, + sm->pairwise_cipher); } @@ -462,9 +463,9 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, if (sm->pairwise_cipher == WPA_CIPHER_TKIP) { u8 buf[8]; /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); - os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); - os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); + os_memcpy(buf, &ptk->tk[16], 8); + os_memcpy(&ptk->tk[16], &ptk->tk[24], 8); + os_memcpy(&ptk->tk[24], buf, 8); os_memset(buf, 0, sizeof(buf)); } sm->tptk_set = 1; @@ -601,7 +602,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, } if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - (u8 *) sm->ptk.tk1, keylen) < 0) { + sm->ptk.tk, keylen) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Failed to set PTK to the " "driver (alg=%d keylen=%d bssid=" MACSTR ")", @@ -610,8 +611,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, } /* TK is not needed anymore in supplicant */ - os_memset(sm->ptk.tk1, 0, sizeof(sm->ptk.tk1)); - os_memset(sm->ptk.u.tk2, 0, sizeof(sm->ptk.u.tk2)); + os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); if (sm->wpa_ptk_rekey) { eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); @@ -1087,7 +1087,7 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, WPA_PUT_BE16(reply->key_data_length, 0); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, + wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; @@ -1209,7 +1209,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, struct rsn_pmksa_cache_entry *sa; sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, - sm->ptk.kck, sizeof(sm->ptk.kck), + sm->ptk.kck, sm->ptk.kck_len, sm->bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt); if (!sm->cur_pmksa) @@ -1303,7 +1303,7 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, gd->gtk_len = gtk_len; gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> WPA_KEY_INFO_KEY_INDEX_SHIFT; - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { u8 ek[32]; if (key_data_len > sizeof(gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -1312,7 +1312,7 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, return -1; } os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); os_memcpy(gd->gtk, key_data, key_data_len); if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) { os_memset(ek, 0, sizeof(ek)); @@ -1336,8 +1336,8 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, (unsigned long) maxkeylen); return -1; } - if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data, - gd->gtk)) { + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8, + key_data, gd->gtk)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - could not decrypt " "GTK"); @@ -1383,8 +1383,8 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, WPA_PUT_BE16(reply->key_data_length, 0); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid, + ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0; } @@ -1455,15 +1455,16 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, u16 ver, const u8 *buf, size_t len) { - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; int ok = 0; + size_t mic_len = 16; - os_memcpy(mic, key->key_mic, 16); + os_memcpy(mic, key->key_mic, mic_len); if (sm->tptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->tptk.kck, sm->key_mgmt, ver, buf, len, - key->key_mic); - if (os_memcmp_const(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " "when using TPTK - ignoring TPTK"); @@ -1477,10 +1478,10 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, } if (!ok && sm->ptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->ptk.kck, sm->key_mgmt, ver, buf, len, - key->key_mic); - if (os_memcmp_const(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC - " "dropping packet"); @@ -1519,10 +1520,10 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, /* Decrypt key data here so that this operation does not need * to be implemented separately for each message type. */ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { u8 ek[32]; os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { os_memset(ek, 0, sizeof(ek)); wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, @@ -1548,7 +1549,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, "WPA: No memory for AES-UNWRAP buffer"); return -1; } - if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8, + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8, key_data, buf)) { os_free(buf); wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -2870,15 +2871,18 @@ void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter) } -void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck, - const u8 *ptk_kek) +void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, + const u8 *ptk_kck, size_t ptk_kck_len, + const u8 *ptk_kek, size_t ptk_kek_len) { - if (ptk_kck) { - os_memcpy(sm->ptk.kck, ptk_kck, 16); + if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) { + os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len); + sm->ptk.kck_len = ptk_kck_len; wpa_printf(MSG_DEBUG, "Updated PTK KCK"); } - if (ptk_kek) { - os_memcpy(sm->ptk.kek, ptk_kek, 16); + if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) { + os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len); + sm->ptk.kek_len = ptk_kek_len; wpa_printf(MSG_DEBUG, "Updated PTK KEK"); } sm->ptk_set = 1; diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index cc128935c..e163b7010 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -1,6 +1,6 @@ /* * wpa_supplicant - WPA definitions - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -73,7 +73,8 @@ struct wpa_sm_ctx { const struct hostapd_freq_params *params); int (*tdls_disable_channel_switch)(void *ctx, const u8 *addr); #endif /* CONFIG_TDLS */ - void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck, + void (*set_rekey_offload)(void *ctx, const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, const u8 *replay_ctr); int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len); }; @@ -155,8 +156,9 @@ void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx); int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf); void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter); -void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck, - const u8 *ptk_kek); +void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, + const u8 *ptk_kck, size_t ptk_kck_len, + const u8 *ptk_kek, size_t ptk_kek_len); #else /* CONFIG_NO_WPA */ diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 3b3c9d0da..06dea0550 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2006-2007, Jouni Malinen + * Copyright (c) 2006-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -19,8 +19,7 @@ #ifdef CONFIG_IEEE80211R int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len) + const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *anonce = key->key_nonce; @@ -43,13 +42,9 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr, - sm->bssid, sm->pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; + return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr, + sm->bssid, sm->pmk_r1_name, ptk, ptk_name, + sm->key_mgmt, sm->pairwise_cipher); } @@ -134,6 +129,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) * @anonce: ANonce or %NULL if not yet available * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List * @kck: 128-bit KCK for MIC or %NULL if no MIC is used + * @kck_len: KCK length in octets * @target_ap: Target AP address * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL * @ric_ies_len: Length of ric_ies buffer in octets @@ -144,7 +140,8 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) */ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, const u8 *anonce, const u8 *pmk_name, - const u8 *kck, const u8 *target_ap, + const u8 *kck, size_t kck_len, + const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len, const u8 *ap_mdie) { @@ -298,7 +295,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, /* Information element count */ ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies, ric_ies_len); - if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5, + if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5, ((u8 *) mdie) - 2, 2 + sizeof(*mdie), ftie_pos, 2 + *ftie_len, (u8 *) rsnie, 2 + rsnie->len, ric_ies, @@ -333,7 +330,7 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) keylen = wpa_cipher_key_len(sm->pairwise_cipher); if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc, - sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) { + sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen) < 0) { wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); return -1; } @@ -360,7 +357,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, sm->bssid, NULL, 0, mdie); + NULL, 0, sm->bssid, NULL, 0, mdie); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -376,7 +373,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, const u8 *ric_ies, size_t ric_ies_len) { u8 *ft_ies; - size_t ft_ies_len, ptk_len; + size_t ft_ies_len; struct wpa_ft_ies parse; struct rsn_mdie *mdie; struct rsn_ftie *ftie; @@ -478,16 +475,14 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name, WPA_PMK_NAME_LEN); bssid = target_ap; - ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64; - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr, - bssid, sm->pmk_r1_name, - (u8 *) &sm->ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); + if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, + sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk, + ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0) + return -1; ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce, - sm->pmk_r1_name, sm->ptk.kck, bssid, + sm->pmk_r1_name, + sm->ptk.kck, sm->ptk.kck_len, bssid, ric_ies, ric_ies_len, parse.mdie ? parse.mdie - 2 : NULL); if (ft_ies) { @@ -566,7 +561,8 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, return -1; } gtk_len = gtk_elem_len - 19; - if (aes_unwrap(sm->ptk.kek, 16, gtk_len / 8, gtk_elem + 11, gtk)) { + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11, + gtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt GTK"); return -1; @@ -645,8 +641,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, return -1; } - if (aes_unwrap(sm->ptk.kek, 16, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) - { + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8, + igtk_elem + 9, igtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt IGTK"); return -1; @@ -677,7 +673,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, struct rsn_mdie *mdie; struct rsn_ftie *ftie; unsigned int count; - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); @@ -770,7 +766,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } - if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6, + if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, @@ -839,7 +835,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, target_ap, NULL, 0, mdie); + NULL, 0, target_ap, NULL, 0, mdie); if (ft_ies) { sm->over_the_ds_in_progress = 1; os_memcpy(sm->target_ap, target_ap, ETH_ALEN); diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 07f3692ca..431bb2075 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -1,6 +1,6 @@ /* * Internal WPA/RSN supplicant state machine definitions - * Copyright (c) 2004-2010, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -254,8 +254,9 @@ static inline void wpa_sm_set_rekey_offload(struct wpa_sm *sm) { if (!sm->ctx->set_rekey_offload) return; - sm->ctx->set_rekey_offload(sm->ctx->ctx, sm->ptk.kek, - sm->ptk.kck, sm->rx_replay_counter); + sm->ctx->set_rekey_offload(sm->ctx->ctx, sm->ptk.kek, sm->ptk.kek_len, + sm->ptk.kck, sm->ptk.kck_len, + sm->rx_replay_counter); } #ifdef CONFIG_TDLS @@ -347,7 +348,7 @@ static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm, return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len); } -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, +void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic); int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, @@ -361,8 +362,7 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, struct wpa_ptk *ptk); int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len); + const struct wpa_eapol_key *key, struct wpa_ptk *ptk); void wpa_tdls_assoc(struct wpa_sm *sm); void wpa_tdls_disassoc(struct wpa_sm *sm); diff --git a/wlantest/inject.c b/wlantest/inject.c index 04cd96183..ed250332a 100644 --- a/wlantest/inject.c +++ b/wlantest/inject.c @@ -1,6 +1,6 @@ /* * wlantest frame injection - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -248,11 +248,11 @@ static int wlantest_inject_prot(struct wlantest *wt, struct wlantest_bss *bss, frame, len, hdrlen, qos, pn, 0, &crypt_len); else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) - crypt = tkip_encrypt(incorrect_key ? dummy : sta->ptk.tk1, + crypt = tkip_encrypt(incorrect_key ? dummy : sta->ptk.tk, frame, len, hdrlen, qos, pn, 0, &crypt_len); else - crypt = ccmp_encrypt(incorrect_key ? dummy : sta->ptk.tk1, + crypt = ccmp_encrypt(incorrect_key ? dummy : sta->ptk.tk, frame, len, hdrlen, qos, pn, 0, &crypt_len); diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 3c500d61f..4c55e7d49 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -1,6 +1,6 @@ /* * Received Data frame processing - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -107,21 +107,21 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, decrypted = NULL; if ((pairwise_cipher == WPA_CIPHER_CCMP || pairwise_cipher == 0) && tk_len == 16) { - decrypted = ccmp_decrypt(ptk->ptk.tk1, hdr, data, + decrypted = ccmp_decrypt(ptk->ptk.tk, hdr, data, data_len, decrypted_len); } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || pairwise_cipher == 0) && tk_len == 32) { - decrypted = ccmp_256_decrypt(ptk->ptk.tk1, hdr, data, + decrypted = ccmp_256_decrypt(ptk->ptk.tk, hdr, data, data_len, decrypted_len); } else if ((pairwise_cipher == WPA_CIPHER_GCMP || pairwise_cipher == WPA_CIPHER_GCMP_256 || pairwise_cipher == 0) && (tk_len == 16 || tk_len == 32)) { - decrypted = gcmp_decrypt(ptk->ptk.tk1, tk_len, hdr, + decrypted = gcmp_decrypt(ptk->ptk.tk, tk_len, hdr, data, data_len, decrypted_len); } else if ((pairwise_cipher == WPA_CIPHER_TKIP || pairwise_cipher == 0) && tk_len == 32) { - decrypted = tkip_decrypt(ptk->ptk.tk1, hdr, data, + decrypted = tkip_decrypt(ptk->ptk.tk, hdr, data, data_len, decrypted_len); } if (decrypted) { @@ -411,19 +411,19 @@ skip_replay_det: else decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); } else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) { - decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); + decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen); } else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) { decrypted = wep_decrypt(wt, hdr, data, len, &dlen); } else if (sta->ptk_set) { if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) - decrypted = ccmp_256_decrypt(sta->ptk.tk1, hdr, data, + decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, data, len, &dlen); else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || sta->pairwise_cipher == WPA_CIPHER_GCMP_256) - decrypted = gcmp_decrypt(sta->ptk.tk1, sta->tk_len, + decrypted = gcmp_decrypt(sta->ptk.tk, sta->tk_len, hdr, data, len, &dlen); else - decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, + decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len, &dlen); } else { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 704c0eb9f..04ea6acb8 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -1,6 +1,6 @@ /* * Received Data frame processing for EAPOL messages - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -31,14 +31,15 @@ static int is_zero(const u8 *buf, size_t len) } -static int check_mic(const u8 *kck, int akmp, int ver, const u8 *data, - size_t len) +static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver, + const u8 *data, size_t len) { u8 *buf; int ret = -1; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - u8 rx_mic[16]; + u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; buf = os_malloc(len); if (buf == NULL) @@ -47,11 +48,12 @@ static int check_mic(const u8 *kck, int akmp, int ver, const u8 *data, hdr = (struct ieee802_1x_hdr *) buf; key = (struct wpa_eapol_key *) (hdr + 1); - os_memcpy(rx_mic, key->key_mic, 16); - os_memset(key->key_mic, 0, 16); + os_memcpy(rx_mic, key->key_mic, mic_len); + os_memset(key->key_mic, 0, mic_len); - if (wpa_eapol_key_mic(kck, akmp, ver, buf, len, key->key_mic) == 0 && - os_memcmp(rx_mic, key->key_mic, 16) == 0) + if (wpa_eapol_key_mic(kck, kck_len, akmp, ver, buf, len, + key->key_mic) == 0 && + os_memcmp(rx_mic, key->key_mic, mic_len) == 0) ret = 0; os_free(buf); @@ -97,16 +99,12 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, struct wlantest_pmk *pmk) { struct wpa_ptk ptk; - size_t ptk_len; - ptk_len = wpa_cipher_key_len(sta->pairwise_cipher) + 32; - - wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk), - "Pairwise key expansion", - bss->bssid, sta->addr, sta->anonce, sta->snonce, - (u8 *) &ptk, ptk_len, - wpa_key_mgmt_sha256(sta->key_mgmt)); - if (check_mic(ptk.kck, sta->key_mgmt, ver, data, len) < 0) + if (wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk), + "Pairwise key expansion", + bss->bssid, sta->addr, sta->anonce, sta->snonce, + &ptk, sta->key_mgmt, sta->pairwise_cipher) < 0 || + check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0) return -1; sta->tk_len = wpa_cipher_key_len(sta->pairwise_cipher); @@ -120,22 +118,20 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, */ add_note(wt, MSG_DEBUG, "Derived PTK during rekeying"); os_memcpy(&sta->tptk, &ptk, sizeof(ptk)); - wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16); - wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16); - wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16); - if (ptk_len > 48) - wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2, - 16); + wpa_hexdump(MSG_DEBUG, "TPTK:KCK", + sta->tptk.kck, sta->tptk.kck_len); + wpa_hexdump(MSG_DEBUG, "TPTK:KEK", + sta->tptk.kek, sta->tptk.kek_len); + wpa_hexdump(MSG_DEBUG, "TPTK:TK", + sta->tptk.tk, sta->tptk.tk_len); sta->tptk_set = 1; return 0; } add_note(wt, MSG_DEBUG, "Derived new PTK"); os_memcpy(&sta->ptk, &ptk, sizeof(ptk)); - wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16); - wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16); - wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16); - if (ptk_len > 48) - wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16); + wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, sta->ptk.kck_len); + wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, sta->ptk.kek_len); + wpa_hexdump(MSG_DEBUG, "PTK:TK", sta->ptk.tk, sta->ptk.tk_len); sta->ptk_set = 1; os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); @@ -169,8 +165,8 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss, wpa_debug_level = MSG_WARNING; dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) { - if (check_mic(ptk->ptk.kck, sta->key_mgmt, ver, data, - len) < 0) + if (check_mic(ptk->ptk.kck, ptk->ptk.kck_len, + sta->key_mgmt, ver, data, len) < 0) continue; wpa_printf(MSG_INFO, "Pre-set PTK matches for STA " MACSTR " BSSID " MACSTR, @@ -179,12 +175,12 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss, ptk->ptk_len = 32 + wpa_cipher_key_len(sta->pairwise_cipher); os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk)); - wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16); - wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16); - wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16); - if (ptk->ptk_len > 48) - wpa_hexdump(MSG_DEBUG, "PTK:TK2", - sta->ptk.u.tk2, 16); + wpa_hexdump(MSG_DEBUG, "PTK:KCK", + sta->ptk.kck, sta->ptk.kck_len); + wpa_hexdump(MSG_DEBUG, "PTK:KEK", + sta->ptk.kek, sta->ptk.kek_len); + wpa_hexdump(MSG_DEBUG, "PTK:TK", + sta->ptk.tk, sta->ptk.tk_len); sta->ptk_set = 1; os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); @@ -204,6 +200,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, const struct ieee802_1x_hdr *eapol; const struct wpa_eapol_key *hdr; const u8 *key_data, *kck; + size_t kck_len; u16 key_info, key_data_len; struct wpa_eapol_ie_parse ie; @@ -238,13 +235,15 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; if (sta->tptk_set) { add_note(wt, MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; + kck_len = sta->tptk.kck_len; } - if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + if (check_mic(kck, kck_len, sta->key_mgmt, + key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC"); return; } @@ -371,10 +370,13 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek, } -static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, u16 ver, +static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, + size_t kek_len, u16 ver, const struct wpa_eapol_key *hdr, size_t *len) { + if (kek_len != 16) + return NULL; switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: return decrypt_eapol_key_data_rc4(wt, kek, hdr, len); @@ -513,6 +515,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, const struct ieee802_1x_hdr *eapol; const struct wpa_eapol_key *hdr; const u8 *key_data, *kck, *kek; + size_t kck_len, kek_len; int recalc = 0; u16 key_info, ver; u8 *decrypted_buf = NULL; @@ -551,15 +554,19 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } kek = sta->ptk.kek; + kek_len = sta->ptk.kek_len; kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; if (sta->tptk_set) { add_note(wt, MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; + kck_len = sta->tptk.kck_len; kek = sta->tptk.kek; + kek_len = sta->tptk.kek_len; } - if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + if (check_mic(kck, kck_len, sta->key_mgmt, + key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC"); return; } @@ -574,8 +581,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, decrypted_len = WPA_GET_BE16(hdr->key_data_length); } else { ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted_buf = decrypt_eapol_key_data(wt, kek, ver, hdr, - &decrypted_len); + decrypted_buf = decrypt_eapol_key_data(wt, kek, kek_len, ver, + hdr, &decrypted_len); if (decrypted_buf == NULL) { add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data"); @@ -674,6 +681,7 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, const struct wpa_eapol_key *hdr; u16 key_info; const u8 *kck; + size_t kck_len; wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); @@ -699,13 +707,15 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, } kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; if (sta->tptk_set) { add_note(wt, MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; + kck_len = sta->tptk.kck_len; } - if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + if (check_mic(kck, kck_len, sta->key_mgmt, + key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC"); return; } @@ -752,7 +762,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, } if (sta->ptk_set && - check_mic(sta->ptk.kck, sta->key_mgmt, + check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC"); @@ -766,8 +776,8 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, return; } ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, ver, hdr, - &decrypted_len); + decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, sta->ptk.kek_len, + ver, hdr, &decrypted_len); if (decrypted == NULL) { add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data"); return; @@ -877,7 +887,7 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst, } if (sta->ptk_set && - check_mic(sta->ptk.kck, sta->key_mgmt, + check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC"); diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 2d7ef1d74..5f60abec4 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1,6 +1,6 @@ /* * Received Management frame processing - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -983,7 +983,7 @@ static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len, wpa_hexdump(MSG_INFO, "RSC", rsc, 6); } - decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data + 24, len - 24, dlen); + decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data + 24, len - 24, dlen); if (decrypted) { os_memcpy(rsc, pn, 6); frame = os_malloc(24 + *dlen); diff --git a/wlantest/wlantest.c b/wlantest/wlantest.c index a2141414a..ab3b2fc6b 100644 --- a/wlantest/wlantest.c +++ b/wlantest/wlantest.c @@ -1,6 +1,6 @@ /* * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010-2013, Jouni Malinen + * Copyright (c) 2010-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -210,10 +210,16 @@ static int add_ptk_file(struct wlantest *wt, const char *ptk_file) if (p == NULL) break; if (ptk_len < 48) { - os_memcpy(p->ptk.tk1, ptk, ptk_len); + os_memcpy(p->ptk.tk, ptk, ptk_len); + p->ptk.tk_len = ptk_len; p->ptk_len = 32 + ptk_len; } else { - os_memcpy(&p->ptk, ptk, ptk_len); + os_memcpy(p->ptk.kck, ptk, 16); + p->ptk.kck_len = 16; + os_memcpy(p->ptk.kek, ptk + 16, 16); + p->ptk.kek_len = 16; + os_memcpy(p->ptk.tk, ptk + 32, ptk_len - 32); + p->ptk.tk_len = ptk_len - 32; p->ptk_len = ptk_len; } dl_list_add(&wt->ptk, &p->list); diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 9debcf849..65b430d4a 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -1,6 +1,6 @@ /* * wpa_supplicant - Internal driver interface wrappers - * Copyright (c) 2003-2009, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -569,12 +569,14 @@ static inline int wpa_drv_driver_cmd(struct wpa_supplicant *wpa_s, #endif /* ANDROID */ static inline void wpa_drv_set_rekey_info(struct wpa_supplicant *wpa_s, - const u8 *kek, const u8 *kck, + const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, const u8 *replay_ctr) { if (!wpa_s->driver->set_rekey_info) return; - wpa_s->driver->set_rekey_info(wpa_s->drv_priv, kek, kck, replay_ctr); + wpa_s->driver->set_rekey_info(wpa_s->drv_priv, kek, kek_len, + kck, kck_len, replay_ctr); } static inline int wpa_drv_radio_disable(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 240ee1c72..07d160783 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2014, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -2992,7 +2992,9 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, } wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr); wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck, - data->assoc_info.ptk_kek); + data->assoc_info.ptk_kck_len, + data->assoc_info.ptk_kek, + data->assoc_info.ptk_kek_len); } diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 838704335..99e735122 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Glue code to setup EAPOL and RSN modules - * Copyright (c) 2003-2012, Jouni Malinen + * Copyright (c) 2003-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -968,13 +968,14 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) #ifndef CONFIG_NO_WPA -static void wpa_supplicant_set_rekey_offload(void *ctx, const u8 *kek, - const u8 *kck, +static void wpa_supplicant_set_rekey_offload(void *ctx, + const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, const u8 *replay_ctr) { struct wpa_supplicant *wpa_s = ctx; - wpa_drv_set_rekey_info(wpa_s, kek, kck, replay_ctr); + wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr); } #endif /* CONFIG_NO_WPA */