AlphaProof Code: Verifying Signal’s Security at the Machine-Code Level

Paper › arm64-semantics/ProofLib/Hoare › MultiCodeROHook.leanTier 3 · arm64-semantics

MultiCodeROHook.lean🔗

Tier 3 · arm64-semantics used by the symbolic proof 2 headline theorems depend on it 69 of 1,153 lines trusted source ↗

Trusted, reviewed with the engine. The AArch64 model in arm64-semantics is Tier 3: it is reviewed in its own repository (check-trust-guards). The declarations that the headline statements use are shown for completeness.

Read-Only Multi-Block Subroutine Hooks

Lifts verified Obj.MultiPlacedLib subroutines to state-transformer hooks (HookOk) backed by read-only byte-slice ownership lib.codeRO mpl (↦ᵣ) in spec.pre, without requiring PermsRX, CodeLoaded s0.mem, or SepProp.NoRO. Defines the multi-block overlay and restoration primitives loadMultiCodeMem and restoreMultiCodeMem, the induced hook codeROSubroutineHook, and the lifting theorems subroutineHook_ok_of_multiCodeRO_at, subroutineHook_ok_of_multiCodeRO_framed, and subroutineHook_ok_of_multiCodeRO.

@[expose] public section

def Arm64.Obj.MultiPlacedLib.blockPatchedL29–32 ↗#

Relocated byte sequence of block k of lib under placement mpl.

