wifi-scripts: allow GCMP-256 for EHT stations

WPA3 Specification v3.5 2.5 item 10: "A STA that enables EHT or MLO
shall, in its Network Profile, allow GCMP-256 to be selected as a
pairwise cipher." setup_sta() wrote pairwise=CCMP for every RSN mode,
because parse_encryption() got no phy features in station mode.

Read the GCMP-256 support of the phy in supplicant.generate() for an
EHT htmode, and write pairwise=CCMP GCMP-256 for an RSN station when
the phy supports GCMP-256. An explicit cipher or gcmp256 0 is kept.
The GCMP-256 test moves to iface.phy_cipher_gcmp256(), which
hostapd.uc uses as well.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau committed 2026-10-08 09:50:39 +02:00
1 parent 17557a6692
commit 01494494ce
3 files changed
+24 -8

No files matched your search

@@ -14,8 +14,6 @@ import * as fs from 'fs';
const NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 33;
const NL80211_EXT_FEATURE_RADAR_BACKGROUND = 61;
const WLAN_CIPHER_SUITE_GCMP_256 = 0x000fac09;
let phy_features = {};
let phy_capabilities = {};
@@ -493,7 +491,7 @@ function device_capabilities(config) {
phy_features.ftm_responder = device_extended_features(phy.extended_features, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
phy_features.radar_background = device_extended_features(phy.extended_features, NL80211_EXT_FEATURE_RADAR_BACKGROUND);
phy_features.cipher_gcmp256 = WLAN_CIPHER_SUITE_GCMP_256 in (phy.cipher_suites ?? []);
phy_features.cipher_gcmp256 = iface.phy_cipher_gcmp256(phy);
}
function generate(config) {
@@ -3,6 +3,12 @@
import { append_value, log } from 'wifi.common';
import * as fs from 'fs';
const WLAN_CIPHER_SUITE_GCMP_256 = 0x000fac09;
export function phy_cipher_gcmp256(phy) {
return WLAN_CIPHER_SUITE_GCMP_256 in (phy?.cipher_suites ?? []);
};
/*
* The 6 GHz band allows WPA3 and OWE only (IEEE 802.11-2024 12.12.2,
* WPA3 Specification v3.5 11.2).
@@ -62,7 +62,7 @@ export function ratelist(rates) {
const sae_compat_re = /^sae-compat/;
function setup_sta(data, config) {
function setup_sta(data, config, phy_features) {
/* WPA3 Specification v3.5 2.4: no separate Compatibility Mode for STAs */
if (config.mode == 'sta' && config.encryption)
config.encryption = replace(config.encryption, sae_compat_re, 'sae-mixed');
@@ -71,11 +71,19 @@ function setup_sta(data, config) {
if (config.mode == 'sta')
config.encryption = iface.encryption_band(config.encryption, data.band);
/* WPA3 Specification v3.5 2.5 items 9 and 10 */
if (wildcard(data.htmode ?? '', 'EHT*'))
/* WPA3 Specification v3.5 2.5 items 9 and 10: "A STA that enables EHT
* or MLO shall, in its Network Profile, allow AKM suite selector
* 00-0F-AC:24" and "allow GCMP-256 to be selected as a pairwise cipher" */
let eht = wildcard(data.htmode ?? '', 'EHT*');
if (eht)
set_default(config, 'sae_ext_key', true);
let sta_gcmp256 = eht && config.mode == 'sta' && config.gcmp256 !== false &&
phy_features?.cipher_gcmp256;
iface.parse_encryption(config, data);
iface.parse_encryption(config, data, phy_features);
if (sta_gcmp256 && (config.wpa & 2) && config.wpa_pairwise == 'CCMP')
config.wpa_pairwise = 'CCMP GCMP-256';
if (config.auth_type in [ 'sae', 'owe', 'eap2', 'eap192', 'dpp' ])
config.ieee80211w = 2;
@@ -326,7 +334,11 @@ export function generate(config_list, data, interface) {
append_vars(interface.config, [ 'ctrl_interface', 'country', 'beacon_int', 'freq_list' ]);
setup_sta(data.config, interface.config);
let phy_features = {};
if (wildcard(data.config.htmode ?? '', 'EHT*'))
phy_features.cipher_gcmp256 = iface.phy_cipher_gcmp256(wiphy_info(data.phy));
setup_sta(data.config, interface.config, phy_features);
let file_name = `/var/run/wpa-supplicant-${interface.config.ifname}.conf`;
if (fs.stat(file_name))