HS 2.0R2: Add OSEN client implementation

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-07-23 21:24:05 +03:00 committed by Jouni Malinen
parent a5d75636f9
commit df0f01d91f
6 changed files with 137 additions and 11 deletions

View file

@ -89,7 +89,10 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
int key_info, ver; int key_info, ver;
u8 bssid[ETH_ALEN], *rbuf; u8 bssid[ETH_ALEN], *rbuf;
if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) if (sm->key_mgmt == WPA_KEY_MGMT_OSEN)
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
wpa_key_mgmt_sha256(sm->key_mgmt))
ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
@ -1480,7 +1483,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
return -1; return -1;
} }
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
u8 *buf; u8 *buf;
if (keydatalen % 8) { if (keydatalen % 8) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@ -1662,13 +1666,22 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Unsupported EAPOL-Key descriptor version %d", "WPA: Unsupported EAPOL-Key descriptor version %d",
ver); ver);
goto out; goto out;
} }
if (sm->key_mgmt == WPA_KEY_MGMT_OSEN &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"OSEN: Unsupported EAPOL-Key descriptor version %d",
ver);
goto out;
}
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt)) { if (wpa_key_mgmt_ft(sm->key_mgmt)) {
/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
@ -1681,7 +1694,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_IEEE80211W
if (wpa_key_mgmt_sha256(sm->key_mgmt)) { if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: AP did not use the " "WPA: AP did not use the "
"negotiated AES-128-CMAC"); "negotiated AES-128-CMAC");

View file

@ -222,6 +222,64 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
} }
#ifdef CONFIG_HS20
static int wpa_gen_wpa_ie_osen(u8 *wpa_ie, size_t wpa_ie_len,
int pairwise_cipher, int group_cipher,
int key_mgmt)
{
u8 *pos, *len;
u32 suite;
if (wpa_ie_len < 2 + 4 + RSN_SELECTOR_LEN +
2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN)
return -1;
pos = wpa_ie;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
len = pos++; /* to be filled */
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
*pos++ = HS20_OSEN_OUI_TYPE;
/* Group Data Cipher Suite */
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
if (suite == 0) {
wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
group_cipher);
return -1;
}
RSN_SELECTOR_PUT(pos, suite);
pos += RSN_SELECTOR_LEN;
/* Pairwise Cipher Suite Count and List */
WPA_PUT_LE16(pos, 1);
pos += 2;
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
if (suite == 0 ||
(!wpa_cipher_valid_pairwise(pairwise_cipher) &&
pairwise_cipher != WPA_CIPHER_NONE)) {
wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
pairwise_cipher);
return -1;
}
RSN_SELECTOR_PUT(pos, suite);
pos += RSN_SELECTOR_LEN;
/* AKM Suite Count and List */
WPA_PUT_LE16(pos, 1);
pos += 2;
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
pos += RSN_SELECTOR_LEN;
*len = pos - len - 1;
WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
return pos - wpa_ie;
}
#endif /* CONFIG_HS20 */
/** /**
* wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
* @sm: Pointer to WPA state machine data from wpa_sm_init() * @sm: Pointer to WPA state machine data from wpa_sm_init()
@ -237,6 +295,13 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
sm->group_cipher, sm->group_cipher,
sm->key_mgmt, sm->mgmt_group_cipher, sm->key_mgmt, sm->mgmt_group_cipher,
sm); sm);
#ifdef CONFIG_HS20
else if (sm->proto == WPA_PROTO_OSEN)
return wpa_gen_wpa_ie_osen(wpa_ie, wpa_ie_len,
sm->pairwise_cipher,
sm->group_cipher,
sm->key_mgmt);
#endif /* CONFIG_HS20 */
else else
return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
sm->pairwise_cipher, sm->pairwise_cipher,

View file

@ -405,6 +405,8 @@ static int wpa_config_parse_proto(const struct parse_data *data,
else if (os_strcmp(start, "RSN") == 0 || else if (os_strcmp(start, "RSN") == 0 ||
os_strcmp(start, "WPA2") == 0) os_strcmp(start, "WPA2") == 0)
val |= WPA_PROTO_RSN; val |= WPA_PROTO_RSN;
else if (os_strcmp(start, "OSEN") == 0)
val |= WPA_PROTO_OSEN;
else { else {
wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
line, start); line, start);
@ -516,6 +518,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
else if (os_strcmp(start, "FT-SAE") == 0) else if (os_strcmp(start, "FT-SAE") == 0)
val |= WPA_KEY_MGMT_FT_SAE; val |= WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#ifdef CONFIG_HS20
else if (os_strcmp(start, "OSEN") == 0)
val |= WPA_KEY_MGMT_OSEN;
#endif /* CONFIG_HS20 */
else { else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start); line, start);

View file

@ -398,6 +398,9 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
if (wpa_key_mgmt_wpa(ssid->key_mgmt)) if (wpa_key_mgmt_wpa(ssid->key_mgmt))
privacy = 1; privacy = 1;
if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)
privacy = 1;
if (bss->caps & IEEE80211_CAP_PRIVACY) if (bss->caps & IEEE80211_CAP_PRIVACY)
return privacy; return privacy;
return !privacy; return !privacy;
@ -539,6 +542,12 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
return 0; return 0;
} }
if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) &&
wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) {
wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN");
return 1;
}
if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) { if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2"); wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
return 1; return 1;
@ -736,6 +745,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
struct wpa_blacklist *e; struct wpa_blacklist *e;
const u8 *ie; const u8 *ie;
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
int osen;
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0; wpa_ie_len = ie ? ie[1] : 0;
@ -743,14 +753,18 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
rsn_ie_len = ie ? ie[1] : 0; rsn_ie_len = ie ? ie[1] : 0;
ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
osen = ie != NULL;
wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s", "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s%s",
i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
wpa_ie_len, rsn_ie_len, bss->caps, bss->level, wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "", wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "",
(wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ? wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ?
" p2p" : ""); " p2p" : "",
osen ? " osen=1" : "");
e = wpa_blacklist_get(wpa_s, bss->bssid); e = wpa_blacklist_get(wpa_s, bss->bssid);
if (e) { if (e) {
@ -848,7 +862,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
continue; continue;
if (!wpa && if (!osen && !wpa &&
!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) {
@ -863,6 +877,12 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
continue; continue;
} }
if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-OSEN network "
"not allowed");
continue;
}
if (!wpa_supplicant_match_privacy(bss, ssid)) { if (!wpa_supplicant_match_privacy(bss, ssid)) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy " wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy "
"mismatch"); "mismatch");

View file

@ -757,6 +757,10 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
params.wpa_proto = WPA_PROTO_WPA; params.wpa_proto = WPA_PROTO_WPA;
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
elems.wpa_ie_len + 2); elems.wpa_ie_len + 2);
} else if (elems.osen) {
params.wpa_proto = WPA_PROTO_OSEN;
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
elems.osen_len + 2);
} else } else
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)

View file

@ -937,13 +937,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
{ {
struct wpa_ie_data ie; struct wpa_ie_data ie;
int sel, proto; int sel, proto;
const u8 *bss_wpa, *bss_rsn; const u8 *bss_wpa, *bss_rsn, *bss_osen;
if (bss) { if (bss) {
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
} else } else
bss_wpa = bss_rsn = NULL; bss_wpa = bss_rsn = bss_osen = NULL;
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) && if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 && wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
@ -959,11 +960,22 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
(ie.key_mgmt & ssid->key_mgmt)) { (ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA; proto = WPA_PROTO_WPA;
#ifdef CONFIG_HS20
} else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
/* TODO: parse OSEN element */
ie.group_cipher = WPA_CIPHER_CCMP;
ie.pairwise_cipher = WPA_CIPHER_CCMP;
ie.key_mgmt = WPA_KEY_MGMT_OSEN;
proto = WPA_PROTO_OSEN;
#endif /* CONFIG_HS20 */
} else if (bss) { } else if (bss) {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN"); wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
return -1; return -1;
} else { } else {
if (ssid->proto & WPA_PROTO_RSN) if (ssid->proto & WPA_PROTO_OSEN)
proto = WPA_PROTO_OSEN;
else if (ssid->proto & WPA_PROTO_RSN)
proto = WPA_PROTO_RSN; proto = WPA_PROTO_RSN;
else else
proto = WPA_PROTO_WPA; proto = WPA_PROTO_WPA;
@ -996,7 +1008,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_s->wpa_proto = proto; wpa_s->wpa_proto = proto;
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
!!(ssid->proto & WPA_PROTO_RSN)); !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
if (bss || !wpa_s->ap_ies_from_associnfo) { if (bss || !wpa_s->ap_ies_from_associnfo) {
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa, if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
@ -1067,6 +1079,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
} else if (sel & WPA_KEY_MGMT_WPA_NONE) { } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE; wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE"); wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
#ifdef CONFIG_HS20
} else if (sel & WPA_KEY_MGMT_OSEN) {
wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
#endif /* CONFIG_HS20 */
} else { } else {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
"authenticated key management type"); "authenticated key management type");