Add Suite B 192-bit AKM

WPA-EAP-SUITE-B-192 can now be used to select 192-bit level Suite B into
use as the key management method.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2015-01-25 23:32:01 +02:00
parent 97ae35a848
commit 5e3b5197cc
26 changed files with 397 additions and 106 deletions

View file

@ -215,6 +215,11 @@ NEED_SHA256=y
NEED_AES_OMAC1=y NEED_AES_OMAC1=y
endif endif
ifdef CONFIG_SUITEB192
L_CFLAGS += -DCONFIG_SUITEB192
NEED_SHA384=y
endif
ifdef CONFIG_IEEE80211W ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y NEED_SHA256=y

View file

@ -204,6 +204,11 @@ NEED_SHA256=y
NEED_AES_OMAC1=y NEED_AES_OMAC1=y
endif endif
ifdef CONFIG_SUITEB192
CFLAGS += -DCONFIG_SUITEB192
NEED_SHA384=y
endif
ifdef CONFIG_IEEE80211W ifdef CONFIG_IEEE80211W
CFLAGS += -DCONFIG_IEEE80211W CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y NEED_SHA256=y

View file

@ -1,6 +1,6 @@
/* /*
* hostapd / Configuration file parser * hostapd / Configuration file parser
* 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.
@ -680,8 +680,14 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
else if (os_strcmp(start, "FT-SAE") == 0) else if (os_strcmp(start, "FT-SAE") == 0)
val |= WPA_KEY_MGMT_FT_SAE; val |= WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#ifdef CONFIG_SUITEB
else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif /* CONFIG_SUITEB192 */
else { else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start); line, start);

View file

