1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
"""Smoke tests: images load, ARM/Thumb detection works, leaf routines execute."""
import os, sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from pspemu import Component, consts
def test_load_all():
for name in ("hdcp", "asd", "dtm", "sys_drv"):
c = Component(name)
assert c.entry, name
print(f" {name:8s} entry={c.entry:#x} regions={len(c.cmap.regions)}")
def test_mode_detection():
"""Call-site voting must classify the mixed ARM/Thumb leaf routines."""
c = Component("hdcp")
assert c.mode_of(consts.HDCP["ta_memcpy"]) is False, "ta_memcpy must be ARM"
assert c.mode_of(consts.HDCP["ta_memclr"]) is True, "ta_memclr must be Thumb"
assert c.mode_of(consts.HDCP["subcmd12_rxinfo"]) is True
assert c.mode_of(consts.HDCP["verify_mac"]) is True
print(" ta_memcpy=ARM ta_memclr=Thumb subcmd12=Thumb verify_mac=Thumb")
def test_memcpy_leaf():
c = Component("hdcp")
src, dst = c.alloc(64), c.alloc(64)
c.write(src, bytes(range(64)))
c.run_function(consts.HDCP["ta_memcpy"], (dst, src, 32))
assert c.read(dst, 32) == bytes(range(32)), "ta_memcpy mismatch"
assert c.read(dst + 32, 8) == b"\x00" * 8, "ta_memcpy overran"
print(" ta_memcpy: 32 bytes copied, no overrun")
def test_memclr_leaf():
c = Component("hdcp")
d = c.alloc(64)
c.write(d, b"\xAA" * 64)
c.run_function(consts.HDCP["ta_memclr"], (d, 16))
assert c.read(d, 16) == b"\x00" * 16, "memclr failed"
assert c.read(d + 16, 8) == b"\xAA" * 8, "memclr overran"
print(" ta_memclr: 16 bytes cleared, no overrun")
def test_write_tracer():
"""The tracer must recover a copy's exact extent (core investigative tool)."""
c = Component("hdcp")
src, dst = c.alloc(256), c.alloc(256)
c.write(src, bytes(i & 0xFF for i in range(256)))
tr = c.trace_writes([(dst, dst + 256, "dst")])
c.run_function(consts.HDCP["ta_memcpy"], (dst, src, 100))
ext = tr.extent(dst, dst + 256)
assert ext is not None, "no writes traced"
lo, hi, n = ext
assert lo == dst and hi == dst + 100, f"extent {lo-dst}..{hi-dst} != 0..100"
print(f" tracer recovered exact extent: +{lo-dst}..+{hi-dst} ({n} writes)")
def test_ccp_sha224_and_error_names():
"""SHA-224 (CCP SHA type 2) and the CCP command-error table.
Type 2 came from AMD's own ccp.h rather than from observation -- no firmware
we hold requests SHA-224 -- so it is verified against hashlib here instead
of being trusted. Empty and multi-block inputs are both covered, since the
padding path is where a borrowed constant would most plausibly be wrong.
"""
import hashlib, struct
from pspemu.ccp import SHA_TYPES, SHA_NAMED_UNIMPLEMENTED, cmd_error_name
name, ctxlen, blocksz, fmt, compress, dlen = SHA_TYPES[2]
assert (name, dlen) == ("SHA-224", 28), f"unexpected SHA-224 entry {name}/{dlen}"
iv = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
for msg in (b"", b"abc", b"the quick brown fox" * 7, bytes(range(256))):
data = msg + b"\x80"
data += b"\x00" * ((blocksz - (len(msg) + 1 + 8)) % blocksz)
data += (len(msg) * 8).to_bytes(8, "big")
state = list(iv)
for i in range(0, len(data), blocksz):
state = compress(state, data[i:i + blocksz])
got = struct.pack(fmt, *state)[:dlen]
assert got == hashlib.sha224(msg).digest(), f"SHA-224 mismatch at len {len(msg)}"
print(f" SHA-224 matches hashlib on 4 inputs (0..256 bytes)")
assert cmd_error_name(0x14) == "IDMA_PROTECTION_FAULT"
assert cmd_error_name(0x24) == "ODMA_PROTECTION_FAULT"
assert cmd_error_name(0x00) == "NONE"
assert "UNKNOWN" in cmd_error_name(0x99), "out-of-table code must be flagged"
assert SHA_NAMED_UNIMPLEMENTED == {1: "SHA-1"}, "SHA-1 must stay named-but-unimplemented"
print(" CCP error names resolve; unknown codes flagged, not invented")
if __name__ == "__main__":
fails = 0
for fn in (test_load_all, test_mode_detection, test_memcpy_leaf,
test_memclr_leaf, test_write_tracer,
test_ccp_sha224_and_error_names):
print(fn.__name__)
try:
fn(); print(" PASS")
except Exception as e:
fails += 1; print(f" FAIL: {e}")
sys.exit(1 if fails else 0)
|