Currently, mac80211 does not encrypt or decrypt (Re)Association frames
(Request and Response) because temporal keys are not yet available at
that stage.
With extensions from IEEE P802.11bi, e.g. EPPKE, temporal keys can be
established before association. This enables the encryption and
decryption of (Re)Association Request/Response frames.
Add support to unset the IEEE80211_TX_INTFL_DONT_ENCRYPT flag when
the peer is marked as an Enhanced Privacy Protection (EPP) peer and
encryption keys are available for the connection in non-AP STA mode,
allowing secure transmission of (Re)Association Request frames.
Drop unprotected (Re)Association Request/Response frames received from
an EPP peer.
Co-developed-by: Sai Pratyusha Magam <quic_smagam@quicinc.com>
Signed-off-by: Sai Pratyusha Magam <quic_smagam@quicinc.com>
Signed-off-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Link: https://patch.msgid.link/20260114111900.2196941-9-kavita.kavita@oss.qualcomm.com
[remove useless parentheses]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
struct sk_buff *skb, int tid, int link_id,
enum nl80211_band band);
+static inline bool ieee80211_require_encrypted_assoc(__le16 fc,
+ struct sta_info *sta)
+{
+ return (sta && sta->sta.epp_peer &&
+ (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc) ||
+ ieee80211_is_assoc_resp(fc) || ieee80211_is_reassoc_resp(fc)));
+}
+
/* sta_out needs to be checked for ERR_PTR() before using */
int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct ieee80211_prep_tx_info info = {};
unsigned int link_id, n_links = 0;
u16 present_elems[PRESENT_ELEMS_MAX] = {};
+ struct sta_info *sta;
+ bool assoc_encrypt;
void *capab_pos;
size_t size;
int ret;
info.link_id = assoc_data->assoc_link_id;
drv_mgd_prepare_tx(local, sdata, &info);
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ sta = sta_info_get_bss(sdata, sdata->vif.cfg.ap_addr);
+
+ assoc_encrypt = sta && sta->sta.epp_peer &&
+ wiphy_dereference(sdata->local->hw.wiphy,
+ sta->ptk[sta->ptk_idx]);
+
+ if (!assoc_encrypt)
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_INTFL_MLME_CONN_TX;
(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))
return RX_DROP_U_UNPROT_ROBUST_ACTION;
+ /*
+ * Drop unprotected (Re)Association Request/Response frame received from
+ * an EPP Peer.
+ */
+ if (!ieee80211_has_protected(fc) &&
+ ieee80211_require_encrypted_assoc(fc, rx->sta))
+ return RX_DROP_U_UNPROT_UCAST_MGMT;
+
return RX_CONTINUE;
}
EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee80211_drop_unencrypted_mgmt);
if (!ieee80211_is_data_present(hdr->frame_control) &&
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
tx->skb) &&
- !ieee80211_is_group_privacy_action(tx->skb))
+ !ieee80211_is_group_privacy_action(tx->skb) &&
+ !ieee80211_require_encrypted_assoc(hdr->frame_control,
+ tx->sta))
tx->key = NULL;
else
skip_hw = (tx->key->conf.flags &
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (!ieee80211_is_data(hdr->frame_control) &&
- !ieee80211_is_robust_mgmt_frame(skb))
+ !ieee80211_is_robust_mgmt_frame(skb) &&
+ !ieee80211_require_encrypted_assoc(hdr->frame_control, rx->sta))
return RX_CONTINUE;
if (status->flag & RX_FLAG_DECRYPTED) {
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (!ieee80211_is_data(hdr->frame_control) &&
- !ieee80211_is_robust_mgmt_frame(skb))
+ !ieee80211_is_robust_mgmt_frame(skb) &&
+ !ieee80211_require_encrypted_assoc(hdr->frame_control, rx->sta))
return RX_CONTINUE;
if (status->flag & RX_FLAG_DECRYPTED) {