Step 1: $40k overpriced LA (could be replaced easily with a $150 FPGA board), some wires
Step 2: 20 lines of python code
Difference between those? Just some simple XOR and ADD. Ok, now a better step-for-step description what’s this all about.
As you might have seen, GDROM-games for the Naomi/Triforce/Chihiro come with a security chip, which has to be plugged into the “DIMM Board”. The “DIMM board” is, as previously explained, in charge for loading and decrypting the GDROM data. As part of that, the “security PIC” (yes, it’s a PIC. Does this gives you enough warning lights that there might be a problem?) is queried. No PIC, no game. (Additionally, the GD-ROM is copy protected, i.e. has features which cannot be copied easily. As far as I know, this hasn’t been broken. The Dreamcast incidents were all caused by backdoors in the BIOS code there).
There have been some rumors about this “security PIC”, including that it “just spits out the game name in ascii” or that it’s “impossible to copy”. Both isn’t true. In fact, the PIC does some security, but it’s done very badly. But I’m too fast again.
What I did was to attach my temporary logic analyzer (TLA) to all the pins of the security PIC (Usually, I’m not using a TLA but a GoLogic, but my GoLogic-U72-2M is, well, busy). I quickly located 2 continuous clock lines, and 4 data lines (3 data+1clock). The rest seems static. I captured a whole session, i.e. the complete powerup and some minutes of the game.
When looking at the captured data (see first picture), it was clear that there were several “packets” of 24 cycles each, with 3 transmitted bits per cycle.
I’ve reversed the DIMM Board SH-4 firmware, and found the Challenge/Response-function. It was easy to reverse the function (in both senses) into python code. Basically, the transmission of 8 bytes works the following way:
- For each byte, a parity is calculated, and stored.
- Each byte is “encrypted” versus a 16-byte password. The password is split into two halves. Then, for each byte to encrypted, one byte of every pair is used. The byte from the first half is XORed with the input value, the byte from the second half is ADDed to the input value. This scheme might look dead simple, but is actually not as bad as it might seem at first. Sure, it’s not secure, but you cannot easily derive the key from a few known plaintext attack vectors due to the nonlinearities and ambiguities. I’m not promoting this kind of “n00b security”, but it’s a hell better than the usual “just XOR in a constant”.
- 3, 3 and 2 (+the parity) bits are taken (LSB to MSB,parity), and clocked (3 cycles per byte, 24 cycles total, 72 bits)
After 8 transmitted bytes, the PIC does answer with 8 bytes, with the same protocol (and password).
For example, the first packet which is transmitted looks like “7b 7f 85 87 55 69 64 91”. After applying the decryption, it will read “bsec_ver” - yes, ascii. This is a command to the PIC to answer with a version string, encrypted in the same way. In my case, it decrypts to “8VER0001”. The next query, “kaijyo!?” (does anybody know what this means?), is answered with some binary data, not sure what this is about. After that, the version is queried again. Then it gets interesting: The DIMM board generates a random string (starting with ‘!’, however), and sends that to the PIC. The PIC responds, but the result is scrambled. It shows that three commands, ‘!’, ‘”’ and ‘#’, actually modify the password. This is probably done to disable relay attacks - otherwise the transmitted data would be the same all the time. So, when a ‘!’-command is sent to the PIC, the payload (i.e. after the ‘!’) re-defines the first 7 characters of the password. ‘”’ redefines bytes 7..13, and ‘#’ bytes 14..15 (the rest is unused). Of course the actual command is still encrypted with the old password, but the PIC response is already encrypted with the new one. If you follow that correctly, the PIC will respond to the 3 password re-define commands with “0DIMMID0”/”1DIMMID1”/”2DIMMID2”.
After that, two properties are queried, with the command “C1strdf0” (yields “5BEY.BIN”) and “D1strdf1” (yields zeros). Not sure what this is about.
Then something interesting is sent: “AKEYCODE” and “Bkeycode”. In both cases, the PIC responds with a part of a “key” (7 bytes in first command, 1 byte in second command), which is re-assembled and directly written into a hardware register.
Now the game is starting. To prevent removal of the PIC after the initial key exchange, every minute a “ping”-packet is sent: “atestpic”, which has to be answered with “7TEST_OK”.
So, here is a full log of the communication, minus the key part:
DIMM -> PIC PIC -> DIMM bsec_ver 8VER0001 kaijyo!? :binary bsec_ver 8VER0001 !session key bytes 0..7 0DIMMID0 “session key bytes 7..13 1DIMMID1 #session key bytes 14..15 2DIMMID2 C1strdf0 5BEY.BIN D1strdf1 6zeros AKEYCODE 3key Bkeycode 4key kaijyo!? :binary atestpic 7TEST_OK atestpic 7TEST_OK
While there might be other commands as well (the DIMM firmware lists some of them, but some of them sound rather funny - not sure if they are real), there doesn’t seem to be a real secret inside the “security PIC” which cannot simply be read out.
So, this was the tale of the Naomi/Triforce/Chihiro GD-ROM System. No black magic, no real security.
Total time required to gather enough knowledge to dump&replicate the security PIC: Maybe 6h in total, including playing (and loosing) VS2002.