@ -1,6 +1,6 @@
/* /*
* hostapd / UNIX domain socket -based control interface * hostapd / UNIX domain socket -based control interface
* 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.
@ -1171,6 +1171,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
return pos - buf; return pos - buf;
pos += ret; pos += ret;
} }
if (hapd->conf->wpa_key_mgmt &
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
ret = os_snprintf(pos, end - pos,
"WPA-EAP-SUITE-B-192 ");
if (os_snprintf_error(end - pos, ret))
return pos - buf;
pos += ret;
}
ret = os_snprintf(pos, end - pos, "\n"); ret = os_snprintf(pos, end - pos, "\n");
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))

View file

@ -1,6 +1,6 @@
/* /*
* hostapd - PMKSA cache for IEEE 802.11i RSN * hostapd - PMKSA cache for IEEE 802.11i RSN
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2008, 2012-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.
@ -269,7 +269,9 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
return NULL; return NULL;
os_memcpy(entry->pmk, pmk, pmk_len); os_memcpy(entry->pmk, pmk, pmk_len);
entry->pmk_len = pmk_len; entry->pmk_len = pmk_len;
if (wpa_key_mgmt_suite_b(akmp)) if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
else else
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,

View file

@ -849,34 +849,45 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
{ {
struct ieee802_1x_hdr *hdr; struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key; struct wpa_eapol_key *key;
struct wpa_eapol_key_192 *key192;
u16 key_info, key_data_length; u16 key_info, key_data_length;
enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST,
SMK_M1, SMK_M3, SMK_ERROR } msg; SMK_M1, SMK_M3, SMK_ERROR } msg;
char *msgtxt; char *msgtxt;
struct wpa_eapol_ie_parse kde; struct wpa_eapol_ie_parse kde;
int ft; int ft;
const u8 *eapol_key_ie; const u8 *eapol_key_ie, *key_data;
size_t eapol_key_ie_len; size_t eapol_key_ie_len, keyhdrlen, mic_len;
if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
return; return;
if (data_len < sizeof(*hdr) + sizeof(*key)) mic_len = wpa_mic_len(sm->wpa_key_mgmt);
keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
if (data_len < sizeof(*hdr) + keyhdrlen)
return; return;
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);
key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
key_info = WPA_GET_BE16(key->key_info); key_info = WPA_GET_BE16(key->key_info);
if (mic_len == 24) {
key_data = (const u8 *) (key192 + 1);
key_data_length = WPA_GET_BE16(key192->key_data_length);
} else {
key_data = (const u8 *) (key + 1);
key_data_length = WPA_GET_BE16(key->key_data_length); key_data_length = WPA_GET_BE16(key->key_data_length);
}
wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
" key_info=0x%x type=%u key_data_length=%u", " key_info=0x%x type=%u key_data_length=%u",
MAC2STR(sm->addr), key_info, key->type, key_data_length); MAC2STR(sm->addr), key_info, key->type, key_data_length);
if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
"key_data overflow (%d > %lu)", "key_data overflow (%d > %lu)",
key_data_length, key_data_length,
(unsigned long) (data_len - sizeof(*hdr) - (unsigned long) (data_len - sizeof(*hdr) -
sizeof(*key))); keyhdrlen));
return; return;
} }
@ -1083,8 +1094,7 @@ continue_processing:
wpa_sta_disconnect(wpa_auth, sm->addr); wpa_sta_disconnect(wpa_auth, sm->addr);
return; return;
} }
if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length, if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
&kde) < 0) {
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key msg 2/4 with " "received EAPOL-Key msg 2/4 with "
"invalid Key Data contents"); "invalid Key Data contents");
@ -1241,8 +1251,7 @@ continue_processing:
*/ */
if (msg == SMK_ERROR) { if (msg == SMK_ERROR) {
#ifdef CONFIG_PEERKEY #ifdef CONFIG_PEERKEY
wpa_smk_error(wpa_auth, sm, (const u8 *) (key + 1), wpa_smk_error(wpa_auth, sm, key_data, key_data_length);
key_data_length);
#endif /* CONFIG_PEERKEY */ #endif /* CONFIG_PEERKEY */
return; return;
} else if (key_info & WPA_KEY_INFO_ERROR) { } else if (key_info & WPA_KEY_INFO_ERROR) {
@ -1257,12 +1266,12 @@ continue_processing:
wpa_request_new_ptk(sm); wpa_request_new_ptk(sm);
#ifdef CONFIG_PEERKEY #ifdef CONFIG_PEERKEY
} else if (msg == SMK_M1) { } else if (msg == SMK_M1) {
wpa_smk_m1(wpa_auth, sm, key, (const u8 *) (key + 1), wpa_smk_m1(wpa_auth, sm, key, key_data,
key_data_length); key_data_length);
#endif /* CONFIG_PEERKEY */ #endif /* CONFIG_PEERKEY */
} else if (key_data_length > 0 && } else if (key_data_length > 0 &&
wpa_parse_kde_ies((const u8 *) (key + 1), wpa_parse_kde_ies(key_data, key_data_length,
key_data_length, &kde) == 0 && &kde) == 0 &&
kde.mac_addr) { kde.mac_addr) {
} else { } else {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
@ -1300,8 +1309,7 @@ continue_processing:
#ifdef CONFIG_PEERKEY #ifdef CONFIG_PEERKEY
if (msg == SMK_M3) { if (msg == SMK_M3) {
wpa_smk_m3(wpa_auth, sm, key, (const u8 *) (key + 1), wpa_smk_m3(wpa_auth, sm, key, key_data, key_data_length);
key_data_length);
return; return;
} }
#endif /* CONFIG_PEERKEY */ #endif /* CONFIG_PEERKEY */
@ -1376,14 +1384,19 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
{ {
struct ieee802_1x_hdr *hdr; struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key; struct wpa_eapol_key *key;
size_t len; struct wpa_eapol_key_192 *key192;
size_t len, mic_len, keyhdrlen;
int alg; int alg;
int key_data_len, pad_len = 0; int key_data_len, pad_len = 0;
u8 *buf, *pos; u8 *buf, *pos;
int version, pairwise; int version, pairwise;
int i; int i;
u8 *key_data;
len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); mic_len = wpa_mic_len(sm->wpa_key_mgmt);
keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
if (force_version) if (force_version)
version = force_version; version = force_version;
@ -1430,6 +1443,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
hdr->length = host_to_be16(len - sizeof(*hdr)); hdr->length = host_to_be16(len - sizeof(*hdr));
key = (struct wpa_eapol_key *) (hdr + 1); key = (struct wpa_eapol_key *) (hdr + 1);
key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
key->type = sm->wpa == WPA_VERSION_WPA2 ? key->type = sm->wpa == WPA_VERSION_WPA2 ?
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
@ -1466,7 +1481,10 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
if (kde && !encr) { if (kde && !encr) {
os_memcpy(key + 1, kde, kde_len); os_memcpy(key_data, kde, kde_len);
if (mic_len == 24)
WPA_PUT_BE16(key192->key_data_length, kde_len);
else
WPA_PUT_BE16(key->key_data_length, kde_len); WPA_PUT_BE16(key->key_data_length, kde_len);
} else if (encr && kde) { } else if (encr && kde) {
buf = os_zalloc(key_data_len); buf = os_zalloc(key_data_len);
@ -1488,13 +1506,17 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
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, sm->PTK.kek_len, if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
(key_data_len - 8) / 8, buf, (key_data_len - 8) / 8, buf, key_data)) {
(u8 *) (key + 1))) {
os_free(hdr); os_free(hdr);
os_free(buf); os_free(buf);
return; return;
} }
WPA_PUT_BE16(key->key_data_length, key_data_len); if (mic_len == 24)
WPA_PUT_BE16(key192->key_data_length,
key_data_len);
else
WPA_PUT_BE16(key->key_data_length,
key_data_len);
} else if (sm->PTK.kek_len == 16) { } else if (sm->PTK.kek_len == 16) {
u8 ek[32]; u8 ek[32];
os_memcpy(key->key_iv, os_memcpy(key->key_iv,
@ -1502,9 +1524,14 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
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, sm->PTK.kek_len); os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
os_memcpy(key + 1, buf, key_data_len); os_memcpy(key_data, buf, key_data_len);
rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); rc4_skip(ek, 32, 256, key_data, key_data_len);
WPA_PUT_BE16(key->key_data_length, key_data_len); if (mic_len == 24)
WPA_PUT_BE16(key192->key_data_length,
key_data_len);
else
WPA_PUT_BE16(key->key_data_length,
key_data_len);
} else { } else {
os_free(hdr); os_free(hdr);
os_free(buf); os_free(buf);
@ -1514,6 +1541,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
} }
if (key_info & WPA_KEY_INFO_MIC) { if (key_info & WPA_KEY_INFO_MIC) {
u8 *key_mic;
if (!sm->PTK_valid) { if (!sm->PTK_valid) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
"PTK not valid when sending EAPOL-Key " "PTK not valid when sending EAPOL-Key "
@ -1521,9 +1550,11 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
os_free(hdr); os_free(hdr);
return; return;
} }
key_mic = key192->key_mic; /* same offset for key and key192 */
wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
sm->wpa_key_mgmt, version, sm->wpa_key_mgmt, version,
(u8 *) hdr, len, key->key_mic); (u8 *) hdr, len, 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 &&
@ -1531,7 +1562,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"Corrupting group EAPOL-Key Key MIC"); "Corrupting group EAPOL-Key Key MIC");
key->key_mic[0]++; key_mic[0]++;
} }
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
} }
@ -1580,25 +1611,27 @@ static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
{ {
struct ieee802_1x_hdr *hdr; struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key; struct wpa_eapol_key *key;
struct wpa_eapol_key_192 *key192;
u16 key_info; u16 key_info;
int ret = 0; int ret = 0;
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
size_t mic_len = 16; size_t mic_len = wpa_mic_len(akmp);
if (data_len < sizeof(*hdr) + sizeof(*key)) if (data_len < sizeof(*hdr) + sizeof(*key))
return -1; return -1;
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);
key192 = (struct wpa_eapol_key_192 *) (hdr + 1);
key_info = WPA_GET_BE16(key->key_info); key_info = WPA_GET_BE16(key->key_info);
os_memcpy(mic, key->key_mic, mic_len); os_memcpy(mic, key192->key_mic, mic_len);
os_memset(key->key_mic, 0, mic_len); os_memset(key192->key_mic, 0, mic_len);
if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
key_info & WPA_KEY_INFO_TYPE_MASK, key_info & WPA_KEY_INFO_TYPE_MASK,
data, data_len, key->key_mic) || data, data_len, key192->key_mic) ||
os_memcmp_const(mic, key->key_mic, mic_len) != 0) os_memcmp_const(mic, key192->key_mic, mic_len) != 0)
ret = -1; ret = -1;
os_memcpy(key->key_mic, mic, mic_len); os_memcpy(key192->key_mic, mic, mic_len);
return ret; return ret;
} }

View file

@ -1,6 +1,6 @@
/* /*
* hostapd - WPA/RSN IE and KDE definitions * hostapd - WPA/RSN IE and KDE definitions
* Copyright (c) 2004-2008, 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.
@ -205,6 +205,11 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += RSN_SELECTOR_LEN; pos += RSN_SELECTOR_LEN;
num_suites++; num_suites++;
} }
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_RSN_TESTING #ifdef CONFIG_RSN_TESTING
if (rsn_testing) { if (rsn_testing) {
@ -482,6 +487,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
if (0) { if (0) {
} }
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
@ -562,6 +569,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
} }
if (0) { if (0) {
} }
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant - Common definitions * WPA Supplicant - Common definitions
* Copyright (c) 2004-2008, 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.
@ -50,6 +50,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_KEY_MGMT_CCKM BIT(14) #define WPA_KEY_MGMT_CCKM BIT(14)
#define WPA_KEY_MGMT_OSEN BIT(15) #define WPA_KEY_MGMT_OSEN BIT(15)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) #define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{ {
@ -58,7 +59,8 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
WPA_KEY_MGMT_CCKM | WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN | WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SUITE_B)); WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
} }
static inline int wpa_key_mgmt_wpa_psk(int akm) static inline int wpa_key_mgmt_wpa_psk(int akm)
@ -91,9 +93,15 @@ static inline int wpa_key_mgmt_sha256(int akm)
WPA_KEY_MGMT_IEEE8021X_SUITE_B)); WPA_KEY_MGMT_IEEE8021X_SUITE_B));
} }
static inline int wpa_key_mgmt_sha384(int akm)
{
return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192);
}
static inline int wpa_key_mgmt_suite_b(int akm) static inline int wpa_key_mgmt_suite_b(int akm)
{ {
return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B); return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
} }
static inline int wpa_key_mgmt_wpa(int akm) static inline int wpa_key_mgmt_wpa(int akm)

View file

@ -1,6 +1,6 @@
/* /*
* IEEE 802.11 Frame type definitions * IEEE 802.11 Frame type definitions
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2008 Intel Corporation * Copyright (c) 2007-2008 Intel Corporation
* *
* This software may be distributed under the terms of the BSD license. * This software may be distributed under the terms of the BSD license.
@ -1192,6 +1192,7 @@ enum plink_action_field {
#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 #define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 #define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11 #define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11
#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC12
#define WLAN_AKM_SUITE_CCKM 0x00409600 #define WLAN_AKM_SUITE_CCKM 0x00409600
#define WLAN_AKM_SUITE_OSEN 0x506f9a01 #define WLAN_AKM_SUITE_OSEN 0x506f9a01

View file

@ -12,6 +12,7 @@
#include "crypto/md5.h" #include "crypto/md5.h"
#include "crypto/sha1.h" #include "crypto/sha1.h"
#include "crypto/sha256.h" #include "crypto/sha256.h"
#include "crypto/sha384.h"
#include "crypto/aes_wrap.h" #include "crypto/aes_wrap.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "ieee802_11_defs.h" #include "ieee802_11_defs.h"
@ -21,12 +22,24 @@
static unsigned int wpa_kck_len(int akmp) static unsigned int wpa_kck_len(int akmp)
{ {
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
return 24;
return 16; return 16;
} }
static unsigned int wpa_kek_len(int akmp) static unsigned int wpa_kek_len(int akmp)
{ {
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
return 32;
return 16;
}
unsigned int wpa_mic_len(int akmp)
{
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
return 24;
return 16; return 16;
} }
@ -54,7 +67,7 @@ static unsigned int wpa_kek_len(int akmp)
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
const u8 *buf, size_t len, u8 *mic) const u8 *buf, size_t len, u8 *mic)
{ {
u8 hash[SHA256_MAC_LEN]; u8 hash[SHA384_MAC_LEN];
switch (ver) { switch (ver) {
#ifndef CONFIG_FIPS #ifndef CONFIG_FIPS
@ -83,6 +96,13 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
os_memcpy(mic, hash, MD5_MAC_LEN); os_memcpy(mic, hash, MD5_MAC_LEN);
break; break;
#endif /* CONFIG_SUITEB */ #endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
if (hmac_sha384(key, key_len, buf, len, hash))
return -1;
os_memcpy(mic, hash, 24);
break;
#endif /* CONFIG_SUITEB192 */
default: default:
return -1; return -1;
} }
@ -452,6 +472,8 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B; return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
return 0; return 0;
} }
@ -1034,6 +1056,39 @@ int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
#endif /* CONFIG_SUITEB */ #endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
/**
* rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
* @kck: Key confirmation key
* @kck_len: Length of kck in bytes
* @aa: Authenticator address
* @spa: Supplicant address
* @pmkid: Buffer for PMKID
* Returns: 0 on success, -1 on failure
*
* IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
* PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
*/
int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
const u8 *spa, u8 *pmkid)
{
char *title = "PMK Name";
const u8 *addr[3];
const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
unsigned char hash[SHA384_MAC_LEN];
addr[0] = (u8 *) title;
addr[1] = aa;
addr[2] = spa;
if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
return -1;
os_memcpy(pmkid, hash, PMKID_LEN);
return 0;
}
#endif /* CONFIG_SUITEB192 */
/** /**
* wpa_cipher_txt - Convert cipher suite to a text string * wpa_cipher_txt - Convert cipher suite to a text string
* @cipher: Cipher suite (WPA_CIPHER_* enum) * @cipher: Cipher suite (WPA_CIPHER_* enum)
@ -1113,6 +1168,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
return "OSEN"; return "OSEN";
case WPA_KEY_MGMT_IEEE8021X_SUITE_B: case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
return "WPA2-EAP-SUITE-B"; return "WPA2-EAP-SUITE-B";
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
return "WPA2-EAP-SUITE-B-192";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }
@ -1141,6 +1198,8 @@ u32 wpa_akm_to_suite(int akm)
return WLAN_AKM_SUITE_OSEN; return WLAN_AKM_SUITE_OSEN;
if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B) if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
return WLAN_AKM_SUITE_8021X_SUITE_B; return WLAN_AKM_SUITE_8021X_SUITE_B;
if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
return WLAN_AKM_SUITE_8021X_SUITE_B_192;
return 0; return 0;
} }

View file

@ -63,8 +63,8 @@ WPA_CIPHER_GTK_NOT_USED)
#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8) #define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_384 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384 \ #define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \
RSN_SELECTOR(0x00, 0x0f, 0xac, 13) RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00) #define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00)
#define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01) #define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01)
@ -191,9 +191,24 @@ 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 struct wpa_eapol_key_192 {
#define WPA_KCK_MAX_LEN 16 u8 type;
#define WPA_KEK_MAX_LEN 16 /* Note: key_info, key_length, and key_data_length are unaligned */
u8 key_info[2]; /* big endian */
u8 key_length[2]; /* big endian */
u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
u8 key_nonce[WPA_NONCE_LEN];
u8 key_iv[16];
u8 key_rsc[WPA_KEY_RSC_LEN];
u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
u8 key_mic[24];
u8 key_data_length[2]; /* big endian */
/* followed by key_data_length bytes of key_data */
} STRUCT_PACKED;
#define WPA_EAPOL_KEY_MIC_MAX_LEN 24
#define WPA_KCK_MAX_LEN 24
#define WPA_KEK_MAX_LEN 32
#define WPA_TK_MAX_LEN 32 #define WPA_TK_MAX_LEN 32
/** /**
@ -386,6 +401,16 @@ static inline int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
return -1; return -1;
} }
#endif /* CONFIG_SUITEB */ #endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
const u8 *spa, u8 *pmkid);
#else /* CONFIG_SUITEB192 */
static inline int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len,
const u8 *aa, const u8 *spa, u8 *pmkid)
{
return -1;
}
#endif /* CONFIG_SUITEB192 */
const char * wpa_cipher_txt(int cipher); const char * wpa_cipher_txt(int cipher);
const char * wpa_key_mgmt_txt(int key_mgmt, int proto); const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
@ -431,5 +456,6 @@ int wpa_pick_group_cipher(int ciphers);
int wpa_parse_cipher(const char *value); int wpa_parse_cipher(const char *value);
int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim); int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim);
int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise); int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise);
unsigned int wpa_mic_len(int akmp);
#endif /* WPA_COMMON_H */ #endif /* WPA_COMMON_H */

