Changes

2,878 bytes added ,  26 May
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.
25

edits