* 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
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);
#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
}
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) {
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) {
"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);
/*
* hostapd - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
* 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
#include "common.h"
#include "eloop.h"
#include "sha1.h"
+#include "sha256.h"
#include "wpa.h"
#include "defs.h"
#include "wpa_auth_i.h"
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);
/*
* hostapd - PMKSA cache for IEEE 802.11i RSN
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
#include "common.h"
#include "eloop.h"
#include "sha1.h"
+#include "sha256.h"
#include "ieee802_1x.h"
#include "eapol_sm.h"
#include "pmksa_cache.h"
* @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);
}
* @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
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;
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);
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;
/*
* hostapd - PMKSA cache for IEEE 802.11i RSN
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
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,
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 */
#include "eapol_sm.h"
#include "wpa.h"
#include "sha1.h"
+#include "sha256.h"
#include "rc4.h"
#include "aes_wrap.h"
#include "crypto.h"
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;
}
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);
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);
}
* 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;
* 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,
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;
}
* 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;
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;
}
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.
*/
/* 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);
}
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;
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;
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;
/*
* hostapd - WPA/RSN IE and KDE definitions
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
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).",
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)
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
#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");
/*
* WPA Supplicant - Common definitions
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
#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)
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;
/**
* @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",
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];
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));
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 */
/*
* WPA definitions shared between hostapd and wpa_supplicant
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* 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
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,
/*
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
* 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
#include "common.h"
#include "sha1.h"
+#include "sha256.h"
#include "eloop.h"
#include "wpa.h"
#include "wpa_i.h"
/* 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,
* @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;
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);
}
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);
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);
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;
}
/* 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,
/*
* WPA Supplicant - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
* 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
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;
/*
* WPA Supplicant - RSN PMKSA cache
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
#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"
* @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);
}
* @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
*/
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;
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;
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;
/*
* wpa_supplicant - WPA2/RSN PMKSA cache functions
- * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
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);
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;
}
/*
* WPA Supplicant - RSN pre-authentication
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
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 "
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 */
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";
}
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;
#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);
"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 "
}
}
- 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;
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;
}
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
}
#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);
}
}
#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 */
}
#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 "
}
} 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 "
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:
} 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
/*
* wpa_supplicant - WPA/RSN IE and KDE processing
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
} 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);
* 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
/*
* WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
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);
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 */
/*
* WPA Supplicant / Configuration backend: text file
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
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);
/*
* WPA Supplicant / Configuration backend: Windows registry
- * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
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 "'.",
/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* 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
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)
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);
"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,
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;
}
}
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");
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);
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.
}
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");
}
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);
}
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 */
* 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.
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;
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");
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);
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);
} 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)) {
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++;
* 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
# 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
/*
* WPA Supplicant - Glue code to setup EAPOL and RSN modules
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* 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
/* 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
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 "
{
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);