aboutsummaryrefslogtreecommitdiffstats
path: root/fw/verify_gcp_loggates_fault.py
diff options
context:
space:
mode:
authoruser <user@clank>2026-10-09 16:11:31 +0200
committeruser <user@clank>2026-10-09 16:11:31 +0200
commitbc43149d914325e15dc0490dee9d982e21287623 (patch)
treea632cf70de742d5a60d01c9c0d806bf5b9257538 /fw/verify_gcp_loggates_fault.py
parentGCP->ASD 0x403: ASD-internal chain PROVEN end-to-end in emulator (real handlers) (diff)
downloadamd-psp-re-main.tar.gz
amd-psp-re-main.tar.xz
amd-psp-re-main.zip
Record PSP security investigation artifacts and probesHEADmain
Diffstat (limited to 'fw/verify_gcp_loggates_fault.py')
-rw-r--r--fw/verify_gcp_loggates_fault.py43
1 files changed, 43 insertions, 0 deletions
diff --git a/fw/verify_gcp_loggates_fault.py b/fw/verify_gcp_loggates_fault.py
new file mode 100644
index 0000000..05a376e
--- /dev/null
+++ b/fw/verify_gcp_loggates_fault.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+"""Offline check of preserved log-gate fault frame against signed GCP .77.
+
+No hardware access. This identifies word2 as the faulting instruction; word0
+is a known build-specific constant, not the program counter of this fault.
+"""
+from pathlib import Path
+import struct
+
+from capstone import CS_ARCH_ARM, CS_MODE_ARM, Cs
+
+ELF = Path(__file__).resolve().parents[1] / 'psp_out/versions_win/elf_all/gcp_22.0.0.77_7c426e7f.elf'
+FRAME = (0x4055D8, 0x25031016, 0x4011D8, 0x867, 0x42CFA0, 0, 0x8DA7463D)
+
+
+def file_offset(image: bytes, va: int) -> int:
+ assert image[:6] == b'\x7fELF\x01\x01'
+ phoff = struct.unpack_from('<I', image, 28)[0]
+ size, count = struct.unpack_from('<HH', image, 42)
+ for i in range(count):
+ typ, off, base, _, length, _, flags, _ = struct.unpack_from(
+ '<8I', image, phoff + size * i)
+ if typ == 1 and flags & 1 and base <= va < base + length:
+ return off + va - base
+ raise ValueError(f'VA 0x{va:x} is not in an executable file-backed PT_LOAD')
+
+
+def main() -> None:
+ image = ELF.read_bytes()
+ pc, fsr, far = FRAME[2:5]
+ off = file_offset(image, pc)
+ ins = next(Cs(CS_ARCH_ARM, CS_MODE_ARM).disasm(image[off:off+4], pc, count=1))
+ assert (ins.address, ins.mnemonic, ins.op_str) == (
+ pc, 'stmmi', 'r0!, {r3, r4}'), (hex(ins.address), ins.mnemonic, ins.op_str)
+ status = (fsr & 0xf) | (((fsr >> 10) & 1) << 4)
+ assert status == 7 and fsr & (1 << 11) and far == 0x42CFA0
+ print(f'word2=0x{pc:08x}: {ins.mnemonic} {ins.op_str}; '
+ f'DFSR FS={status} (translation), write=1, FAR=0x{far:08x}')
+ print(f'word0=0x{FRAME[0]:08x}: build constant, NOT this faulting PC')
+
+
+if __name__ == '__main__':
+ main()