feat: wi-fi - join WPA2/WPA3-PSK networks and carry traffic like ethernet
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user