mac80211: Beacon protection using the new BIGTK (STA)
This adds support for mac80211 to verify that received Beacon frames have a valid MME in station mode when a BIGTK is configured. Signed-off-by: Jouni Malinen <jouni@codeaurora.org> Link: https://lore.kernel.org/r/20200222132548.20835-6-jouni@codeaurora.org Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
0a3a84360b
commit
af2d14b01c
|
@ -983,7 +983,8 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
|
|||
if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
|
||||
return -1;
|
||||
|
||||
if (!ieee80211_is_robust_mgmt_frame(skb))
|
||||
if (!ieee80211_is_robust_mgmt_frame(skb) &&
|
||||
!ieee80211_is_beacon(hdr->frame_control))
|
||||
return -1; /* not a robust management frame */
|
||||
|
||||
mmie = (struct ieee80211_mmie *)
|
||||
|
@ -1868,6 +1869,41 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
return RX_CONTINUE;
|
||||
} /* ieee80211_rx_h_sta_process */
|
||||
|
||||
static struct ieee80211_key *
|
||||
ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx)
|
||||
{
|
||||
struct ieee80211_key *key = NULL;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
int idx2;
|
||||
|
||||
/* Make sure key gets set if either BIGTK key index is set so that
|
||||
* ieee80211_drop_unencrypted_mgmt() can properly drop both unprotected
|
||||
* Beacon frames and Beacon frames that claim to use another BIGTK key
|
||||
* index (i.e., a key that we do not have).
|
||||
*/
|
||||
|
||||
if (idx < 0) {
|
||||
idx = NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
|
||||
idx2 = idx + 1;
|
||||
} else {
|
||||
if (idx == NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
|
||||
idx2 = idx + 1;
|
||||
else
|
||||
idx2 = idx - 1;
|
||||
}
|
||||
|
||||
if (rx->sta)
|
||||
key = rcu_dereference(rx->sta->gtk[idx]);
|
||||
if (!key)
|
||||
key = rcu_dereference(sdata->keys[idx]);
|
||||
if (!key && rx->sta)
|
||||
key = rcu_dereference(rx->sta->gtk[idx2]);
|
||||
if (!key)
|
||||
key = rcu_dereference(sdata->keys[idx2]);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
|
@ -1885,17 +1921,18 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
/*
|
||||
* Key selection 101
|
||||
*
|
||||
* There are four types of keys:
|
||||
* There are five types of keys:
|
||||
* - GTK (group keys)
|
||||
* - IGTK (group keys for management frames)
|
||||
* - BIGTK (group keys for Beacon frames)
|
||||
* - PTK (pairwise keys)
|
||||
* - STK (station-to-station pairwise keys)
|
||||
*
|
||||
* When selecting a key, we have to distinguish between multicast
|
||||
* (including broadcast) and unicast frames, the latter can only
|
||||
* use PTKs and STKs while the former always use GTKs and IGTKs.
|
||||
* Unless, of course, actual WEP keys ("pre-RSNA") are used, then
|
||||
* unicast frames can also use key indices like GTKs. Hence, if we
|
||||
* use PTKs and STKs while the former always use GTKs, IGTKs, and
|
||||
* BIGTKs. Unless, of course, actual WEP keys ("pre-RSNA") are used,
|
||||
* then unicast frames can also use key indices like GTKs. Hence, if we
|
||||
* don't have a PTK/STK we check the key index for a WEP key.
|
||||
*
|
||||
* Note that in a regular BSS, multicast frames are sent by the
|
||||
|
@ -1939,6 +1976,20 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
/* Skip decryption if the frame is not protected. */
|
||||
if (!ieee80211_has_protected(fc))
|
||||
return RX_CONTINUE;
|
||||
} else if (mmie_keyidx >= 0 && ieee80211_is_beacon(fc)) {
|
||||
/* Broadcast/multicast robust management frame / BIP */
|
||||
if ((status->flag & RX_FLAG_DECRYPTED) &&
|
||||
(status->flag & RX_FLAG_IV_STRIPPED))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS ||
|
||||
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
|
||||
NUM_DEFAULT_BEACON_KEYS)
|
||||
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
|
||||
|
||||
rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx);
|
||||
if (!rx->key)
|
||||
return RX_CONTINUE; /* Beacon protection not in use */
|
||||
} else if (mmie_keyidx >= 0) {
|
||||
/* Broadcast/multicast robust management frame / BIP */
|
||||
if ((status->flag & RX_FLAG_DECRYPTED) &&
|
||||
|
@ -1968,11 +2019,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
int i;
|
||||
|
||||
if (ieee80211_is_mgmt(fc) &&
|
||||
is_multicast_ether_addr(hdr->addr1) &&
|
||||
(key = rcu_dereference(rx->sdata->default_mgmt_key)))
|
||||
rx->key = key;
|
||||
else {
|
||||
if (ieee80211_is_beacon(fc)) {
|
||||
key = ieee80211_rx_get_bigtk(rx, -1);
|
||||
} else if (ieee80211_is_mgmt(fc) &&
|
||||
is_multicast_ether_addr(hdr->addr1)) {
|
||||
key = rcu_dereference(rx->sdata->default_mgmt_key);
|
||||
} else {
|
||||
if (rx->sta) {
|
||||
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
|
||||
key = rcu_dereference(rx->sta->gtk[i]);
|
||||
|
@ -1987,9 +2039,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
rx->key = key;
|
||||
}
|
||||
if (key)
|
||||
rx->key = key;
|
||||
return RX_CONTINUE;
|
||||
} else {
|
||||
/*
|
||||
|
@ -2358,6 +2410,9 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
|
|||
rx->skb->len);
|
||||
return -EACCES;
|
||||
}
|
||||
if (unlikely(ieee80211_is_beacon(fc) && rx->key &&
|
||||
ieee80211_get_mmie_keyidx(rx->skb) < 0))
|
||||
return -EACCES;
|
||||
/*
|
||||
* When using MFP, Action frames are not allowed prior to
|
||||
* having configured keys.
|
||||
|
|
Loading…
Reference in New Issue