Suite B: Select EAPOL-Key integrity and key-wrap algorithms based on AKM
This adds support for AKM 00-0F-AC:11 to specify the integrity and key-wrap algorithms for EAPOL-Key frames using the new design where descriptor version is set to 0 and algorithms are determined based on AKM. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
087a1f4efd
commit
929a2ea5df
6 changed files with 90 additions and 38 deletions
|
@ -33,7 +33,8 @@
|
||||||
|
|
||||||
static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
static int wpa_sm_step(struct wpa_state_machine *sm);
|
static int wpa_sm_step(struct wpa_state_machine *sm);
|
||||||
static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len);
|
static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
|
||||||
|
size_t data_len);
|
||||||
static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
|
static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
|
||||||
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
|
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_group *group);
|
struct wpa_group *group);
|
||||||
|
@ -884,6 +885,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
sm->pairwise == WPA_CIPHER_GCMP) {
|
sm->pairwise == WPA_CIPHER_GCMP) {
|
||||||
if (wpa_use_aes_cmac(sm) &&
|
if (wpa_use_aes_cmac(sm) &&
|
||||||
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) &&
|
||||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||||
wpa_auth_logger(wpa_auth, sm->addr,
|
wpa_auth_logger(wpa_auth, sm->addr,
|
||||||
LOGGER_WARNING,
|
LOGGER_WARNING,
|
||||||
|
@ -902,6 +904,13 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) &&
|
||||||
|
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
|
||||||
|
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
|
||||||
|
"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_info & WPA_KEY_INFO_REQUEST) {
|
if (key_info & WPA_KEY_INFO_REQUEST) {
|
||||||
|
@ -1123,7 +1132,8 @@ continue_processing:
|
||||||
|
|
||||||
sm->MICVerified = FALSE;
|
sm->MICVerified = FALSE;
|
||||||
if (sm->PTK_valid && !sm->update_snonce) {
|
if (sm->PTK_valid && !sm->update_snonce) {
|
||||||
if (wpa_verify_key_mic(&sm->PTK, data, data_len)) {
|
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data,
|
||||||
|
data_len)) {
|
||||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
|
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
|
||||||
"received EAPOL-Key with invalid MIC");
|
"received EAPOL-Key with invalid MIC");
|
||||||
return;
|
return;
|
||||||
|
@ -1295,7 +1305,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
|
|
||||||
if (force_version)
|
if (force_version)
|
||||||
version = force_version;
|
version = force_version;
|
||||||
else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
|
else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||||
|
wpa_key_mgmt_suite_b(sm->wpa_key_mgmt))
|
||||||
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
||||||
else if (wpa_use_aes_cmac(sm))
|
else if (wpa_use_aes_cmac(sm))
|
||||||
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
|
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
|
||||||
|
@ -1320,6 +1331,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
|
|
||||||
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||||
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) ||
|
||||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
|
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
|
||||||
pad_len = key_data_len % 8;
|
pad_len = key_data_len % 8;
|
||||||
if (pad_len)
|
if (pad_len)
|
||||||
|
@ -1389,6 +1401,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
buf, key_data_len);
|
buf, key_data_len);
|
||||||
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||||
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) ||
|
||||||
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, 16,
|
||||||
(key_data_len - 8) / 8, buf,
|
(key_data_len - 8) / 8, buf,
|
||||||
|
@ -1420,8 +1433,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, version, (u8 *) hdr, len,
|
wpa_eapol_key_mic(sm->PTK.kck, sm->wpa_key_mgmt, version,
|
||||||
key->key_mic);
|
(u8 *) hdr, len, key->key_mic);
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (!pairwise &&
|
if (!pairwise &&
|
||||||
wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
|
wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
|
||||||
|
@ -1473,7 +1486,8 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len)
|
static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
|
||||||
|
size_t data_len)
|
||||||
{
|
{
|
||||||
struct ieee802_1x_hdr *hdr;
|
struct ieee802_1x_hdr *hdr;
|
||||||
struct wpa_eapol_key *key;
|
struct wpa_eapol_key *key;
|
||||||
|
@ -1489,7 +1503,7 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len)
|
||||||
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, 16);
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, 16);
|
||||||
if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,
|
if (wpa_eapol_key_mic(PTK->kck, 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, 16) != 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -1795,10 +1809,13 @@ SM_STATE(WPA_PTK, PTKSTART)
|
||||||
pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
|
pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
|
||||||
RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
|
RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
|
||||||
if (sm->pmksa)
|
if (sm->pmksa) {
|
||||||
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
|
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
|
||||||
sm->pmksa->pmkid, PMKID_LEN);
|
sm->pmksa->pmkid, PMKID_LEN);
|
||||||
else {
|
} else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
|
||||||
|
/* No KCK available to derive PMKID */
|
||||||
|
pmkid = NULL;
|
||||||
|
} else {
|
||||||
/*
|
/*
|
||||||
* Calculate PMKID since no PMKSA cache entry was
|
* Calculate PMKID since no PMKSA cache entry was
|
||||||
* available with pre-calculated PMKID.
|
* available with pre-calculated PMKID.
|
||||||
|
@ -1856,7 +1873,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
||||||
|
|
||||||
wpa_derive_ptk(sm, pmk, &PTK);
|
wpa_derive_ptk(sm, pmk, &PTK);
|
||||||
|
|
||||||
if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key,
|
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK,
|
||||||
|
sm->last_rx_eapol_key,
|
||||||
sm->last_rx_eapol_key_len) == 0) {
|
sm->last_rx_eapol_key_len) == 0) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
|
* @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)
|
||||||
* @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
|
* @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
|
||||||
|
@ -37,10 +38,10 @@
|
||||||
* 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 ver, const u8 *buf, size_t len,
|
int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
||||||
u8 *mic)
|
size_t len, u8 *mic)
|
||||||
{
|
{
|
||||||
u8 hash[SHA1_MAC_LEN];
|
u8 hash[SHA256_MAC_LEN];
|
||||||
|
|
||||||
switch (ver) {
|
switch (ver) {
|
||||||
#ifndef CONFIG_FIPS
|
#ifndef CONFIG_FIPS
|
||||||
|
@ -56,11 +57,23 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
||||||
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
||||||
return omac1_aes_128(key, buf, len, mic);
|
return omac1_aes_128(key, buf, len, mic);
|
||||||
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
|
||||||
#ifdef CONFIG_HS20
|
|
||||||
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
|
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
|
||||||
/* FIX: This should be based on negotiated AKM */
|
switch (akmp) {
|
||||||
|
#ifdef CONFIG_HS20
|
||||||
|
case WPA_KEY_MGMT_OSEN:
|
||||||
return omac1_aes_128(key, buf, len, mic);
|
return omac1_aes_128(key, buf, len, mic);
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
|
#ifdef CONFIG_SUITEB
|
||||||
|
case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
|
||||||
|
if (hmac_sha256(key, 16, buf, len, hash))
|
||||||
|
return -1;
|
||||||
|
os_memcpy(mic, hash, MD5_MAC_LEN);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_SUITEB */
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,8 +327,8 @@ struct rsn_rdie {
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
|
||||||
int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
|
||||||
u8 *mic);
|
size_t len, u8 *mic);
|
||||||
void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
void 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,
|
||||||
|
|
|
@ -928,8 +928,8 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
os_memcpy(mic, key->key_mic, 16);
|
os_memcpy(mic, key->key_mic, 16);
|
||||||
if (peerkey->tstk_set) {
|
if (peerkey->tstk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, 16);
|
||||||
wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
|
wpa_eapol_key_mic(peerkey->tstk.kck, sm->key_mgmt, ver, buf,
|
||||||
key->key_mic);
|
len, key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, 16) != 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");
|
||||||
|
@ -944,7 +944,7 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
|
|
||||||
if (!ok && peerkey->stk_set) {
|
if (!ok && peerkey->stk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, 16);
|
||||||
wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
|
wpa_eapol_key_mic(peerkey->stk.kck, sm->key_mgmt, ver, buf, len,
|
||||||
key->key_mic);
|
key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
||||||
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
|
||||||
|
|
|
@ -56,10 +56,10 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key_mic &&
|
if (key_mic &&
|
||||||
wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) {
|
wpa_eapol_key_mic(kck, 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 "
|
"WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
|
||||||
"version %d MIC", ver);
|
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, 16);
|
||||||
|
@ -89,7 +89,8 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
|
||||||
int key_info, ver;
|
int key_info, ver;
|
||||||
u8 bssid[ETH_ALEN], *rbuf;
|
u8 bssid[ETH_ALEN], *rbuf;
|
||||||
|
|
||||||
if (sm->key_mgmt == WPA_KEY_MGMT_OSEN)
|
if (sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||||
|
wpa_key_mgmt_suite_b(sm->key_mgmt))
|
||||||
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
||||||
else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
|
else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
|
||||||
wpa_key_mgmt_sha256(sm->key_mgmt))
|
wpa_key_mgmt_sha256(sm->key_mgmt))
|
||||||
|
@ -1451,7 +1452,7 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
|
||||||
os_memcpy(mic, key->key_mic, 16);
|
os_memcpy(mic, key->key_mic, 16);
|
||||||
if (sm->tptk_set) {
|
if (sm->tptk_set) {
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, 16);
|
||||||
wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
|
wpa_eapol_key_mic(sm->tptk.kck, sm->key_mgmt, ver, buf, len,
|
||||||
key->key_mic);
|
key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
|
@ -1468,7 +1469,7 @@ 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, 16);
|
||||||
wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
|
wpa_eapol_key_mic(sm->ptk.kck, sm->key_mgmt, ver, buf, len,
|
||||||
key->key_mic);
|
key->key_mic);
|
||||||
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
|
@ -1522,7 +1523,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
|
||||||
os_memset(ek, 0, sizeof(ek));
|
os_memset(ek, 0, sizeof(ek));
|
||||||
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
|
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
|
||||||
sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
|
sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||||
|
wpa_key_mgmt_suite_b(sm->key_mgmt)) {
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
if (*key_data_len < 8 || *key_data_len % 8) {
|
if (*key_data_len < 8 || *key_data_len % 8) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||||
|
@ -1720,6 +1722,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
||||||
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
|
||||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
|
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
|
||||||
|
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
|
||||||
sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
|
sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
"WPA: Unsupported EAPOL-Key descriptor version %d",
|
"WPA: Unsupported EAPOL-Key descriptor version %d",
|
||||||
|
@ -1735,6 +1738,14 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wpa_key_mgmt_suite_b(sm->key_mgmt) &&
|
||||||
|
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
|
||||||
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
|
"RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)",
|
||||||
|
ver);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
|
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
|
||||||
/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
|
/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
|
||||||
|
@ -1748,7 +1759,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
|
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
|
||||||
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
||||||
sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
|
sm->key_mgmt != WPA_KEY_MGMT_OSEN &&
|
||||||
|
!wpa_key_mgmt_suite_b(sm->key_mgmt)) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
"WPA: AP did not use the "
|
"WPA: AP did not use the "
|
||||||
"negotiated AES-128-CMAC");
|
"negotiated AES-128-CMAC");
|
||||||
|
@ -1757,6 +1769,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
} else
|
} else
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
|
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
|
||||||
|
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
|
||||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
"WPA: CCMP is used, but EAPOL-Key "
|
"WPA: CCMP is used, but EAPOL-Key "
|
||||||
|
@ -1776,6 +1789,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||||
} else
|
} else
|
||||||
goto out;
|
goto out;
|
||||||
} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
|
} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
|
||||||
|
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
|
||||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||||
"WPA: GCMP is used, but EAPOL-Key "
|
"WPA: GCMP is used, but EAPOL-Key "
|
||||||
|
|
|
@ -31,7 +31,8 @@ static int is_zero(const u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
|
static int check_mic(const u8 *kck, int akmp, int ver, const u8 *data,
|
||||||
|
size_t len)
|
||||||
{
|
{
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -49,7 +50,7 @@ static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
|
||||||
os_memcpy(rx_mic, key->key_mic, 16);
|
os_memcpy(rx_mic, key->key_mic, 16);
|
||||||
os_memset(key->key_mic, 0, 16);
|
os_memset(key->key_mic, 0, 16);
|
||||||
|
|
||||||
if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
|
if (wpa_eapol_key_mic(kck, akmp, ver, buf, len, key->key_mic) == 0 &&
|
||||||
os_memcmp(rx_mic, key->key_mic, 16) == 0)
|
os_memcmp(rx_mic, key->key_mic, 16) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
bss->bssid, sta->addr, sta->anonce, sta->snonce,
|
bss->bssid, sta->addr, sta->anonce, sta->snonce,
|
||||||
(u8 *) &ptk, ptk_len,
|
(u8 *) &ptk, ptk_len,
|
||||||
wpa_key_mgmt_sha256(sta->key_mgmt));
|
wpa_key_mgmt_sha256(sta->key_mgmt));
|
||||||
if (check_mic(ptk.kck, ver, data, len) < 0)
|
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);
|
||||||
|
@ -168,7 +169,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, ver, data, len) < 0)
|
if (check_mic(ptk->ptk.kck, 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,
|
||||||
|
@ -241,7 +243,8 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
"Use TPTK for validation EAPOL-Key MIC");
|
"Use TPTK for validation EAPOL-Key MIC");
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
if (check_mic(kck, 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");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -532,7 +535,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
kek = sta->tptk.kek;
|
kek = sta->tptk.kek;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
if (check_mic(kck, 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");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -677,7 +681,8 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
"Use TPTK for validation EAPOL-Key MIC");
|
"Use TPTK for validation EAPOL-Key MIC");
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
if (check_mic(kck, 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");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -724,7 +729,8 @@ 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, key_info & WPA_KEY_INFO_TYPE_MASK,
|
check_mic(sta->ptk.kck, sta->key_mgmt,
|
||||||
|
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");
|
||||||
return;
|
return;
|
||||||
|
@ -848,7 +854,8 @@ 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, key_info & WPA_KEY_INFO_TYPE_MASK,
|
check_mic(sta->ptk.kck, sta->key_mgmt,
|
||||||
|
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");
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue