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 <j@w1.fi>
This commit is contained in:
parent
287eb3f9d7
commit
98cd3d1c3b
21 changed files with 401 additions and 317 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* IEEE 802.11 RSN / WPA Authenticator
|
* IEEE 802.11 RSN / WPA Authenticator
|
||||||
* Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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 ||
|
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||||
wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) ||
|
wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) ||
|
||||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
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,
|
(key_data_len - 8) / 8, buf,
|
||||||
(u8 *) (key + 1))) {
|
(u8 *) (key + 1))) {
|
||||||
os_free(hdr);
|
os_free(hdr);
|
||||||
|
@ -1495,16 +1495,20 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WPA_PUT_BE16(key->key_data_length, key_data_len);
|
WPA_PUT_BE16(key->key_data_length, key_data_len);
|
||||||
} else {
|
} else if (sm->PTK.kek_len == 16) {
|
||||||
u8 ek[32];
|
u8 ek[32];
|
||||||
os_memcpy(key->key_iv,
|
os_memcpy(key->key_iv,
|
||||||
sm->group->Counter + WPA_NONCE_LEN - 16, 16);
|
sm->group->Counter + WPA_NONCE_LEN - 16, 16);
|
||||||
inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
|
inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
|
||||||
os_memcpy(ek, key->key_iv, 16);
|
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);
|
os_memcpy(key + 1, buf, key_data_len);
|
||||||
rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len);
|
rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len);
|
||||||
WPA_PUT_BE16(key->key_data_length, key_data_len);
|
WPA_PUT_BE16(key->key_data_length, key_data_len);
|
||||||
|
} else {
|
||||||
|
os_free(hdr);
|
||||||
|
os_free(buf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
}
|
}
|
||||||
|
@ -1517,7 +1521,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
os_free(hdr);
|
os_free(hdr);
|
||||||
return;
|
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);
|
(u8 *) hdr, len, key->key_mic);
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (!pairwise &&
|
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;
|
struct wpa_eapol_key *key;
|
||||||
u16 key_info;
|
u16 key_info;
|
||||||
int ret = 0;
|
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))
|
if (data_len < sizeof(*hdr) + sizeof(*key))
|
||||||
return -1;
|
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;
|
hdr = (struct ieee802_1x_hdr *) data;
|
||||||
key = (struct wpa_eapol_key *) (hdr + 1);
|
key = (struct wpa_eapol_key *) (hdr + 1);
|
||||||
key_info = WPA_GET_BE16(key->key_info);
|
key_info = WPA_GET_BE16(key->key_info);
|
||||||
os_memcpy(mic, key->key_mic, 16);
|
os_memcpy(mic, key->key_mic, mic_len);
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
if (wpa_eapol_key_mic(PTK->kck, akmp, key_info & WPA_KEY_INFO_TYPE_MASK,
|
if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
|
||||||
|
key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
data, data_len, key->key_mic) ||
|
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;
|
ret = -1;
|
||||||
os_memcpy(key->key_mic, mic, 16);
|
os_memcpy(key->key_mic, mic, mic_len);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1928,18 +1935,14 @@ SM_STATE(WPA_PTK, PTKSTART)
|
||||||
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
||||||
const u8 *pmk, struct wpa_ptk *ptk)
|
const u8 *pmk, struct wpa_ptk *ptk)
|
||||||
{
|
{
|
||||||
size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32;
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
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 */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
|
return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
|
||||||
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
|
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
|
||||||
(u8 *) ptk, ptk_len,
|
ptk, sm->wpa_key_mgmt, sm->pairwise);
|
||||||
wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2271,7 +2274,7 @@ SM_STATE(WPA_PTK, PTKINITDONE)
|
||||||
enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
|
enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
|
||||||
int klen = wpa_cipher_key_len(sm->pairwise);
|
int klen = wpa_cipher_key_len(sm->pairwise);
|
||||||
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
|
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);
|
wpa_sta_disconnect(sm->wpa_auth, sm->addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3171,7 +3174,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
|
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,
|
sm->wpa_auth->addr, sm->addr, session_timeout,
|
||||||
eapol, sm->wpa_key_mgmt))
|
eapol, sm->wpa_key_mgmt))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* hostapd - IEEE 802.11r - Fast BSS Transition
|
* hostapd - IEEE 802.11r - Fast BSS Transition
|
||||||
* Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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,
|
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_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
|
||||||
u8 pmk_r1[PMK_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;
|
const u8 *ssid = sm->wpa_auth->conf.ssid;
|
||||||
size_t ssid_len = sm->wpa_auth->conf.ssid_len;
|
size_t ssid_len = sm->wpa_auth->conf.ssid_len;
|
||||||
|
|
||||||
|
|
||||||
if (sm->xxkey_len == 0) {
|
if (sm->xxkey_len == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
|
wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
|
||||||
"derivation");
|
"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,
|
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name,
|
||||||
sm->pairwise);
|
sm->pairwise);
|
||||||
|
|
||||||
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
return wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
||||||
sm->wpa_auth->addr, sm->pmk_r1_name,
|
sm->wpa_auth->addr, sm->pmk_r1_name,
|
||||||
(u8 *) ptk, ptk_len, ptk_name);
|
ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
|
||||||
subelem[4] = gsm->GTK_len;
|
subelem[4] = gsm->GTK_len;
|
||||||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
|
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);
|
os_free(subelem);
|
||||||
return NULL;
|
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);
|
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
|
||||||
pos += 6;
|
pos += 6;
|
||||||
*pos++ = WPA_IGTK_LEN;
|
*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)) {
|
gsm->IGTK[gsm->GN_igtk - 4], pos)) {
|
||||||
os_free(subelem);
|
os_free(subelem);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -745,7 +741,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||||
ric_start = NULL;
|
ric_start = NULL;
|
||||||
|
|
||||||
if (auth_alg == WLAN_AUTH_FT &&
|
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,
|
mdie, mdie_len, ftie, ftie_len,
|
||||||
rsnie, rsnie_len,
|
rsnie, rsnie_len,
|
||||||
ric_start, ric_start ? pos - ric_start : 0,
|
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.
|
* optimized by adding the STA entry earlier.
|
||||||
*/
|
*/
|
||||||
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
|
if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
|
||||||
sm->PTK.tk1, klen))
|
sm->PTK.tk, klen))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
|
/* 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];
|
u8 ptk_name[WPA_PMK_NAME_LEN];
|
||||||
struct wpa_auth_config *conf;
|
struct wpa_auth_config *conf;
|
||||||
struct wpa_ft_ies parse;
|
struct wpa_ft_ies parse;
|
||||||
size_t buflen, ptk_len;
|
size_t buflen;
|
||||||
int ret;
|
int ret;
|
||||||
u8 *pos, *end;
|
u8 *pos, *end;
|
||||||
int pairwise;
|
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",
|
wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
|
||||||
sm->ANonce, WPA_NONCE_LEN);
|
sm->ANonce, WPA_NONCE_LEN);
|
||||||
|
|
||||||
ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48;
|
if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
||||||
wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
|
sm->wpa_auth->addr, pmk_r1_name,
|
||||||
sm->wpa_auth->addr, pmk_r1_name,
|
&sm->PTK, ptk_name, sm->wpa_key_mgmt,
|
||||||
(u8 *) &sm->PTK, ptk_len, ptk_name);
|
pairwise) < 0)
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
(u8 *) &sm->PTK, ptk_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
|
|
||||||
|
|
||||||
sm->pairwise = pairwise;
|
sm->pairwise = pairwise;
|
||||||
sm->PTK_valid = TRUE;
|
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 wpa_ft_ies parse;
|
||||||
struct rsn_mdie *mdie;
|
struct rsn_mdie *mdie;
|
||||||
struct rsn_ftie *ftie;
|
struct rsn_ftie *ftie;
|
||||||
u8 mic[16];
|
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||||
|
size_t mic_len = 16;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
|
||||||
if (sm == NULL)
|
if (sm == NULL)
|
||||||
|
@ -1108,7 +1104,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||||
return -1;
|
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.mdie - 2, parse.mdie_len + 2,
|
||||||
parse.ftie - 2, parse.ftie_len + 2,
|
parse.ftie - 2, parse.ftie_len + 2,
|
||||||
parse.rsn - 2, parse.rsn_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;
|
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: Invalid MIC in FTIE");
|
||||||
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
|
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
|
||||||
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
|
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
|
||||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
|
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
|
||||||
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
|
ftie->mic, mic_len);
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len);
|
||||||
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
|
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
|
||||||
parse.mdie - 2, parse.mdie_len + 2);
|
parse.mdie - 2, parse.mdie_len + 2);
|
||||||
wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
|
wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
|
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
|
||||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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,
|
u8 *buf, size_t len, const u8 *subelem,
|
||||||
size_t subelem_len);
|
size_t subelem_len);
|
||||||
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
|
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);
|
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_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
|
||||||
void wpa_ft_install_ptk(struct wpa_state_machine *sm);
|
void wpa_ft_install_ptk(struct wpa_state_machine *sm);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA/RSN - Shared functions for supplicant and authenticator
|
* WPA/RSN - Shared functions for supplicant and authenticator
|
||||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -19,9 +19,22 @@
|
||||||
#include "wpa_common.h"
|
#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
|
* wpa_eapol_key_mic - Calculate EAPOL-Key MIC
|
||||||
* @key: EAPOL-Key Key Confirmation Key (KCK)
|
* @key: EAPOL-Key Key Confirmation Key (KCK)
|
||||||
|
* @key_len: KCK length in octets
|
||||||
* @akmp: WPA_KEY_MGMT_* used in key derivation
|
* @akmp: WPA_KEY_MGMT_* used in key derivation
|
||||||
* @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
|
* @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
|
||||||
* @buf: Pointer to the beginning of the EAPOL header (version field)
|
* @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
|
* happened during final editing of the standard and the correct behavior is
|
||||||
* defined in the last draft (IEEE 802.11i/D10).
|
* defined in the last draft (IEEE 802.11i/D10).
|
||||||
*/
|
*/
|
||||||
int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
|
||||||
size_t len, u8 *mic)
|
const u8 *buf, size_t len, u8 *mic)
|
||||||
{
|
{
|
||||||
u8 hash[SHA256_MAC_LEN];
|
u8 hash[SHA256_MAC_LEN];
|
||||||
|
|
||||||
switch (ver) {
|
switch (ver) {
|
||||||
#ifndef CONFIG_FIPS
|
#ifndef CONFIG_FIPS
|
||||||
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
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 */
|
#endif /* CONFIG_FIPS */
|
||||||
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
|
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;
|
return -1;
|
||||||
os_memcpy(mic, hash, MD5_MAC_LEN);
|
os_memcpy(mic, hash, MD5_MAC_LEN);
|
||||||
break;
|
break;
|
||||||
|
@ -65,7 +78,7 @@ int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
#ifdef CONFIG_SUITEB
|
#ifdef CONFIG_SUITEB
|
||||||
case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
|
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;
|
return -1;
|
||||||
os_memcpy(mic, hash, MD5_MAC_LEN);
|
os_memcpy(mic, hash, MD5_MAC_LEN);
|
||||||
break;
|
break;
|
||||||
|
@ -92,8 +105,9 @@ int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
||||||
* @nonce1: ANonce or SNonce
|
* @nonce1: ANonce or SNonce
|
||||||
* @nonce2: SNonce or ANonce
|
* @nonce2: SNonce or ANonce
|
||||||
* @ptk: Buffer for pairwise transient key
|
* @ptk: Buffer for pairwise transient key
|
||||||
* @ptk_len: Length of PTK
|
* @akmp: Negotiated AKM
|
||||||
* @use_sha256: Whether to use SHA256-based KDF
|
* @cipher: Negotiated pairwise cipher
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
*
|
*
|
||||||
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
||||||
* PTK = PRF-X(PMK, "Pairwise key expansion",
|
* 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(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
|
||||||
* Min(INonce, PNonce) || Max(INonce, PNonce))
|
* Min(INonce, PNonce) || Max(INonce, PNonce))
|
||||||
*/
|
*/
|
||||||
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
||||||
const u8 *addr1, const u8 *addr2,
|
const u8 *addr1, const u8 *addr2,
|
||||||
const u8 *nonce1, const u8 *nonce2,
|
const u8 *nonce1, const u8 *nonce2,
|
||||||
u8 *ptk, size_t ptk_len, int use_sha256)
|
struct wpa_ptk *ptk, int akmp, int cipher)
|
||||||
{
|
{
|
||||||
u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
|
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) {
|
if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
|
||||||
os_memcpy(data, addr1, ETH_ALEN);
|
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);
|
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
|
#ifdef CONFIG_IEEE80211W
|
||||||
if (use_sha256)
|
if (wpa_key_mgmt_sha256(akmp))
|
||||||
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
|
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
|
||||||
ptk, ptk_len);
|
tmp, ptk_len);
|
||||||
else
|
else
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
|
sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len);
|
||||||
ptk_len);
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
|
wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
|
||||||
MAC2STR(addr1), MAC2STR(addr2));
|
MAC2STR(addr1), MAC2STR(addr2));
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
|
wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, 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: 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
|
#ifdef CONFIG_IEEE80211R
|
||||||
int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
|
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
|
||||||
u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
|
const u8 *ap_addr, u8 transaction_seqnum,
|
||||||
|
const u8 *mdie, size_t mdie_len,
|
||||||
const u8 *ftie, size_t ftie_len,
|
const u8 *ftie, size_t ftie_len,
|
||||||
const u8 *rsnie, size_t rsnie_len,
|
const u8 *rsnie, size_t rsnie_len,
|
||||||
const u8 *ric, size_t ric_len, u8 *mic)
|
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;
|
u8 *buf, *pos;
|
||||||
size_t buf_len;
|
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_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
|
||||||
buf = os_malloc(buf_len);
|
buf = os_malloc(buf_len);
|
||||||
if (buf == NULL)
|
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
|
* 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,
|
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 *sta_addr, const u8 *bssid,
|
||||||
const u8 *pmk_r1_name,
|
const u8 *pmk_r1_name,
|
||||||
u8 *ptk, size_t ptk_len, u8 *ptk_name)
|
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
|
||||||
{
|
{
|
||||||
u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
|
u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
|
||||||
u8 *pos, hash[32];
|
u8 *pos, hash[32];
|
||||||
const u8 *addr[6];
|
const u8 *addr[6];
|
||||||
size_t len[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 ||
|
* 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);
|
os_memcpy(pos, sta_addr, ETH_ALEN);
|
||||||
pos += 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 ||
|
* 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);
|
sha256_vector(6, addr, len, hash);
|
||||||
os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
|
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 */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA definitions shared between hostapd and wpa_supplicant
|
* WPA definitions shared between hostapd and wpa_supplicant
|
||||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -191,22 +191,23 @@ struct wpa_eapol_key {
|
||||||
/* followed by key_data_length bytes of key_data */
|
/* followed by key_data_length bytes of key_data */
|
||||||
} STRUCT_PACKED;
|
} 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
|
* struct wpa_ptk - WPA Pairwise Transient Key
|
||||||
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
* IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
|
||||||
*/
|
*/
|
||||||
struct wpa_ptk {
|
struct wpa_ptk {
|
||||||
u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */
|
u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */
|
||||||
u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */
|
u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */
|
||||||
u8 tk1[16]; /* Temporal Key 1 (TK1) */
|
u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */
|
||||||
union {
|
size_t kck_len;
|
||||||
u8 tk2[16]; /* Temporal Key 2 (TK2) */
|
size_t kek_len;
|
||||||
struct {
|
size_t tk_len;
|
||||||
u8 tx_mic_key[8];
|
};
|
||||||
u8 rx_mic_key[8];
|
|
||||||
} auth;
|
|
||||||
} u;
|
|
||||||
} STRUCT_PACKED;
|
|
||||||
|
|
||||||
|
|
||||||
/* WPA IE version 1
|
/* WPA IE version 1
|
||||||
|
@ -327,16 +328,17 @@ struct rsn_rdie {
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
|
||||||
int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
|
||||||
size_t len, u8 *mic);
|
const u8 *buf, size_t len, u8 *mic);
|
||||||
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
||||||
const u8 *addr1, const u8 *addr2,
|
const u8 *addr1, const u8 *addr2,
|
||||||
const u8 *nonce1, const u8 *nonce2,
|
const u8 *nonce1, const u8 *nonce2,
|
||||||
u8 *ptk, size_t ptk_len, int use_sha256);
|
struct wpa_ptk *ptk, int akmp, int cipher);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
|
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
|
||||||
u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
|
const u8 *ap_addr, u8 transaction_seqnum,
|
||||||
|
const u8 *mdie, size_t mdie_len,
|
||||||
const u8 *ftie, size_t ftie_len,
|
const u8 *ftie, size_t ftie_len,
|
||||||
const u8 *rsnie, size_t rsnie_len,
|
const u8 *rsnie, size_t rsnie_len,
|
||||||
const u8 *ric, size_t ric_len, u8 *mic);
|
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,
|
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
|
||||||
const u8 *r1kh_id, const u8 *s1kh_id,
|
const u8 *r1kh_id, const u8 *s1kh_id,
|
||||||
u8 *pmk_r1, u8 *pmk_r1_name);
|
u8 *pmk_r1, u8 *pmk_r1_name);
|
||||||
void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
|
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 *sta_addr, const u8 *bssid,
|
||||||
const u8 *pmk_r1_name,
|
const u8 *pmk_r1_name,
|
||||||
u8 *ptk, size_t ptk_len, u8 *ptk_name);
|
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher);
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
struct wpa_ie_data {
|
struct wpa_ie_data {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Driver interface definition
|
* Driver interface definition
|
||||||
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -2859,14 +2859,17 @@ struct wpa_driver_ops {
|
||||||
* set_rekey_info - Set rekey information
|
* set_rekey_info - Set rekey information
|
||||||
* @priv: Private driver interface data
|
* @priv: Private driver interface data
|
||||||
* @kek: Current KEK
|
* @kek: Current KEK
|
||||||
|
* @kek_len: KEK length in octets
|
||||||
* @kck: Current KCK
|
* @kck: Current KCK
|
||||||
|
* @kck_len: KCK length in octets
|
||||||
* @replay_ctr: Current EAPOL-Key Replay Counter
|
* @replay_ctr: Current EAPOL-Key Replay Counter
|
||||||
*
|
*
|
||||||
* This optional function can be used to provide information for the
|
* This optional function can be used to provide information for the
|
||||||
* driver/firmware to process EAPOL-Key frames in Group Key Handshake
|
* driver/firmware to process EAPOL-Key frames in Group Key Handshake
|
||||||
* while the host (including wpa_supplicant) is sleeping.
|
* 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);
|
const u8 *replay_ctr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Driver interaction with Linux nl80211/cfg80211
|
* Driver interaction with Linux nl80211/cfg80211
|
||||||
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
|
||||||
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
|
||||||
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
* Copyright (c) 2005-2006, Devicescape Software, Inc.
|
||||||
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
|
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
|
||||||
|
@ -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)
|
const u8 *replay_ctr)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
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");
|
wpa_printf(MSG_DEBUG, "nl80211: Set rekey offload");
|
||||||
if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_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)) ||
|
!(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_KEK, kek_len, kek) ||
|
||||||
nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) ||
|
nla_put(msg, NL80211_REKEY_DATA_KCK, kck_len, kck) ||
|
||||||
nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
|
nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
|
||||||
replay_ctr)) {
|
replay_ctr)) {
|
||||||
nl80211_nlmsg_clear(msg);
|
nl80211_nlmsg_clear(msg);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
|
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
|
||||||
* Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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);
|
"(mui %d error_type %d)", mui, error_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
|
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst,
|
||||||
rbuf, rlen, err->key_mic);
|
ETH_P_EAPOL, rbuf, rlen, err->key_mic);
|
||||||
|
|
||||||
return 0;
|
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_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
|
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
|
||||||
wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
|
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr,
|
||||||
rbuf, rlen, reply->key_mic);
|
ETH_P_EAPOL, rbuf, rlen, reply->key_mic);
|
||||||
|
|
||||||
return 0;
|
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);
|
os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
|
||||||
peerkey->rsnie_i_len = kde.rsn_ie_len;
|
peerkey->rsnie_i_len = kde.rsn_ie_len;
|
||||||
peerkey->cipher = cipher;
|
peerkey->cipher = cipher;
|
||||||
#ifdef CONFIG_IEEE80211W
|
peerkey->akmp = ie.key_mgmt;
|
||||||
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 */
|
|
||||||
|
|
||||||
if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
|
if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
|
@ -289,14 +284,14 @@ static int wpa_supplicant_process_smk_m2(
|
||||||
* @mac_p: Peer MAC address
|
* @mac_p: Peer MAC address
|
||||||
* @inonce: Initiator Nonce
|
* @inonce: Initiator Nonce
|
||||||
* @mac_i: Initiator MAC address
|
* @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
|
* 8.5.1.4 Station to station (STK) key hierarchy
|
||||||
* SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
|
* 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,
|
static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
|
||||||
const u8 *inonce, const u8 *mac_i, u8 *smkid,
|
const u8 *inonce, const u8 *mac_i, u8 *smkid,
|
||||||
int use_sha256)
|
int akmp)
|
||||||
{
|
{
|
||||||
char *title = "SMK Name";
|
char *title = "SMK Name";
|
||||||
const u8 *addr[5];
|
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;
|
addr[4] = mac_i;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
if (use_sha256)
|
if (wpa_key_mgmt_sha256(akmp))
|
||||||
hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
|
hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
|
||||||
else
|
else
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#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,
|
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
|
||||||
MAC2STR(peerkey->addr));
|
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);
|
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,
|
wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
|
||||||
MAC2STR(peerkey->addr));
|
MAC2STR(peerkey->addr));
|
||||||
wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
|
wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver,
|
||||||
ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
|
peerkey->addr, ETH_P_EAPOL, mbuf, mlen,
|
||||||
|
msg->key_mic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -576,12 +572,12 @@ static int wpa_supplicant_process_smk_m45(
|
||||||
if (peerkey->initiator) {
|
if (peerkey->initiator) {
|
||||||
rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
|
rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
|
||||||
peerkey->inonce, sm->own_addr, peerkey->smkid,
|
peerkey->inonce, sm->own_addr, peerkey->smkid,
|
||||||
peerkey->use_sha256);
|
peerkey->akmp);
|
||||||
wpa_supplicant_send_stk_1_of_4(sm, peerkey);
|
wpa_supplicant_send_stk_1_of_4(sm, peerkey);
|
||||||
} else {
|
} else {
|
||||||
rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
|
rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
|
||||||
peerkey->inonce, peerkey->addr, peerkey->smkid,
|
peerkey->inonce, peerkey->addr, peerkey->smkid,
|
||||||
peerkey->use_sha256);
|
peerkey->akmp);
|
||||||
}
|
}
|
||||||
wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
|
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",
|
wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
|
||||||
sm->own_addr, peerkey->addr,
|
sm->own_addr, peerkey->addr,
|
||||||
peerkey->pnonce, key->key_nonce,
|
peerkey->pnonce, key->key_nonce,
|
||||||
(u8 *) stk, sizeof(*stk),
|
stk, peerkey->akmp, peerkey->cipher);
|
||||||
peerkey->use_sha256);
|
|
||||||
/* Supplicant: swap tx/rx Mic keys */
|
/* Supplicant: swap tx/rx Mic keys */
|
||||||
os_memcpy(buf, stk->u.auth.tx_mic_key, 8);
|
os_memcpy(buf, &stk->tk[16], 8);
|
||||||
os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8);
|
os_memcpy(&stk->tk[16], &stk->tk[24], 8);
|
||||||
os_memcpy(stk->u.auth.rx_mic_key, buf, 8);
|
os_memcpy(&stk->tk[24], buf, 8);
|
||||||
peerkey->tstk_set = 1;
|
peerkey->tstk_set = 1;
|
||||||
|
|
||||||
kde_buf_len = peerkey->rsnie_p_len +
|
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))
|
&peerkey->stk))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_key = (u8 *) peerkey->stk.tk1;
|
_key = peerkey->stk.tk;
|
||||||
if (peerkey->cipher == WPA_CIPHER_TKIP) {
|
if (peerkey->cipher == WPA_CIPHER_TKIP) {
|
||||||
/* Swap Tx/Rx keys for Michael MIC */
|
/* Swap Tx/Rx keys for Michael MIC */
|
||||||
os_memcpy(key_buf, _key, 16);
|
os_memcpy(key_buf, _key, 16);
|
||||||
os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8);
|
os_memcpy(key_buf + 16, _key + 24, 8);
|
||||||
os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8);
|
os_memcpy(key_buf + 24, _key + 16, 8);
|
||||||
_key = key_buf;
|
_key = key_buf;
|
||||||
key_len = 32;
|
key_len = 32;
|
||||||
} else
|
} else
|
||||||
|
@ -870,10 +865,12 @@ static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
|
||||||
os_memset(rsc, 0, 6);
|
os_memset(rsc, 0, 6);
|
||||||
if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
|
if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
|
||||||
rsc, sizeof(rsc), _key, key_len) < 0) {
|
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 "
|
wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
|
||||||
"driver.");
|
"driver.");
|
||||||
return;
|
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);
|
os_memset(rsc, 0, 6);
|
||||||
if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
|
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) {
|
peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
|
||||||
wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
|
wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
|
||||||
"driver.");
|
"driver.");
|
||||||
|
@ -913,24 +910,24 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
struct wpa_eapol_key *key, u16 ver,
|
struct wpa_eapol_key *key, u16 ver,
|
||||||
const u8 *buf, size_t len)
|
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;
|
int ok = 0;
|
||||||
|
|
||||||
if (peerkey->initiator && !peerkey->stk_set) {
|
if (peerkey->initiator && !peerkey->stk_set) {
|
||||||
wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
|
wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
|
||||||
sm->own_addr, peerkey->addr,
|
sm->own_addr, peerkey->addr,
|
||||||
peerkey->inonce, key->key_nonce,
|
peerkey->inonce, key->key_nonce,
|
||||||
(u8 *) &peerkey->stk, sizeof(peerkey->stk),
|
&peerkey->stk, peerkey->akmp, peerkey->cipher);
|
||||||
peerkey->use_sha256);
|
|
||||||
peerkey->stk_set = 1;
|
peerkey->stk_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_memcpy(mic, key->key_mic, 16);
|
os_memcpy(mic, key->key_mic, mic_len);
|
||||||
if (peerkey->tstk_set) {
|
if (peerkey->tstk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
wpa_eapol_key_mic(peerkey->tstk.kck, sm->key_mgmt, ver, buf,
|
wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len,
|
||||||
len, key->key_mic);
|
sm->key_mgmt, ver, buf, len, key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
|
||||||
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
||||||
"when using TSTK - ignoring TSTK");
|
"when using TSTK - ignoring TSTK");
|
||||||
} else {
|
} else {
|
||||||
|
@ -939,14 +936,15 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
peerkey->stk_set = 1;
|
peerkey->stk_set = 1;
|
||||||
os_memcpy(&peerkey->stk, &peerkey->tstk,
|
os_memcpy(&peerkey->stk, &peerkey->tstk,
|
||||||
sizeof(peerkey->stk));
|
sizeof(peerkey->stk));
|
||||||
|
os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok && peerkey->stk_set) {
|
if (!ok && peerkey->stk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
wpa_eapol_key_mic(peerkey->stk.kck, sm->key_mgmt, ver, buf, len,
|
wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len,
|
||||||
key->key_mic);
|
sm->key_mgmt, ver, buf, len, key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
|
||||||
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
||||||
"- dropping packet");
|
"- dropping packet");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1015,10 +1013,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
|
||||||
return -1;
|
return -1;
|
||||||
peerkey->initiator = 1;
|
peerkey->initiator = 1;
|
||||||
os_memcpy(peerkey->addr, peer, ETH_ALEN);
|
os_memcpy(peerkey->addr, peer, ETH_ALEN);
|
||||||
#ifdef CONFIG_IEEE80211W
|
peerkey->akmp = sm->key_mgmt;
|
||||||
if (wpa_key_mgmt_sha256(sm->key_mgmt))
|
|
||||||
peerkey->use_sha256 = 1;
|
|
||||||
#endif /* CONFIG_IEEE80211W */
|
|
||||||
|
|
||||||
/* SMK M1:
|
/* SMK M1:
|
||||||
* EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
|
* 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 "
|
wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
|
||||||
MACSTR ")", MAC2STR(peer));
|
MACSTR ")", MAC2STR(peer));
|
||||||
wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
|
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
|
||||||
rbuf, rlen, req->key_mic);
|
ETH_P_EAPOL, rbuf, rlen, req->key_mic);
|
||||||
|
|
||||||
peerkey->next = sm->peerkey;
|
peerkey->next = sm->peerkey;
|
||||||
sm->peerkey = peerkey;
|
sm->peerkey = peerkey;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
|
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
|
||||||
* Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -27,7 +27,7 @@ struct wpa_peerkey {
|
||||||
int cipher; /* Selected cipher (WPA_CIPHER_*) */
|
int cipher; /* Selected cipher (WPA_CIPHER_*) */
|
||||||
u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
|
u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||||
int replay_counter_set;
|
int replay_counter_set;
|
||||||
int use_sha256; /* whether AKMP indicate SHA256-based derivations */
|
int akmp;
|
||||||
|
|
||||||
struct wpa_ptk stk, tstk;
|
struct wpa_ptk stk, tstk;
|
||||||
int stk_set, tstk_set;
|
int stk_set, tstk_set;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - WPA state machine and EAPOL-Key processing
|
* WPA Supplicant - WPA state machine and EAPOL-Key processing
|
||||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
|
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
|
||||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||||
* @kck: Key Confirmation Key (KCK, part of PTK)
|
* @kck: Key Confirmation Key (KCK, part of PTK)
|
||||||
|
* @kck_len: KCK length in octets
|
||||||
* @ver: Version field from Key Info
|
* @ver: Version field from Key Info
|
||||||
* @dest: Destination address for the frame
|
* @dest: Destination address for the frame
|
||||||
* @proto: Ethertype (usually ETH_P_EAPOL)
|
* @proto: Ethertype (usually ETH_P_EAPOL)
|
||||||
|
@ -34,10 +35,12 @@
|
||||||
* @msg_len: Length of message
|
* @msg_len: Length of message
|
||||||
* @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
|
* @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,
|
int ver, const u8 *dest, u16 proto,
|
||||||
u8 *msg, size_t msg_len, u8 *key_mic)
|
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)) {
|
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
|
||||||
/*
|
/*
|
||||||
* Association event was not yet received; try to fetch
|
* 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 &&
|
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_msg(sm->ctx->msg_ctx, MSG_ERROR,
|
||||||
"WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
|
"WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
|
||||||
ver, sm->key_mgmt);
|
ver, sm->key_mgmt);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16);
|
wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16);
|
wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len);
|
||||||
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
|
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
|
||||||
wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
|
wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
|
||||||
eapol_sm_notify_tx_eapol_key(sm->eapol);
|
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 "
|
"WPA: Sending EAPOL-Key Request (error=%d "
|
||||||
"pairwise=%d ptk_set=%d len=%lu)",
|
"pairwise=%d ptk_set=%d len=%lu)",
|
||||||
error, pairwise, sm->ptk_set, (unsigned long) rlen);
|
error, pairwise, sm->ptk_set, (unsigned long) rlen);
|
||||||
wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
|
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
|
||||||
rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?
|
ETH_P_EAPOL, rbuf, rlen,
|
||||||
reply->key_mic : NULL);
|
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);
|
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
|
||||||
|
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
|
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);
|
rbuf, rlen, reply->key_mic);
|
||||||
|
|
||||||
return 0;
|
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,
|
static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
|
||||||
const struct wpa_eapol_key *key,
|
const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
|
||||||
struct wpa_ptk *ptk)
|
|
||||||
{
|
{
|
||||||
size_t ptk_len = wpa_cipher_key_len(sm->pairwise_cipher) + 32;
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->key_mgmt))
|
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 */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
|
return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
|
||||||
sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
|
sm->own_addr, sm->bssid, sm->snonce,
|
||||||
(u8 *) ptk, ptk_len,
|
key->key_nonce, ptk, sm->key_mgmt,
|
||||||
wpa_key_mgmt_sha256(sm->key_mgmt));
|
sm->pairwise_cipher);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -462,9 +463,9 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
||||||
if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
|
if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
|
||||||
u8 buf[8];
|
u8 buf[8];
|
||||||
/* Supplicant: swap tx/rx Mic keys */
|
/* Supplicant: swap tx/rx Mic keys */
|
||||||
os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
|
os_memcpy(buf, &ptk->tk[16], 8);
|
||||||
os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
|
os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
|
||||||
os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
|
os_memcpy(&ptk->tk[24], buf, 8);
|
||||||
os_memset(buf, 0, sizeof(buf));
|
os_memset(buf, 0, sizeof(buf));
|
||||||
}
|
}
|
||||||
sm->tptk_set = 1;
|
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,
|
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_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
"WPA: Failed to set PTK to the "
|
"WPA: Failed to set PTK to the "
|
||||||
"driver (alg=%d keylen=%d bssid=" MACSTR ")",
|
"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 */
|
/* TK is not needed anymore in supplicant */
|
||||||
os_memset(sm->ptk.tk1, 0, sizeof(sm->ptk.tk1));
|
os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
|
||||||
os_memset(sm->ptk.u.tk2, 0, sizeof(sm->ptk.u.tk2));
|
|
||||||
|
|
||||||
if (sm->wpa_ptk_rekey) {
|
if (sm->wpa_ptk_rekey) {
|
||||||
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
|
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_PUT_BE16(reply->key_data_length, 0);
|
||||||
|
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
|
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);
|
rbuf, rlen, reply->key_mic);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1209,7 +1209,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
||||||
struct rsn_pmksa_cache_entry *sa;
|
struct rsn_pmksa_cache_entry *sa;
|
||||||
|
|
||||||
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
|
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->bssid, sm->own_addr,
|
||||||
sm->network_ctx, sm->key_mgmt);
|
sm->network_ctx, sm->key_mgmt);
|
||||||
if (!sm->cur_pmksa)
|
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->gtk_len = gtk_len;
|
||||||
gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
|
gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
|
||||||
WPA_KEY_INFO_KEY_INDEX_SHIFT;
|
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];
|
u8 ek[32];
|
||||||
if (key_data_len > sizeof(gd->gtk)) {
|
if (key_data_len > sizeof(gd->gtk)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
os_memcpy(ek, key->key_iv, 16);
|
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);
|
os_memcpy(gd->gtk, key_data, key_data_len);
|
||||||
if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
|
if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
|
||||||
os_memset(ek, 0, sizeof(ek));
|
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);
|
(unsigned long) maxkeylen);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data,
|
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
|
||||||
gd->gtk)) {
|
key_data, gd->gtk)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
"WPA: AES unwrap failed - could not decrypt "
|
"WPA: AES unwrap failed - could not decrypt "
|
||||||
"GTK");
|
"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_PUT_BE16(reply->key_data_length, 0);
|
||||||
|
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
|
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,
|
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid,
|
||||||
rbuf, rlen, reply->key_mic);
|
ETH_P_EAPOL, rbuf, rlen, reply->key_mic);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1455,15 +1455,16 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
u16 ver,
|
u16 ver,
|
||||||
const u8 *buf, size_t len)
|
const u8 *buf, size_t len)
|
||||||
{
|
{
|
||||||
u8 mic[16];
|
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||||
int ok = 0;
|
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) {
|
if (sm->tptk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
wpa_eapol_key_mic(sm->tptk.kck, sm->key_mgmt, ver, buf, len,
|
wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt,
|
||||||
key->key_mic);
|
ver, buf, len, key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
"WPA: Invalid EAPOL-Key MIC "
|
"WPA: Invalid EAPOL-Key MIC "
|
||||||
"when using TPTK - ignoring TPTK");
|
"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) {
|
if (!ok && sm->ptk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
wpa_eapol_key_mic(sm->ptk.kck, sm->key_mgmt, ver, buf, len,
|
wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt,
|
||||||
key->key_mic);
|
ver, buf, len, key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
"WPA: Invalid EAPOL-Key MIC - "
|
"WPA: Invalid EAPOL-Key MIC - "
|
||||||
"dropping packet");
|
"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
|
/* Decrypt key data here so that this operation does not need
|
||||||
* to be implemented separately for each message type. */
|
* 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];
|
u8 ek[32];
|
||||||
os_memcpy(ek, key->key_iv, 16);
|
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)) {
|
if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
|
||||||
os_memset(ek, 0, sizeof(ek));
|
os_memset(ek, 0, sizeof(ek));
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
|
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");
|
"WPA: No memory for AES-UNWRAP buffer");
|
||||||
return -1;
|
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)) {
|
key_data, buf)) {
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
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,
|
void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
|
||||||
const u8 *ptk_kek)
|
const u8 *ptk_kck, size_t ptk_kck_len,
|
||||||
|
const u8 *ptk_kek, size_t ptk_kek_len)
|
||||||
{
|
{
|
||||||
if (ptk_kck) {
|
if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) {
|
||||||
os_memcpy(sm->ptk.kck, ptk_kck, 16);
|
os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len);
|
||||||
|
sm->ptk.kck_len = ptk_kck_len;
|
||||||
wpa_printf(MSG_DEBUG, "Updated PTK KCK");
|
wpa_printf(MSG_DEBUG, "Updated PTK KCK");
|
||||||
}
|
}
|
||||||
if (ptk_kek) {
|
if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) {
|
||||||
os_memcpy(sm->ptk.kek, ptk_kek, 16);
|
os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len);
|
||||||
|
sm->ptk.kek_len = ptk_kek_len;
|
||||||
wpa_printf(MSG_DEBUG, "Updated PTK KEK");
|
wpa_printf(MSG_DEBUG, "Updated PTK KEK");
|
||||||
}
|
}
|
||||||
sm->ptk_set = 1;
|
sm->ptk_set = 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant - WPA definitions
|
* wpa_supplicant - WPA definitions
|
||||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -73,7 +73,8 @@ struct wpa_sm_ctx {
|
||||||
const struct hostapd_freq_params *params);
|
const struct hostapd_freq_params *params);
|
||||||
int (*tdls_disable_channel_switch)(void *ctx, const u8 *addr);
|
int (*tdls_disable_channel_switch)(void *ctx, const u8 *addr);
|
||||||
#endif /* CONFIG_TDLS */
|
#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);
|
const u8 *replay_ctr);
|
||||||
int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len);
|
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);
|
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_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,
|
void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
|
||||||
const u8 *ptk_kek);
|
const u8 *ptk_kck, size_t ptk_kck_len,
|
||||||
|
const u8 *ptk_kek, size_t ptk_kek_len);
|
||||||
|
|
||||||
#else /* CONFIG_NO_WPA */
|
#else /* CONFIG_NO_WPA */
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
|
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
|
||||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -19,8 +19,7 @@
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
|
|
||||||
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
||||||
const struct wpa_eapol_key *key,
|
const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
|
||||||
struct wpa_ptk *ptk, size_t ptk_len)
|
|
||||||
{
|
{
|
||||||
u8 ptk_name[WPA_PMK_NAME_LEN];
|
u8 ptk_name[WPA_PMK_NAME_LEN];
|
||||||
const u8 *anonce = key->key_nonce;
|
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_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
|
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
|
||||||
WPA_PMK_NAME_LEN);
|
WPA_PMK_NAME_LEN);
|
||||||
wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
|
return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
|
||||||
sm->bssid, sm->pmk_r1_name,
|
sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
|
||||||
(u8 *) ptk, ptk_len, ptk_name);
|
sm->key_mgmt, sm->pairwise_cipher);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
* @anonce: ANonce or %NULL if not yet available
|
||||||
* @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
|
* @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: 128-bit KCK for MIC or %NULL if no MIC is used
|
||||||
|
* @kck_len: KCK length in octets
|
||||||
* @target_ap: Target AP address
|
* @target_ap: Target AP address
|
||||||
* @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
|
* @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
|
* @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,
|
static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
|
||||||
const u8 *anonce, const u8 *pmk_name,
|
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 *ric_ies, size_t ric_ies_len,
|
||||||
const u8 *ap_mdie)
|
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 */
|
/* Information element count */
|
||||||
ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
|
ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
|
||||||
ric_ies_len);
|
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),
|
((u8 *) mdie) - 2, 2 + sizeof(*mdie),
|
||||||
ftie_pos, 2 + *ftie_len,
|
ftie_pos, 2 + *ftie_len,
|
||||||
(u8 *) rsnie, 2 + rsnie->len, ric_ies,
|
(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);
|
keylen = wpa_cipher_key_len(sm->pairwise_cipher);
|
||||||
|
|
||||||
if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
|
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");
|
wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
|
||||||
return -1;
|
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,
|
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) {
|
if (ft_ies) {
|
||||||
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
|
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
|
||||||
ft_ies, ft_ies_len);
|
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)
|
const u8 *ric_ies, size_t ric_ies_len)
|
||||||
{
|
{
|
||||||
u8 *ft_ies;
|
u8 *ft_ies;
|
||||||
size_t ft_ies_len, ptk_len;
|
size_t ft_ies_len;
|
||||||
struct wpa_ft_ies parse;
|
struct wpa_ft_ies parse;
|
||||||
struct rsn_mdie *mdie;
|
struct rsn_mdie *mdie;
|
||||||
struct rsn_ftie *ftie;
|
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);
|
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||||
|
|
||||||
bssid = target_ap;
|
bssid = target_ap;
|
||||||
ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
|
if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
|
||||||
wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
|
sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
|
||||||
bssid, sm->pmk_r1_name,
|
ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
|
||||||
(u8 *) &sm->ptk, ptk_len, ptk_name);
|
return -1;
|
||||||
wpa_hexdump_key(MSG_DEBUG, "FT: PTK",
|
|
||||||
(u8 *) &sm->ptk, ptk_len);
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
|
|
||||||
|
|
||||||
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
|
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,
|
ric_ies, ric_ies_len,
|
||||||
parse.mdie ? parse.mdie - 2 : NULL);
|
parse.mdie ? parse.mdie - 2 : NULL);
|
||||||
if (ft_ies) {
|
if (ft_ies) {
|
||||||
|
@ -566,7 +561,8 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
gtk_len = gtk_elem_len - 19;
|
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 "
|
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
|
||||||
"decrypt GTK");
|
"decrypt GTK");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -645,8 +641,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
|
||||||
return -1;
|
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 "
|
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
|
||||||
"decrypt IGTK");
|
"decrypt IGTK");
|
||||||
return -1;
|
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_mdie *mdie;
|
||||||
struct rsn_ftie *ftie;
|
struct rsn_ftie *ftie;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
u8 mic[16];
|
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_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;
|
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.mdie - 2, parse.mdie_len + 2,
|
||||||
parse.ftie - 2, parse.ftie_len + 2,
|
parse.ftie - 2, parse.ftie_len + 2,
|
||||||
parse.rsn - 2, parse.rsn_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,
|
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) {
|
if (ft_ies) {
|
||||||
sm->over_the_ds_in_progress = 1;
|
sm->over_the_ds_in_progress = 1;
|
||||||
os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
|
os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Internal WPA/RSN supplicant state machine definitions
|
* Internal WPA/RSN supplicant state machine definitions
|
||||||
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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)
|
if (!sm->ctx->set_rekey_offload)
|
||||||
return;
|
return;
|
||||||
sm->ctx->set_rekey_offload(sm->ctx->ctx, sm->ptk.kek,
|
sm->ctx->set_rekey_offload(sm->ctx->ctx, sm->ptk.kek, sm->ptk.kek_len,
|
||||||
sm->ptk.kck, sm->rx_replay_counter);
|
sm->ptk.kck, sm->ptk.kck_len,
|
||||||
|
sm->rx_replay_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#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);
|
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,
|
int ver, const u8 *dest, u16 proto,
|
||||||
u8 *msg, size_t msg_len, u8 *key_mic);
|
u8 *msg, size_t msg_len, u8 *key_mic);
|
||||||
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
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);
|
struct wpa_ptk *ptk);
|
||||||
|
|
||||||
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
||||||
const struct wpa_eapol_key *key,
|
const struct wpa_eapol_key *key, struct wpa_ptk *ptk);
|
||||||
struct wpa_ptk *ptk, size_t ptk_len);
|
|
||||||
|
|
||||||
void wpa_tdls_assoc(struct wpa_sm *sm);
|
void wpa_tdls_assoc(struct wpa_sm *sm);
|
||||||
void wpa_tdls_disassoc(struct wpa_sm *sm);
|
void wpa_tdls_disassoc(struct wpa_sm *sm);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wlantest frame injection
|
* wlantest frame injection
|
||||||
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2010-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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,
|
frame, len, hdrlen, qos, pn, 0,
|
||||||
&crypt_len);
|
&crypt_len);
|
||||||
else if (sta->pairwise_cipher == WPA_CIPHER_TKIP)
|
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,
|
frame, len, hdrlen, qos, pn, 0,
|
||||||
&crypt_len);
|
&crypt_len);
|
||||||
else
|
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,
|
frame, len, hdrlen, qos, pn, 0,
|
||||||
&crypt_len);
|
&crypt_len);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Received Data frame processing
|
* Received Data frame processing
|
||||||
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2010-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -107,21 +107,21 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher,
|
||||||
decrypted = NULL;
|
decrypted = NULL;
|
||||||
if ((pairwise_cipher == WPA_CIPHER_CCMP ||
|
if ((pairwise_cipher == WPA_CIPHER_CCMP ||
|
||||||
pairwise_cipher == 0) && tk_len == 16) {
|
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);
|
data_len, decrypted_len);
|
||||||
} else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 ||
|
} else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 ||
|
||||||
pairwise_cipher == 0) && tk_len == 32) {
|
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);
|
data_len, decrypted_len);
|
||||||
} else if ((pairwise_cipher == WPA_CIPHER_GCMP ||
|
} else if ((pairwise_cipher == WPA_CIPHER_GCMP ||
|
||||||
pairwise_cipher == WPA_CIPHER_GCMP_256 ||
|
pairwise_cipher == WPA_CIPHER_GCMP_256 ||
|
||||||
pairwise_cipher == 0) &&
|
pairwise_cipher == 0) &&
|
||||||
(tk_len == 16 || tk_len == 32)) {
|
(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);
|
data, data_len, decrypted_len);
|
||||||
} else if ((pairwise_cipher == WPA_CIPHER_TKIP ||
|
} else if ((pairwise_cipher == WPA_CIPHER_TKIP ||
|
||||||
pairwise_cipher == 0) && tk_len == 32) {
|
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);
|
data_len, decrypted_len);
|
||||||
}
|
}
|
||||||
if (decrypted) {
|
if (decrypted) {
|
||||||
|
@ -411,19 +411,19 @@ skip_replay_det:
|
||||||
else
|
else
|
||||||
decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen);
|
decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen);
|
||||||
} else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) {
|
} 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) {
|
} else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) {
|
||||||
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
|
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
|
||||||
} else if (sta->ptk_set) {
|
} else if (sta->ptk_set) {
|
||||||
if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256)
|
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);
|
len, &dlen);
|
||||||
else if (sta->pairwise_cipher == WPA_CIPHER_GCMP ||
|
else if (sta->pairwise_cipher == WPA_CIPHER_GCMP ||
|
||||||
sta->pairwise_cipher == WPA_CIPHER_GCMP_256)
|
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);
|
hdr, data, len, &dlen);
|
||||||
else
|
else
|
||||||
decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len,
|
decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len,
|
||||||
&dlen);
|
&dlen);
|
||||||
} else {
|
} else {
|
||||||
decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data,
|
decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Received Data frame processing for EAPOL messages
|
* Received Data frame processing for EAPOL messages
|
||||||
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2010-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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,
|
static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
|
||||||
size_t len)
|
const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct ieee802_1x_hdr *hdr;
|
struct ieee802_1x_hdr *hdr;
|
||||||
struct wpa_eapol_key *key;
|
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);
|
buf = os_malloc(len);
|
||||||
if (buf == NULL)
|
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;
|
hdr = (struct ieee802_1x_hdr *) buf;
|
||||||
key = (struct wpa_eapol_key *) (hdr + 1);
|
key = (struct wpa_eapol_key *) (hdr + 1);
|
||||||
|
|
||||||
os_memcpy(rx_mic, key->key_mic, 16);
|
os_memcpy(rx_mic, key->key_mic, mic_len);
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, mic_len);
|
||||||
|
|
||||||
if (wpa_eapol_key_mic(kck, akmp, ver, buf, len, key->key_mic) == 0 &&
|
if (wpa_eapol_key_mic(kck, kck_len, akmp, ver, buf, len,
|
||||||
os_memcmp(rx_mic, key->key_mic, 16) == 0)
|
key->key_mic) == 0 &&
|
||||||
|
os_memcmp(rx_mic, key->key_mic, mic_len) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
|
@ -97,16 +99,12 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
struct wlantest_pmk *pmk)
|
struct wlantest_pmk *pmk)
|
||||||
{
|
{
|
||||||
struct wpa_ptk ptk;
|
struct wpa_ptk ptk;
|
||||||
size_t ptk_len;
|
|
||||||
|
|
||||||
ptk_len = wpa_cipher_key_len(sta->pairwise_cipher) + 32;
|
if (wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
|
||||||
|
"Pairwise key expansion",
|
||||||
wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
|
bss->bssid, sta->addr, sta->anonce, sta->snonce,
|
||||||
"Pairwise key expansion",
|
&ptk, sta->key_mgmt, sta->pairwise_cipher) < 0 ||
|
||||||
bss->bssid, sta->addr, sta->anonce, sta->snonce,
|
check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0)
|
||||||
(u8 *) &ptk, ptk_len,
|
|
||||||
wpa_key_mgmt_sha256(sta->key_mgmt));
|
|
||||||
if (check_mic(ptk.kck, sta->key_mgmt, ver, data, len) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sta->tk_len = wpa_cipher_key_len(sta->pairwise_cipher);
|
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");
|
add_note(wt, MSG_DEBUG, "Derived PTK during rekeying");
|
||||||
os_memcpy(&sta->tptk, &ptk, sizeof(ptk));
|
os_memcpy(&sta->tptk, &ptk, sizeof(ptk));
|
||||||
wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16);
|
wpa_hexdump(MSG_DEBUG, "TPTK:KCK",
|
||||||
wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16);
|
sta->tptk.kck, sta->tptk.kck_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16);
|
wpa_hexdump(MSG_DEBUG, "TPTK:KEK",
|
||||||
if (ptk_len > 48)
|
sta->tptk.kek, sta->tptk.kek_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2,
|
wpa_hexdump(MSG_DEBUG, "TPTK:TK",
|
||||||
16);
|
sta->tptk.tk, sta->tptk.tk_len);
|
||||||
sta->tptk_set = 1;
|
sta->tptk_set = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
add_note(wt, MSG_DEBUG, "Derived new PTK");
|
add_note(wt, MSG_DEBUG, "Derived new PTK");
|
||||||
os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
|
os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
|
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, sta->ptk.kck_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
|
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, sta->ptk.kek_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
|
wpa_hexdump(MSG_DEBUG, "PTK:TK", sta->ptk.tk, sta->ptk.tk_len);
|
||||||
if (ptk_len > 48)
|
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16);
|
|
||||||
sta->ptk_set = 1;
|
sta->ptk_set = 1;
|
||||||
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
|
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
|
||||||
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
|
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;
|
wpa_debug_level = MSG_WARNING;
|
||||||
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
|
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
|
||||||
if (check_mic(ptk->ptk.kck, sta->key_mgmt, ver, data,
|
if (check_mic(ptk->ptk.kck, ptk->ptk.kck_len,
|
||||||
len) < 0)
|
sta->key_mgmt, ver, data, len) < 0)
|
||||||
continue;
|
continue;
|
||||||
wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
|
wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
|
||||||
MACSTR " BSSID " MACSTR,
|
MACSTR " BSSID " MACSTR,
|
||||||
|
@ -179,12 +175,12 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
ptk->ptk_len = 32 +
|
ptk->ptk_len = 32 +
|
||||||
wpa_cipher_key_len(sta->pairwise_cipher);
|
wpa_cipher_key_len(sta->pairwise_cipher);
|
||||||
os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
|
os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
|
wpa_hexdump(MSG_DEBUG, "PTK:KCK",
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
|
sta->ptk.kck, sta->ptk.kck_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
|
wpa_hexdump(MSG_DEBUG, "PTK:KEK",
|
||||||
if (ptk->ptk_len > 48)
|
sta->ptk.kek, sta->ptk.kek_len);
|
||||||
wpa_hexdump(MSG_DEBUG, "PTK:TK2",
|
wpa_hexdump(MSG_DEBUG, "PTK:TK",
|
||||||
sta->ptk.u.tk2, 16);
|
sta->ptk.tk, sta->ptk.tk_len);
|
||||||
sta->ptk_set = 1;
|
sta->ptk_set = 1;
|
||||||
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
|
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
|
||||||
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
|
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 ieee802_1x_hdr *eapol;
|
||||||
const struct wpa_eapol_key *hdr;
|
const struct wpa_eapol_key *hdr;
|
||||||
const u8 *key_data, *kck;
|
const u8 *key_data, *kck;
|
||||||
|
size_t kck_len;
|
||||||
u16 key_info, key_data_len;
|
u16 key_info, key_data_len;
|
||||||
struct wpa_eapol_ie_parse ie;
|
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 = sta->ptk.kck;
|
||||||
|
kck_len = sta->ptk.kck_len;
|
||||||
if (sta->tptk_set) {
|
if (sta->tptk_set) {
|
||||||
add_note(wt, MSG_DEBUG,
|
add_note(wt, MSG_DEBUG,
|
||||||
"Use TPTK for validation EAPOL-Key MIC");
|
"Use TPTK for validation EAPOL-Key MIC");
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
|
kck_len = sta->tptk.kck_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
|
if (check_mic(kck, kck_len, sta->key_mgmt,
|
||||||
data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
|
||||||
return;
|
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,
|
const struct wpa_eapol_key *hdr,
|
||||||
size_t *len)
|
size_t *len)
|
||||||
{
|
{
|
||||||
|
if (kek_len != 16)
|
||||||
|
return NULL;
|
||||||
switch (ver) {
|
switch (ver) {
|
||||||
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
||||||
return decrypt_eapol_key_data_rc4(wt, kek, hdr, len);
|
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 ieee802_1x_hdr *eapol;
|
||||||
const struct wpa_eapol_key *hdr;
|
const struct wpa_eapol_key *hdr;
|
||||||
const u8 *key_data, *kck, *kek;
|
const u8 *key_data, *kck, *kek;
|
||||||
|
size_t kck_len, kek_len;
|
||||||
int recalc = 0;
|
int recalc = 0;
|
||||||
u16 key_info, ver;
|
u16 key_info, ver;
|
||||||
u8 *decrypted_buf = NULL;
|
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 = sta->ptk.kek;
|
||||||
|
kek_len = sta->ptk.kek_len;
|
||||||
kck = sta->ptk.kck;
|
kck = sta->ptk.kck;
|
||||||
|
kck_len = sta->ptk.kck_len;
|
||||||
if (sta->tptk_set) {
|
if (sta->tptk_set) {
|
||||||
add_note(wt, MSG_DEBUG,
|
add_note(wt, MSG_DEBUG,
|
||||||
"Use TPTK for validation EAPOL-Key MIC");
|
"Use TPTK for validation EAPOL-Key MIC");
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
|
kck_len = sta->tptk.kck_len;
|
||||||
kek = sta->tptk.kek;
|
kek = sta->tptk.kek;
|
||||||
|
kek_len = sta->tptk.kek_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
|
if (check_mic(kck, kck_len, sta->key_mgmt,
|
||||||
data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
|
||||||
return;
|
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);
|
decrypted_len = WPA_GET_BE16(hdr->key_data_length);
|
||||||
} else {
|
} else {
|
||||||
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||||
decrypted_buf = decrypt_eapol_key_data(wt, kek, ver, hdr,
|
decrypted_buf = decrypt_eapol_key_data(wt, kek, kek_len, ver,
|
||||||
&decrypted_len);
|
hdr, &decrypted_len);
|
||||||
if (decrypted_buf == NULL) {
|
if (decrypted_buf == NULL) {
|
||||||
add_note(wt, MSG_INFO,
|
add_note(wt, MSG_INFO,
|
||||||
"Failed to decrypt EAPOL-Key Key Data");
|
"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;
|
const struct wpa_eapol_key *hdr;
|
||||||
u16 key_info;
|
u16 key_info;
|
||||||
const u8 *kck;
|
const u8 *kck;
|
||||||
|
size_t kck_len;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
|
wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
|
||||||
MAC2STR(src), MAC2STR(dst));
|
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 = sta->ptk.kck;
|
||||||
|
kck_len = sta->ptk.kck_len;
|
||||||
if (sta->tptk_set) {
|
if (sta->tptk_set) {
|
||||||
add_note(wt, MSG_DEBUG,
|
add_note(wt, MSG_DEBUG,
|
||||||
"Use TPTK for validation EAPOL-Key MIC");
|
"Use TPTK for validation EAPOL-Key MIC");
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
|
kck_len = sta->tptk.kck_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
|
if (check_mic(kck, kck_len, sta->key_mgmt,
|
||||||
data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -752,7 +762,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->ptk_set &&
|
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,
|
key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
data, len) < 0) {
|
data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||||
decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, ver, hdr,
|
decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, sta->ptk.kek_len,
|
||||||
&decrypted_len);
|
ver, hdr, &decrypted_len);
|
||||||
if (decrypted == NULL) {
|
if (decrypted == NULL) {
|
||||||
add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
|
add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
|
||||||
return;
|
return;
|
||||||
|
@ -877,7 +887,7 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->ptk_set &&
|
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,
|
key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
data, len) < 0) {
|
data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Received Management frame processing
|
* Received Management frame processing
|
||||||
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2010-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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);
|
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) {
|
if (decrypted) {
|
||||||
os_memcpy(rsc, pn, 6);
|
os_memcpy(rsc, pn, 6);
|
||||||
frame = os_malloc(24 + *dlen);
|
frame = os_malloc(24 + *dlen);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wlantest - IEEE 802.11 protocol monitoring and testing tool
|
* wlantest - IEEE 802.11 protocol monitoring and testing tool
|
||||||
* Copyright (c) 2010-2013, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2010-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -210,10 +210,16 @@ static int add_ptk_file(struct wlantest *wt, const char *ptk_file)
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
break;
|
break;
|
||||||
if (ptk_len < 48) {
|
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;
|
p->ptk_len = 32 + ptk_len;
|
||||||
} else {
|
} 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;
|
p->ptk_len = ptk_len;
|
||||||
}
|
}
|
||||||
dl_list_add(&wt->ptk, &p->list);
|
dl_list_add(&wt->ptk, &p->list);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* wpa_supplicant - Internal driver interface wrappers
|
* wpa_supplicant - Internal driver interface wrappers
|
||||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -569,12 +569,14 @@ static inline int wpa_drv_driver_cmd(struct wpa_supplicant *wpa_s,
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
|
||||||
static inline void wpa_drv_set_rekey_info(struct wpa_supplicant *wpa_s,
|
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)
|
const u8 *replay_ctr)
|
||||||
{
|
{
|
||||||
if (!wpa_s->driver->set_rekey_info)
|
if (!wpa_s->driver->set_rekey_info)
|
||||||
return;
|
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,
|
static inline int wpa_drv_radio_disable(struct wpa_supplicant *wpa_s,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - Driver event processing
|
* WPA Supplicant - Driver event processing
|
||||||
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* 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_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,
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* WPA Supplicant - Glue code to setup EAPOL and RSN modules
|
* WPA Supplicant - Glue code to setup EAPOL and RSN modules
|
||||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -968,13 +968,14 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_NO_WPA
|
#ifndef CONFIG_NO_WPA
|
||||||
static void wpa_supplicant_set_rekey_offload(void *ctx, const u8 *kek,
|
static void wpa_supplicant_set_rekey_offload(void *ctx,
|
||||||
const u8 *kck,
|
const u8 *kek, size_t kek_len,
|
||||||
|
const u8 *kck, size_t kck_len,
|
||||||
const u8 *replay_ctr)
|
const u8 *replay_ctr)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
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 */
|
#endif /* CONFIG_NO_WPA */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue