3DO Encryption
3DO Encryption
It looks as though the modulus n (x2) for the public and PRIVATE keys protecting against unauthorized code running on retail 3DO consoles has been successfully factored, revealing the private keys.
I've been told that Altmer plans to add support in the OperaFS[De]Compiler for signing images.
The day we've all been looking forward to could be upon us
I've been told that Altmer plans to add support in the OperaFS[De]Compiler for signing images.
The day we've all been looking forward to could be upon us
Plissken wrote:Great news!
They bruteforced it or detected the algorythm?
The algorithm has been known for quite some time now. A pair of 512-bit RSA keys along with an MD5 hash function were used to digitally sign the disks.
A network of distributed computing was utilized to sieve the RSA keys. So, technically, you could say the keys were "bruteforced".
- 3DO Experience
- 3DO ZONE ADMIN
- Posts: 3686
- Joined: Sun Jun 24, 2007 8:47 am
- Location: U.S.A.
-
- 3DO ZERO USER
- Posts: 267
- Joined: Thu Nov 27, 2008 3:01 am
- Location: UK
Been looking into RSA encryption a bit to understand how to put these to use. I have absolutely no previous experience with encryption, so these are some notes on what I've found from Google searches.
If Altmer goes ahead and creates an image compiler that does this, then that's cool. Otherwise, I will (extremely slowly) do more research as I have time with the intention of (eventually) coding a small app to do disc encryption. So here's what I know so far:
With RSA encryption, there is a series of equations for determining public and private keys. The input and output variables are p, q, N, d, and e. It starts with p and q, which are arbitrary prime numbers (preferably large and of similar size). N is p * q. e is a value that is "relatively prime" to/coprime with (p-1)*(q-1) (in other words, e and (p-1)*(q-1) share no divisors but 1).
e and N constitute the public key.
The last value, d, comes from the equation e*d = 1 mod (p-1)*(q-1).
d and N constitute the private key.
So that's what all those different numbers are all about in the file that tport released. For us, we really care about d, e, and N, since those are the "magic values" that we can use to encrypt and decrypt data. But how do we do that?
Well, we need to convert our message (our data) to a number (m) and create an encrypted version of it (c) based on the following equation:
c = m^e mod N
Since we know e and N, we can calculate an encrypted message given an input message m.
When we have an encrypted message (c), we can find the decrypted message (m) with the following equation:
m = c^d mod N
So there are a few things to consider still, before we can apply this to the 3DO. The following are questions that I personally still don't understand:
If Altmer goes ahead and creates an image compiler that does this, then that's cool. Otherwise, I will (extremely slowly) do more research as I have time with the intention of (eventually) coding a small app to do disc encryption. So here's what I know so far:
With RSA encryption, there is a series of equations for determining public and private keys. The input and output variables are p, q, N, d, and e. It starts with p and q, which are arbitrary prime numbers (preferably large and of similar size). N is p * q. e is a value that is "relatively prime" to/coprime with (p-1)*(q-1) (in other words, e and (p-1)*(q-1) share no divisors but 1).
e and N constitute the public key.
The last value, d, comes from the equation e*d = 1 mod (p-1)*(q-1).
d and N constitute the private key.
So that's what all those different numbers are all about in the file that tport released. For us, we really care about d, e, and N, since those are the "magic values" that we can use to encrypt and decrypt data. But how do we do that?
Well, we need to convert our message (our data) to a number (m) and create an encrypted version of it (c) based on the following equation:
c = m^e mod N
Since we know e and N, we can calculate an encrypted message given an input message m.
When we have an encrypted message (c), we can find the decrypted message (m) with the following equation:
m = c^d mod N
So there are a few things to consider still, before we can apply this to the 3DO. The following are questions that I personally still don't understand:
- 1. Why do encryption examples always use the public key to do the encryption, and the private key to do the decryption? This seems backwards.
2. What exactly is the difference between encrypting and signing? Which is the 3DO doing? Or is it doing both?
3. Why are there two key sets for 3DO encryption/signing?
4. How do we get a number for the message in encrypting/signing 3DO data? Presumably, this is where the MD5 hash function comes in, but I don't know what that function is.
5. What files do we need to encrypt/sign?
Okay, some more thoughts...
RSA signing is interesting. It works roughly like this (in 3DO terms):
Also, what is the hashing algorithm? I'm skeptical that it's MD5 because MD5 doesn't produce a number as its output, which is required for this sort of encryption. Since every 3DO system would have to perform this hashing, the algorithm must be stored in the system BIOS. Maybe we could reverse engineer it to find it?
RSA signing is interesting. It works roughly like this (in 3DO terms):
- * The 3DO Company wants to send my 3DO a signed message (an approved game)
* The 3DO Company will take my unsigned game and run a hash function on it to produce a number.
* They will then take this number, raise it to the power of (d mod n) and attach it to the message as a signature.
* My 3DO system will read the message and produce the same hash as the 3DO Company originally did.
* To verify the signature, my 3DO system will raise the signature value to the power of (e mod n). Due to some crazy math I don't understand, this has the effect of decrypting the signature value
* My 3DO then compares the decrypted hash to the hash it calculated itself. If these values are the same, then that confirms the 3DO Company's identity and verifies that this is an authorized message/game. (That's because only their private key would create a message that could be decrypted with the given public key)
Also, what is the hashing algorithm? I'm skeptical that it's MD5 because MD5 doesn't produce a number as its output, which is required for this sort of encryption. Since every 3DO system would have to perform this hashing, the algorithm must be stored in the system BIOS. Maybe we could reverse engineer it to find it?
Maybe... Eventually... But at this point, who the hell knows if I'll actually get that far?oldskool wrote:Uh.. so what does all this mean in English?
Homebrew?
Anyway, mini update: I found the location in the FZ-1 BIOS where the public keys (N) are stored. Key #1 starts at offset 0x00014F49 and Key #2 starts at offset 0x00014F8d. They're stored in hexadecimal. How is this useful? It probably isn't. But it's nifty to look at.
In the meantime, I'm installing cygwin so that I can use some Linux tools (specifically, binutils and objdump) to maybe disassemble the FZ-1 BIOS. Maybe then I can relearn some assembly and figure out the hash function? We'll see.
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
Rehashing the encryption stuff
I'm starting to tear apart a few of the smaller 3DO games to find out what is encrypted.
Alex Troosh wrote a utility to display the misc_code RSA:
http://altmer.arts-union.ru/3DO/downloa ... nGroup.zip
in system/kernel/misc_code is an offset to a 64 byte RSA signature.
In Putt Putt it was 0x00000B20, which points to:
system/kernel/os_code follows the same pattern (offset points to 0x0133c4):
Alex Troosh wrote a utility to display the misc_code RSA:
http://altmer.arts-union.ru/3DO/downloa ... nGroup.zip
in system/kernel/misc_code is an offset to a 64 byte RSA signature.
In Putt Putt it was 0x00000B20, which points to:
Code: Select all
4C F9 5E 9B 42 6D 06 44 42 FD 55 6E 72 6D B2 F8
1F E9 B8 72 7C DE 52 8E B3 38 8F D3 9C 25 99 B4
DF 8E EE 20 14 45 E9 9F C2 03 DF DD C8 71 5B CD
9F BF 0C FE 2B 36 1F A4 E3 89 06 33 75 C8 77 E2
Code: Select all
75 9C 2D 11 4A CC 74 F6 D7 66 F1 5B 36 4A C4 01
87 20 F2 00 01 77 0A E6 E8 40 28 5E E7 B1 B3 03
76 A8 4E B3 2F 7B E3 80 8A 2A 46 8B EA 21 5D 4C
C4 08 88 6D EA 77 D7 11 7D 46 5F AE 9F C0 3E E8
Last edited by cdoty on Tue Jun 22, 2010 7:05 am, edited 2 times in total.
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
SIGNATURES contains a signature for every sector.
Each 16 byte line in the signatures file represents 16 2048 byte sectors. An entire 16 sectors of 'iamaduck' is encoded as:
There are a few rows with all zeros. The blocks containing the signatures is one of those. The signature file start at 0xE5F000, in Putt Putt Fun Pack.
Each 16 byte line in the signatures file represents 16 2048 byte sectors. An entire 16 sectors of 'iamaduck' is encoded as:
Code: Select all
FE 5B 22 29 C7 82 BD 04 E6 80 DE 55 CC 23 87 25
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
The signatures are just md5 checksums of the 16 sectors.
I ran md5sums on a 32k block full of 'iamaduck' and got the same value posted above.
Any idea about using the provided values to sign something?
I need to sign this file http://www.rastersoft.net/Sign.zip
And I need to get back:
Sign.zip is the used part of the signature, and the value is store at the end of the next sector following the used signature. The rest of the signature is padded with 0x55.
I ran md5sums on a 32k block full of 'iamaduck' and got the same value posted above.
Code: Select all
Test.bin fe5b2229c782bd04e680de55cc238725
I need to sign this file http://www.rastersoft.net/Sign.zip
And I need to get back:
Code: Select all
57 C8 26 F3 00 44 D9 F6 83 08 D4 AE A6 F2 01 72
A2 B1 1B 0D 10 39 36 0A 05 C6 B1 4D 0D 36 49 D7
43 01 AC C3 22 44 E7 23 80 7D DE 62 8B 94 91 8A
FE 23 12 FA 4F D1 85 FF 1A 53 7C 51 DC D5 33 96
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
I'm able to generate a working key for the disc_label rom_tags and boot (This is the 64 byte value stored at 0x900 on the homebrew/game guru disks).
It's simply a matter of combining:
First 0x84 bytes of the cd image (disc_label)
The table located at 0x800 on the cd image (rom_tags). This is variable length and ends with a 32 byte section of 0's. On the homebrew image it's 0x100 bytes long.
The code located at 0x1000 (boot_code). The first line of the rom_tags specifies the length (starts with 0x0F 0D 02 05). The length of the data is the 4th 32 bin value in the line (0x176C).
Combining all of this data give you a file that is 6384 bytes long.
The md5 value of this file is attached to the string "1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410"
So you end up with 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
The "e787304693b23647f594d901c827f5f6" is the md5 value from the homebrew disk.
Then you calculate s = m^d mod n
m = 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
d and n are from the first key.
s then goes after rom_tags (at 0x900 in the homebrew image).
It's simply a matter of combining:
First 0x84 bytes of the cd image (disc_label)
The table located at 0x800 on the cd image (rom_tags). This is variable length and ends with a 32 byte section of 0's. On the homebrew image it's 0x100 bytes long.
The code located at 0x1000 (boot_code). The first line of the rom_tags specifies the length (starts with 0x0F 0D 02 05). The length of the data is the 4th 32 bin value in the line (0x176C).
Combining all of this data give you a file that is 6384 bytes long.
The md5 value of this file is attached to the string "1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410"
So you end up with 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
The "e787304693b23647f594d901c827f5f6" is the md5 value from the homebrew disk.
Then you calculate s = m^d mod n
m = 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
d and n are from the first key.
s then goes after rom_tags (at 0x900 in the homebrew image).
Last edited by cdoty on Fri Jul 02, 2010 7:27 am, edited 1 time in total.
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
Applying this to the orbatak iso enabled it to boot to the banner screen, but it went to the 3DO logo and startup screen after that. My guess is there's a problem with the signatures, since the key for it hasn't been fixed.
I had to replace the boot_code, os_code and banner screen with those from the homebrew CD.
Most of the information to accomplish this came from Alex Trush's 3DODiskCheck perl script http://www.arts-union.ru/node/20
I was able to work backwards from what he was doing; which is pretty amazing, considered I've never touched perl in my life.
I used md5sums to calculate the md5 value.
And, to generate the RSA values I used t_bdRSA.c from the BigDigits library http://www.di-mgt.com.au/bigdigits.html. But, instead of generating the key, I plugged in the values from the 3do key.
I should be able to get all of this into a tool this weekend.
Alex's tool also contains code to verify the signature key, so that should also be easy to fix. And, I already have code to generate the MD5 values for the sectors.
The same process works with the banner screen. I was able to insert the bogus developer screen into orbatak.
I had to replace the boot_code, os_code and banner screen with those from the homebrew CD.
Most of the information to accomplish this came from Alex Trush's 3DODiskCheck perl script http://www.arts-union.ru/node/20
I was able to work backwards from what he was doing; which is pretty amazing, considered I've never touched perl in my life.
I used md5sums to calculate the md5 value.
And, to generate the RSA values I used t_bdRSA.c from the BigDigits library http://www.di-mgt.com.au/bigdigits.html. But, instead of generating the key, I plugged in the values from the 3do key.
I should be able to get all of this into a tool this weekend.
Alex's tool also contains code to verify the signature key, so that should also be easy to fix. And, I already have code to generate the MD5 values for the sectors.
The same process works with the banner screen. I was able to insert the bogus developer screen into orbatak.
- 3DO Experience
- 3DO ZONE ADMIN
- Posts: 3686
- Joined: Sun Jun 24, 2007 8:47 am
- Location: U.S.A.
Orbatak might not be the best test since it is possible that it would look for the special hardware for the controls.
I know it works in the emulator but it is just an emulator. I have a copy of just obit in iso from before the homebrew disc came out it you want that. You can PM me and I'll give it to you.
I know it works in the emulator but it is just an emulator. I have a copy of just obit in iso from before the homebrew disc came out it you want that. You can PM me and I'll give it to you.
"Wait. You don't have a bag of charcoal in your gaming room???"
-
- Bringer of game signing
- Posts: 112
- Joined: Thu Jan 18, 2007 5:42 pm
- Location: Houston, TX
- Contact:
The first target is taking a working disk, and writing all of the values, and comparing it against the original.3DO Experience wrote:Orbatak might not be the best test since it is possible that it would look for the special hardware for the controls.
I know it works in the emulator but it is just an emulator. I have a copy of just obit in iso from before the homebrew disc came out it you want that. You can PM me and I'll give it to you.
I have the methods to generate the keys for everything. I just have to write the software to do it, which I plan to start on tonight.
cdoty wrote:I'm able to generate a working key for the disc_label rom_tags and boot (This is the 64 byte value stored at 0x900 on the homebrew/game guru disks).
It's simply a matter of combining:
First 0x84 bytes of the cd image (disc_label)
The table located at 0x800 on the cd image (rom_tags). This variable length and ends with a 32 byte section of 0's. On the homebrew image it's 0x100 bytes long.
The code located at 0x1000 (boot_code). The first line of the rom_tags specifies the length (starts with 0x0F 0D 02 05). The length of the data is the 4th 32 bin value in the line (0x176C).
Combining all of this data give you a file that is 6384 bytes long.
The md5 value of this file is attached to the string "1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410"
So you end up with 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
The "e787304693b23647f594d901c827f5f6" is the md5 value from the homebrew disk.
Then you calculate s = m^d mod n
m = 1ffffffffffffffffffffffffffffffffffffffffffffffffffffff003020300c06082a864886f70d020505000410e787304693b23647f594d901c827f5f6
d and n are from the first key.
s then goes after rom_tags (at 0x900 in the homebrew image).
Oh, so MD5 is a number, it's just hexadecimal... Durrrfff, I don't know why I didn't realize that sooner.