View file

@ -4463,7 +4463,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
params->key_mgmt_suite == WPA_KEY_MGMT_OSEN || params->key_mgmt_suite == WPA_KEY_MGMT_OSEN ||
params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
int mgmt = WLAN_AKM_SUITE_PSK; int mgmt = WLAN_AKM_SUITE_PSK;
switch (params->key_mgmt_suite) { switch (params->key_mgmt_suite) {
@ -4491,6 +4492,9 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
case WPA_KEY_MGMT_IEEE8021X_SUITE_B: case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
mgmt = WLAN_AKM_SUITE_8021X_SUITE_B; mgmt = WLAN_AKM_SUITE_8021X_SUITE_B;
break; break;
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
mgmt = WLAN_AKM_SUITE_8021X_SUITE_B_192;
break;
case WPA_KEY_MGMT_PSK: case WPA_KEY_MGMT_PSK:
default: default:
mgmt = WLAN_AKM_SUITE_PSK; mgmt = WLAN_AKM_SUITE_PSK;

View file

@ -65,6 +65,7 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
{ {
size_t rlen; size_t rlen;
struct wpa_eapol_key *err; struct wpa_eapol_key *err;
struct wpa_eapol_key_192 *err192;
struct rsn_error_kde error; struct rsn_error_kde error;
u8 *rbuf, *pos; u8 *rbuf, *pos;
size_t kde_len; size_t kde_len;
@ -79,6 +80,7 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
(void *) &err); (void *) &err);
if (rbuf == NULL) if (rbuf == NULL)
return -1; return -1;
err192 = (struct wpa_eapol_key_192 *) err;
err->type = EAPOL_KEY_TYPE_RSN; err->type = EAPOL_KEY_TYPE_RSN;
key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
@ -113,7 +115,7 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
} }
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst, wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst,
ETH_P_EAPOL, rbuf, rlen, err->key_mic); ETH_P_EAPOL, rbuf, rlen, err192->key_mic);
return 0; return 0;
} }
@ -126,6 +128,7 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
{ {
size_t rlen; size_t rlen;
struct wpa_eapol_key *reply; struct wpa_eapol_key *reply;
struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *pos; u8 *rbuf, *pos;
size_t kde_len; size_t kde_len;
u16 key_info; u16 key_info;
@ -140,6 +143,7 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
(void *) &reply); (void *) &reply);
if (rbuf == NULL) if (rbuf == NULL)
return -1; return -1;
reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = EAPOL_KEY_TYPE_RSN; reply->type = EAPOL_KEY_TYPE_RSN;
key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
@ -165,7 +169,7 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
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, sm->ptk.kck_len, ver, src_addr, wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr,
ETH_P_EAPOL, rbuf, rlen, reply->key_mic); ETH_P_EAPOL, rbuf, rlen, reply192->key_mic);
return 0; return 0;
} }
@ -907,7 +911,7 @@ static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
*/ */
int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
struct wpa_peerkey *peerkey, struct wpa_peerkey *peerkey,
struct wpa_eapol_key *key, u16 ver, struct wpa_eapol_key_192 *key, u16 ver,
const u8 *buf, size_t len) const u8 *buf, size_t len)
{ {
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];

View file

@ -38,7 +38,7 @@ struct wpa_peerkey {
int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
struct wpa_peerkey *peerkey, struct wpa_peerkey *peerkey,
struct wpa_eapol_key *key, u16 ver, struct wpa_eapol_key_192 *key, u16 ver,
const u8 *buf, size_t len); const u8 *buf, size_t len);
void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
struct wpa_eapol_key *key, u16 key_info, u16 ver, struct wpa_eapol_key *key, u16 key_info, u16 ver,

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant - RSN PMKSA cache * WPA Supplicant - RSN PMKSA cache
* Copyright (c) 2004-2009, 2011-2012, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2009, 2011-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.
@ -141,7 +141,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
return NULL; return NULL;
os_memcpy(entry->pmk, pmk, pmk_len); os_memcpy(entry->pmk, pmk, pmk_len);
entry->pmk_len = pmk_len; entry->pmk_len = pmk_len;
if (wpa_key_mgmt_suite_b(akmp)) if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
else if (wpa_key_mgmt_suite_b(akmp))
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
else else
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,