def Arm64.Obj.MultiPlacedLib.blockPatched (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (k : Nat) : List (BitVec 8) := (lib.blockLib k).text.patched (lib.blockPlacement mpl k)

def Arm64.Obj.MultiPlacedLib.findCodeBlockL34–40 ↗#

First block index k < lib.blocks.length whose relocated code region under mpl contains a (none if a lies outside all code blocks of lib). Under lib.Placeable mpl, block regions are pairwise disjoint so at most one block contains a.

def Arm64.Obj.MultiPlacedLib.findCodeBlock (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (a : BitVec 64) : Option Nat := (List.range lib.blocks.length).find? fun k => decide (Arm64.InRegion (mpl.base k) (lib.blockPatched mpl k).length a)

def Arm64.loadMultiCodeMemL42–58 ↗#

Overlay all blocks k < lib.blocks.length of lib with some Perm.rx and their relocated code bytes lib.blockPatched mpl k in m, leaving all addresses outside lib's blocks unchanged.

def Arm64.loadMultiCodeMem (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (m : Arm64.Memory) : Arm64.Memory := ⟨fun a => match h : lib.findCodeBlock mpl a with | some k => have hf : (List.range lib.blocks.length).find? (fun j => decide (Arm64.InRegion (mpl.base j) (lib.blockPatched mpl j).length a)) = some k := h have hd := List.find?_some hf have hin : Arm64.InRegion (mpl.base k) (lib.blockPatched mpl k).length a := of_decide_eq_true hd some (some { Arm64.Perm.rx with anon := m.isAnon a }, (lib.blockPatched mpl k)[(a - mpl.base k).toNat]'hin) | none => m.cells a⟩

def Arm64.restoreMultiCodeMemL60–67 ↗#

Restore m0.cells across all code blocks of lib under mpl, keeping mf.cells outside lib's code blocks.

def Arm64.restoreMultiCodeMem (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (m0 mf : Arm64.Memory) : Arm64.Memory := ⟨fun a => match lib.findCodeBlock mpl a with | some _ => m0.cells a | none => mf.cells a⟩

def Arm64.multiCodeROHookEntryL69–74 ↗#

Entry state for running block i of lib at entry_pc under mpl: sets lr := mpl.base i + 1, pc := entry_pc, and overlays all blocks of lib via loadMultiCodeMem.

def Arm64.multiCodeROHookEntry (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (i : Nat) (entry_pc : BitVec 64) (s0 : Arm64.State) : Arm64.State := ((s0.writeReg64 .lr (mpl.base i + 1#64)).setPC entry_pc).setMem (Arm64.loadMultiCodeMem lib mpl s0.mem)

def Arm64.multiCodeROHookExitL76–82 ↗#

Exit state restoring caller lr, return pc (when sf' stopped at the sentinel mpl.base i + 1), and code-block memory cells via restoreMultiCodeMem.

def Arm64.multiCodeROHookExit (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (i : Nat) (s0 sf' : Arm64.State) : Arm64.State := let lr0 := s0.readReg64 .lr let sf1 := if sf'.pc = mpl.base i + 1#64 ∧ sf'.status = .Running then sf'.setPC lr0 else sf' (sf1.writeReg64 .lr lr0).setMem (Arm64.restoreMultiCodeMem lib mpl s0.mem sf'.mem)

def Arm64.Obj.MultiPlacedLib.codeROSubroutineHookL84–104 ↗#

State-transformer hook (State → State) induced by exported subroutine fnName of lib under placement mpl, overlaying all blocks via loadMultiCodeMem on entry and restoring caller code-block cells via restoreMultiCodeMem on exit so lib.codeRO mpl (↦ᵣ) suffices in spec.pre without PermsRX or CodeLoaded s0.mem.

open Classical in noncomputable def Arm64.Obj.MultiPlacedLib.codeROSubroutineHook (lib : Arm64.Obj.MultiPlacedLib) (mpl : Arm64.Obj.MultiPlacement) (fnName : String) (externs : String → Option (Arm64.State → Arm64.State) := fun _ => none) (overrides : String → Option (Arm64.State → Arm64.State) := fun _ => none) (svc : Arm64.State → Arm64.State := Arm64.Syscall.standard) : Arm64.State → Arm64.State := match Arm64.Obj.lookupBlockSym fnName lib.blocks with | some (i, _) => fun s0 => let prog := lib.blockProgram mpl i externs overrides svc let s0' := Arm64.multiCodeROHookEntry lib mpl i (lib.fnAddr mpl fnName) s0 if h : ∃ sf', Arm64.StepsUntil prog (Arm64.SubroutineStop s0') s0' sf' ∧ Arm64.SubroutineStop s0' sf' then Arm64.multiCodeROHookExit lib mpl i s0 (Classical.choose h) else s0 | none => id
69 declarations not shown (lines 106–1151): theorems, which Lean checks, or definitions that no headline statement uses

Arm64.multiCodeROSubroutineHook, Arm64.Spec.codeROMultiSubroutineHook, Arm64.Obj.MultiPlacedLib.codeROSubroutineHookSpec, ProofLib.multiCodeROHookEntry_pc, ProofLib.multiCodeROHookEntry_sp, ProofLib.multiCodeROHookEntry_spAligned, ProofLib.multiCodeROHookEntry_status, ProofLib.multiCodeROHookEntry_mem, ProofLib.multiCodeROHookEntry_tpidrEl0, ProofLib.multiCodeROHookEntry_brk, ProofLib.multiCodeROHookEntry_brkStart, ProofLib.multiCodeROHookEntry_fs, ProofLib.multiCodeROHookEntry_trace, ProofLib.multiCodeROHookEntry_symtab, ProofLib.multiCodeROHookEntry_sigActions, ProofLib.multiCodeROHookEntry_physMemAvail, ProofLib.multiCodeROHookEntry_oracle, ProofLib.multiCodeROHookEntry_oracleIdx, ProofLib.multiCodeROHookEntry_readReg64_lr, ProofLib.multiCodeROHookEntry_readReg64, ProofLib.calleeSavedVRegs_multiCodeROHookEntry, ProofLib.multiCodeROHookExit_mem, ProofLib.multiCodeROHookExit_sp, ProofLib.multiCodeROHookExit_status, ProofLib.multiCodeROHookExit_tpidrEl0, ProofLib.multiCodeROHookExit_brk, ProofLib.multiCodeROHookExit_brkStart, ProofLib.multiCodeROHookExit_fs, ProofLib.multiCodeROHookExit_trace, ProofLib.multiCodeROHookExit_symtab, ProofLib.multiCodeROHookExit_sigActions, ProofLib.multiCodeROHookExit_physMemAvail, ProofLib.multiCodeROHookExit_oracle, ProofLib.multiCodeROHookExit_oracleIdx, ProofLib.multiCodeROHookExit_readReg64_lr, ProofLib.multiCodeROHookExit_readReg64, ProofLib.calleeSavedVRegs_multiCodeROHookExit, ProofLib.multiCodeROHookExit_returned, ProofLib.multiCodeROHookExit_cc, ProofLib.blockPatched_length_of_placeable, _private.0.ProofLib.toNat_bounds_of_inRegion, ProofLib.inRegion_blockPatched_unique, ProofLib.findCodeBlock_lt, ProofLib.findCodeBlock_inRegion, ProofLib.findCodeBlock_eq_some_of_inRegion, ProofLib.findCodeBlock_eq_none_iff, ProofLib.loadMultiCodeMem_cells_some, ProofLib.loadMultiCodeMem_cells_none, ProofLib.restoreMultiCodeMem_cells_some, ProofLib.restoreMultiCodeMem_cells_none, _private.0.ProofLib.read8_eq_of_cells_eq, _private.0.ProofLib.perm_eq_of_cells_eq, _private.0.ProofLib.isLazyFree_eq_of_cells_eq, _private.0.ProofLib.isAnon_eq_of_cells_eq, ProofLib.codeLoaded_loadMultiCodeMem, ProofLib.keepsFrozen_restoreMultiCodeMem, _private.0.ProofLib.read8_of_readBytes_inRegion, _private.0.ProofLib.blockCodeRO_holds_phys, _private.0.ProofLib.sepAll_blockCodeRO_holds_phys, ProofLib.codeRO_holds_phys_some, …