HS 2.0R2 AP: Add OSEN implementation
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
6ca0853d18
commit
a14896e8bb
19 changed files with 294 additions and 25 deletions
|
@ -2810,6 +2810,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->hs20 = atoi(pos);
|
||||
} else if (os_strcmp(buf, "disable_dgaf") == 0) {
|
||||
bss->disable_dgaf = atoi(pos);
|
||||
} else if (os_strcmp(buf, "osen") == 0) {
|
||||
bss->osen = atoi(pos);
|
||||
} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
|
||||
bss->anqp_domain_id = atoi(pos);
|
||||
} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
|
||||
|
|
|
@ -1582,6 +1582,9 @@ own_ip_addr=127.0.0.1
|
|||
# forging such frames to other stations in the BSS.
|
||||
#disable_dgaf=1
|
||||
|
||||
# OSU Server-Only Authenticated L2 Encryption Network
|
||||
#osen=1
|
||||
|
||||
# ANQP Domain ID (0..65535)
|
||||
# An identifier for a set of APs in an ESS that share the same common ANQP
|
||||
# information. 0 = Some of the ANQP information is unique to this AP (default).
|
||||
|
|
|
@ -890,6 +890,11 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss)
|
|||
bss->wpa_group = cipher;
|
||||
bss->wpa_pairwise = cipher;
|
||||
bss->rsn_pairwise = cipher;
|
||||
} else if (bss->osen) {
|
||||
bss->ssid.security_policy = SECURITY_OSEN;
|
||||
bss->wpa_group = WPA_CIPHER_CCMP;
|
||||
bss->wpa_pairwise = 0;
|
||||
bss->rsn_pairwise = WPA_CIPHER_CCMP;
|
||||
} else {
|
||||
bss->ssid.security_policy = SECURITY_PLAINTEXT;
|
||||
bss->wpa_group = WPA_CIPHER_NONE;
|
||||
|
|
|
@ -45,7 +45,8 @@ typedef enum hostap_security_policy {
|
|||
SECURITY_STATIC_WEP = 1,
|
||||
SECURITY_IEEE_802_1X = 2,
|
||||
SECURITY_WPA_PSK = 3,
|
||||
SECURITY_WPA = 4
|
||||
SECURITY_WPA = 4,
|
||||
SECURITY_OSEN = 5
|
||||
} secpolicy;
|
||||
|
||||
struct hostapd_ssid {
|
||||
|
@ -452,6 +453,7 @@ struct hostapd_bss_config {
|
|||
u8 qos_map_set[16 + 2 * 21];
|
||||
unsigned int qos_map_set_len;
|
||||
|
||||
int osen;
|
||||
#ifdef CONFIG_HS20
|
||||
int hs20;
|
||||
int disable_dgaf;
|
||||
|
|
|
@ -170,6 +170,17 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
|||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
|
||||
pos = hostapd_eid_osen(hapd, buf);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
|
|
|
@ -442,6 +442,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
pos = hostapd_eid_osen(hapd, pos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
|
@ -854,6 +855,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef CONFIG_HS20
|
||||
tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
|
||||
tailpos = hostapd_eid_osen(hapd, tailpos);
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
|
@ -925,6 +927,10 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
|
||||
#ifdef CONFIG_HS20
|
||||
params->disable_dgaf = hapd->conf->disable_dgaf;
|
||||
if (hapd->conf->osen) {
|
||||
params->privacy = 1;
|
||||
params->osen = 1;
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
ie = elems.wpa_ie - 2;
|
||||
ielen = elems.wpa_ie_len + 2;
|
||||
wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
|
||||
#ifdef CONFIG_HS20
|
||||
} else if (elems.osen) {
|
||||
ie = elems.osen - 2;
|
||||
ielen = elems.osen_len + 2;
|
||||
wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
|
||||
#endif /* CONFIG_HS20 */
|
||||
} else {
|
||||
ie = NULL;
|
||||
ielen = 0;
|
||||
|
@ -281,6 +287,29 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||
wpabuf_free(wps);
|
||||
#endif /* CONFIG_WPS */
|
||||
#ifdef CONFIG_HS20
|
||||
} else if (hapd->conf->osen) {
|
||||
if (elems.osen == NULL) {
|
||||
hostapd_logger(
|
||||
hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"No HS 2.0 OSEN element in association request");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
sta->addr, NULL);
|
||||
if (sta->wpa_sm == NULL) {
|
||||
wpa_printf(MSG_WARNING, "Failed to initialize WPA "
|
||||
"state machine");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
|
||||
elems.osen - 2, elems.osen_len + 2) < 0)
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
#endif /* CONFIG_HS20 */
|
||||
}
|
||||
#ifdef CONFIG_WPS
|
||||
skip_wpa_check:
|
||||
|
|
|
@ -87,7 +87,7 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||
else
|
||||
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
|
||||
|
||||
if (hapd->conf->wpa && hapd->wpa_auth == NULL) {
|
||||
if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) {
|
||||
hostapd_setup_wpa(hapd);
|
||||
if (hapd->wpa_auth)
|
||||
wpa_init_keys(hapd->wpa_auth);
|
||||
|
@ -802,7 +802,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
|
||||
if ((hapd->conf->wpa || hapd->conf->osen) && hostapd_setup_wpa(hapd))
|
||||
return -1;
|
||||
|
||||
if (accounting_init(hapd)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2009, Atheros Communications, Inc.
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -39,6 +39,58 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
|
|||
}
|
||||
|
||||
|
||||
u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
|
||||
{
|
||||
u8 *len;
|
||||
u16 capab;
|
||||
|
||||
if (!hapd->conf->osen)
|
||||
return eid;
|
||||
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
len = eid++; /* to be filled */
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = HS20_OSEN_OUI_TYPE;
|
||||
|
||||
/* Group Data Cipher Suite */
|
||||
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* Pairwise Cipher Suite Count and List */
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* AKM Suite Count and List */
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* RSN Capabilities */
|
||||
capab = 0;
|
||||
if (hapd->conf->wmm_enabled) {
|
||||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
WPA_PUT_LE16(eid, capab);
|
||||
eid += 2;
|
||||
|
||||
*len = eid - len - 1;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 osu_method, const char *url)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Hotspot 2.0 AP ANQP processing
|
||||
* Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -12,6 +12,7 @@
|
|||
struct hostapd_data;
|
||||
|
||||
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid);
|
||||
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
|
||||
u8 osu_method, const char *url);
|
||||
|
||||
|
|
|
@ -162,6 +162,11 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
if (hapd->conf->wpa)
|
||||
privacy = 1;
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
if (hapd->conf->osen)
|
||||
privacy = 1;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (sta) {
|
||||
int policy, def_klen;
|
||||
if (probe && sta->ssid_probe) {
|
||||
|
@ -1089,6 +1094,29 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211N */
|
||||
#ifdef CONFIG_HS20
|
||||
} else if (hapd->conf->osen) {
|
||||
if (elems.osen == NULL) {
|
||||
hostapd_logger(
|
||||
hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO,
|
||||
"No HS 2.0 OSEN element in association request");
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
|
||||
if (sta->wpa_sm == NULL)
|
||||
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
||||
sta->addr, NULL);
|
||||
if (sta->wpa_sm == NULL) {
|
||||
wpa_printf(MSG_WARNING, "Failed to initialize WPA "
|
||||
"state machine");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
|
||||
elems.osen - 2, elems.osen_len + 2) < 0)
|
||||
return WLAN_STATUS_INVALID_IE;
|
||||
#endif /* CONFIG_HS20 */
|
||||
} else
|
||||
wpa_auth_sta_no_wpa(sta->wpa_sm);
|
||||
|
||||
|
@ -1924,7 +1952,7 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
|
|||
new_assoc = 0;
|
||||
sta->flags |= WLAN_STA_ASSOC;
|
||||
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
|
||||
if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
|
||||
if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) ||
|
||||
sta->auth_alg == WLAN_AUTH_FT) {
|
||||
/*
|
||||
* Open, static WEP, or FT protocol; no separate authorization
|
||||
|
|
|
@ -686,7 +686,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
int key_mgmt;
|
||||
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen &&
|
||||
!hapd->conf->wps_state)
|
||||
return;
|
||||
|
||||
|
@ -737,7 +737,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!hapd->conf->ieee802_1x &&
|
||||
if (!hapd->conf->ieee802_1x && !hapd->conf->osen &&
|
||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - "
|
||||
"802.1X not enabled and WPS not used");
|
||||
|
@ -757,7 +757,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
|||
return;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (!hapd->conf->ieee802_1x) {
|
||||
if (!hapd->conf->ieee802_1x && hapd->conf->wps_state) {
|
||||
u32 wflags = sta->flags & (WLAN_STA_WPS |
|
||||
WLAN_STA_WPS2 |
|
||||
WLAN_STA_MAYBE_WPS);
|
||||
|
@ -875,7 +875,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (!force_1x && !hapd->conf->ieee802_1x) {
|
||||
if (!force_1x && !hapd->conf->ieee802_1x && !hapd->conf->osen) {
|
||||
wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - "
|
||||
"802.1X not enabled or forced for WPS");
|
||||
/*
|
||||
|
@ -913,7 +913,8 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
|||
|
||||
#ifdef CONFIG_WPS
|
||||
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
|
||||
if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
|
||||
if (!hapd->conf->ieee802_1x && hapd->conf->wps_state &&
|
||||
!(sta->flags & WLAN_STA_WPS2)) {
|
||||
/*
|
||||
* Delay EAPOL frame transmission until a possible WPS STA
|
||||
* initiates the handshake with EAPOL-Start. Only allow the
|
||||
|
|
|
@ -211,6 +211,8 @@ static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
|
|||
if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt))
|
||||
ret = 1;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -878,6 +880,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
|||
if (sm->pairwise == WPA_CIPHER_CCMP ||
|
||||
sm->pairwise == WPA_CIPHER_GCMP) {
|
||||
if (wpa_use_aes_cmac(sm) &&
|
||||
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN &&
|
||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
wpa_auth_logger(wpa_auth, sm->addr,
|
||||
LOGGER_WARNING,
|
||||
|
@ -1001,6 +1004,9 @@ continue_processing:
|
|||
if (kde.rsn_ie) {
|
||||
eapol_key_ie = kde.rsn_ie;
|
||||
eapol_key_ie_len = kde.rsn_ie_len;
|
||||
} else if (kde.osen) {
|
||||
eapol_key_ie = kde.osen;
|
||||
eapol_key_ie_len = kde.osen_len;
|
||||
} else {
|
||||
eapol_key_ie = kde.wpa_ie;
|
||||
eapol_key_ie_len = kde.wpa_ie_len;
|
||||
|
@ -1286,6 +1292,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
if (force_version)
|
||||
version = force_version;
|
||||
else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN)
|
||||
version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
||||
else if (wpa_use_aes_cmac(sm))
|
||||
version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
|
||||
else if (sm->pairwise != WPA_CIPHER_TKIP)
|
||||
|
@ -1308,6 +1316,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
key_data_len = kde_len;
|
||||
|
||||
if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
|
||||
pad_len = key_data_len % 8;
|
||||
if (pad_len)
|
||||
|
@ -1376,6 +1385,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
|||
wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
|
||||
buf, key_data_len);
|
||||
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
|
||||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,
|
||||
(u8 *) (key + 1))) {
|
||||
|
@ -1774,7 +1784,8 @@ SM_STATE(WPA_PTK, PTKSTART)
|
|||
* one possible PSK for this STA.
|
||||
*/
|
||||
if (sm->wpa == WPA_VERSION_WPA2 &&
|
||||
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) {
|
||||
wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
|
||||
sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
|
||||
pmkid = buf;
|
||||
pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
|
||||
pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
|
||||
|
|
|
@ -232,6 +232,9 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
struct wpa_state_machine *sm,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *mdie, size_t mdie_len);
|
||||
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *osen_ie, size_t osen_ie_len);
|
||||
int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
|
||||
struct wpa_state_machine *
|
||||
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
|
|
|
@ -73,6 +73,19 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_HS20
|
||||
wconf->disable_gtk = conf->disable_dgaf;
|
||||
if (conf->osen) {
|
||||
wconf->disable_gtk = 1;
|
||||
wconf->wpa = WPA_PROTO_OSEN;
|
||||
wconf->wpa_key_mgmt = WPA_KEY_MGMT_OSEN;
|
||||
wconf->wpa_pairwise = 0;
|
||||
wconf->wpa_group = WPA_CIPHER_CCMP;
|
||||
wconf->rsn_pairwise = WPA_CIPHER_CCMP;
|
||||
wconf->rsn_preauth = 0;
|
||||
wconf->disable_pmksa_caching = 1;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
wconf->ieee80211w = 1;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
wconf->corrupt_gtk_rekey_mic_probability =
|
||||
|
|
|
@ -295,6 +295,55 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
|||
}
|
||||
|
||||
|
||||
static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
||||
{
|
||||
u8 *len;
|
||||
u16 capab;
|
||||
|
||||
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
len = eid++; /* to be filled */
|
||||
WPA_PUT_BE24(eid, OUI_WFA);
|
||||
eid += 3;
|
||||
*eid++ = HS20_OSEN_OUI_TYPE;
|
||||
|
||||
/* Group Data Cipher Suite */
|
||||
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* Pairwise Cipher Suite Count and List */
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* AKM Suite Count and List */
|
||||
WPA_PUT_LE16(eid, 1);
|
||||
eid += 2;
|
||||
RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
|
||||
eid += RSN_SELECTOR_LEN;
|
||||
|
||||
/* RSN Capabilities */
|
||||
capab = 0;
|
||||
if (conf->wmm_enabled) {
|
||||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
WPA_PUT_LE16(eid, capab);
|
||||
eid += 2;
|
||||
|
||||
*len = eid - len - 1;
|
||||
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
{
|
||||
u8 *pos, buf[128];
|
||||
|
@ -302,6 +351,9 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
|||
|
||||
pos = buf;
|
||||
|
||||
if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) {
|
||||
pos = wpa_write_osen(&wpa_auth->conf, pos);
|
||||
}
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
||||
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos, NULL);
|
||||
|
@ -626,6 +678,36 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *osen_ie, size_t osen_ie_len)
|
||||
{
|
||||
if (wpa_auth == NULL || sm == NULL)
|
||||
return -1;
|
||||
|
||||
/* TODO: parse OSEN element */
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN;
|
||||
sm->mgmt_frame_prot = 1;
|
||||
sm->pairwise = WPA_CIPHER_CCMP;
|
||||
sm->wpa = WPA_VERSION_WPA2;
|
||||
|
||||
if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) {
|
||||
os_free(sm->wpa_ie);
|
||||
sm->wpa_ie = os_malloc(osen_ie_len);
|
||||
if (sm->wpa_ie == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len);
|
||||
sm->wpa_ie_len = osen_ie_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
|
||||
* @pos: Pointer to the IE header
|
||||
|
@ -648,6 +730,12 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) {
|
||||
ie->osen = pos;
|
||||
ie->osen_len = pos[1] + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 + RSN_SELECTOR_LEN < end &&
|
||||
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
|
||||
|
|
|
@ -43,6 +43,9 @@ struct wpa_eapol_ie_parse {
|
|||
const u8 *ip_addr_req;
|
||||
const u8 *ip_addr_alloc;
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
const u8 *osen;
|
||||
size_t osen_len;
|
||||
};
|
||||
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len,
|
||||
|
|
|
@ -847,6 +847,11 @@ struct wpa_driver_ap_params {
|
|||
* disable_dgaf - Whether group-addressed frames are disabled
|
||||
*/
|
||||
int disable_dgaf;
|
||||
|
||||
/**
|
||||
* osen - Whether OSEN security is enabled
|
||||
*/
|
||||
int osen;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -110,7 +110,8 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
|
|||
if (rbuf == NULL)
|
||||
return;
|
||||
|
||||
reply->type = sm->proto == WPA_PROTO_RSN ?
|
||||
reply->type = (sm->proto == WPA_PROTO_RSN ||
|
||||
sm->proto == WPA_PROTO_OSEN) ?
|
||||
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
|
||||
key_info = WPA_KEY_INFO_REQUEST | ver;
|
||||
if (sm->ptk_set)
|
||||
|
@ -234,7 +235,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
|||
}
|
||||
|
||||
if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
|
||||
!wpa_key_mgmt_ft(sm->key_mgmt)) {
|
||||
!wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
|
||||
{
|
||||
/* Send EAPOL-Start to trigger full EAP authentication. */
|
||||
u8 *buf;
|
||||
size_t buflen;
|
||||
|
@ -328,11 +330,12 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
|||
return -1;
|
||||
}
|
||||
|
||||
reply->type = sm->proto == WPA_PROTO_RSN ?
|
||||
reply->type = (sm->proto == WPA_PROTO_RSN ||
|
||||
sm->proto == WPA_PROTO_OSEN) ?
|
||||
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
|
||||
WPA_PUT_BE16(reply->key_info,
|
||||
ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
|
||||
if (sm->proto == WPA_PROTO_RSN)
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
|
||||
WPA_PUT_BE16(reply->key_length, 0);
|
||||
else
|
||||
os_memcpy(reply->key_length, key->key_length, 2);
|
||||
|
@ -397,7 +400,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
|||
|
||||
os_memset(&ie, 0, sizeof(ie));
|
||||
|
||||
if (sm->proto == WPA_PROTO_RSN) {
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
|
||||
/* RSN: msg 1/4 should contain PMKID for the selected PMK */
|
||||
const u8 *_buf = (const u8 *) (key + 1);
|
||||
size_t len = WPA_GET_BE16(key->key_data_length);
|
||||
|
@ -564,7 +567,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
|
|||
keylen = wpa_cipher_key_len(sm->pairwise_cipher);
|
||||
rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
|
||||
|
||||
if (sm->proto == WPA_PROTO_RSN) {
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
|
||||
key_rsc = null_rsc;
|
||||
} else {
|
||||
key_rsc = key->key_rsc;
|
||||
|
@ -1036,12 +1039,13 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
|||
if (rbuf == NULL)
|
||||
return -1;
|
||||
|
||||
reply->type = sm->proto == WPA_PROTO_RSN ?
|
||||
reply->type = (sm->proto == WPA_PROTO_RSN ||
|
||||
sm->proto == WPA_PROTO_OSEN) ?
|
||||
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
|
||||
key_info &= WPA_KEY_INFO_SECURE;
|
||||
key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
|
||||
WPA_PUT_BE16(reply->key_info, key_info);
|
||||
if (sm->proto == WPA_PROTO_RSN)
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
|
||||
WPA_PUT_BE16(reply->key_length, 0);
|
||||
else
|
||||
os_memcpy(reply->key_length, key->key_length, 2);
|
||||
|
@ -1323,12 +1327,13 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
|
|||
if (rbuf == NULL)
|
||||
return -1;
|
||||
|
||||
reply->type = sm->proto == WPA_PROTO_RSN ?
|
||||
reply->type = (sm->proto == WPA_PROTO_RSN ||
|
||||
sm->proto == WPA_PROTO_OSEN) ?
|
||||
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
|
||||
key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
|
||||
key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
|
||||
WPA_PUT_BE16(reply->key_info, key_info);
|
||||
if (sm->proto == WPA_PROTO_RSN)
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
|
||||
WPA_PUT_BE16(reply->key_length, 0);
|
||||
else
|
||||
os_memcpy(reply->key_length, key->key_length, 2);
|
||||
|
@ -1363,7 +1368,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
|
|||
key_info = WPA_GET_BE16(key->key_info);
|
||||
keydatalen = WPA_GET_BE16(key->key_data_length);
|
||||
|
||||
if (sm->proto == WPA_PROTO_RSN) {
|
||||
if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
|
||||
ret = wpa_supplicant_process_1_of_2_rsn(sm,
|
||||
(const u8 *) (key + 1),
|
||||
keydatalen, key_info,
|
||||
|
@ -1811,7 +1816,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
|||
}
|
||||
extra_len = WPA_GET_BE16(key->key_data_length);
|
||||
|
||||
if (sm->proto == WPA_PROTO_RSN &&
|
||||
if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
|
||||
(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
|
||||
if (wpa_supplicant_decrypt_key_data(sm, key, ver))
|
||||
goto out;
|
||||
|
@ -1865,7 +1870,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
|
|||
{
|
||||
switch (sm->key_mgmt) {
|
||||
case WPA_KEY_MGMT_IEEE8021X:
|
||||
return (sm->proto == WPA_PROTO_RSN ?
|
||||
return ((sm->proto == WPA_PROTO_RSN ||
|
||||
sm->proto == WPA_PROTO_OSEN) ?
|
||||
RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
|
||||
WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
case WPA_KEY_MGMT_PSK:
|
||||
|
|
Loading…
Reference in a new issue