Files
MontaukOS/tests/wifi/supplicant_harness.cpp
T

95 lines
3.4 KiB
C++

// Host harness: drives the real kernel supplicant through a 4-way handshake.
// Frames come in / go out as hex on stdio so an independent Python AP can be
// the oracle.
#include <cstdio>
#include <cstring>
#include <cstdint>
#include <string>
#include <iostream>
#include "Drivers/Net/Wifi/Wpa.hpp"
#include "Drivers/Net/Wifi/Ieee80211.hpp"
namespace Timekeeping { static uint64_t g_ms = 0; uint64_t GetMilliseconds() { return g_ms; } }
using namespace Drivers::Net::Wifi;
static void puthex(const char* tag, const uint8_t* p, size_t n) {
printf("%s ", tag);
for (size_t i = 0; i < n; i++) printf("%02x", p[i]);
printf("\n");
}
// --- hooks the supplicant calls back into ---
namespace Drivers::Net::Wifi {
bool WpaTxEapol(const uint8_t* body, uint32_t len) {
puthex("TX", body, len);
return true;
}
bool WpaInstallPtk(const uint8_t* tk, uint32_t tkLen, uint8_t cipher) {
printf("PTK-CIPHER %u\n", cipher);
puthex("PTK", tk, tkLen);
return true;
}
bool WpaInstallGtk(const uint8_t* gtk, uint32_t gtkLen, uint8_t keyIdx,
uint8_t cipher, const uint8_t* rsc) {
printf("GTK-IDX %u\nGTK-CIPHER %u\n", keyIdx, cipher);
puthex("GTK", gtk, gtkLen);
puthex("GTK-RSC", rsc, 8);
return true;
}
}
static int unhex(const std::string& s, uint8_t* out) {
int n = 0;
for (size_t i = 0; i + 1 < s.size(); i += 2) {
unsigned v; sscanf(s.c_str() + i, "%2x", &v); out[n++] = (uint8_t)v;
}
return n;
}
int main() {
std::string line;
uint8_t buf[2048];
while (std::getline(std::cin, line)) {
if (line.rfind("START ", 0) == 0) {
// START <ownmac> <bssid> <ssid> <passphrase> <akm> <pcipher> <gcipher>
char own[64], bss[64], ssid[64], pass[128];
unsigned akm, pc, gc;
sscanf(line.c_str(), "START %63s %63s %63s %127s %u %u %u",
own, bss, ssid, pass, &akm, &pc, &gc);
WpaConfig cfg = {};
unhex(own, cfg.OwnMac);
unhex(bss, cfg.Bssid);
cfg.SsidLen = (uint8_t)strlen(ssid);
memcpy(cfg.Ssid, ssid, cfg.SsidLen);
cfg.PassLen = (uint8_t)strlen(pass);
memcpy(cfg.Passphrase, pass, cfg.PassLen);
cfg.Akm = (uint8_t)akm;
cfg.PairwiseCipher = (uint8_t)pc;
cfg.GroupCipher = (uint8_t)gc;
printf("START-OK %d\n", WpaStart(cfg) ? 1 : 0);
uint8_t ie[64];
uint32_t ieLen = WpaBuildRsnIe(ie, sizeof(ie));
puthex("RSNIE", ie, ieLen);
} else if (line.rfind("RX ", 0) == 0) {
int n = unhex(line.substr(3), buf);
bool consumed = WpaOnEapol(buf, (uint32_t)n);
printf("RX-OK %d STATE %d\n", consumed ? 1 : 0, (int)WpaGetState());
} else if (line.rfind("PARSE ", 0) == 0) {
int n = unhex(line.substr(6), buf);
WpaConfig cfg = {};
bool ok = WpaParseApRsn(buf, (uint32_t)n, cfg);
printf("PARSE-OK %d AKM %u PCIPHER %u GCIPHER %u\n", ok ? 1 : 0,
(unsigned)cfg.Akm, (unsigned)cfg.PairwiseCipher,
(unsigned)cfg.GroupCipher);
} else if (line.rfind("STATE", 0) == 0) {
printf("STATE %d\n", (int)WpaGetState());
} else if (line.rfind("QUIT", 0) == 0) {
break;
}
fflush(stdout);
}
return 0;
}