1- This repository reflects the v0.3.0-alpha research prototype described in the submitted manuscript.
1+ This repository reflects the v0.3.0-alpha research prototype described in the submitted manuscript
2+ * "Proportional-Cost Per-Read Provenance: Making Continuous File Integrity Verification Affordable on Edge Hardware."*
23
34# Axiom OS
45
5- A bare-metal OS kernel in Rust enforcing BLAKE3 cryptographic
6- provenance on every file read — not just at load time .
6+ A bare-metal ` no_std ` Rust kernel that enforces BLAKE3 file-integrity provenance on ** every read ** —
7+ not just at load time — and makes that affordable by verifying only the file blocks a read actually touches .
78
89## Core Contribution
910
10- Every ` read() ` call unconditionally recomputes the BLAKE3 hash
11- and compares it against the stored provenance record before
12- returning data. There is no API to bypass this check. The
13- verification IS the read path .
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 .
1415
15- This differs architecturally from Linux IMA, which verifies
16- at file open/exec time only. A file modified in memory after
17- load is invisible to IMA but blocked by Axiom OS on the next
18- read.
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** :
18+
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.
24+
25+ This is the affordability result: per-read verification cost stays flat regardless of file size (see Results).
26+
27+ ## How it differs from fs-verity / IMA
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.
1932
2033## Architecture
2134
22- - ** Target:** x86_64 (primary) + ARM64 (QEMU virt)
23- - ** Language:** Rust (no_std, no libc)
24- - ** Lines :** ~ 3,200
25- - ** Release:** v0.3.0-alpha
35+ - ** Target:** x86_64 (primary) + ARM64 (QEMU ` virt ` )
36+ - ** Language:** Rust (` no_std ` , no libc)
37+ - ** Source :** ~ 3,600 lines across 36 files
38+ - ** Release:** v0.3.0-alpha (research prototype)
2639
27- ** Kernel subsystems:**
28- GDT/IDT, 8MB linked-list heap, priority scheduler,
29- per-process page tables (CR3 isolation), IPC message queues,
30- ATA PIO driver, syscall interface (INT 0x80), 28-command shell
40+ ** Kernel subsystems:** GDT/IDT, 8 MB linked-list heap, priority scheduler, per-process page tables
41+ (CR3 isolation), IPC message queues, ATA PIO driver, syscall interface (INT 0x80), interactive shell.
3142
3243** Provenance layer:**
33- - VFS: per-read BLAKE3 verify, constant_time_eq comparison
34- - FAT32: 32-byte hash store at sector 1, full 256-bit comparison
35- - Mitra DSL: ` trusted_data ` type routes through kernel read path
44+ - ` vfs.rs ` — per-block BLAKE3 leaves, ` read_range ` /` verify_range ` (verify only touched blocks),
45+ ` write_block ` + lazy ` merkle_root ` , ` constant_time_eq ` comparison.
46+ - ` provenance.rs ` — ` provenance_hash ` (BLAKE3) and constant-time comparison primitive.
47+ - ` fat32.rs ` — on-disk hash store for the persistent path.
48+ - ` mitra/ ` — small DSL whose ` trusted_data ` type routes through the verified read path.
3649
3750## Quick Start
3851
@@ -43,66 +56,80 @@ rustup target add aarch64-unknown-none
4356cargo install bootimage
4457sudo apt install qemu-system-x86 qemu-system-arm nasm
4558
46- # Boot x86_64
59+ # Boot x86_64 (use the bin target; plain `cargo build` also tries the ARM bin)
4760cargo run --bin axiom_os
4861
4962# Boot ARM64
5063./run_arm.sh
5164```
5265
53- ## Tamper Detection Demo
54-
55- trust secret hello world
56-
57- cat secret # returns: hello world
58-
59- tamper secret # flips byte in memory
66+ ## Tamper-Detection Demo
6067
61- cat secret # READ BLOCKED: provenance violation
68+ Inside the booted shell:
6269
63- ## Benchmarks
70+ ```
71+ trust secret hello world # store a file + its provenance
72+ cat secret # -> hello world
73+ tamper secret # flip a byte in memory
74+ cat secret # -> READ BLOCKED: provenance violation
75+ ```
6476
65- RDTSC bare-metal x86_64, 5 independent cold-boot runs:
77+ ## Results
6678
67- | Operation | Mean cycles/op | CV | Latency @ 3GHz |
68- | --- | --- | --- | --- |
69- | BLAKE3 hash | 424,013 | 2.9% | 0.141ms |
70- | VFS read+verify | 2,153,973 | 3.0% | 0.718ms |
79+ The headline result is ** proportional access ** : block-level verification cost is constant ( ~ 3.6 µs)
80+ across file sizes, while whole-file verification grows with size. Numbers below are ** median wall-clock
81+ times on real hardware ** (a commodity x86-64 laptop and a mobile-class ARM64 core), produced by the
82+ standalone ` bench-native ` harness:
7183
72- BLAKE3 constitutes 19.7% of total read+verify overhead.
84+ | File size | Blocks | x86-64 whole (ms) | x86-64 block (ms) | ARM64 whole (ms) | ARM64 block (ms) |
85+ | ---| ---| ---| ---| ---| ---|
86+ | 4 KiB | 1 | 0.0040 | 0.0037 | 0.0037 | 0.0037 |
87+ | 16 KiB | 4 | 0.0097 | 0.0033 | 0.0143 | 0.0037 |
88+ | 64 KiB | 16 | 0.046 | 0.0035 | 0.057 | 0.0037 |
89+ | 256 KiB | 64 | 0.159 | 0.0037 | 0.230 | 0.0037 |
90+ | 1 MiB | 256 | 0.580 | 0.0035 | 0.923 | 0.0037 |
91+ | 4 MiB | 1024 | 2.51 | 0.0039 | 3.74 | 0.0037 |
7392
74- ## Mitra DSL
93+ Block-level verification is >640× cheaper (x86-64) and >1000× cheaper (ARM64) than whole-file at 4 MiB.
7594
76- Domain-specific language with kernel-enforced provenance :
95+ Reproduce the real-hardware numbers :
7796
78- trusted_data secret = classified report
97+ ``` bash
98+ cd bench-native
99+ cargo run --release # prints the whole-file vs block table for this CPU
100+ ```
79101
80- verify secret → KERNEL VERIFIED
102+ Reproduce the in-kernel proportional ratio under emulation:
81103
82- [ tamper]
104+ ```
105+ bench # in the booted shell; RDTSC, proportional-access size sweep
106+ ```
83107
84- verify secret → KERNEL BLOCKED
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.
85111
86- ## Known Limitations
112+ ## Limitations
87113
88- - QEMU only — UEFI bootloader pending (v0.3.0)
89- - Single-core — SMP planned
90- - In-memory VFS — persistence via ATA only
91- - Pure Rust BLAKE3 — SIMD (NEON/AVX-512) pending
92- - ARM64 cycle benchmarks invalid on QEMU (CNTVCT_EL0)
114+ - Boots under QEMU; UEFI bootloader for bare-metal boot is pending.
115+ - Single-core; SMP and multi-core verification are future work.
116+ - 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.
93119
94120## Threat Model
95121
96- Defends against post-write in-memory tampering by ring-3
97- processes within a single-core, non-DMA execution model.
98- Does not defend against ring-0 compromise, DMA attacks,
99- multicore races, or speculative execution side channels.
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.
100127
101128## Paper
102129
103- Under review. Data and full methodology available upon
104- acceptance .
130+ - Earlier formulation (whole-file per-read, equity framing): Zenodo, Apr. 2026,
131+ [ doi:10.5281/zenodo.19387932 ] ( https://doi.org/10.5281/zenodo.19387932 ) .
105132
106133## License
107134
108- MIT, Apache-2.0
135+ MIT and Apache-2.0
0 commit comments