diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index a338cdf6e..54045ac60 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -13,6 +13,8 @@ ChangeLog for hostapd * updated management frame protection to use IEEE 802.11w/D6.0 (adds a new association ping to protect against unauthenticated authenticate or (re)associate request frames dropping association) + * added support for using SHA256-based stronger key derivation for WPA2 + (IEEE 802.11w) 2008-08-10 - v0.6.4 * added peer identity into EAP-FAST PAC-Opaque and skip Phase 2 diff --git a/hostapd/config.c b/hostapd/config.c index 0c251a9f5..d92296212 100644 --- a/hostapd/config.c +++ b/hostapd/config.c @@ -817,6 +817,12 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "FT-EAP") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) + val |= WPA_KEY_MGMT_PSK_SHA256; + else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA256; +#endif /* CONFIG_IEEE80211W */ else { printf("Line %d: invalid key_mgmt '%s'\n", line, start); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index d369c7c6f..75895af80 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -653,7 +653,8 @@ own_ip_addr=127.0.0.1 #wpa_psk_file=/etc/hostapd.wpa_psk # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. +# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be +# added to enable SHA256-based stronger algorithms. # (dot11RSNAConfigAuthenticationSuitesTable) #wpa_key_mgmt=WPA-PSK WPA-EAP diff --git a/hostapd/ieee802_1x.c b/hostapd/ieee802_1x.c index a3641badb..f8e421a52 100644 --- a/hostapd/ieee802_1x.c +++ b/hostapd/ieee802_1x.c @@ -719,8 +719,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, } if (!hapd->conf->ieee802_1x || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_FT_PSK) + wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm))) return; if (!sta->eapol_sm) { @@ -802,8 +801,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) int force_1x = 0; if ((!force_1x && !hapd->conf->ieee802_1x) || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_FT_PSK) + wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm))) return; if (sta->eapol_sm == NULL) { @@ -1938,10 +1936,9 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, "dot1xAuthSessionTerminateCause=999\n" "dot1xAuthSessionUserName=%s\n", sta->acct_session_id_hi, sta->acct_session_id_lo, - (wpa_auth_sta_key_mgmt(sta->wpa_sm) == - WPA_KEY_MGMT_IEEE8021X || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == - WPA_KEY_MGMT_FT_IEEE8021X) ? 1 : 2, + (wpa_key_mgmt_wpa_ieee8021x( + wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? + 1 : 2, (unsigned int) (time(NULL) - sta->acct_session_start), sm->identity); diff --git a/hostapd/peerkey.c b/hostapd/peerkey.c index 26097b723..83f3ce513 100644 --- a/hostapd/peerkey.c +++ b/hostapd/peerkey.c @@ -1,6 +1,6 @@ /* * hostapd - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2007, Jouni Malinen + * Copyright (c) 2006-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,6 +17,7 @@ #include "common.h" #include "eloop.h" #include "sha1.h" +#include "sha256.h" #include "wpa.h" #include "defs.h" #include "wpa_auth_i.h" @@ -309,8 +310,13 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth, os_memcpy(pos, kde.nonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN); +#ifdef CONFIG_IEEE80211W + sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), + smk, PMK_LEN); +#else /* CONFIG_IEEE80211W */ sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), smk, PMK_LEN); +#endif /* CONFIG_IEEE80211W */ wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN); diff --git a/hostapd/pmksa_cache.c b/hostapd/pmksa_cache.c index bbeb7aa55..77797943c 100644 --- a/hostapd/pmksa_cache.c +++ b/hostapd/pmksa_cache.c @@ -1,6 +1,6 @@ /* * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2006, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,6 +20,7 @@ #include "common.h" #include "eloop.h" #include "sha1.h" +#include "sha256.h" #include "ieee802_1x.h" #include "eapol_sm.h" #include "pmksa_cache.h" @@ -46,23 +47,29 @@ struct rsn_pmksa_cache { * @pmk_len: Length of pmk in bytes * @aa: Authenticator address * @spa: Supplicant address + * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) */ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid) + u8 *pmkid, int use_sha256) { char *title = "PMK Name"; const u8 *addr[3]; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; + unsigned char hash[SHA256_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = aa; addr[2] = spa; - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); +#ifdef CONFIG_IEEE80211W + if (use_sha256) + hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); + else +#endif /* CONFIG_IEEE80211W */ + hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); os_memcpy(pmkid, hash, PMKID_LEN); } @@ -248,6 +255,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, * @spa: Supplicant address * @session_timeout: Session timeout * @eapol: Pointer to EAPOL state machine data + * @akmp: WPA_KEY_MGMT_* used in key derivation * Returns: Pointer to the added PMKSA cache entry or %NULL on error * * This function create a PMKSA entry for a new PMK and adds it to the PMKSA @@ -258,7 +266,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol) + struct eapol_state_machine *eapol, int akmp) { struct rsn_pmksa_cache_entry *entry, *pos; struct os_time now; @@ -271,14 +279,15 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, return NULL; os_memcpy(entry->pmk, pmk, pmk_len); entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid); + rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, + wpa_key_mgmt_sha256(akmp)); os_get_time(&now); entry->expiration = now.sec; if (session_timeout > 0) entry->expiration += session_timeout; else entry->expiration += dot11RSNAConfigPMKLifetime; - entry->akmp = WPA_KEY_MGMT_IEEE8021X; + entry->akmp = akmp; os_memcpy(entry->spa, spa, ETH_ALEN); pmksa_cache_from_eapol_data(entry, eapol); @@ -412,7 +421,8 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( while (entry) { if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) continue; - rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid); + rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, + wpa_key_mgmt_sha256(entry->akmp)); if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) return entry; entry = entry->next; diff --git a/hostapd/pmksa_cache.h b/hostapd/pmksa_cache.h index d5afc6fc4..6ba2da607 100644 --- a/hostapd/pmksa_cache.h +++ b/hostapd/pmksa_cache.h @@ -1,6 +1,6 @@ /* * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2006, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -49,7 +49,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol); + struct eapol_state_machine *eapol, int akmp); struct rsn_pmksa_cache_entry * pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, const struct rsn_pmksa_cache_entry *old_entry, @@ -57,6 +57,6 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, struct eapol_state_machine *eapol); void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid); + u8 *pmkid, int use_sha256); #endif /* PMKSA_CACHE_H */ diff --git a/hostapd/wpa.c b/hostapd/wpa.c index a922ae530..bee3ffad4 100644 --- a/hostapd/wpa.c +++ b/hostapd/wpa.c @@ -21,6 +21,7 @@ #include "eapol_sm.h" #include "wpa.h" #include "sha1.h" +#include "sha256.h" #include "rc4.h" #include "aes_wrap.h" #include "crypto.h" @@ -207,12 +208,16 @@ static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, static int wpa_use_aes_cmac(struct wpa_state_machine *sm) { + int ret = 0; #ifdef CONFIG_IEEE80211R - return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK; -#else /* CONFIG_IEEE80211R */ - return 0; + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) + ret = 1; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) + ret = 1; +#endif /* CONFIG_IEEE80211W */ + return ret; } @@ -847,8 +852,13 @@ static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const u8 *gnonce, os_memcpy(data, addr, ETH_ALEN); os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); +#ifdef CONFIG_IEEE80211W + sha256_prf(gmk, WPA_GMK_LEN, "Group key expansion", + data, sizeof(data), gtk, gtk_len); +#else /* CONFIG_IEEE80211W */ sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion", data, sizeof(data), gtk, gtk_len); +#endif /* CONFIG_IEEE80211W */ wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN); wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len); @@ -1171,8 +1181,7 @@ SM_STATE(WPA_PTK, INITIALIZE) wpa_remove_ptk(sm); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); sm->TimeoutCtr = 0; - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 0); } @@ -1290,7 +1299,7 @@ SM_STATE(WPA_PTK, PTKSTART) * one possible PSK for this STA. */ if (sm->wpa == WPA_VERSION_WPA2 && - sm->wpa_key_mgmt != WPA_KEY_MGMT_PSK) { + wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { pmkid = buf; pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; @@ -1305,7 +1314,8 @@ SM_STATE(WPA_PTK, PTKSTART) * available with pre-calculated PMKID. */ rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, - sm->addr, &pmkid[2 + RSN_SELECTOR_LEN]); + sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], + wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); } } wpa_send_eapol(sm->wpa_auth, sm, @@ -1319,14 +1329,14 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk) { #ifdef CONFIG_IEEE80211R - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) return wpa_auth_derive_ptk_ft(sm, pmk, ptk); #endif /* CONFIG_IEEE80211R */ wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, - (u8 *) ptk, sizeof(*ptk)); + (u8 *) ptk, sizeof(*ptk), + wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); return 0; } @@ -1345,8 +1355,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) * WPA-PSK: iterate through possible PSKs and select the one matching * the packet */ for (;;) { - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); if (pmk == NULL) break; @@ -1361,8 +1370,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) break; } - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_PSK && - sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_PSK) + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) break; } @@ -1374,8 +1382,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { /* PSK may have changed from the previous choice, so update * state machine data based on whatever PSK was selected here. */ @@ -1537,8 +1544,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1); } @@ -1600,13 +1606,11 @@ SM_STEP(WPA_PTK) SM_ENTER(WPA_PTK, AUTHENTICATION2); break; case WPA_PTK_AUTHENTICATION2: - if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_IEEE8021X || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) && + if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && wpa_auth_get_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun) > 0) SM_ENTER(WPA_PTK, INITPMK); - else if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) + else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) /* FIX: && 802.1X::keyRun */) SM_ENTER(WPA_PTK, INITPSK); break; @@ -2252,7 +2256,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, if (pmksa_cache_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, sm->wpa_auth->addr, sm->addr, session_timeout, - eapol)) + eapol, sm->wpa_key_mgmt)) return 0; return -1; @@ -2268,7 +2272,8 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, return -1; if (pmksa_cache_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, - sta_addr, session_timeout, eapol)) + sta_addr, session_timeout, eapol, + WPA_KEY_MGMT_IEEE8021X)) return 0; return -1; diff --git a/hostapd/wpa_auth_ie.c b/hostapd/wpa_auth_ie.c index 78b069399..3f6551fee 100644 --- a/hostapd/wpa_auth_ie.c +++ b/hostapd/wpa_auth_ie.c @@ -1,6 +1,6 @@ /* * hostapd - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -189,6 +189,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, num_suites++; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211W */ if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", @@ -470,6 +482,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) selector = RSN_AUTH_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; + else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; else if (data.key_mgmt & WPA_KEY_MGMT_PSK) @@ -564,6 +582,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; + else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; else @@ -610,8 +634,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " "MDIE not included"); diff --git a/src/common/defs.h b/src/common/defs.h index 300adff56..9adc2ac0a 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -1,6 +1,6 @@ /* * WPA Supplicant - Common definitions - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -40,6 +40,35 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_WPA_NONE BIT(4) #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) #define WPA_KEY_MGMT_FT_PSK BIT(6) +#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) +#define WPA_KEY_MGMT_PSK_SHA256 BIT(8) + +static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) +{ + return akm == WPA_KEY_MGMT_IEEE8021X || + akm == WPA_KEY_MGMT_FT_IEEE8021X || + akm == WPA_KEY_MGMT_IEEE8021X_SHA256; +} + +static inline int wpa_key_mgmt_wpa_psk(int akm) +{ + return akm == WPA_KEY_MGMT_PSK || + akm == WPA_KEY_MGMT_FT_PSK || + akm == WPA_KEY_MGMT_PSK_SHA256; +} + +static inline int wpa_key_mgmt_ft(int akm) +{ + return akm == WPA_KEY_MGMT_FT_PSK || + akm == WPA_KEY_MGMT_FT_IEEE8021X; +} + +static inline int wpa_key_mgmt_sha256(int akm) +{ + return akm == WPA_KEY_MGMT_PSK_SHA256 || + akm == WPA_KEY_MGMT_IEEE8021X_SHA256; +} + #define WPA_PROTO_WPA BIT(0) #define WPA_PROTO_RSN BIT(1) @@ -55,7 +84,8 @@ typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 } wpa_cipher; typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, - KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK + KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK, + KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256 } wpa_key_mgmt; /** diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index e1ae894ba..c9ff319cc 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -79,6 +79,7 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @ptk_len: Length of PTK + * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", @@ -92,7 +93,7 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len) + u8 *ptk, size_t ptk_len, int use_sha256) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; @@ -114,7 +115,14 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); +#ifdef CONFIG_IEEE80211W + if (use_sha256) + sha256_prf(pmk, pmk_len, label, data, sizeof(data), + ptk, ptk_len); + else +#endif /* CONFIG_IEEE80211W */ + sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, + ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); @@ -214,6 +222,12 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) + return WPA_KEY_MGMT_IEEE8021X_SHA256; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) + return WPA_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ return 0; } #endif /* CONFIG_NO_WPA2 */ diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index fa5a154aa..3074cd44a 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -1,6 +1,6 @@ /* * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -294,7 +294,7 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len); + u8 *ptk, size_t ptk_len, int use_sha256); #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index 92ced5b6b..45c256a02 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2007, Jouni Malinen + * Copyright (c) 2006-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,6 +18,7 @@ #include "common.h" #include "sha1.h" +#include "sha256.h" #include "eloop.h" #include "wpa.h" #include "wpa_i.h" @@ -239,15 +240,19 @@ static int wpa_supplicant_process_smk_m2( /* TODO: find existing entry and if found, use that instead of adding * a new one; how to handle the case where both ends initiate at the * same time? */ - peerkey = os_malloc(sizeof(*peerkey)); + peerkey = os_zalloc(sizeof(*peerkey)); if (peerkey == NULL) return -1; - os_memset(peerkey, 0, sizeof(*peerkey)); os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); peerkey->rsnie_i_len = kde.rsn_ie_len; peerkey->cipher = cipher; +#ifdef CONFIG_IEEE80211W + if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_PSK_SHA256)) + peerkey->use_sha256 = 1; +#endif /* CONFIG_IEEE80211W */ if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->ctx, MSG_WARNING, @@ -294,18 +299,20 @@ static int wpa_supplicant_process_smk_m2( * @mac_p: Peer MAC address * @inonce: Initiator Nonce * @mac_i: Initiator MAC address + * @use_sha256: Whether to use SHA256-based KDF * * 8.5.1.4 Station to station (STK) key hierarchy * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) */ static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, - const u8 *inonce, const u8 *mac_i, u8 *smkid) + const u8 *inonce, const u8 *mac_i, u8 *smkid, + int use_sha256) { char *title = "SMK Name"; const u8 *addr[5]; const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; + unsigned char hash[SHA256_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = pnonce; @@ -313,7 +320,12 @@ static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, addr[3] = inonce; addr[4] = mac_i; - hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); +#ifdef CONFIG_IEEE80211W + if (use_sha256) + hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); + else +#endif /* CONFIG_IEEE80211W */ + hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); os_memcpy(smkid, hash, PMKID_LEN); } @@ -578,11 +590,13 @@ static int wpa_supplicant_process_smk_m45( if (peerkey->initiator) { rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, - peerkey->inonce, sm->own_addr, peerkey->smkid); + peerkey->inonce, sm->own_addr, peerkey->smkid, + peerkey->use_sha256); wpa_supplicant_send_stk_1_of_4(sm, peerkey); } else { rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, - peerkey->inonce, peerkey->addr, peerkey->smkid); + peerkey->inonce, peerkey->addr, peerkey->smkid, + peerkey->use_sha256); } wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); @@ -695,7 +709,8 @@ static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", sm->own_addr, peerkey->addr, peerkey->pnonce, key->key_nonce, - (u8 *) stk, sizeof(*stk)); + (u8 *) stk, sizeof(*stk), + peerkey->use_sha256); /* Supplicant: swap tx/rx Mic keys */ os_memcpy(buf, stk->u.auth.tx_mic_key, 8); os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); @@ -927,7 +942,8 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", sm->own_addr, peerkey->addr, peerkey->inonce, key->key_nonce, - (u8 *) &peerkey->stk, sizeof(peerkey->stk)); + (u8 *) &peerkey->stk, sizeof(peerkey->stk), + peerkey->use_sha256); peerkey->stk_set = 1; } @@ -1016,12 +1032,15 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) /* TODO: find existing entry and if found, use that instead of adding * a new one */ - peerkey = os_malloc(sizeof(*peerkey)); + peerkey = os_zalloc(sizeof(*peerkey)); if (peerkey == NULL) return -1; - os_memset(peerkey, 0, sizeof(*peerkey)); peerkey->initiator = 1; os_memcpy(peerkey->addr, peer, ETH_ALEN); +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->key_mgmt)) + peerkey->use_sha256 = 1; +#endif /* CONFIG_IEEE80211W */ /* SMK M1: * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, diff --git a/src/rsn_supp/peerkey.h b/src/rsn_supp/peerkey.h index f69c68f40..2613127c3 100644 --- a/src/rsn_supp/peerkey.h +++ b/src/rsn_supp/peerkey.h @@ -1,6 +1,6 @@ /* * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006, Jouni Malinen + * Copyright (c) 2006-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,6 +34,7 @@ struct wpa_peerkey { int cipher; /* Selected cipher (WPA_CIPHER_*) */ u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; int replay_counter_set; + int use_sha256; /* whether AKMP indicate SHA256-based derivations */ struct wpa_ptk stk, tstk; int stk_set, tstk_set; diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index 2a5bb5ae5..f8373de6d 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - RSN PMKSA cache - * Copyright (c) 2004-2006, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,6 +18,7 @@ #include "wpa.h" #include "eloop.h" #include "sha1.h" +#include "sha256.h" #include "wpa_i.h" #include "eapol_supp/eapol_supp_sm.h" #include "pmksa_cache.h" @@ -43,23 +44,29 @@ struct rsn_pmksa_cache { * @pmk_len: Length of pmk in bytes * @aa: Authenticator address * @spa: Supplicant address + * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) */ -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid) +static void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, + const u8 *spa, u8 *pmkid, int use_sha256) { char *title = "PMK Name"; const u8 *addr[3]; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; + unsigned char hash[SHA256_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = aa; addr[2] = spa; - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); +#ifdef CONFIG_IEEE80211W + if (use_sha256) + hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); + else +#endif /* CONFIG_IEEE80211W */ + hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); os_memcpy(pmkid, hash, PMKID_LEN); } @@ -145,6 +152,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) * @aa: Authenticator address * @spa: Supplicant address * @network_ctx: Network configuration context for this PMK + * @akmp: WPA_KEY_MGMT_* used in key derivation * Returns: Pointer to the added PMKSA cache entry or %NULL on error * * This function create a PMKSA entry for a new PMK and adds it to the PMKSA @@ -154,7 +162,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) */ struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx) + const u8 *aa, const u8 *spa, void *network_ctx, int akmp) { struct rsn_pmksa_cache_entry *entry, *pos, *prev; struct os_time now; @@ -167,12 +175,13 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, return NULL; os_memcpy(entry->pmk, pmk, pmk_len); entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid); + rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, + wpa_key_mgmt_sha256(akmp)); os_get_time(&now); entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100; - entry->akmp = WPA_KEY_MGMT_IEEE8021X; + entry->akmp = akmp; os_memcpy(entry->aa, aa, ETH_ALEN); entry->network_ctx = network_ctx; @@ -324,7 +333,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, aa, pmksa->sm->own_addr, - old_entry->network_ctx); + old_entry->network_ctx, old_entry->akmp); if (new_entry == NULL) return NULL; diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h index bf3b4d256..a329b25b0 100644 --- a/src/rsn_supp/pmksa_cache.h +++ b/src/rsn_supp/pmksa_cache.h @@ -1,6 +1,6 @@ /* * wpa_supplicant - WPA2/RSN PMKSA cache functions - * Copyright (c) 2003-2006, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -56,7 +56,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len); struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx); + const u8 *aa, const u8 *spa, void *network_ctx, int akmp); void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa); struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); void pmksa_cache_clear_current(struct wpa_sm *sm); @@ -100,7 +100,7 @@ static inline int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) static inline struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx) + const u8 *aa, const u8 *spa, void *network_ctx, int akmp) { return NULL; } diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index 7bc3c0492..b00c004cf 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - RSN pre-authentication - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -104,7 +104,8 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, sm->pmk_len = pmk_len; pmksa_cache_add(sm->pmksa, pmk, pmk_len, sm->preauth_bssid, sm->own_addr, - sm->network_ctx); + sm->network_ctx, + WPA_KEY_MGMT_IEEE8021X); } else { wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: failed to get " "master session key from pre-auth EAPOL state " @@ -304,7 +305,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) if (sm->preauth_eapol || sm->proto != WPA_PROTO_RSN || 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)) { wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state " "for new pre-authentication"); return; /* invalid state for new pre-auth */ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 89ca4731a..5ec1dabdc 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -77,6 +77,12 @@ static const char * wpa_key_mgmt_txt(int key_mgmt, int proto) case WPA_KEY_MGMT_FT_PSK: return "FT-PSK"; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + case WPA_KEY_MGMT_IEEE8021X_SHA256: + return "WPA2-EAP-SHA256"; + case WPA_KEY_MGMT_PSK_SHA256: + return "WPA2-PSK-SHA256"; +#endif /* CONFIG_IEEE80211W */ default: return "UNKNOWN"; } @@ -140,8 +146,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) int key_info, ver; u8 bssid[ETH_ALEN], *rbuf; - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) + if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; @@ -216,8 +221,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, #ifdef CONFIG_IEEE80211R sm->xxkey_len = 0; #endif /* CONFIG_IEEE80211R */ - } else if ((sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) && sm->eapol) { + } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { int res, pmk_len; pmk_len = PMK_LEN; res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); @@ -244,7 +248,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, "machines", sm->pmk, pmk_len); sm->pmk_len = pmk_len; pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr, - sm->own_addr, sm->network_ctx); + sm->own_addr, sm->network_ctx, + sm->key_mgmt); if (!sm->cur_pmksa && pmkid && pmksa_cache_get(sm->pmksa, src_addr, pmkid)) { wpa_printf(MSG_DEBUG, "RSN: the new PMK " @@ -268,8 +273,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, } } - if (abort_cached && (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)) { + if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { /* Send EAPOL-Start to trigger full EAP authentication. */ u8 *buf; size_t buflen; @@ -356,14 +360,14 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, struct wpa_ptk *ptk) { #ifdef CONFIG_IEEE80211R - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) + if (wpa_key_mgmt_ft(sm->key_mgmt)) return wpa_derive_ptk_ft(sm, src_addr, key, ptk); #endif /* CONFIG_IEEE80211R */ wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, sizeof(*ptk)); + (u8 *) ptk, sizeof(*ptk), + wpa_key_mgmt_sha256(sm->key_mgmt)); return 0; } @@ -458,8 +462,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); - if (sm->key_mgmt == WPA_KEY_MGMT_PSK || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) + if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) eapol_sm_notify_eap_success(sm->eapol, TRUE); /* * Start preauthentication after a short wait to avoid a @@ -478,8 +481,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, } #ifdef CONFIG_IEEE80211R - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_ft(sm->key_mgmt)) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(sm); } @@ -834,8 +836,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, } #ifdef CONFIG_IEEE80211R - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_ft(sm->key_mgmt)) { struct rsn_mdie *mdie; /* TODO: verify that full MDIE matches with the one from scan * results, not only mobility domain */ @@ -1463,8 +1464,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } #ifdef CONFIG_IEEE80211R - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_ft(sm->key_mgmt)) { /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_printf(MSG_INFO, "FT: AP did not use " @@ -1473,6 +1473,15 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } } else #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->key_mgmt)) { + if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_printf(MSG_INFO, "WPA: AP did not use the " + "negotiated AES-128-CMAC."); + goto out; + } + } else +#endif /* CONFIG_IEEE80211W */ if (sm->pairwise_cipher == WPA_CIPHER_CCMP && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_printf(MSG_INFO, "WPA: CCMP is used, but EAPOL-Key " @@ -1651,6 +1660,12 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) case WPA_KEY_MGMT_FT_PSK: return RSN_AUTH_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + case WPA_KEY_MGMT_IEEE8021X_SHA256: + return RSN_AUTH_KEY_MGMT_802_1X_SHA256; + case WPA_KEY_MGMT_PSK_SHA256: + return RSN_AUTH_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ case WPA_KEY_MGMT_WPA_NONE: return WPA_AUTH_KEY_MGMT_NONE; default: @@ -1708,10 +1723,8 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) } else pmkid_txt[0] = '\0'; - if ((sm->key_mgmt == WPA_KEY_MGMT_PSK || - sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - sm->key_mgmt == WPA_KEY_MGMT_FT_PSK || - sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) && + if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || + wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && sm->proto == WPA_PROTO_RSN) rsna = 1; else diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 94a542dd0..84f2811b8 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -1,6 +1,6 @@ /* * wpa_supplicant - WPA/RSN IE and KDE processing - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -316,6 +316,12 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); + } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); +#endif /* CONFIG_IEEE80211W */ } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index a7a843cae..9b6d7b0b0 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -4,6 +4,8 @@ ChangeLog for wpa_supplicant * added support for SHA-256 as X.509 certificate digest when using the internal X.509/TLSv1 implementation * updated management frame protection to use IEEE 802.11w/D6.0 + * added support for using SHA256-based stronger key derivation for WPA2 + (IEEE 802.11w) 2008-08-10 - v0.6.4 * added support for EAP Sequences in EAP-FAST Phase 2 diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 22255d920..e8065d097 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Configuration parser and common functions - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -500,6 +500,12 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "FT-EAP") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) + val |= WPA_KEY_MGMT_PSK_SHA256; + else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA256; +#endif /* CONFIG_IEEE80211W */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); @@ -596,6 +602,16 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, pos == buf ? "" : " "); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", + pos == buf ? "" : " "); + + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", + pos == buf ? "" : " "); +#endif /* CONFIG_IEEE80211W */ + return buf; } #endif /* NO_CONFIG_WRITE */ diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index ce9f0b628..60650ae7c 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Configuration backend: text file - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -104,7 +104,8 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) wpa_config_update_psk(ssid); } - if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)) && + if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)) && !ssid->psk_set) { wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " "management, but no PSK configured.", line); diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index fe43d781e..974672793 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Configuration backend: Windows registry - * Copyright (c) 2003-2006, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -264,7 +264,8 @@ static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw, wpa_config_update_psk(ssid); } - if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)) && + if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)) && !ssid->psk_set) { wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, " "but no PSK configured for network '" TSTR "'.", diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 98ac08f1e..036365dde 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -285,9 +285,8 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, pos += ret; } - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { + if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); if (res >= 0) @@ -493,6 +492,24 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, first = 0; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", + first ? "" : "+"); + if (ret < 0 || ret >= end - pos) + return pos; + pos += ret; + first = 0; + } + if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", + first ? "" : "+"); + if (ret < 0 || ret >= end - pos) + return pos; + pos += ret; + first = 0; + } +#endif /* CONFIG_IEEE80211W */ pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index a3859c4e3..0f9b3383d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -58,8 +58,9 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) "AP"); if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_WPA_NONE | - WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) - { + WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256)) { u8 wpa_ie[80]; size_t wpa_ie_len = sizeof(wpa_ie); wpa_supplicant_set_suites(wpa_s, NULL, ssid, @@ -99,8 +100,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK) + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; } @@ -500,7 +500,10 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, } if ((ssid->key_mgmt & - (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK)) && + (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_PSK_SHA256)) && (wpa_ie_len != 0 || rsn_ie_len != 0)) { wpa_printf(MSG_DEBUG, " skip - " "WPA network"); @@ -750,8 +753,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK || ft_completed) + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); @@ -767,8 +769,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_supplicant_cancel_scan(wpa_s); if (wpa_s->driver_4way_handshake && - (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK)) { + wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. @@ -797,8 +798,7 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s) } if (wpa_s->wpa_state == WPA_4WAY_HANDSHAKE && - (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK)) { + wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " "pre-shared key may be incorrect"); } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index bffc0bead..4936a078a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -251,8 +251,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) struct eapol_config eapol_conf; struct wpa_ssid *ssid = wpa_s->current_ssid; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); } @@ -282,8 +281,8 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) if (wpa_s->conf) eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; eapol_conf.workaround = ssid->eap_workaround; - eapol_conf.eap_disabled = wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - wpa_s->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && + eapol_conf.eap_disabled = + !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA; eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); #endif /* IEEE8021X_EAPOL */ @@ -562,8 +561,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * TODO: should notify EAPOL SM about changes in opensc_engine_path, * pkcs11_engine_path, pkcs11_module_path. */ - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK) { + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * Clear forced success to clear EAP state for next * authentication. @@ -634,6 +632,10 @@ static wpa_key_mgmt key_mgmt2driver(int key_mgmt) return KEY_MGMT_FT_802_1X; case WPA_KEY_MGMT_FT_PSK: return KEY_MGMT_FT_PSK; + case WPA_KEY_MGMT_IEEE8021X_SHA256: + return KEY_MGMT_802_1X_SHA256; + case WPA_KEY_MGMT_PSK_SHA256: + return KEY_MGMT_PSK_SHA256; case WPA_KEY_MGMT_PSK: default: return KEY_MGMT_PSK; @@ -822,6 +824,16 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK; wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK"); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; + wpa_msg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT 802.1X with SHA256"); + } else if (sel & WPA_KEY_MGMT_PSK_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; + wpa_msg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT PSK with SHA256"); +#endif /* CONFIG_IEEE80211W */ } else if (sel & WPA_KEY_MGMT_IEEE8021X) { wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X"); @@ -864,7 +876,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, return -1; } - if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)) + if (ssid->key_mgmt & + (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_PSK_SHA256)) wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN); else wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); @@ -950,7 +963,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_scan_get_ie(bss, WLAN_EID_RSN)) && (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | - WPA_KEY_MGMT_FT_PSK))) { + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_PSK_SHA256))) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); @@ -968,7 +983,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } else if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_FT_IEEE8021X)) { + WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256)) { wpa_ie_len = sizeof(wpa_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_ie, &wpa_ie_len)) { @@ -1428,15 +1444,13 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, if (wpa_s->eapol_received == 0 && (!wpa_s->driver_4way_handshake || - (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK && - wpa_s->key_mgmt != WPA_KEY_MGMT_FT_PSK) || + !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->wpa_state != WPA_COMPLETED)) { /* Timeout for completing IEEE 802.1X and WPA authentication */ wpa_supplicant_req_auth_timeout( wpa_s, - (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) ? + (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) ? 70 : 10, 0); } wpa_s->eapol_received++; @@ -1454,15 +1468,13 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, * still sent to the current BSSID (if available), though. */ os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); - if (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK && - wpa_s->key_mgmt != WPA_KEY_MGMT_FT_PSK && + if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) return; wpa_drv_poll(wpa_s); if (!wpa_s->driver_4way_handshake) wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); - else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { + else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* * Set portValid = TRUE here since we are going to skip 4-way * handshake processing which would normally set portValid. We diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index e3f33a100..6da4883dd 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -211,6 +211,8 @@ fast_reauth=1 # IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically # generated WEP keys # NONE = WPA is not used; plaintext or static WEP could be used +# WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms +# WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms # If not set, this defaults to: WPA-PSK WPA-EAP # # auth_alg: list of allowed IEEE 802.11 authentication algorithms diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 6efcbdc8c..cbe2381c6 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - Glue code to setup EAPOL and RSN modules - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -122,8 +122,7 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, /* TODO: could add l2_packet_sendmsg that allows fragments to avoid * extra copy here */ - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK || + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { /* Current SSID is not using IEEE 802.1X/EAP, so drop possible * EAPOL frames (mainly, EAPOL-Start) from EAPOL state @@ -225,8 +224,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success, if (!success || !wpa_s->driver_4way_handshake) return; - if (wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - wpa_s->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X) + if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) return; wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way " @@ -265,8 +263,7 @@ static void wpa_supplicant_notify_eapol_done(void *ctx) { struct wpa_supplicant *wpa_s = ctx; wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { + if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); } else { wpa_supplicant_cancel_auth_timeout(wpa_s);