Gamecards: Difference between revisions

AriA99 (talk | contribs)
Details on CRC-32
AriA99 (talk | contribs)
Describe cart cryptography protocol now that it is confirmed the Switch uses a different protocol
Line 117: Line 117:
The communication protocol between the 3DS system and the 3DS gamecard has changed almost completely in comparison with the [http://problemkaputt.de/gbatek.htm#dscartridgeprotocol DS and DSi gamecard communication protocol].
The communication protocol between the 3DS system and the 3DS gamecard has changed almost completely in comparison with the [http://problemkaputt.de/gbatek.htm#dscartridgeprotocol DS and DSi gamecard communication protocol].


After the sixth transfer, commands change size from 8 bytes to 16 bytes. Possibly a new encryption is used, such as AES CTR.
The protocol begins in a DS-compatible 8-byte command mode (unencrypted). It switches to a 3DS-only 16-byte mode (encrypted) after the 0x3e command. When 16-byte commands are used, the data bus maintains the value 0x00 until the card signals it is ready by clocking a single byte 0x01, followed by the actual data. After each 0x200-byte block of actual data, a 4-byte standard CRC32 of the block data (before encryption, polynomial 0x82608edb and the final output is xored with 0xffffffff) follows.
When 16-byte commands are used, the data bus maintains the value 0x00 until the card signals it is ready by clocking a single byte 0x01, followed by the actual data. After each 0x200-byte block of actual data, a 4-byte standard CRC32 of the block data (before encryption, polynomial 0x82608edb and the final output is xored with 0xffffffff) follows.


Here's a set of sample gamecard commands that a 3DS sends to a 3DS gamecard:
Here's a set of sample gamecard commands for the title LEGO Star Wars III The Clone Wars (EUR), title ID 0004000000038c00, that a 3DS sends to a 3DS gamecard:


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 131: Line 130:
|<tt>2000</tt>
|<tt>2000</tt>
|<tt>9F00000000000000</tt>
|<tt>9F00000000000000</tt>
|?
|<tt>9F00000000000000</tt>
|Reset
|Reset
|-
|-
|<tt>0000</tt>
|<tt>0000</tt>
|<tt>71C93FE9BB0A3B18</tt>
|<tt>71C93FE9BB0A3B18</tt>
|?
|<tt>71C93FE9BB0A3B18</tt>
|Unknown
|Signal that the gamecard should act as a 3DS gamecard
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>9000000000000000</tt>
|<tt>9000000000000000</tt>
|?
|<tt>9000000000000000</tt>
|Get gamecard ID, response=9000FEC2
|Get gamecard ID1, response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>9000000000000000</tt>
|<tt>9000000000000000</tt>
|?
|<tt>9000000000000000</tt>
| Get gamecard ID, response=9000FEC2
|Get gamecard ID1, response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>A000000000000000</tt>
|<tt>A000000000000000</tt>
|?
|<tt>A000000000000000</tt>
| Unknown, response=00000000
|Get gamecard ID2, response=00000000
|-
|-
|<tt>0000</tt>
|<tt>0000</tt>
|<tt>3E00000000000000</tt>
|<tt>3E00000000000000</tt>
|?
|<tt>3E00000000000000</tt>
| Enter 16-byte command mode.
|Enter 16-byte command mode
|-
|-
|<tt>0200</tt>
|<tt>0200</tt>
|<tt>82000000000000000000000000000000</tt>
|<tt>82000000000000000000000000000000</tt>
|?
|<tt>82000000000000000000000000000000</tt>
| Get header
|Get gamecard header and enable encryption
|-
|-
|<tt>0000</tt>
|<tt>0000</tt>
|<tt>F32C92D85C9D44DED3E0E41DBE7C90D9</tt>
|<tt>F32C92D85C9D44DED3E0E41DBE7C90D9</tt>
|<tt>8300000000000000708DF1A731717D0B</tt>  
|<tt>8300000000000000708DF1A731717D0B</tt>  
| Seed
|Seed (rekey cryptography)
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>696B9D8582FB55D31B68CAFE70C74A95</tt>
|<tt>696B9D8582FB55D31B68CAFE70C74A95</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>BAA4812CA0AC9C5D19399530E3ACCCAB</tt>
|<tt>BAA4812CA0AC9C5D19399530E3ACCCAB</tt>
|<tt>A300000000000000708DF1A731717D0B</tt>
|<tt>A300000000000000708DF1A731717D0B</tt>
| Unknown
|Get gamecard ID2 (using cryptography)
|-
|-
|<tt>0000</tt>
|<tt>0000</tt>
|<tt>178E427C22D87ADB86387249A97D321A</tt>
|<tt>178E427C22D87ADB86387249A97D321A</tt>
|<tt>C500000000000000708DF1A731717D0B</tt>
|<tt>C500000000000000708DF1A731717D0B</tt>
| Unknown
|Refresh cart NAND
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>E06019B1BD5C9130ED6A4D9F4A9E7193</tt>
|<tt>E06019B1BD5C9130ED6A4D9F4A9E7193</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>4E0D224862523BBFE2E6255F80E15F37</tt>
|<tt>4E0D224862523BBFE2E6255F80E15F37</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>4CDF93D319FB62D0DB632A45E3E8D84C</tt>
|<tt>4CDF93D319FB62D0DB632A45E3E8D84C</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>9AA5D80551002F955546D296A57F0FEF</tt>
|<tt>9AA5D80551002F955546D296A57F0FEF</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0004</tt>
|<tt>0004</tt>
|<tt>C12BA81AEF30DDDBD93FAD5D544C6334</tt>
|<tt>C12BA81AEF30DDDBD93FAD5D544C6334</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
|<tt>A200000000000000708DF1A731717D0B</tt>
| Get secured gamecard ID, response=9000FEC2
|Get gamecard ID1 (using cryptography), response=9000FEC2
|-
|-
|<tt>0200</tt>
|<tt>0200</tt>
|<tt>62EC5FB7F420AE1DC6253AE18AFA5BB3</tt>
|<tt>62EC5FB7F420AE1DC6253AE18AFA5BB3</tt>
|<tt>BF000000000000000000000000000000</tt>
|<tt>BF000000000000000000000000000000</tt>
| Read address 0
|Read gamecard at address 0
|-
|-
|<tt>0200</tt>
|<tt>0200</tt>
|<tt>E3FA23AA016BE0C93430D1F42FF41324</tt>
|<tt>E3FA23AA016BE0C93430D1F42FF41324</tt>
|<tt>BF000000000040000000000000000000</tt>
|<tt>BF000000000040000000000000000000</tt>
| Read address 0x4000
|Read gamecard at address 0x4000
|}
|}


