You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> This repository is the `v0.3.0-alpha` research prototype described in the manuscript
17
+
> *"Proportional-Cost Per-Read Provenance: Making Continuous File Integrity Verification Affordable on Edge Hardware,"* submitted to IEEE Embedded Systems Letters.
10
18
11
-
Most integrity mechanisms verify once: at boot, at open, or when a page is first read from storage
12
-
(e.g. fs-verity, dm-verity, IMA). After that, the cached in-memory copy is trusted. Axiom re-verifies
13
-
the in-memory data on **every** read, so tampering that happens *after* the initial check (a memory bug,
14
-
DMA, a row-hammer flip) is caught on the next read.
19
+
A bare-metal `no_std` Rust kernel that enforces BLAKE3 file-integrity provenance on **every read** — not just at load time — and makes that affordable by verifying only the file blocks a read actually touches.
15
20
16
-
The naive way to do this — re-hash the whole file on every read — costs O(file size) per read and is
17
-
impractical on small devices. Axiom instead uses **block-level provenance**:
21
+
> *No data is better than faulty data.*
18
22
19
-
- A file is split into fixed 4 KiB blocks; each block has its own stored BLAKE3 leaf hash.
20
-
- A ranged read `read_range(offset, len)` maps to the blocks it overlaps and re-hashes **only those blocks**,
21
-
comparing each against its stored leaf in constant time. Per-read cost becomes O(bytes read), not O(file size).
22
-
- A **lazy Merkle root** over the block leaves gives a single 32-byte commitment to the file; a single-block
23
-
write updates one leaf and defers the root recomputation, so writes cost one block hash instead of a full rehash.
23
+
---
24
24
25
-
This is the affordability result: per-read verification cost stays flat regardless of file size (see Results).
25
+
## Why
26
26
27
-
## How it differs from fs-verity / IMA
27
+
Most integrity mechanisms verify **once**: at boot, at open, or when a page is first read from storage (fs-verity, dm-verity, IMA). After that, the cached in-memory copy is trusted. If something tampers with that cached page *after* the check — a memory bug, a DMA-capable peripheral, a row-hammer flip — every later read returns the corrupted bytes as authentic. This is a live class of attack (e.g. Dirty Pipe, Copy Fail).
28
28
29
-
fs-verity and IMA bind verification to the storage-access path — a page is checked when read from the device,
30
-
then trusted in the page cache. They do not re-verify the cached copy on subsequent reads. Axiom's check *is*
31
-
the read path, on every read, against per-block hashes. See Table II of the paper for the full comparison.
29
+
Axiom re-verifies the in-memory data on **every read**, so that tampering is caught on the next read. The naive way to do this — re-hash the whole file each read — costs *O(file size)* per read and is impractical on small devices. Axiom makes it affordable.
- A file is split into fixed **4 KiB blocks**; each block stores its own BLAKE3 leaf hash.
38
+
- A ranged read `read_range(offset, len)` maps to the blocks it overlaps and re-hashes **only those blocks**, comparing each against its stored leaf in constant time. Per-read cost becomes *O(bytes read)*, not *O(file size)*.
39
+
- A **lazy Merkle root** over the block leaves is a single 32-byte commitment to the file; a single-block write updates one leaf and defers the root recomputation, so a write costs one block hash instead of a full rehash.
40
+
41
+
Unlike out-of-band detectors that periodically re-scan files, Axiom enforces integrity **inline** on the read path — every read is verified before its bytes are returned, leaving no detection window.
42
+
43
+
## Results
44
+
45
+
Per-read **block-level verification is constant** regardless of file size — about **2.7 µs** (x86-64) and **3.65 µs** (ARM64) — while whole-file verification grows with size. Median wall-clock times on real hardware, from the `bench-native` harness:
Block-level verification is >640× cheaper (x86-64) and >1000× cheaper (ARM64) than whole-file at 4 MiB.
101
+
### Reproducing the benchmark numbers
94
102
95
-
Reproduce the real-hardware numbers:
103
+
`bench-native` is a `std` crate that lives inside this `no_std` kernel repo, so it inherits the kernel's bare-metal cargo config. **Build it outside the kernel tree:**
96
104
97
105
```bash
98
-
cdbench-native
99
-
cargo run --release # prints the whole-file vs block table for this CPU
cargo run --release # prints the whole-file vs block table + inline-vs-periodic comparison
100
108
```
101
109
102
-
Reproduce the in-kernel proportional ratio under emulation:
110
+
To reproduce the in-kernel proportional *ratio* under emulation, run `bench` in the booted shell (RDTSC size sweep). In-kernel cycle counts are emulated and used only to confirm the ratio; all millisecond figures above are from real hardware.
103
111
104
-
```
105
-
bench # in the booted shell; RDTSC, proportional-access size sweep
106
-
```
112
+
## Threat Model
107
113
108
-
**Note on QEMU:** in-kernel cycle counts are emulated and are used only to confirm the *ratio*
109
-
(block-flat vs whole-file-growing). All absolute millisecond figures above come from real hardware,
110
-
not emulation.
114
+
Assumes an adversary who can modify a file's in-memory bytes after they were validated, but cannot forge the stored provenance record (per-block leaves + root). Single-core, no DMA, no ring-0. Within this model, per-read verification **reduces** the TOCTOU window: bytes returned by `read()` are verified at the moment of return. It does **not** eliminate TOCTOU (corruption after a verified read is out of scope), nor address replay/splicing on persistent storage or hardware memory-integrity attacks.
111
115
112
116
## Limitations
113
117
114
-
- Boots under QEMU; UEFI bootloader for bare-metal boot is pending.
115
-
- Single-core; SMP and multi-core verification are future work.
118
+
- Boots under QEMU; a UEFI bootloader for bare-metal boot is pending.
119
+
- Single-core; SMP / multi-core verification is future work.
116
120
- BLAKE3 runs in portable mode in-kernel (no in-kernel SIMD yet); the native harness uses runtime SIMD.
117
-
- Real-hardware results use a consumer laptop and phone; a dedicated embedded SoC (e.g. Raspberry Pi)
118
-
measurement is the immediate next step.
119
-
120
-
## Threat Model
121
-
122
-
Assumes an adversary who can modify a file's in-memory bytes after they were validated, but cannot forge
123
-
the stored provenance record (per-block leaves + root); single-core, no DMA, no ring-0. Within this model,
124
-
per-read verification **reduces** the TOCTOU window: bytes returned by `read()` are verified at the moment
125
-
of return. It does **not** eliminate TOCTOU (corruption after a verified read is out of scope), nor address
126
-
replay/splicing on persistent storage or hardware memory-integrity attacks.
121
+
- Real-hardware results use a laptop and a phone; a dedicated embedded SoC (e.g. Raspberry Pi) measurement is the immediate next step.
0 commit comments