Fix cipher suite selector default value in RSNE for DMG
According to IEEE Std 802.11-2016, 9.4.2.25 when fields of an RSNE are not included, the default values are used. The cipher suite defaults were hardcoded to CCMP in the previous implementation, but the default is actually different for DMG: GCMP (per 9.4.2.25.2). It is not possible to find out from the RSNE if the network is non-DMG or DMG, so callers of wpa_parse_wpa_ie_rsn() need to handle this case based on context, which can be different for each caller. In order to fix this issue, add flags to the wpa_ie_data indicating whether pairwise/group ciphers were included in the RSNE. Callers can check these flags and fill in the appropriate ciphers. The wpa_parse_wpa_ie_rsn() function still initializes the ciphers to CCMP by default so existing callers will not break. This change also fixes some callers which need to handle the DMG network case. Signed-off-by: Lior David <liord@codeaurora.org>
This commit is contained in:
parent
239794018e
commit
2c129a1b71
9 changed files with 43 additions and 5 deletions
|
@ -305,6 +305,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||
return -1;
|
||||
}
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
hapd->iface->freq,
|
||||
ie, ielen,
|
||||
elems.mdie, elems.mdie_len,
|
||||
elems.owe_dh, elems.owe_dh_len);
|
||||
|
|
|
@ -1328,6 +1328,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
}
|
||||
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
hapd->iface->freq,
|
||||
elems.rsn_ie - 2, elems.rsn_ie_len + 2,
|
||||
elems.mdie, elems.mdie_len, NULL, 0);
|
||||
resp = wpa_res_to_status_code(res);
|
||||
|
@ -2700,6 +2701,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||
hapd->iface->freq,
|
||||
wpa_ie, wpa_ie_len,
|
||||
elems.mdie, elems.mdie_len,
|
||||
elems.owe_dh, elems.owe_dh_len);
|
||||
|
|
|
@ -318,7 +318,7 @@ enum {
|
|||
};
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_state_machine *sm, int freq,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *mdie, size_t mdie_len,
|
||||
const u8 *owe_dh, size_t owe_dh_len);
|
||||
|
|
|
@ -530,7 +530,7 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
|
|||
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_state_machine *sm, int freq,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
const u8 *mdie, size_t mdie_len,
|
||||
const u8 *owe_dh, size_t owe_dh_len)
|
||||
|
@ -560,6 +560,10 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
|
||||
if (version == WPA_PROTO_RSN) {
|
||||
res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
|
||||
if (!data.has_pairwise)
|
||||
data.pairwise_cipher = wpa_default_rsn_cipher(freq);
|
||||
if (!data.has_group)
|
||||
data.group_cipher = wpa_default_rsn_cipher(freq);
|
||||
|
||||
if (wpa_key_mgmt_ft(data.key_mgmt) && !mdie &&
|
||||
!wpa_key_mgmt_only_ft(data.key_mgmt)) {
|
||||
|
|
|
@ -1209,6 +1209,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
|||
left = rsn_ie_len - 6;
|
||||
|
||||
data->group_cipher = WPA_CIPHER_GTK_NOT_USED;
|
||||
data->has_group = 1;
|
||||
data->key_mgmt = WPA_KEY_MGMT_OSEN;
|
||||
data->proto = WPA_PROTO_OSEN;
|
||||
} else {
|
||||
|
@ -1230,6 +1231,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
|||
|
||||
if (left >= RSN_SELECTOR_LEN) {
|
||||
data->group_cipher = rsn_selector_to_bitfield(pos);
|
||||
data->has_group = 1;
|
||||
if (!wpa_cipher_valid_group(data->group_cipher)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: invalid group cipher 0x%x (%08x)",
|
||||
|
@ -1255,6 +1257,8 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
|||
"count %u left %u", __func__, count, left);
|
||||
return -4;
|
||||
}
|
||||
if (count)
|
||||
data->has_pairwise = 1;
|
||||
for (i = 0; i < count; i++) {
|
||||
data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
@ -1473,6 +1477,15 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
|
|||
}
|
||||
|
||||
|
||||
int wpa_default_rsn_cipher(int freq)
|
||||
{
|
||||
if (freq > 56160)
|
||||
return WPA_CIPHER_GCMP; /* DMG */
|
||||
|
||||
return WPA_CIPHER_CCMP;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
|
||||
/**
|
||||
|
|
|
@ -392,7 +392,9 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, const u8 *snonce,
|
|||
struct wpa_ie_data {
|
||||
int proto;
|
||||
int pairwise_cipher;
|
||||
int has_pairwise;
|
||||
int group_cipher;
|
||||
int has_group;
|
||||
int key_mgmt;
|
||||
int capabilities;
|
||||
size_t num_pmkid;
|
||||
|
@ -405,6 +407,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
|||
struct wpa_ie_data *data);
|
||||
int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
int wpa_default_rsn_cipher(int freq);
|
||||
|
||||
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
|
||||
u8 *pmkid, int akmp);
|
||||
|
|
|
@ -559,6 +559,10 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
|||
" skip RSN IE - parse failed");
|
||||
break;
|
||||
}
|
||||
if (!ie.has_pairwise)
|
||||
ie.pairwise_cipher = wpa_default_rsn_cipher(bss->freq);
|
||||
if (!ie.has_group)
|
||||
ie.group_cipher = wpa_default_rsn_cipher(bss->freq);
|
||||
|
||||
if (wep_ok &&
|
||||
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
|
||||
|
|
|
@ -459,7 +459,7 @@ static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn,
|
|||
}
|
||||
|
||||
/* TODO: get peer RSN IE with Probe Request */
|
||||
if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth,
|
||||
if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth, 0,
|
||||
(u8 *) "\x30\x14\x01\x00"
|
||||
"\x00\x0f\xac\x04"
|
||||
"\x01\x00\x00\x0f\xac\x04"
|
||||
|
|
|
@ -1189,6 +1189,18 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
|
||||
int freq)
|
||||
{
|
||||
if (!ie->has_group)
|
||||
ie->group_cipher = wpa_default_rsn_cipher(freq);
|
||||
if (!ie->has_pairwise)
|
||||
ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
|
||||
return (ie->group_cipher & ssid->group_cipher) &&
|
||||
(ie->pairwise_cipher & ssid->pairwise_cipher);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_supplicant_set_suites - Set authentication and encryption parameters
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
|
@ -1220,8 +1232,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
|
||||
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
|
||||
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
|
||||
(ie.group_cipher & ssid->group_cipher) &&
|
||||
(ie.pairwise_cipher & ssid->pairwise_cipher) &&
|
||||
matching_ciphers(ssid, &ie, bss->freq) &&
|
||||
(ie.key_mgmt & ssid->key_mgmt)) {
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
|
||||
proto = WPA_PROTO_RSN;
|
||||
|
|
Loading…
Reference in a new issue