Repository navigation
Add 802.1X (WPA2-Enterprise) support for a userspace supplicant - #1075
Open
dantdmdarealguy wants to merge 2 commits into
Open
dantdmdarealguy wants to merge 2 commits into
dantdmdarealguy wants to merge 2 commits into
Conversation
selector == IOCTL_ID_MAX passed the bounds check and indexed one past the end of sMethods[], calling through whatever pointer followed (a NULL in practice, panicking the kernel). selector is unsigned, so the < 0 half of the check was dead code.
itlwm can't join WPA2-Enterprise networks today. This adds the minimum
kernel support for a userspace EAP supplicant (HeliPort) to do so. No
EAP, TLS or certificate handling is in the kext: it only moves EAPOL
frames and installs the PMK that userspace derives. The existing net80211
4-way handshake code is reused unchanged.
- For 802.1X AKMs, non-Key EAPOL frames (EAP-Packet/Start/Logoff) are
handed to itlwm through a global hook and queued in a small ring buffer
for userspace, instead of being dropped by ieee80211_eapol_key_input().
EAPOL-Key frames stay in the kernel. The hook gets the ieee80211com and
routes to the itlwm instance that owns it; an instance accepts frames
only between a successful start() and stop(). Only the itlwm build is
affected (not IO80211FAMILY_V2 / AirportItlwm). struct ieee80211com is
unchanged.
- New user-client calls, appended after the existing IDs:
- IOCTL_80211_ASSOCIATE_ENTERPRISE: join an SSID with WPA2, AKM 802.1X
and no PSK.
- IOCTL_80211_TX_EAPOL: transmit a userspace-built EAPOL frame. Needed
because the link stays down until the 4-way handshake and macOS drops
ordinary writes on a down interface. Only EtherType 0x888E accepted.
- IOCTL_80211_RX_EAPOL: fetch the next queued EAPOL frame.
- ID 13 is reserved and rejected: kexts without the bounds fix panic on
it, so new clients probe with RX_EAPOL instead.
- IOCTL_80211_WPA_KEY (previously a no-op stub) delivers the PMK, or a
failure status that deauths, after EAP. The PMK goes into the PMKSA
cache for the negotiated AKM, the same mechanism as OpenBSD's
SIOCS80211KEYAVAIL, so ieee80211_recv_4way_msg1() picks it up as-is.
It and ASSOCIATE_ENTERPRISE run on the driver's work loop, so they don't
race the receive path.
- externalMethod now also checks the input struct size per selector.
- ClientKit headers updated to match HeliPort's copy.
Tested on macOS 15.7.7 with an Intel Wireless-AC 9560 on a PEAP/MSCHAPv2
network (Texas A&M TAMU_WiFi): first connect, auto-join at login, and
reauthentication. PSK and open networks are unaffected.
This was referenced Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related: #101 (also asked in #230, #240), OpenIntelWireless/HeliPort#4, OpenIntelWireless/HeliPort#288
Includes the one-line fix from #1074 as its first commit; merge that first or together.
Summary
itlwm can't join WPA2-Enterprise networks today. This adds the minimum kernel
support needed for a userspace EAP supplicant (implemented in HeliPort, OpenIntelWireless/HeliPort#288) to do it.
In line with the concern raised in #101, the kext has no certificate handling, TLS
or EAP logic. It only moves EAPOL frames and installs the PMK that userspace
derives. The existing net80211 4-way handshake code is reused unchanged.
Changes
Start / Logoff) are handed to itlwm through a global hook
(
ieee80211_eapol_input). itlwm queues them in a small ring buffer (16 frames)for userspace. Previously
ieee80211_eapol_key_input()dropped them. EAPOL-Keyframes stay in the kernel for the 4-way handshake.
struct ieee80211comis unchanged, so the HAL softcs that embed it keep theirlayout. The hook gets the
ieee80211comand finds the owning itlwm instancefrom its interface.
start()andstop().mbuf_copydata(), so chained mbufs are handled.IO80211FAMILY_V2) is untouched.IOCTL_80211_ASSOCIATE_ENTERPRISE: join an SSID with RSN, AKM 802.1X and no PSK.IOCTL_80211_TX_EAPOL: transmit an EAPOL frame built in userspace. It's neededbecause the interface link stays down until the 4-way handshake completes, and
macOS drops ordinary writes on a down interface. Only EtherType 0x888E is
accepted.
IOCTL_80211_RX_EAPOL: fetch the next queued frame. It returns length 0 whenthe queue is empty.
Clients detect support by calling
RX_EAPOL; older kexts reject that selectorsafely.
IOCTL_80211_WPA_KEYwas a no-op stub. It now delivers the PMK after EAP, or afailure status, which deauths.
OpenBSD's
SIOCS80211KEYAVAIL, soieee80211_recv_4way_msg1()picks it upas-is.
state machine aren't changed while the receive path is using them. So does
ASSOCIATE_ENTERPRISE.externalMethod()checks the input/output size against each selector'sstruct before the handler casts the buffer.
SHA256-802.1X / 802.11w).
ClientKitheaders updated to match HeliPort's copy.Prebuilt binaries
Until this is merged, an unofficial prebuilt
itlwm.kext+HeliPort.appbuilt from these PRs is on my fork's releases page: https://github.com/dantdmdarealguy/itlwm/releases. The two only work together, and only with itlwm (not AirportItlwm).Testing
TAMU_WiFi(PEAP / MSCHAPv2):EAPOL-Start).
itlwmandAirportItlwm (all)(Debug), plusitlwmRelease.
Known limitations
TAMU_WiFi, the AP ran a second full EAP exchange about 3 s later. Bothsucceeded, but connectivity dropped for about 1.4 s.
ieee80211_recv_4way_msg1()rejects.