View file

@ -1,6 +1,6 @@
/* /*
* RSN pre-authentication (supplicant) * RSN pre-authentication (supplicant)
* 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.
@ -300,7 +300,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
wpa_sm_get_state(sm) != WPA_COMPLETED || wpa_sm_get_state(sm) != WPA_COMPLETED ||
(sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 && sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 &&
sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B)) { sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B &&
sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) {
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
"state for new pre-authentication"); "state for new pre-authentication");
return; /* invalid state for new pre-auth */ return; /* invalid state for new pre-auth */

View file

@ -39,7 +39,7 @@ 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; size_t mic_len = wpa_mic_len(sm->key_mgmt);
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
/* /*
@ -88,10 +88,11 @@ out:
*/ */
void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
{ {
size_t rlen; size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply; struct wpa_eapol_key *reply;
struct wpa_eapol_key_192 *reply192;
int key_info, ver; int key_info, ver;
u8 bssid[ETH_ALEN], *rbuf; u8 bssid[ETH_ALEN], *rbuf, *key_mic;
if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || if (sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
wpa_key_mgmt_suite_b(sm->key_mgmt)) wpa_key_mgmt_suite_b(sm->key_mgmt))
@ -110,10 +111,13 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
return; return;
} }
mic_len = wpa_mic_len(sm->key_mgmt);
hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
sizeof(*reply), &rlen, (void *) &reply); hdrlen, &rlen, (void *) &reply);
if (rbuf == NULL) if (rbuf == NULL)
return; return;
reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN || reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ? sm->proto == WPA_PROTO_OSEN) ?
@ -131,15 +135,21 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
WPA_REPLAY_COUNTER_LEN); WPA_REPLAY_COUNTER_LEN);
inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
if (mic_len == 24)
WPA_PUT_BE16(reply192->key_data_length, 0);
else
WPA_PUT_BE16(reply->key_data_length, 0); WPA_PUT_BE16(reply->key_data_length, 0);
if (!(key_info & WPA_KEY_INFO_MIC))
key_mic = NULL;
else
key_mic = reply192->key_mic; /* same offset in reply */
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"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, sm->ptk.kck_len, ver, bssid, wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
ETH_P_EAPOL, rbuf, rlen, ETH_P_EAPOL, rbuf, rlen, key_mic);
key_info & WPA_KEY_INFO_MIC ? reply->key_mic : NULL);
} }
@ -305,9 +315,10 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
const u8 *wpa_ie, size_t wpa_ie_len, const u8 *wpa_ie, size_t wpa_ie_len,
struct wpa_ptk *ptk) struct wpa_ptk *ptk)
{ {
size_t rlen; size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply; struct wpa_eapol_key *reply;
u8 *rbuf; struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
u8 *rsn_ie_buf = NULL; u8 *rsn_ie_buf = NULL;
if (wpa_ie == NULL) { if (wpa_ie == NULL) {
@ -349,13 +360,16 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
mic_len = wpa_mic_len(sm->key_mgmt);
hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
NULL, sizeof(*reply) + wpa_ie_len, NULL, hdrlen + wpa_ie_len,
&rlen, (void *) &reply); &rlen, (void *) &reply);
if (rbuf == NULL) { if (rbuf == NULL) {
os_free(rsn_ie_buf); os_free(rsn_ie_buf);
return -1; return -1;
} }
reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN || reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ? sm->proto == WPA_PROTO_OSEN) ?
@ -371,15 +385,21 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
WPA_REPLAY_COUNTER_LEN); WPA_REPLAY_COUNTER_LEN);
key_mic = reply192->key_mic; /* same offset for reply and reply192 */
if (mic_len == 24) {
WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len);
os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len);
} else {
WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
os_memcpy(reply + 1, wpa_ie, wpa_ie_len); os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
}
os_free(rsn_ie_buf); os_free(rsn_ie_buf);
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, ptk->kck_len, 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, key_mic);
return 0; return 0;
} }
@ -1062,14 +1082,18 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
u16 ver, u16 key_info, u16 ver, u16 key_info,
struct wpa_ptk *ptk) struct wpa_ptk *ptk)
{ {
size_t rlen; size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply; struct wpa_eapol_key *reply;
u8 *rbuf; struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
mic_len = wpa_mic_len(sm->key_mgmt);
hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
sizeof(*reply), &rlen, (void *) &reply); hdrlen, &rlen, (void *) &reply);
if (rbuf == NULL) if (rbuf == NULL)
return -1; return -1;
reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN || reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ? sm->proto == WPA_PROTO_OSEN) ?
@ -1084,11 +1108,15 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
os_memcpy(reply->replay_counter, key->replay_counter, os_memcpy(reply->replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN); WPA_REPLAY_COUNTER_LEN);
key_mic = reply192->key_mic; /* same offset for reply and reply192 */
if (mic_len == 24)
WPA_PUT_BE16(reply192->key_data_length, 0);
else
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, ptk->kck_len, 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, key_mic);
return 0; return 0;
} }
@ -1358,14 +1386,18 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
const struct wpa_eapol_key *key, const struct wpa_eapol_key *key,
int ver, u16 key_info) int ver, u16 key_info)
{ {
size_t rlen; size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply; struct wpa_eapol_key *reply;
u8 *rbuf; struct wpa_eapol_key_192 *reply192;
u8 *rbuf, *key_mic;
mic_len = wpa_mic_len(sm->key_mgmt);
hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
sizeof(*reply), &rlen, (void *) &reply); hdrlen, &rlen, (void *) &reply);
if (rbuf == NULL) if (rbuf == NULL)
return -1; return -1;
reply192 = (struct wpa_eapol_key_192 *) reply;
reply->type = (sm->proto == WPA_PROTO_RSN || reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ? sm->proto == WPA_PROTO_OSEN) ?
@ -1380,11 +1412,15 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
os_memcpy(reply->replay_counter, key->replay_counter, os_memcpy(reply->replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN); WPA_REPLAY_COUNTER_LEN);
key_mic = reply192->key_mic; /* same offset for reply and reply192 */
if (mic_len == 24)
WPA_PUT_BE16(reply192->key_data_length, 0);
else
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, sm->ptk.kck_len, ver, sm->bssid, wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid,
ETH_P_EAPOL, rbuf, rlen, reply->key_mic); ETH_P_EAPOL, rbuf, rlen, key_mic);
return 0; return 0;
} }
@ -1451,13 +1487,13 @@ failed:
static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
struct wpa_eapol_key *key, struct wpa_eapol_key_192 *key,
u16 ver, u16 ver,
const u8 *buf, size_t len) const u8 *buf, size_t len)
{ {
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
int ok = 0; int ok = 0;
size_t mic_len = 16; size_t mic_len = wpa_mic_len(sm->key_mgmt);
os_memcpy(mic, key->key_mic, mic_len); os_memcpy(mic, key->key_mic, mic_len);
if (sm->tptk_set) { if (sm->tptk_set) {
@ -1586,7 +1622,9 @@ void wpa_sm_aborted_cached(struct wpa_sm *sm)
static void wpa_eapol_key_dump(struct wpa_sm *sm, static void wpa_eapol_key_dump(struct wpa_sm *sm,
const struct wpa_eapol_key *key) const struct wpa_eapol_key *key,
unsigned int key_data_len,
const u8 *mic, unsigned int mic_len)
{ {
#ifndef CONFIG_NO_STDOUT_DEBUG #ifndef CONFIG_NO_STDOUT_DEBUG
u16 key_info = WPA_GET_BE16(key->key_info); u16 key_info = WPA_GET_BE16(key->key_info);
@ -1608,15 +1646,14 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm,
key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
" key_length=%u key_data_length=%u", " key_length=%u key_data_length=%u",
WPA_GET_BE16(key->key_length), WPA_GET_BE16(key->key_length), key_data_len);
WPA_GET_BE16(key->key_data_length));
wpa_hexdump(MSG_DEBUG, " replay_counter", wpa_hexdump(MSG_DEBUG, " replay_counter",
key->replay_counter, WPA_REPLAY_COUNTER_LEN); key->replay_counter, WPA_REPLAY_COUNTER_LEN);
wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16);
wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8);
wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8);
wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); wpa_hexdump(MSG_DEBUG, " key_mic", mic, mic_len);
#endif /* CONFIG_NO_STDOUT_DEBUG */ #endif /* CONFIG_NO_STDOUT_DEBUG */
} }
@ -1643,22 +1680,27 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
size_t plen, data_len, key_data_len; size_t plen, data_len, key_data_len;
const struct ieee802_1x_hdr *hdr; const struct ieee802_1x_hdr *hdr;
struct wpa_eapol_key *key; struct wpa_eapol_key *key;
struct wpa_eapol_key_192 *key192;
u16 key_info, ver; u16 key_info, ver;
u8 *tmp = NULL; u8 *tmp = NULL;
int ret = -1; int ret = -1;
struct wpa_peerkey *peerkey = NULL; struct wpa_peerkey *peerkey = NULL;
u8 *key_data; u8 *key_data;
size_t mic_len, keyhdrlen;
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
sm->ft_completed = 0; sm->ft_completed = 0;
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
if (len < sizeof(*hdr) + sizeof(*key)) { mic_len = wpa_mic_len(sm->key_mgmt);
keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
if (len < sizeof(*hdr) + keyhdrlen) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: EAPOL frame too short to be a WPA " "WPA: EAPOL frame too short to be a WPA "
"EAPOL-Key (len %lu, expecting at least %lu)", "EAPOL-Key (len %lu, expecting at least %lu)",
(unsigned long) len, (unsigned long) len,
(unsigned long) sizeof(*hdr) + sizeof(*key)); (unsigned long) sizeof(*hdr) + keyhdrlen);
return 0; return 0;
} }
@ -1680,7 +1722,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out; goto out;
} }
wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len); wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { if (plen > len - sizeof(*hdr) || plen < keyhdrlen) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: EAPOL frame payload size %lu " "WPA: EAPOL frame payload size %lu "
"invalid (frame size %lu)", "invalid (frame size %lu)",
@ -1703,6 +1745,11 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
goto out; goto out;
os_memcpy(tmp, buf, data_len); os_memcpy(tmp, buf, data_len);
key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
key192 = (struct wpa_eapol_key_192 *)
(tmp + sizeof(struct ieee802_1x_hdr));
if (mic_len == 24)
key_data = (u8 *) (key192 + 1);
else
key_data = (u8 *) (key + 1); key_data = (u8 *) (key + 1);
if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
@ -1713,14 +1760,18 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
ret = 0; ret = 0;
goto out; goto out;
} }
wpa_eapol_key_dump(sm, key);
if (mic_len == 24)
key_data_len = WPA_GET_BE16(key192->key_data_length);
else
key_data_len = WPA_GET_BE16(key->key_data_length); key_data_len = WPA_GET_BE16(key->key_data_length);
if (key_data_len > plen - sizeof(struct wpa_eapol_key)) { wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len);
if (key_data_len > plen - keyhdrlen) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
"frame - key_data overflow (%u > %u)", "frame - key_data overflow (%u > %u)",
(unsigned int) key_data_len, (unsigned int) key_data_len,
(unsigned int) (plen - sizeof(struct wpa_eapol_key))); (unsigned int) (plen - keyhdrlen));
goto out; goto out;
} }
@ -1870,12 +1921,13 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
} }
if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len))
goto out; goto out;
#ifdef CONFIG_PEERKEY #ifdef CONFIG_PEERKEY
if ((key_info & WPA_KEY_INFO_MIC) && peerkey && if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp,
data_len))
goto out; goto out;
#endif /* CONFIG_PEERKEY */ #endif /* CONFIG_PEERKEY */
@ -1965,6 +2017,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
return WPA_AUTH_KEY_MGMT_NONE; return WPA_AUTH_KEY_MGMT_NONE;
case WPA_KEY_MGMT_IEEE8021X_SUITE_B: case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
default: default:
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
/* /*
* wpa_supplicant - WPA/RSN IE and KDE processing * wpa_supplicant - WPA/RSN IE and KDE processing
* Copyright (c) 2003-2008, 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.
@ -173,6 +173,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) { } else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
} else { } else {

View file

@ -1,6 +1,6 @@
/* /*
* wlantest control interface * wlantest control interface
* 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.
@ -954,6 +954,9 @@ static void info_print_key_mgmt(char *buf, size_t len, int key_mgmt)
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
pos += os_snprintf(pos, end - pos, "%sEAP-SUITE-B", pos += os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
pos == buf ? "" : " "); pos == buf ? "" : " ");
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
pos += os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
pos == buf ? "" : " ");
} }

View file

@ -1,6 +1,6 @@
/* /*
* STA list * STA list
* 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.
@ -170,7 +170,7 @@ skip_rsn_wpa:
wpa_printf(MSG_INFO, "STA " MACSTR wpa_printf(MSG_INFO, "STA " MACSTR
" proto=%s%s%s%s" " proto=%s%s%s%s"
"pairwise=%s%s%s%s%s%s%s" "pairwise=%s%s%s%s%s%s%s"
"key_mgmt=%s%s%s%s%s%s%s%s%s%s" "key_mgmt=%s%s%s%s%s%s%s%s%s%s%s"
"rsn_capab=%s%s%s%s%s", "rsn_capab=%s%s%s%s%s",
MAC2STR(sta->addr), MAC2STR(sta->addr),
sta->proto == 0 ? "OPEN " : "", sta->proto == 0 ? "OPEN " : "",
@ -199,6 +199,8 @@ skip_rsn_wpa:
sta->key_mgmt & WPA_KEY_MGMT_OSEN ? "OSEN " : "", sta->key_mgmt & WPA_KEY_MGMT_OSEN ? "OSEN " : "",
sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B ? sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B ?
"EAP-SUITE-B " : "", "EAP-SUITE-B " : "",
sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ?
"EAP-SUITE-B-192 " : "",
sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "",
sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ?
"NO_PAIRWISE " : "", "NO_PAIRWISE " : "",

View file

@ -189,6 +189,11 @@ NEED_SHA256=y
NEED_AES_OMAC1=y NEED_AES_OMAC1=y
endif endif
ifdef CONFIG_SUITEB192
L_CFLAGS += -DCONFIG_SUITEB192
NEED_SHA384=y
endif
ifdef CONFIG_IEEE80211W ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y NEED_SHA256=y

View file

@ -192,6 +192,11 @@ NEED_SHA256=y
NEED_AES_OMAC1=y NEED_AES_OMAC1=y
endif endif
ifdef CONFIG_SUITEB192
CFLAGS += -DCONFIG_SUITEB192
NEED_SHA384=y
endif
ifdef CONFIG_IEEE80211W ifdef CONFIG_IEEE80211W
CFLAGS += -DCONFIG_IEEE80211W CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y NEED_SHA256=y

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant / Configuration parser and common functions * WPA Supplicant / Configuration parser and common functions
* 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.
@ -678,8 +678,14 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
else if (os_strcmp(start, "OSEN") == 0) else if (os_strcmp(start, "OSEN") == 0)
val |= WPA_KEY_MGMT_OSEN; val |= WPA_KEY_MGMT_OSEN;
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
#ifdef CONFIG_SUITEB
else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif /* CONFIG_SUITEB192 */
else { else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start); line, start);
@ -856,6 +862,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
} }
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
#ifdef CONFIG_SUITEB
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B", ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B",
pos == buf ? "" : " "); pos == buf ? "" : " ");
@ -865,6 +872,19 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
} }
pos += ret; pos += ret;
} }
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192",
pos == buf ? "" : " ");
if (os_snprintf_error(end - pos, ret)) {
end[-1] = '\0';
return buf;
}
pos += ret;
}
#endif /* CONFIG_SUITEB192 */
if (pos == buf) { if (pos == buf) {
os_free(buf); os_free(buf);

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant / Control interface (shared code for all backends) * WPA Supplicant / Control interface (shared code for all backends)
* 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.
@ -2323,6 +2323,7 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
} }
#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SUITEB
if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B", ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B",
pos == start ? "" : "+"); pos == start ? "" : "+");
@ -2330,6 +2331,17 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
return pos; return pos;
pos += ret; pos += ret;
} }
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192",
pos == start ? "" : "+");
if (os_snprintf_error(end - pos, ret))
return pos;
pos += ret;
}
#endif /* CONFIG_SUITEB192 */
pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);

View file

@ -2,7 +2,7 @@
* WPA Supplicant / dbus-based control interface * WPA Supplicant / dbus-based control interface
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com> * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi> * Copyright (c) 2009-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.
@ -3590,7 +3590,7 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
DBusMessageIter iter_dict, variant_iter; DBusMessageIter iter_dict, variant_iter;
const char *group; const char *group;
const char *pairwise[5]; /* max 5 pairwise ciphers is supported */ const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
const char *key_mgmt[8]; /* max 8 key managements may be supported */ const char *key_mgmt[9]; /* max 9 key managements may be supported */
int n; int n;
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
@ -3614,8 +3614,14 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
key_mgmt[n++] = "wpa-ft-eap"; key_mgmt[n++] = "wpa-ft-eap";
if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
key_mgmt[n++] = "wpa-eap-sha256"; key_mgmt[n++] = "wpa-eap-sha256";
#ifdef CONFIG_SUITEB
if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
key_mgmt[n++] = "wpa-eap-suite-b"; key_mgmt[n++] = "wpa-eap-suite-b";
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_SUITEB192
if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
key_mgmt[n++] = "wpa-eap-suite-b-192";
#endif /* CONFIG_SUITEB192 */
if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
key_mgmt[n++] = "wpa-none"; key_mgmt[n++] = "wpa-none";

View file

@ -1,6 +1,6 @@
/* /*
* WPA Supplicant * WPA Supplicant
* 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.
@ -1138,10 +1138,18 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
if (0) { if (0) {
#ifdef CONFIG_SUITEB192
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
#endif /* CONFIG_SUITEB192 */
#ifdef CONFIG_SUITEB
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
wpa_dbg(wpa_s, MSG_DEBUG, wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with Suite B"); "WPA: using KEY_MGMT 802.1X with Suite B");
#endif /* CONFIG_SUITEB */
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) { } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
@ -2143,7 +2151,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if (wpa_s->conf->key_mgmt_offload) { if (wpa_s->conf->key_mgmt_offload) {
if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B) params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
params.req_key_mgmt_offload = params.req_key_mgmt_offload =
ssid->proactive_key_caching < 0 ? ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc : ssid->proactive_key_caching; wpa_s->conf->okc : ssid->proactive_key_caching;