]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
wifi-scripts: ucode: default BIP cipher from wpa_pairwise
authorHauke Mehrtens <hauke@hauke-m.de>
Sun, 19 Apr 2026 14:50:37 +0000 (16:50 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 2 May 2026 18:34:22 +0000 (20:34 +0200)
The WPA3 and Wi-Fi Enhanced Open Deployment and Implementation Guide
v1.1 (Tables 4, 5, 6) requires the group-management cipher (BIP) to
match the mode and strength of the pairwise cipher: GCM-mode pairwise
ciphers pair with BIP-GMAC integrity, CCM-mode pairwise ciphers with
BIP-CMAC integrity.  The ucode pipeline hard-coded group_mgmt_cipher
to AES-128-CMAC (BIP-CMAC-128) regardless of the pairwise cipher,
except for the eap192 special case that already forced BIP-GMAC-256.
An EHT WPA3-Personal BSS therefore emitted wpa_pairwise=GCMP-256
alongside group_mgmt_cipher=AES-128-CMAC -- the integrity cipher two
steps weaker than the data cipher and a spec violation on EHT.

hostapd has a single group_mgmt_cipher knob, so the selected BIP has
to be compatible with every pairwise cipher in wpa_pairwise.  Picking
from the first token would mis-select on mixed lists -- e.g.
wpa_pairwise=\"GCMP-256 CCMP\" would yield BIP-GMAC-256, which a
CCMP-only STA cannot negotiate.

Walk the wpa_pairwise tokens and pick the BIP that matches the
weakest cipher present:

  CCMP / TKIP -> AES-128-CMAC (BIP-CMAC-128)
  CCMP-256    -> BIP-CMAC-256
  GCMP        -> BIP-GMAC-128
  GCMP-256    -> BIP-GMAC-256

Token matching uses fnmatch wildcards against a copy of wpa_pairwise
that is padded with leading and trailing spaces, so each token is
space-bounded regardless of its position in the list.

The RSN override pairwise lists are not consulted: in the only
caller that sets them (WPA3-Personal Compatibility Mode), Tables 6
and 7 require BIP-CMAC-128 across RSNE/RSNOE/RSNO2E even when the
override lists advertise GCMP-256, so wpa_pairwise=CCMP already
yields the correct BIP.

An explicit ieee80211w_mgmt_cipher UCI value still wins over the
derived default.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23009
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/ap.uc

index b2890ff6914454cc9adffb2ff60a8672436110c1..f9b676197e69f72a2156fb62c0779c2d25d5bacc 100644 (file)
@@ -418,6 +418,20 @@ function iface_roaming(config) {
        ]);
 }
 
+function default_group_mgmt_cipher(config) {
+       let p = ' ' + (config.wpa_pairwise ?? '') + ' ';
+
+       if (wildcard(p, '* CCMP *') || wildcard(p, '* TKIP *'))
+               return 'AES-128-CMAC';
+       if (wildcard(p, '* CCMP-256 *'))
+               return 'BIP-CMAC-256';
+       if (wildcard(p, '* GCMP *'))
+               return 'BIP-GMAC-128';
+       if (wildcard(p, '* GCMP-256 *'))
+               return 'BIP-GMAC-256';
+       return 'AES-128-CMAC';
+}
+
 function iface_mfp(config) {
        let override_mfp = config.rsn_override_mfp || config.rsn_override_mfp_2;
 
@@ -426,10 +440,7 @@ function iface_mfp(config) {
                return;
        }
 
-       if (config.auth_type == 'eap192')
-               config.group_mgmt_cipher = 'BIP-GMAC-256';
-       else
-               config.group_mgmt_cipher = config.ieee80211w_mgmt_cipher ?? 'AES-128-CMAC';
+       config.group_mgmt_cipher = config.ieee80211w_mgmt_cipher ?? default_group_mgmt_cipher(config);
 
        set_default(config, 'beacon_prot', 1);