Content keys protect secure assets such as games and firmware data.
Meta keys protect the content keys and allows revoking compromised content keys.
We need more information:
After we can examine attack surface.
Ideally we want to read F00D SRAM to enable a targeted attack.
ARM operates with virtual memory whilst F00D does not.
Virtual memory is not guaranteed to be backed by contiguous physical memory.
Copying every memory transaction to contiguous physical memory would be expensive.
There needs to be a better way.
F00D kernel does not blacklist its own SRAM!
Data is copied to its internal memory still, so no leak.
Data is still signature checked, so this is useless.
What if the chunk of memory in SRAM matches the original?
Signature check succeeds and we continue as normal.
Additionally, we learn the contents of that part of SRAM.
00007820 0d f7 3e 8b 33 dc 4e 62 99 37 c3 9c 6f 4f 43 43 |..>.3.Nb.7..oOCC| 00007830 00 01 00 00 00 01 00 01 04 00 00 00 00 00 00 00 |................| 00007840 43 6f 6e 67 72 61 74 75 6c 61 74 69 6f 6e 73 21 |Congratulations!| 00007850 20 41 74 20 6c 61 73 74 20 79 6f 75 20 67 65 74 | At last you get| 00007860 20 74 68 65 20 70 6c 61 69 6e 74 65 78 74 20 6f | the plaintext o| 00007870 66 20 74 68 65 20 50 53 20 56 69 74 61 20 53 65 |f the PS Vita Se| 00007880 63 75 72 65 20 4b 65 72 6e 65 6c 21 00 00 00 00 |cure Kernel!....| 00007890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000078a0 00 00 00 00 00 00 00 00 15 00 00 00 10 94 80 00 |................| 000078b0 80 00 00 00 c0 16 03 40 68 c0 02 40 04 00 00 00 |.......@h..@....|
if (*size < 256) {
return process_data(*size);
} else {
return 0;
}
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00810000 |
$1 0x00000000 |
$pc 0x00800100 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00810000 |
$1 0x00004000 |
$pc 0x00800102 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00000000 |
$1 0x00004000 |
$pc 0x00800104 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00000000 |
$1 0x00004000 |
$pc 0x00800108 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00810000 |
$1 0x00000000 |
$pc 0x00800100 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00810000 |
$1 0x00004000 |
$pc 0x00800102 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00000001 |
$1 0x00004000 |
$pc 0x00800104 |
lw $1, ($0)
sltu3 $0, $1, 0x100
beqz $0, .error
bsr process_data
.error:
ret
$0 0x00000000 |
$1 0x00004000 |
$pc 0x00801000 |
C = ~(A & B)
A | B | C |
0 | 0 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 0 |
Last hurdle: which is the right voltage rail?
repeat 10000000,end
add $0, 1
add $1, 1
add $2, 1
add $3, 1
add $4, 1
add $0, 1
add $1, 1
add $2, 1
end: add $3, 1
add $4, 1
We can now inject logical bugs but how do we exploit it to run code?
Bypass signature check? Don't have decrypted samples, hard to guess how signature is parsed
Easier target: boot partition header, which locates the bootloaders
Unencrypted, unsigned, easy to understand
Look at partition header's size field
Size field is checked to be < 0xDE blocks.
If check passes, bootloader is read for that many blocks.
Otherwise, it halts.
d14585f6defa18fa
8222e683bb8b53ee
aa5bbe7c22f8d513
633d5e1701d8858f
Sony had a history of crypto failures...
Vita is Sony's best security work to date.