mirror of
https://github.com/ruvnet/RuView.git
synced 2026-09-01 13:07:25 +00:00
feat(privshield): E2E hardware program — validated C core + multi-provider firmware scaffolds
Take VEIL from the synthetic Rust reference model toward real WiFi silicon
across multiple hardware providers, around one shared, host-validated core.
Answers the questions "can OpenWRT / open WiFi software implement this?" and
"can ESP32 help scramble signals?" with an honest per-platform feasibility map.
Portable C shield core (firmware/privshield/core/) — VALIDATED (host test):
- veil_shield.{h,c}: keyed Givens-rotation obfuscation of the identity-bearing
"fine" subspace, C99, no malloc / no libc I/O, only <math.h>. SplitMix64 key
schedule byte-identical to the Rust crate, so on-air behavior is consistent
everywhere and every adapter links the same math.
- make test passes: energy conservation (orthogonal => "not jamming"),
reversibility (recover inverts apply), wrong-key-fails, and PRNG stream parity
with the Rust crate. This is build/host evidence, NOT silicon.
Per-provider adapters (all SYNTHETIC / L0, build-only, TODO(hw) markers):
- openwifi/ grade B (ceiling A, effort D): only open PHY/MAC (FPGA) that can
host the full keyed rotation + inverse; needs new HDL + 2nd TX chain. Carries
the P5 measurement protocol (MEASUREMENT.md) for the first MEASURED result.
- openwrt/ grade C: per-packet keyed unitary is blob-blocked on commodity APs;
coarse compliant knobs (TX antenna map, sounding-cadence jitter) reachable
from userspace/hostapd; ath9k is the one credible driver-patch route.
- nexmon/ grade C: reading the compressed-BF angles is solved (nexmon_csi /
Wi-BFI); shaping the transmitted report is research-grade (D11 ucode-adjacent).
- esp32/ grade F (self) / B (supporting): cannot shape its own BF feedback
(closed esp-phy-lib blob); legitimate as a sensing detector and external-RIS
controller — the honest way ESP32 "helps scramble", via an external surface.
Docs:
- firmware/privshield/README.md: architecture, layout, and the feasibility matrix.
- ADR-290: the E2E hardware program, PROOF discipline, and per-provider decision;
added to docs/adr/README.md index.
Compliant waveform controls only, never jamming. No adapter has run on silicon;
no MEASURED claim is made (that is roadmap P5, gated on a captured log).
Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01WEXNqzs7UsfNFBcP5yW21p
This commit is contained in:
116
firmware/privshield/nexmon/BUILD.md
Normal file
116
firmware/privshield/nexmon/BUILD.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Building the VEIL Nexmon patch — **UNTESTED**
|
||||
|
||||
> **This procedure has never been run.** It has not been built with the Nexmon
|
||||
> toolchain, not flashed, and not captured on air. Addresses/symbols in
|
||||
> `patch/veil_patch.c` are placeholders (one is intentionally invalid,
|
||||
> `0xDEAD0000`) so it will **not** produce a flashable image as-is. This file
|
||||
> documents *how it would build* so a hardware operator with real silicon can
|
||||
> take it forward. `SYNTHETIC / L0`, per CLAUDE.md.
|
||||
|
||||
## Prerequisites (host, not in this repo)
|
||||
|
||||
- A Linux host (Nexmon expects an x86_64 Ubuntu-like build host) with the
|
||||
Broadcom-flavored ARM toolchain Nexmon downloads/uses, plus `git`, `make`,
|
||||
`gcc-arm-none-eabi`, `flex`, `bison`, `libisl`, `automake`.
|
||||
- Nexmon checked out **outside** this repo (do not vendor it here):
|
||||
```bash
|
||||
git clone https://github.com/seemoo-lab/nexmon.git
|
||||
cd nexmon
|
||||
source setup_env.sh # sets NEXMON_ROOT, toolchain paths
|
||||
make # builds libISL / firmwares tooling
|
||||
```
|
||||
- The target firmware blob present on the device: BCM43455c0
|
||||
(`brcmfmac43455-sdio.bin`), version **7_45_189** (Cypress) or 7_45_154
|
||||
(Raspbian). Do **not** commit the blob or any extracted symbols/ROM to RuView.
|
||||
|
||||
## Where this patch would live in the Nexmon tree
|
||||
|
||||
Nexmon builds per chip/firmware under `patches/<chip>/<fwver>/<name>/`. This
|
||||
adapter would be a Nexmon project, e.g.:
|
||||
|
||||
```
|
||||
$NEXMON_ROOT/patches/bcm43455c0/7_45_189/veil/
|
||||
├── Makefile # copy of an existing nexmon patch Makefile (e.g. nexmon_csi's)
|
||||
├── src/
|
||||
│ ├── veil_patch.c # <- symlink/copy of firmware/privshield/nexmon/patch/veil_patch.c
|
||||
│ ├── veil_shield.c # <- from firmware/privshield/core/ (compiled into the patch)
|
||||
│ └── veil_shield.h # <- from firmware/privshield/core/
|
||||
└── ...
|
||||
```
|
||||
|
||||
Keep the RuView copies canonical; the Nexmon tree gets copies/symlinks so the
|
||||
core stays byte-identical to `../core/`.
|
||||
|
||||
## Linking the portable core (MCU-friendly)
|
||||
|
||||
The core is `no_std`-style C99: no malloc, no libc I/O, only `<math.h>`
|
||||
(`sinf`/`cosf`/`sqrtf`/`sqrt`). To build it into the patch:
|
||||
|
||||
1. Add `veil_shield.c` to the patch `Makefile`'s object list (alongside
|
||||
`patch.o`/`wrapper.o`), so it compiles with the same ARM flags.
|
||||
2. Ensure the firmware provides `sinf`/`cosf`/`sqrtf`. **TODO(hw):** Broadcom
|
||||
firmware may not export libm. Options, in order of preference:
|
||||
- link a small `libm`/`compiler-rt` for `arm-none-eabi`;
|
||||
- or replace the trig with a fixed-point / CORDIC Givens rotation
|
||||
(`TODO(reverse-engineer)`), which also avoids float on parts without an FPU.
|
||||
3. All VEIL working storage is stack-bounded (`VEIL_MAX_FINE`, `CACHE` in the
|
||||
core) — no heap is introduced on-chip.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
cd $NEXMON_ROOT/patches/bcm43455c0/7_45_189/veil
|
||||
make # produces the patched brcmfmac43455-sdio.bin
|
||||
```
|
||||
|
||||
Before `make` can succeed you must first resolve every `TODO(reverse-engineer)`
|
||||
in `veil_patch.c`:
|
||||
|
||||
- replace `0xDEAD0000` and the `wlc_sendmgmt_veil_target` symbol with the real,
|
||||
disassembled target address/symbol for 7_45_189;
|
||||
- implement `veil_bfr_unpack_fine` / `veil_bfr_pack_fine` (the angle bit-field
|
||||
codec) and the report-body offset/length;
|
||||
- confirm the compressed-beamforming report is assembled in ARM on this chip
|
||||
(else move to hook candidate #2/#3 — see README).
|
||||
|
||||
## Flash (Raspberry Pi, on-device)
|
||||
|
||||
**TODO(hw) — untested.** Typical Nexmon flow on the Pi:
|
||||
|
||||
```bash
|
||||
# back up stock firmware first!
|
||||
sudo cp /lib/firmware/brcm/brcmfmac43455-sdio.bin ~/brcmfmac43455-sdio.bin.orig
|
||||
|
||||
sudo cp brcmfmac43455-sdio.bin /lib/firmware/brcm/brcmfmac43455-sdio.bin
|
||||
# (some setups also need the matching *.clm_blob / nexmon's own copy path)
|
||||
|
||||
sudo rmmod brcmfmac && sudo modprobe brcmfmac # reload driver with new firmware
|
||||
dmesg | tail # confirm firmware loaded
|
||||
```
|
||||
|
||||
Push the session key at runtime (matches the IOCTL stub in `veil_patch.c`):
|
||||
|
||||
```bash
|
||||
# TODO(hw): nexutil vendor-IOCTL id and payload format are placeholders
|
||||
nexutil -s<VEIL_IOCTL_SET_KEY> -b -l8 -v<base64-8-byte-key>
|
||||
```
|
||||
|
||||
**Recovery:** if WiFi breaks, restore the backup blob and reload the driver.
|
||||
A bad flashpatch offset can knock out WiFi until you reflash stock firmware.
|
||||
|
||||
## Validation you can honestly do (still not `MEASURED` firmware)
|
||||
|
||||
1. **Host unit test of the math** (already green in this repo):
|
||||
`cd ../../core && make test`.
|
||||
2. **Read-back on hardware** with `nexmon_csi`/Wi-BFI: capture the report with
|
||||
and without the patch and check the fine subspace changed while SNR/norm is
|
||||
preserved. This validates the transform end-to-end but is a *receiver*
|
||||
observation, not proof the TX hook is robust.
|
||||
3. Only a captured device runtime log showing the shaped report leaving *this*
|
||||
node, plus receiver-side recovery with the shared key, would move any claim
|
||||
from `SYNTHETIC`/`CLAIMED` toward `MEASURED` (roadmap P5).
|
||||
|
||||
## References
|
||||
|
||||
See `README.md` for sources (Nexmon, nexmon_csi, Wi-BFI, D11 reverse
|
||||
engineering).
|
||||
124
firmware/privshield/nexmon/README.md
Normal file
124
firmware/privshield/nexmon/README.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# VEIL protector — Nexmon (Broadcom/Cypress) path
|
||||
|
||||
C-firmware-patch adapter that would call the portable VEIL core
|
||||
(`../core/veil_shield.{h,c}`) on the compressed-beamforming-feedback **angles
|
||||
before transmission**, using the [Nexmon](https://github.com/seemoo-lab/nexmon)
|
||||
patching framework on a Broadcom/Cypress WiFi chip.
|
||||
|
||||
> **Evidence discipline.** Everything here is **`SYNTHETIC` / L0 / build-only**.
|
||||
> Nothing in this directory has been built with the Nexmon toolchain, flashed to
|
||||
> a chip, or captured on air. There are **no** `MEASURED` claims and **no**
|
||||
> hardware logs. The patch is an honest **skeleton** with `TODO(hw)` and
|
||||
> `TODO(reverse-engineer)` markers, not working firmware. Per CLAUDE.md, no
|
||||
> defense claim becomes `MEASURED` without a captured runtime log from real
|
||||
> silicon (roadmap P5).
|
||||
>
|
||||
> **Compliant waveform only — never jamming.** The core applies an *orthogonal*
|
||||
> (energy-preserving) keyed rotation to the node's *own* standards-conformant
|
||||
> feedback report. It does not add power, transmit out of turn, or interfere
|
||||
> with any other station.
|
||||
|
||||
## Feasibility grade: **C** (research-grade, partial, unproven)
|
||||
|
||||
| Sub-path | Grade | Why |
|
||||
|---|---|---|
|
||||
| **Read** the compressed BF feedback | **A** (proven by others) | `nexmon_csi` extracts CSI, and Wi-BFI parses the compressed-beamforming *angles* straight from captured action frames — no firmware change at all. The report content is observable today. |
|
||||
| **Write / shape** the transmitted report | **C / C-** | The report is generated by the proprietary **D11** real-time core, not the ARM firmware Nexmon comfortably patches. The hook point is deep, chip- and firmware-version-specific, and unverified here. Plausible, not demonstrated. |
|
||||
|
||||
Grade **C** reflects *this* deliverable's goal — shaping the **TX** report. The
|
||||
read side is a solved problem and is graded only to contrast honestly.
|
||||
|
||||
### Why the write path is hard (the core honesty point)
|
||||
|
||||
Broadcom/Cypress chips put all time-critical 802.11 MAC/PHY work on the **D11
|
||||
core**, a proprietary microcontroller running a programmable state machine
|
||||
("ucode"). Published reverse-engineering of these chips reports that the D11
|
||||
generates the **VHT/HE compressed beamforming report ~10 µs after the NDP**, with
|
||||
its contents fetched from an **internal memory updated directly by the hardware**
|
||||
on NDP reception. In other words, the angles VEIL wants to touch are staged and
|
||||
emitted inside the ucode/PHY path on a microsecond deadline — *below* the ARM
|
||||
"wl" driver firmware where Nexmon's C hooks (`__attribute__((at(addr, ...)))`
|
||||
flashpatches / branch hooks) live most reliably. Reaching them means either a
|
||||
D11-ucode patch (needs the D11 assembler and SHM/template-RAM layout) or catching
|
||||
the report while the ARM path still assembles the action-frame body — if it does
|
||||
so on this chip at all. Both are `TODO(reverse-engineer)`.
|
||||
|
||||
## Target chip(s)
|
||||
|
||||
Primary: **BCM43455c0** (Raspberry Pi 3B+/4B; also RPi Zero 2 W), firmware
|
||||
**7_45_154** (Raspbian) or **7_45_189** (Cypress) — the best-documented,
|
||||
most-reproducible Nexmon target, and one of the four chips `nexmon_csi` already
|
||||
supports. Secondary candidates that `nexmon_csi` also supports: **BCM4339**
|
||||
(Nexus 5), **BCM4358** (Nexus 6P), **BCM4366c0** (Asus RT-AC86U). We scope the
|
||||
skeleton to BCM43455c0 / 7_45_189 and leave the others as build-matrix `TODO`s.
|
||||
|
||||
Caveat: the RPi BCM43455c0 is an **802.11ac (VHT)** single-stream part; its own
|
||||
*transmit* beamforming/sounding activity as a beamformee is limited. The
|
||||
skeleton targets the **VHT compressed beamforming report** action-frame path;
|
||||
whether this chip emits enough to shape in practice is itself a `TODO(hw)`
|
||||
question.
|
||||
|
||||
## Hook-point candidates (all `TODO(reverse-engineer)`)
|
||||
|
||||
Ordered most-tractable → deepest. Addresses are **placeholders** — real offsets
|
||||
come from disassembling the specific firmware blob and cross-checking the Nexmon
|
||||
symbol tables (`wl_ram.elf` / IDA); none are known-good here.
|
||||
|
||||
1. **ARM action-frame TX assembly (best first target).** If the "wl" driver
|
||||
assembles the VHT Compressed Beamforming Report action-frame *body* in ARM
|
||||
firmware before handing it to the D11 (function family around
|
||||
`wlc_txbf_*` / a `wlc_send*mgmt`/action path), a branch hook there could
|
||||
locate the report's fine-angle block and call `veil_shield_apply` in place.
|
||||
Cheapest if it exists on this chip.
|
||||
2. **ARM → D11 TX descriptor / template handoff.** Hook where the driver stages
|
||||
a frame into the D11 TX FIFO / template RAM (`wlc_d11hdrs` / `wlc_txfifo`
|
||||
region) and rewrite the angle bytes there. Requires knowing the exact
|
||||
template-RAM offset of the report body.
|
||||
3. **D11 ucode patch (deepest).** Patch the ucode routine that copies angles
|
||||
from the hardware-updated internal memory into the outgoing report, applying
|
||||
the rotation in D11 SHM. Needs the D11 assembler and PHY/SHM map; highest
|
||||
fidelity, highest effort, most fragile across firmware versions.
|
||||
|
||||
The skeleton wires candidate **#1** and leaves #2/#3 documented but unimplemented.
|
||||
|
||||
## What is realistic
|
||||
|
||||
- **Realistic now:** verify VEIL's *effect* by reading — capture the shaped vs.
|
||||
unshaped report with `nexmon_csi`/Wi-BFI and confirm the fine subspace changed
|
||||
while energy (SNR/norm) is preserved. This validates the math, not the TX hook.
|
||||
- **Realistic with serious RE effort:** candidate #1, on one pinned firmware, as
|
||||
a demo — partial, brittle, chip-specific.
|
||||
- **Not realistic as a portable product:** a clean, firmware-version-stable TX
|
||||
report-shaping patch across Broadcom parts. Treat as research.
|
||||
|
||||
## Risk / honesty
|
||||
|
||||
- Wrong flashpatch offsets can **brick the WiFi blob** (recoverable by
|
||||
reflashing stock firmware, but real).
|
||||
- Regulatory: the transform is energy-preserving and rides standards-marked
|
||||
spatial-mapping freedom, but any TX-path firmware patch on a certified radio is
|
||||
**outside the device's certification** — bench/anechoic use only.
|
||||
- Firmware blobs are proprietary; do **not** commit extracted firmware, symbols,
|
||||
or ROM dumps to this repo.
|
||||
|
||||
## Sources
|
||||
|
||||
- Nexmon framework — <https://github.com/seemoo-lab/nexmon>
|
||||
- `nexmon_csi` (chips: bcm4339, bcm43455c0, bcm4358, bcm4366c0) —
|
||||
<https://github.com/seemoo-lab/nexmon_csi>
|
||||
- Wi-BFI (reads BFAs/BFI from captured compressed-beamforming action frames) —
|
||||
<https://github.com/kfoysalhaque/Wi-BFI>, paper arXiv:2309.04408
|
||||
<https://arxiv.org/abs/2309.04408>
|
||||
- BCM43455c0 patches / D11 headers (`d11.h`) —
|
||||
<https://github.com/seemoo-lab/nexmon/tree/master/patches/bcm43455c0>
|
||||
- D11 real-time core / ucode reverse engineering (SEEMOO, Quarkslab) —
|
||||
<https://www.seemoo.tu-darmstadt.de/> ,
|
||||
<https://blog.quarkslab.com/reverse-engineering-broadcom-wireless-chipsets.html>
|
||||
- 802.11ac VHT NDP sounding & compressed beamforming report structure (context) —
|
||||
<https://community.cisco.com/t5/wireless-mobility-knowledge-base/802-11ac-transmit-beamforming-and-vht-ndp-sounding-procedure/ta-p/3155879>
|
||||
|
||||
> The "~10 µs / hardware-updated internal memory" characterization above is drawn
|
||||
> from published Broadcom D11 reverse-engineering (reported for BCM4365-class
|
||||
> parts) and is used here as design guidance; it is **not** independently
|
||||
> verified on BCM43455c0 in this repo. `TODO(reverse-engineer)`: confirm on the
|
||||
> target blob.
|
||||
176
firmware/privshield/nexmon/patch/veil_patch.c
Normal file
176
firmware/privshield/nexmon/patch/veil_patch.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/* SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
*
|
||||
* veil_patch.c — VEIL protector, Nexmon (Broadcom/Cypress) path.
|
||||
*
|
||||
* ============================ HONESTY BANNER ============================
|
||||
* SYNTHETIC / L0 / BUILD-ONLY. This file is an HONEST SKELETON in Nexmon
|
||||
* style. It has NOT been built with the Nexmon toolchain, NOT flashed to a
|
||||
* chip, and NOT captured on air. Every __attribute__((at(...))) address and
|
||||
* every firmware symbol below is a PLACEHOLDER. Do not treat this as working
|
||||
* firmware. See ../README.md for the feasibility grade (C, research-grade).
|
||||
*
|
||||
* Goal: call the portable VEIL core (../../core/veil_shield.c)
|
||||
* `veil_shield_apply()` on the compressed-beamforming-feedback FINE ANGLES in
|
||||
* the transmitted VHT/HE compressed beamforming report, so the identity-bearing
|
||||
* fine subspace is obfuscated by a keyed, ENERGY-PRESERVING (orthogonal)
|
||||
* Givens rotation before the frame leaves the radio. Compliant only, never
|
||||
* jamming: the transform preserves the report's L2 norm.
|
||||
*
|
||||
* Target: BCM43455c0 (Raspberry Pi 3B+/4B), firmware 7_45_189. Others TODO.
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#pragma NEXMON targetregion "patch"
|
||||
|
||||
#include <firmware_version.h> /* FW_VER_7_45_189, CHIP_VER_BCM43455c0 (Nexmon) */
|
||||
#include <patcher.h> /* BPatch / GPatch / __attribute__((at(...))) */
|
||||
#include <structs.h> /* struct sk_buff, struct wlc_info, etc. */
|
||||
#include <wrapper.h> /* Nexmon wrappers for ROM/firmware functions */
|
||||
|
||||
/* --- Portable VEIL core, linked/inlined for the MCU -------------------------
|
||||
* The core is pure C99: no malloc, no libc I/O, only <math.h> (sinf/cosf/sqrtf).
|
||||
* On the Nexmon ARM target we compile ../../core/veil_shield.c into this patch
|
||||
* object (see ../BUILD.md) and pull in only the declarations here. Everything
|
||||
* operates on a caller-provided fixed buffer — no dynamic allocation on-chip. */
|
||||
#include "veil_shield.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Configuration (compile-time; no on-chip allocation) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Max fine-angle count we will touch in one report. Sized for a VHT SU report
|
||||
* fine block; bound it so all working storage is on the stack, malloc-free. */
|
||||
#define VEIL_MAX_FINE 64u
|
||||
|
||||
/* Rotation passes — MUST match the associated receiver and the Rust reference
|
||||
* crate default so recover() inverts exactly. TODO(hw): confirm against the
|
||||
* receiver config actually deployed. */
|
||||
#define VEIL_PASSES 96u
|
||||
|
||||
/* Session key. TODO(hw): DO NOT hardcode a real key in flashed firmware. Inject
|
||||
* via nexutil IOCTL (see veil_ioctl_set_key stub) or a provisioning step; this
|
||||
* placeholder exists only so the skeleton type-checks. */
|
||||
static uint64_t g_veil_key = 0x0000000000000000ULL;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Bridge: decode angles -> rotate -> re-encode, in place */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
* TODO(reverse-engineer): The compressed beamforming report packs the phi/psi
|
||||
* angles as bit-fields whose widths depend on the codebook (VHT: (7,5) or (9,7);
|
||||
* HE differs) and on Nc/Nr. The bytes handed to us are NOT plain floats. This
|
||||
* bridge must:
|
||||
* (1) parse the fine-angle bit-fields from `report` into `fine[]` as floats
|
||||
* in the same units/order the receiver + Rust reference expect,
|
||||
* (2) call veil_shield_apply() on that flat vector,
|
||||
* (3) re-quantize and repack the rotated angles back into `report`,
|
||||
* preserving all coarse/header fields and the frame length.
|
||||
* Steps (1)/(3) are the real work and are UNIMPLEMENTED here.
|
||||
*/
|
||||
static void veil_shape_report_inplace(uint8_t *report, uint32_t report_len)
|
||||
{
|
||||
if (report == 0 || report_len == 0)
|
||||
return;
|
||||
|
||||
float fine[VEIL_MAX_FINE];
|
||||
uint32_t n = 0;
|
||||
|
||||
/* TODO(reverse-engineer): unpack fine-angle bit-fields -> fine[0..n) */
|
||||
/* n = veil_bfr_unpack_fine(report, report_len, fine, VEIL_MAX_FINE); */
|
||||
if (n < 2 || n > VEIL_MAX_FINE)
|
||||
return; /* nothing safely shapeable; leave frame untouched (fail-open) */
|
||||
|
||||
/* Orthogonal, energy-preserving, keyed. This is the ONLY validated step. */
|
||||
veil_shield_apply(fine, (size_t)n, g_veil_key, VEIL_PASSES);
|
||||
|
||||
/* TODO(reverse-engineer): repack fine[0..n) back into `report` bit-fields,
|
||||
* keeping report_len and all non-fine fields byte-identical. */
|
||||
/* veil_bfr_pack_fine(report, report_len, fine, n); */
|
||||
(void)report_len;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Hook candidate #1 (see README): ARM action-frame TX assembly */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
* We hook the point where the "wl" driver has assembled the VHT Compressed
|
||||
* Beamforming Report action frame in an sk_buff, just before it is queued to
|
||||
* the D11 for transmission, locate the report body, and shape it.
|
||||
*
|
||||
* TODO(reverse-engineer): the symbol/address below is a PLACEHOLDER. The real
|
||||
* target must be found by disassembling 7_45_189 (IDA + Nexmon's wl_ram.elf
|
||||
* symbol map) and confirming: (a) the report body is assembled in ARM (not
|
||||
* only in D11 ucode), (b) `p` really carries a compressed-beamforming action
|
||||
* frame, and (c) the offset of the report body within the frame.
|
||||
*
|
||||
* If (a) is false on this chip, candidate #1 is dead and we fall to #2/#3
|
||||
* (TX template-RAM rewrite / D11 ucode patch) — both documented in README,
|
||||
* neither implemented here.
|
||||
*/
|
||||
|
||||
/* Original firmware function prototype (PLACEHOLDER signature). */
|
||||
extern int wlc_sendmgmt_veil_target(struct wlc_info *wlc, void *p, void *scb);
|
||||
|
||||
/* Our replacement. GPatch/BPatch below redirects the target to this. */
|
||||
int wlc_sendmgmt_veil_hook(struct wlc_info *wlc, void *p, void *scb)
|
||||
{
|
||||
/* TODO(reverse-engineer): confirm `p` is a struct sk_buff* and that this
|
||||
* frame is a VHT/HE compressed beamforming action frame (category 21
|
||||
* VHT / 30 HE, action = Compressed Beamforming). Guard hard so we never
|
||||
* mangle unrelated management frames. */
|
||||
struct sk_buff *skb = (struct sk_buff *)p;
|
||||
if (skb != 0 /* && veil_is_bf_report_action(skb) */) {
|
||||
/* TODO(reverse-engineer): compute report body pointer + length from the
|
||||
* action-frame layout. PLACEHOLDER offsets: */
|
||||
uint8_t *report = 0; /* skb->data + VEIL_BFR_BODY_OFFSET; */
|
||||
uint32_t report_len = 0; /* skb->len - VEIL_BFR_BODY_OFFSET; */
|
||||
veil_shape_report_inplace(report, report_len);
|
||||
}
|
||||
|
||||
/* Always fall through to the real firmware routine so normal TX proceeds. */
|
||||
return wlc_sendmgmt_veil_target(wlc, p, scb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Redirect the firmware's mgmt/action TX routine to our hook.
|
||||
* PLACEHOLDER ADDRESS — 0xDEAD0000 is intentionally invalid so nobody mistakes
|
||||
* this for a real, flashable patch. TODO(reverse-engineer): replace with the
|
||||
* verified address for CHIP_VER_BCM43455c0 / FW_VER_7_45_189.
|
||||
*
|
||||
* Nexmon idiom: a branch patch that overwrites the target's prologue with a
|
||||
* branch to our replacement (which tail-calls the saved original).
|
||||
*/
|
||||
__attribute__((at(0xDEAD0000, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189)))
|
||||
BPatch(veil_sendmgmt_hook, wlc_sendmgmt_veil_hook);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Key provisioning via nexutil IOCTL (stub) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
* TODO(hw): register a custom IOCTL so `nexutil` can push the 64-bit session
|
||||
* key at runtime instead of baking it into flash. Hook the driver's ioctl
|
||||
* dispatch (wlc_ioctl) the same way nexmon_csi installs its config IOCTLs.
|
||||
* Left as a stub: the dispatch address and the nexmon_ioctl plumbing are
|
||||
* PLACEHOLDERS.
|
||||
*/
|
||||
#define VEIL_IOCTL_SET_KEY 0x7EIL /* TODO(hw): pick a free vendor IOCTL id */
|
||||
|
||||
int veil_ioctl_set_key(struct wlc_info *wlc, const uint8_t *buf, uint32_t len)
|
||||
{
|
||||
(void)wlc;
|
||||
if (buf == 0 || len < sizeof(uint64_t))
|
||||
return -1;
|
||||
uint64_t k = 0;
|
||||
for (uint32_t i = 0; i < sizeof(uint64_t); i++)
|
||||
k |= ((uint64_t)buf[i]) << (8u * i);
|
||||
g_veil_key = k;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------
|
||||
* Candidate #2 (TX template-RAM rewrite) and #3 (D11 ucode patch) are NOT
|
||||
* implemented. See ../README.md "Hook-point candidates". #3 would require the
|
||||
* D11 assembler and the PHY/SHM angle-staging map — deepest and most fragile.
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
Reference in New Issue
Block a user