Skip to content

A saved Wi-Fi network is joined by WPA2 or WPA3 as its passphrase allows, never by 802.1X, with protected management frames where offered - #326

Draft
DevomB wants to merge 1 commit into
mainfrom
wifi-key-management
Draft

DevomB wants to merge 1 commit into
mainfrom
wifi-key-management

Conversation

@DevomB

@DevomB DevomB commented Oct 9, 2026

Copy link
Copy Markdown
Owner

What was wrong

The network blocks kryptikd writes for kryptik wifi add named only ssid and psk. wpa_supplicant 2.12 then used its defaults (DEFAULT_KEY_MGMT in wpa_supplicant/config_ssid.h:21): WPA-PSK WPA-EAP, with no protected management frames. That meant:

  • EAP from a beacon. An access point that announced 802.1X under a saved SSID was joined with EAP, and its RADIUS side reached the supplicant's EAP state machine. The access point chose that, not the person who saved the network.
  • No WPA3. A WPA3 network (SAE only) was never joined. A transition-mode network was joined with WPA2's pre-shared key, whose handshake an observer can test passphrases against offline.
  • Spoofed deauthentication. Management frames went unprotected even where the access point offered protection, so a forged deauthentication always knocked the net zone off.

What changed

  • wifi.rs, the new form: each block names its key management from what was saved:
    • a passphrase: key_mgmt=WPA-PSK WPA-PSK-SHA256 SAE;
    • a raw 64-hex-digit key: key_mgmt=WPA-PSK WPA-PSK-SHA256 (SAE needs the passphrase);
    • in both: ieee80211w=1, protected management frames wherever the access point offers them (SAE always has them).
      No block names 802.1X.
  • wifi.rs, reading files back: the parser accepts those lines only exactly as kryptikd writes them for the block's psk. It also accepts a block with neither line, which is what an older kryptikd wrote. Anything else is refused, as before.
  • spawn.rs, upgrades: when the net zone starts, kryptikd rewrites such an older file once in today's form, through wifi::refresh, with the same 0400 owner. A current, absent or foreign file is left as it is.
  • Docs: a bullet in docs/design/net-zone.md's wireless section.

How the run proves it

  • Unit tests:
    • key_management_follows_what_was_saved checks the lines per psk form and that none names EAP. It also checks the refusals: SAE for a raw key, key_mgmt without ieee80211w and the reverse, WPA-EAP, and a second ieee80211w.
    • older_file_rewritten_with_key_management checks that an older file still reads, is rewritten 0400 once, is then left alone, and that a foreign file is not rewritten.
    • The round-trip test's expected text has the new lines.
  • Zones suite. The plain WPA2 access point stays as it was. Two new checks:
    • wifi-wpa2-plain: after the existing joins, the access point lists the station with AKM 00-0f-ac-2 and no [MFP]. A saved passphrase still joins WPA2 without protection where none is offered.
    • wifi-sae: the access point then offers the same SSID with key_mgmt=SAE and ieee80211w=2. Within 90 s it lists the station with AKM 00-0f-ac-8 and [MFP]. The old file's default key management has no SAE, so on the old code the station never joins and the check fails.

…ows, never by 802.1X, with protected management frames where offered

The network blocks kryptikd writes named no key management, so
wpa_supplicant took its default, WPA-PSK and WPA-EAP: an access point
offering 802.1X under a saved SSID was joined with EAP, a WPA3 network was
never joined with SAE, and management frames went unprotected, so spoofed
deauthentication always worked.

Each block now names what was saved allows: a passphrase WPA-PSK,
WPA-PSK-SHA256 and SAE, a raw key the first two (SAE needs the passphrase),
and ieee80211w=1, protection wherever the access point offers it. The parser
takes these lines only as kryptikd writes them for the block's psk, or a
block from an older kryptikd with neither, and the net zone's start rewrites
such a file once in today's form.

The zones suite keeps its plain WPA2 access point, where the station joins by
its pre-shared key without protection, then offers the same SSID with SAE
alone and protection required, which the old file never joins.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant