auditor

An aarch64 constant-time memory access auditing tool.
git clone git://git.ppad.tech/auditor.git
Log | Files | Refs | README | LICENSE

commit 409a3ed8f7c3eab88eef8563a5ab4d8503b6da0f
parent e4464a0e0b0c43b655369ba77274188bbb1477d0
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 28 Feb 2026 16:19:20 +0400

meta: readme

Diffstat:
MREADME.md | 91+++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 56 insertions(+), 35 deletions(-)

diff --git a/README.md b/README.md @@ -2,28 +2,32 @@ ![](https://img.shields.io/badge/license-MIT-brightgreen) -A Haskell tool for static analysis of GHC-generated AArch64 assembly, -focused on constant-time auditing for cryptographic code. +A Haskell tool for static analysis of AArch64 assembly, focused on +constant-time auditing for cryptographic code. ## Overview ppad-auditor provides two analysis modes: -1. **Taint analysis** (default): Tracks how secret data flows through - registers and memory, flagging loads/stores where the address may - depend on secret values (cache timing side-channels). +1. **Taint analysis** (default): Tracks how secret data flows + through registers and memory, flagging loads/stores where the + address may depend on secret values (cache timing + side-channels). 2. **NCT scan** (`--scan-nct`): Identifies non-constant-time - instructions (variable-time division, conditional branches, etc.) - that may leak secrets through execution timing. + instructions (variable-time division, conditional branches, + etc.) that may leak secrets through execution timing. -The tool understands GHC's calling conventions, treating registers like -X19-X22 and SP as public pointers, and tracking taint propagation -through arithmetic, data movement, and function calls. +The tool is parameterised over a runtime configuration, so it can +adapt to different compilers and calling conventions. The default +runtime (`haskell`) understands GHC's STG calling conventions, +treating registers like X19-X22 and SP as public pointers. A +`generic` runtime is also available as a baseline for C, Rust, or +Go code. ## Taint Analysis -Basic usage: +Basic usage (defaults to Haskell/GHC runtime): ``` $ auditor -i input.s @@ -40,10 +44,25 @@ Memory accesses: 37 Violations: 2 ``` +### Runtime Selection + +Use `--runtime` to select the target runtime: + +``` +$ auditor -i input.s --runtime haskell # default +$ auditor -i input.s --runtime generic # C/Rust/Go baseline +``` + +The `haskell` runtime configures GHC's STG register conventions, +secondary stack tracking (X20), pointer untagging masks, and +runtime pattern filtering. The `generic` runtime uses only +hardware stack/frame pointers and zero registers as public roots, +with no secondary stack or untagging heuristics. + ### Inter-procedural Analysis -Use `-p` to enable inter-procedural analysis, which computes function -summaries and propagates taint across call boundaries: +Use `-p` to enable inter-procedural analysis, which computes +function summaries and propagates taint across call boundaries: ``` $ auditor -i input.s -p @@ -51,8 +70,8 @@ $ auditor -i input.s -p ### Taint Configuration -Seed specific registers or STG stack slots as secret using a JSON -config file: +Seed specific registers or secondary stack slots as secret using a +JSON config file: ```json { @@ -68,9 +87,10 @@ config file: - `secret`: Registers containing secret scalar values - `public`: Registers to mark as public -- `secret_pointee`: Registers that are public pointers to secret data - (loads through them produce secret values) -- `stg_secret` / `stg_public`: STG stack slot offsets (X20-relative) +- `secret_pointee`: Registers that are public pointers to secret + data (loads through them produce secret values) +- `stg_secret` / `stg_public`: Secondary stack slot offsets + (X20-relative when using the `haskell` runtime) Apply with: @@ -84,8 +104,9 @@ $ auditor -i input.s -p --taint-config config.json default) - `-q`: Quiet mode (violations only, no summary) - `-j`: JSON output format -- `--assume-stg-private`: Treat untracked STG stack slots as private - (default assumes they're public closure pointers) +- `--assume-secondary-private`: Treat untracked secondary stack + slots as private (default assumes they're public closure + pointers) ## NCT Scan @@ -108,21 +129,23 @@ Analyze a specific function and its callees: $ auditor -i input.s --scan-nct --symbol _my_func_info ``` -Or use human-readable z-encoded symbols: +Or use human-readable z-encoded symbols (Haskell runtime only): ``` -$ auditor -i input.s --scan-nct --zsymbol "pkg-1.0:Module.Name:function" +$ auditor -i input.s --scan-nct \ + --zsymbol "pkg-1.0:Module.Name:function" ``` -Use `-c` to show callers instead of callees (reverse reachability). +Use `-c` to show callers instead of callees (reverse +reachability). -### GHC Runtime Filtering +### Runtime Pattern Filtering -GHC runtime patterns (heap checks, stack checks, closure evaluation) -are hidden by default. Show them with: +Runtime-specific patterns (heap checks, stack checks, closure +evaluation) are hidden by default. Show them with: ``` -$ auditor -i input.s --scan-nct --show-ghc-runtime +$ auditor -i input.s --scan-nct --show-runtime-patterns ``` ## Utility Commands @@ -141,19 +164,17 @@ $ auditor -i input.s --list-symbols --filter "multiply" ## Limitations -- **Conservative analysis**: Unknown taint is treated as potentially - secret, which may cause over-reporting -- **GHC-specific**: Assumes GHC's STG calling convention and register - usage; may not work well with other compilers -- **No alias analysis**: Heap accesses use coarse tracking; complex - pointer aliasing may cause false positives/negatives +- **Conservative analysis**: Unknown taint is treated as + potentially secret, which may cause over-reporting +- **No alias analysis**: Heap accesses use coarse tracking; + complex pointer aliasing may cause false positives/negatives Manual review of flagged accesses is recommended. ## Development -Requires [Nix][nixos] with [flake][flake] support. Enter a development -shell: +Requires [Nix][nixos] with [flake][flake] support. Enter a +development shell: ``` $ nix develop