| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
131 documents had accumulated organically, with three overlapping "summary"
files, several topics split across 3-6 documents, and ten retracted documents
whose filenames still read as findings. Restructured rather than rewritten, so
no history is lost.
Added psp_out/INDEX.md as the map, built from a scan of all 131 files rather
than memory:
* the spine -- the four documents that govern the rest (CONSTRAINTS,
VULN-AUDIT-WHAT-WE-ACTUALLY-HAVE as the vulnerability register,
ATTACK-SURFACE, INDEX);
* RETRACTED, do not cite -- the ten files carrying retraction banners,
listed explicitly because their names mislead;
* duplicate clusters with the authoritative file named for each of ten
topics (subcmd12, ASD 0x308, SRM walker, Route C, VCN, TMR fence, rollback,
SMN map, emulator bring-up, hardware validation);
* settled negatives, 17 of them, flagged as "do NOT re-run" since repeating
them is the likeliest way to waste a session;
* methodology, including the recurring failure mode named once: a measurement
producing a confident result its own control invalidates, with this
session's five instances listed;
* priorities P1-P4, each with its blocker and next concrete step, plus an
explicit deprioritised list.
Updated the vulnerability register for this session, since it predated it:
added the VCN type-49 write as a Tier-1 entry with its precise wording
constraint ("completes a register-write loop over attacker-controlled entries",
not "arbitrary VCN register write"); qualified Route C's "nothing reads those
registers" with the fact that the scan covered only images we hold and the
window has since been shown to be a PSP-private space, still unidentified; and
corrected the Tier-1 summary from one write primitive to two, neither with a
demonstrated consumer.
Annotated nine non-authoritative documents with a pointer banner so a reader
landing on them directly is not misled, and pointed README at the index.
Retraction checker clean over 59 harvested claims.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
"sOS + TAs running" was already claimed by boot_sos_and_tas, but that claim
could not name a single TA. It classifies blocks by VA, and every TA runs at
VA 0x400000 in its OWN address space, so its "TA/other=28 blocks" line cannot
distinguish HDCP from DTM from RAS -- the VA-aliasing trap this tree documents
elsewhere and then fell into here. Measured by (VA, live PA) instead, that run
was HDCP 205 / DTM 9 / RAS 8 blocks, and ASD zero.
ASD was the real gap. It is driver-class, its boot-time staging slot is gated
off, and it arrives over the host ring -- which boot_sos_and_tas has no ring to
do, and load_asd.py does only in isolation. This harness does both in one
system: boot sOS (bl_stage2_task loads and verifies the boot modules), bring the
ring up, then ring-load ASD.
Attribution is two independent signals that must agree: address space (ASD at
0xD00000, TAs at 0x400000, SYS_DRV at 0xE00000, sOS below 0x300000) and the live
physical page of each block, matched against staged image content. Content
matching intersects several 48-byte slices because a single slice near a page
start hits shared libc boilerplate and matches all five images.
Result, deterministic across runs:
sys_drv 532806 hdcp 204 (0x420e000, 0x420b000) dtm 9 (0x41f3000)
ras 8 (0x41e0000, 0x41de000) asd 145 (5 pages) sOS 214934
4 modules loaded+verified at boot, ASD over the ring, 0 faults
SKIP_ASD=1 is a control, and the first version of it was confounded: skipping
the ring load also removed the run time that drain provided, so HDCP and DTM
stopped executing too and the control proved nothing about ASD. Both paths now
get an equal settle budget, and the control isolates cleanly -- only ASD flips
to NO, RSA verifications drop 4 -> 3 (ASD's), exit 1.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The tree recorded ASD as "not loaded", gated off by an undecoded runtime flag,
with the note that on hardware it arrives through the host-initiated load path
"which needs the ring/mailbox model". That model exists now, so ASD is loaded
through it.
The boot-time gate, decoded. bl_stage2_task guards the +0x6F8000 staging slot:
00204a32 ldr r0, [r4, #4]
00204a34 ldr.w r0, [r0, #0x3e8]
00204a38 cmp r0, #0
00204a3a bge 0x204a76 ; >= 0 -> skip the ASD load entirely
r4 is the global table at 0x2060E8, [r4+4] the state struct at 0x20E000, so the
flag is VA 0x20E3E8. Measured at the branch it is 0x00000000 both times it is
reached, and a write hook over the entire boot records ZERO writes to that word
-- nothing on this path ever sets it, so it keeps its zeroed BSS value and the
skip is unconditional. That also makes ASD's OVERSIZE staging line a red
herring: the image is never handed to the loader, so the 0x30000 slot bound is
never consulted.
Loading it the way hardware does -- boot, ring init, ring command 1 with the
image PA and length, the path already proven for HDCP:
image: asd_full.bin 209152 bytes class body+0x14 = 0x5244 ('DR' driver)
clean image ASD blocks=81 faults=0 RSA ops=3
ASD executes 81 distinct basic blocks in its own address space at 0xD00000,
zero faults, after the firmware's own loader verified it on the CCP model.
Deterministic: 81 blocks on repeated runs.
Controls, since "it ran" is only meaningful if it could have failed:
1 bit flipped in signed body ASD blocks=0
1 bit flipped in signature ASD blocks=0
Both corrupted images execute ZERO ASD blocks, so the 81 are contingent on the
real RSA-PSS check, not on the harness writing bytes into memory. The harness
exits non-zero unless the positive control and both negatives hold. One fresh
emulator per observation, because a rejected load disturbs ring/session state
and reusing an instance makes later observations look dead for the wrong reason.
Scope stated in the finding: this is ASD loaded and running, NOT ASD command
handling. ASD is driver-class, not a TA, so it is not reached through
TA_InvokeCommandEntryPoint and the 81 blocks are its load/init path. Driving its
audited opcode surface needs its RPC dispatcher, which services.py still stubs
(AsdRpcService returns 0) and which Bus can route into but is not wired to by
default. That work is now unblocked rather than done: the real ASD is resident
and running instead of absent.
Regression: smoke, ccp_selftest, verify_real_image, boot_sos_full,
boot_sos_and_tas, boot_and_mailbox all unchanged; fuzz_ta_invoke still exits 2
by design.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds 301 PSP/SMU firmware images (*.bin, *.elf, ~33 MB) that were previously
gitignored. They are public material: the module images come from
linux-firmware and publicly mirrored VBIOS dumps, and nothing was decrypted --
the encrypted on-flash stages (BOOT_LOADER#1, TRUSTED_OS) remain encrypted and
unanalysed, so sOS is the earliest stage present.
Checked the whole-flash dumps before publishing: they carry board SKU strings
only (XFX D702_XTX / 113-31XFSHBS1), no serials, MACs or unique per-board
identifiers.
With the images tracked, the symbol maps in psp_out/phase3/, vdiff/, sigs/ and
handover/symbols/ are now directly reproducible against the exact bytes they
were derived from, and data/MANIFEST.sha256 still pins all 301 hashes.
Still excluded: IDA databases (228 MB, regenerable and churn-prone),
psp_out/decompiled/ (Hex-Rays output mechanically derived from AMD code), and
AMD-internal register maps, which are vendor documents rather than public
firmware.
|
|
|
Split out of a tinygrad working tree, where all of this lived untracked.
tinygrad remains a dependency for hardware-facing scripts only.
Contents:
psp_emu/ Unicorn-based PSP emulator that boots the real signed firmware from
the ARM reset vector: sOS -> SYS_DRV -> HDCP/DTM/RAS TAs, with a CCP
crypto device model faithful enough to run the firmware's own
drivers (RSA-PSS/SHA-256 container verification passes 5/5 with
5/5 negatives rejected). A simulated host drives the real
mailbox/ring path through to TA_InvokeCommandEntryPoint.
psp_out/ Static analysis: six PSP modules fully named (asd 1562, sys_drv
1141, sos 527, ras 119, hdcp 109, dtm 14) plus SMU 1033, a
cross-version diffing pipeline over 34+ builds, per-handler
annotated analysis and ~125 findings documents.
Deliberately not tracked: AMD firmware images, the Hex-Rays decompilation
derived from them, and IDA databases. data/MANIFEST.sha256 pins the SHA-256 of
all 301 blobs results were derived from, so findings remain traceable to their
inputs without redistributing AMD code. 6 MB tracked instead of 315 MB.
Verified from the new location: test_smoke 5/5, ccp_selftest 11/11,
verify_real_image 5/5 + 5/5 negatives, fuzz_ta_invoke controls passing and
host-driven TA invoke working (0.73s per invoke).
|