Line 253: Line 252:
  00001e0: a6 5b ee 10 60 bb 6a 68 21 bb ce c6 00 03 5b 7e  .[..`.jh!.....[~
  00001e0: a6 5b ee 10 60 bb 6a 68 21 bb ce c6 00 03 5b 7e  .[..`.jh!.....[~
  00001f0: 64 fb 6e ac a7 f0 96 0c fb 1f 5a 37 08 77 28 f7  d.n.......Z7.w(.
  00001f0: 64 fb 6e ac a7 f0 96 0c fb 1f 5a 37 08 77 28 f7  d.n.......Z7.w(.
After the 0x82 command, cryptography is initialized, which can be reproduced following this algorithm; unless noted otherwise, all operations are in big endian byte order:
1. Set the [[AES_Registers|AES keyslot 0x3b keyY]] to the values at 0x000:0x010. The corresponding keyX is set in [[Bootloader|Boot9]].
2. Decrypt the 16 bytes at 0x010:0x020 using AES-128-CCM in keyslot 0x3b using the 12-byte nonce at 0x030:0x03c to obtain the primary seed; if the response to the 0xa0 command AND 0x00000003 equals 3, instead use slot 0x11 and set the normalkey to 0x00000000000000000000000000000000. Verify that the 16-byte tag at 0x020:0x030 is valid.
3. Split the primary seed into two halves: left and right.
4. Initialize a context for the SNOW 2.0 stream cipher. The 128-bit key is the primary seed. The 128-bit IV is a 128-bit static value depending on the gamecard ID2.
5. Call the SNOW 2.0 stream cipher 32 times to obtain 1024 bits (32 words) of output. Discard them.
6. Initialize a context for the RC4 stream cipher. The 256-bit key consists of a 128-bit static value depending on the gamecard ID2 followed by four outputs of the SNOW 2.0 stream.
7. Call the RC4 stream cipher 256 times to obtain 2048 bits (256 bytes) of output. Discard them.
All commands and responses are now encrypted using RC4. The gamecard controller and gamecard itself share the RC4 key and advance the state accordingly.
If the 0x83 command is sent, the cryptography is re-keyed:
1. Initialize a new context for the SNOW 2.0 stream cipher. The 128-bit key consists of the left half of the primary seed followed by the lower 64 bytes of the decrypted 0x83 command. The 128-bit IV is the same 128-bit static value depending on the gamecard ID2 as before.
2. Call the SNOW 2.0 stream cipher 32 times to obtain 1024 bits (32 words) of output. Discard them.
3. Initialize a new context for the RC4 stream cipher. The 256-bit key consists of the same 128-bit static value depending on the gamecard ID2 as before followed by four outputs of the new SNOW 2.0 stream.
4. Call the RC4 stream cipher 256 times to obtain 2048 bits (256 bytes) of output. Discard them.
The above example commands can be decrypted in this manner.
The static values are fixed in the gamecard controller and gamecards themselves, they are not obtained from Process9 or anywhere in NATIVE_FIRM.