Step 43 of 56
Wi-Fi: pure Ada around three binary blobs
The one place the from-scratch claim has an asterisk — and the asterisk is smaller, and better fenced, than you would expect.
What is a blob and what is not
The radio's MAC and PHY are undocumented, so the driver runs Espressif's
closed libraries (libnet80211, libpp,
libphy, libcore). Everything around them is
Ada written against the embedded (Jorvik) runtime:
| Ours, in Ada | What it does |
|---|---|
.OS_Adapter, .RTOS |
Maps the blobs' RTOS calls onto Jorvik tasks — so FreeRTOS still never runs. |
.PHY | PHY/RF calibration, and persisting calibration data. |
.Supplicant | The WPA2-PSK 4-way handshake. |
.IP, .DHCP, .Net_Device |
A software TCP/IP stack presenting the radio as a Net_Device. |
.Interrupt, .Port, .Core_Shim |
The interrupt, timer and core glue the blobs expect. |
.Sniffer | Promiscuous-mode capture. |
The blobs are Apache-2.0 and fetched, not committed
— tools/fetch-wifi-blobs.sh pins them to exact upstream
commits and verifies each by sha256. So the repository still contains no opaque
vendor binary for Wi-Fi; you choose to download them.
The supplicant is ours, deliberately
The 4-way handshake is pure Ada: derive the PMK with PBKDF2-HMAC-SHA1, run the handshake (PTK via SHA1-PRF, MIC via HMAC-SHA1, GTK via AES key-unwrap), and reply with message 2 of 4.
That placement is the security-relevant part. Doing the handshake in Ada means your PSK and the derived keys never pass through blob code — the blob is handed an already-established association, not your passphrase. A driver that let the closed library do WPA2 would be trusting it with the one secret that matters.
Using it
type Auth_Mode is ...;
type AP_Record is record ... end record;
type AP_List is array (Positive range <>) of AP_Record;
procedure Initialize (...);
procedure Scan (...);
procedure Connect (...);
function Connected return Boolean;
function Current_Channel return Natural;
Not re-entrant. This package drives a single
radio and one caller — typically the environment task — owns it. Do
not call Scan and Connect from two tasks.
Connect returns as soon as the association is
started. The association and the 4-way handshake then run to completion
on the internal Wi-Fi task, so poll Connected to learn when the link
is actually up. Treating Connect's return as "we are on the network"
is the mistake to avoid.
The version-locked C structs stay in the body; the spec exposes clean Ada records, so a blob update cannot ripple into your code. Examples run scan, promiscuous sniffing, DNS, HTTP and full HTTPS over the radio.