]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: add support for EPPKE authentication protocol in non-AP STA mode
authorKavita Kavita <kavita.kavita@oss.qualcomm.com>
Wed, 14 Jan 2026 11:18:58 +0000 (16:48 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 14 Jan 2026 13:52:50 +0000 (14:52 +0100)
Add support for the Enhanced Privacy Protection Key Exchange (EPPKE)
authentication protocol in non-AP STA mode, as specified in
"IEEE P802.11bi/D3.0, 12.16.9".

EPPKE is an RSNA authentication protocol that operates using
Pre-Association Security Negotiation (PASN) procedures. It consists
of three Authentication frames with transaction sequence numbers 1, 2,
and 3. The first and third from the non-AP STA and the second from the
AP STA.

Extend mac80211 to process EPPKE Authentication frames during the
authentication phase. Currently, mac80211 processes only frames with
the expected transaction number. In the case of EPPKE, process the
Authentication frame from the AP only if the transaction number matches
the expected value, which is 2.

After receiving the final Authentication frame with transaction number 3
from the non-AP STA, it indicates that both the non-AP STA and the AP
confirm there are no issues with authentication. Since this is the final
confirmation frame to send out, mark the state as authenticated in
mac80211.

For EPPKE authentication, the Multi-Link element (MLE) must be included
in the Authentication frame body by userspace in case of MLO connection.
If the MLE is not present, reject the Authentication frame.

Signed-off-by: Kavita Kavita <kavita.kavita@oss.qualcomm.com>
Link: https://patch.msgid.link/20260114111900.2196941-8-kavita.kavita@oss.qualcomm.com
[remove a single stray space]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c

index 649ea9d2ae9bd88d6b5d21fde59e36620205ebbe..0a8875e0709b281dc0f77d1e16b6e01e0a9cd9a5 100644 (file)
@@ -430,7 +430,7 @@ struct ieee80211_mgd_auth_data {
 
        u8 ap_addr[ETH_ALEN] __aligned(2);
 
-       u16 sae_trans, sae_status;
+       u16 trans, status;
        size_t data_len;
        u8 data[];
 };
index 977303fdfd9feac18970536bcf01351a7e864686..0c31a0602ea97c4845d7cb93d6a9c19ecf9c9972 100644 (file)
@@ -4911,6 +4911,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        case WLAN_AUTH_FILS_SK:
        case WLAN_AUTH_FILS_SK_PFS:
        case WLAN_AUTH_FILS_PK:
+       case WLAN_AUTH_EPPKE:
                break;
        case WLAN_AUTH_SHARED_KEY:
                if (ifmgd->auth_data->expected_transaction != 4) {
@@ -8277,6 +8278,12 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
        if (WARN_ON_ONCE(!auth_data))
                return -EINVAL;
 
+       if (auth_data->algorithm == WLAN_AUTH_EPPKE &&
+           ieee80211_vif_is_mld(&sdata->vif) &&
+           !cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_MULTI_LINK,
+                                   auth_data->data, auth_data->data_len))
+               return -EINVAL;
+
        auth_data->tries++;
 
        if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -8305,9 +8312,12 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
        auth_data->expected_transaction = 2;
 
        if (auth_data->algorithm == WLAN_AUTH_SAE) {
-               trans = auth_data->sae_trans;
-               status = auth_data->sae_status;
+               trans = auth_data->trans;
+               status = auth_data->status;
                auth_data->expected_transaction = trans;
+       } else if (auth_data->algorithm == WLAN_AUTH_EPPKE) {
+               trans = auth_data->trans;
+               status = auth_data->status;
        }
 
        if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
@@ -9222,6 +9232,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        case NL80211_AUTHTYPE_FILS_PK:
                auth_alg = WLAN_AUTH_FILS_PK;
                break;
+       case NL80211_AUTHTYPE_EPPKE:
+               auth_alg = WLAN_AUTH_EPPKE;
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -9246,12 +9259,14 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        auth_data->link_id = req->link_id;
 
        if (req->auth_data_len >= 4) {
-               if (req->auth_type == NL80211_AUTHTYPE_SAE) {
+               if (req->auth_type == NL80211_AUTHTYPE_SAE ||
+                   req->auth_type == NL80211_AUTHTYPE_EPPKE) {
                        __le16 *pos = (__le16 *) req->auth_data;
 
-                       auth_data->sae_trans = le16_to_cpu(pos[0]);
-                       auth_data->sae_status = le16_to_cpu(pos[1]);
+                       auth_data->trans = le16_to_cpu(pos[0]);
+                       auth_data->status = le16_to_cpu(pos[1]);
                }
+
                memcpy(auth_data->data, req->auth_data + 4,
                       req->auth_data_len - 4);
                auth_data->data_len += req->auth_data_len - 4;
@@ -9302,7 +9317,11 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
         * out SAE Confirm.
         */
        if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE &&
-           auth_data->peer_confirmed && auth_data->sae_trans == 2)
+           auth_data->peer_confirmed && auth_data->trans == 2)
+               ieee80211_mark_sta_auth(sdata);
+
+       if (cont_auth && req->auth_type == NL80211_AUTHTYPE_EPPKE &&
+           auth_data->trans == 3)
                ieee80211_mark_sta_auth(sdata);
 
        if (ifmgd->associated) {