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:
Jouni Malinen 2015-01-25 16:49:18 +02:00
parent 287eb3f9d7
commit 98cd3d1c3b
21 changed files with 401 additions and 317 deletions

View file

@ -1,6 +1,6 @@
/*
* 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.
* See README for more details.
@ -248,11 +248,11 @@ static int wlantest_inject_prot(struct wlantest *wt, struct wlantest_bss *bss,
frame, len, hdrlen, qos, pn, 0,
&crypt_len);
else if (sta->pairwise_cipher == WPA_CIPHER_TKIP)
crypt = tkip_encrypt(incorrect_key ? dummy : sta->ptk.tk1,
crypt = tkip_encrypt(incorrect_key ? dummy : sta->ptk.tk,
frame, len, hdrlen, qos, pn, 0,
&crypt_len);
else
crypt = ccmp_encrypt(incorrect_key ? dummy : sta->ptk.tk1,
crypt = ccmp_encrypt(incorrect_key ? dummy : sta->ptk.tk,
frame, len, hdrlen, qos, pn, 0,
&crypt_len);

View file

@ -1,6 +1,6 @@
/*
* 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.
* See README for more details.
@ -107,21 +107,21 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher,
decrypted = NULL;
if ((pairwise_cipher == WPA_CIPHER_CCMP ||
pairwise_cipher == 0) && tk_len == 16) {
decrypted = ccmp_decrypt(ptk->ptk.tk1, hdr, data,
decrypted = ccmp_decrypt(ptk->ptk.tk, hdr, data,
data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 ||
pairwise_cipher == 0) && tk_len == 32) {
decrypted = ccmp_256_decrypt(ptk->ptk.tk1, hdr, data,
decrypted = ccmp_256_decrypt(ptk->ptk.tk, hdr, data,
data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_GCMP ||
pairwise_cipher == WPA_CIPHER_GCMP_256 ||
pairwise_cipher == 0) &&
(tk_len == 16 || tk_len == 32)) {
decrypted = gcmp_decrypt(ptk->ptk.tk1, tk_len, hdr,
decrypted = gcmp_decrypt(ptk->ptk.tk, tk_len, hdr,
data, data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_TKIP ||
pairwise_cipher == 0) && tk_len == 32) {
decrypted = tkip_decrypt(ptk->ptk.tk1, hdr, data,
decrypted = tkip_decrypt(ptk->ptk.tk, hdr, data,
data_len, decrypted_len);
}
if (decrypted) {
@ -411,19 +411,19 @@ skip_replay_det:
else
decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen);
} else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) {
decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen);
} else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) {
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
} else if (sta->ptk_set) {
if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256)
decrypted = ccmp_256_decrypt(sta->ptk.tk1, hdr, data,
decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, data,
len, &dlen);
else if (sta->pairwise_cipher == WPA_CIPHER_GCMP ||
sta->pairwise_cipher == WPA_CIPHER_GCMP_256)
decrypted = gcmp_decrypt(sta->ptk.tk1, sta->tk_len,
decrypted = gcmp_decrypt(sta->ptk.tk, sta->tk_len,
hdr, data, len, &dlen);
else
decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len,
decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len,
&dlen);
} else {
decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data,

View file

@ -1,6 +1,6 @@
/*
* 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.
* See README for more details.
@ -31,14 +31,15 @@ static int is_zero(const u8 *buf, size_t len)
}
static int check_mic(const u8 *kck, int akmp, int ver, const u8 *data,
size_t len)
static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
const u8 *data, size_t len)
{
u8 *buf;
int ret = -1;
struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key;
u8 rx_mic[16];
u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
size_t mic_len = 16;
buf = os_malloc(len);
if (buf == NULL)
@ -47,11 +48,12 @@ static int check_mic(const u8 *kck, int akmp, int ver, const u8 *data,
hdr = (struct ieee802_1x_hdr *) buf;
key = (struct wpa_eapol_key *) (hdr + 1);
os_memcpy(rx_mic, key->key_mic, 16);
os_memset(key->key_mic, 0, 16);
os_memcpy(rx_mic, key->key_mic, mic_len);
os_memset(key->key_mic, 0, mic_len);
if (wpa_eapol_key_mic(kck, akmp, ver, buf, len, key->key_mic) == 0 &&
os_memcmp(rx_mic, key->key_mic, 16) == 0)
if (wpa_eapol_key_mic(kck, kck_len, akmp, ver, buf, len,
key->key_mic) == 0 &&
os_memcmp(rx_mic, key->key_mic, mic_len) == 0)
ret = 0;
os_free(buf);
@ -97,16 +99,12 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
struct wlantest_pmk *pmk)
{
struct wpa_ptk ptk;
size_t ptk_len;
ptk_len = wpa_cipher_key_len(sta->pairwise_cipher) + 32;
wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
"Pairwise key expansion",
bss->bssid, sta->addr, sta->anonce, sta->snonce,
(u8 *) &ptk, ptk_len,
wpa_key_mgmt_sha256(sta->key_mgmt));
if (check_mic(ptk.kck, sta->key_mgmt, ver, data, len) < 0)
if (wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
"Pairwise key expansion",
bss->bssid, sta->addr, sta->anonce, sta->snonce,
&ptk, sta->key_mgmt, sta->pairwise_cipher) < 0 ||
check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0)
return -1;
sta->tk_len = wpa_cipher_key_len(sta->pairwise_cipher);
@ -120,22 +118,20 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
*/
add_note(wt, MSG_DEBUG, "Derived PTK during rekeying");
os_memcpy(&sta->tptk, &ptk, sizeof(ptk));
wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16);
wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16);
wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16);
if (ptk_len > 48)
wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2,
16);
wpa_hexdump(MSG_DEBUG, "TPTK:KCK",
sta->tptk.kck, sta->tptk.kck_len);
wpa_hexdump(MSG_DEBUG, "TPTK:KEK",
sta->tptk.kek, sta->tptk.kek_len);
wpa_hexdump(MSG_DEBUG, "TPTK:TK",
sta->tptk.tk, sta->tptk.tk_len);
sta->tptk_set = 1;
return 0;
}
add_note(wt, MSG_DEBUG, "Derived new PTK");
os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
if (ptk_len > 48)
wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16);
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, sta->ptk.kck_len);
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, sta->ptk.kek_len);
wpa_hexdump(MSG_DEBUG, "PTK:TK", sta->ptk.tk, sta->ptk.tk_len);
sta->ptk_set = 1;
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
@ -169,8 +165,8 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
wpa_debug_level = MSG_WARNING;
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
if (check_mic(ptk->ptk.kck, sta->key_mgmt, ver, data,
len) < 0)
if (check_mic(ptk->ptk.kck, ptk->ptk.kck_len,
sta->key_mgmt, ver, data, len) < 0)
continue;
wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
MACSTR " BSSID " MACSTR,
@ -179,12 +175,12 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
ptk->ptk_len = 32 +
wpa_cipher_key_len(sta->pairwise_cipher);
os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
if (ptk->ptk_len > 48)
wpa_hexdump(MSG_DEBUG, "PTK:TK2",
sta->ptk.u.tk2, 16);
wpa_hexdump(MSG_DEBUG, "PTK:KCK",
sta->ptk.kck, sta->ptk.kck_len);
wpa_hexdump(MSG_DEBUG, "PTK:KEK",
sta->ptk.kek, sta->ptk.kek_len);
wpa_hexdump(MSG_DEBUG, "PTK:TK",
sta->ptk.tk, sta->ptk.tk_len);
sta->ptk_set = 1;
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
@ -204,6 +200,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
const struct ieee802_1x_hdr *eapol;
const struct wpa_eapol_key *hdr;
const u8 *key_data, *kck;
size_t kck_len;
u16 key_info, key_data_len;
struct wpa_eapol_ie_parse ie;
@ -238,13 +235,15 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
}
kck = sta->ptk.kck;
kck_len = sta->ptk.kck_len;
if (sta->tptk_set) {
add_note(wt, MSG_DEBUG,
"Use TPTK for validation EAPOL-Key MIC");
kck = sta->tptk.kck;
kck_len = sta->tptk.kck_len;
}
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
data, len) < 0) {
if (check_mic(kck, kck_len, sta->key_mgmt,
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
return;
}
@ -371,10 +370,13 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
}
static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, u16 ver,
static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek,
size_t kek_len, u16 ver,
const struct wpa_eapol_key *hdr,
size_t *len)
{
if (kek_len != 16)
return NULL;
switch (ver) {
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
return decrypt_eapol_key_data_rc4(wt, kek, hdr, len);
@ -513,6 +515,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
const struct ieee802_1x_hdr *eapol;
const struct wpa_eapol_key *hdr;
const u8 *key_data, *kck, *kek;
size_t kck_len, kek_len;
int recalc = 0;
u16 key_info, ver;
u8 *decrypted_buf = NULL;
@ -551,15 +554,19 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
}
kek = sta->ptk.kek;
kek_len = sta->ptk.kek_len;
kck = sta->ptk.kck;
kck_len = sta->ptk.kck_len;
if (sta->tptk_set) {
add_note(wt, MSG_DEBUG,
"Use TPTK for validation EAPOL-Key MIC");
kck = sta->tptk.kck;
kck_len = sta->tptk.kck_len;
kek = sta->tptk.kek;
kek_len = sta->tptk.kek_len;
}
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
data, len) < 0) {
if (check_mic(kck, kck_len, sta->key_mgmt,
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
return;
}
@ -574,8 +581,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
decrypted_len = WPA_GET_BE16(hdr->key_data_length);
} else {
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
decrypted_buf = decrypt_eapol_key_data(wt, kek, ver, hdr,
&decrypted_len);
decrypted_buf = decrypt_eapol_key_data(wt, kek, kek_len, ver,
hdr, &decrypted_len);
if (decrypted_buf == NULL) {
add_note(wt, MSG_INFO,
"Failed to decrypt EAPOL-Key Key Data");
@ -674,6 +681,7 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
const struct wpa_eapol_key *hdr;
u16 key_info;
const u8 *kck;
size_t kck_len;
wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
MAC2STR(src), MAC2STR(dst));
@ -699,13 +707,15 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
}
kck = sta->ptk.kck;
kck_len = sta->ptk.kck_len;
if (sta->tptk_set) {
add_note(wt, MSG_DEBUG,
"Use TPTK for validation EAPOL-Key MIC");
kck = sta->tptk.kck;
kck_len = sta->tptk.kck_len;
}
if (check_mic(kck, sta->key_mgmt, key_info & WPA_KEY_INFO_TYPE_MASK,
data, len) < 0) {
if (check_mic(kck, kck_len, sta->key_mgmt,
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
return;
}
@ -752,7 +762,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
}
if (sta->ptk_set &&
check_mic(sta->ptk.kck, sta->key_mgmt,
check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
key_info & WPA_KEY_INFO_TYPE_MASK,
data, len) < 0) {
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
@ -766,8 +776,8 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
return;
}
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, ver, hdr,
&decrypted_len);
decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, sta->ptk.kek_len,
ver, hdr, &decrypted_len);
if (decrypted == NULL) {
add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
return;
@ -877,7 +887,7 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
}
if (sta->ptk_set &&
check_mic(sta->ptk.kck, sta->key_mgmt,
check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
key_info & WPA_KEY_INFO_TYPE_MASK,
data, len) < 0) {
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");

View file

@ -1,6 +1,6 @@
/*
* 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.
* See README for more details.
@ -983,7 +983,7 @@ static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
}
decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data + 24, len - 24, dlen);
decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data + 24, len - 24, dlen);
if (decrypted) {
os_memcpy(rsc, pn, 6);
frame = os_malloc(24 + *dlen);

View file

@ -1,6 +1,6 @@
/*
* 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.
* See README for more details.
@ -210,10 +210,16 @@ static int add_ptk_file(struct wlantest *wt, const char *ptk_file)
if (p == NULL)
break;
if (ptk_len < 48) {
os_memcpy(p->ptk.tk1, ptk, ptk_len);
os_memcpy(p->ptk.tk, ptk, ptk_len);
p->ptk.tk_len = ptk_len;
p->ptk_len = 32 + ptk_len;
} else {
os_memcpy(&p->ptk, ptk, ptk_len);
os_memcpy(p->ptk.kck, ptk, 16);
p->ptk.kck_len = 16;
os_memcpy(p->ptk.kek, ptk + 16, 16);
p->ptk.kek_len = 16;
os_memcpy(p->ptk.tk, ptk + 32, ptk_len - 32);
p->ptk.tk_len = ptk_len - 32;
p->ptk_len = ptk_len;
}
dl_list_add(&wt->ptk, &p->list);