Line 11: |
Line 11: |
| ! Pin | | ! Pin |
| ! Name | | ! Name |
− | ! Description | + | !colspan="2"| Description |
| |- | | |- |
| | 1 | | | 1 |
| | GND | | | GND |
− | | Ground | + | |colspan="2"| Ground |
| |- | | |- |
| | 2 | | | 2 |
| | CLK | | | CLK |
− | | Clock. Frequencies 6.7MHz and 4.2MHz) | + | |colspan="2"| Clock. Frequencies 6.7MHz and 4.2MHz for DS/DSi gamecards, up to 16.6MHz for 3DS gamecards (for both SPI and ROM transfers). |
| |- | | |- |
| | 3 | | | 3 |
| | NC | | | NC |
− | | Not connected. Possibly used to program cards. | + | |colspan="2"| Not connected. Possibly used to program cards. |
| |- | | |- |
| | 4 | | | 4 |
| | RCS | | | RCS |
− | | ROM select, active low. Pulled low to start a ROM transfer. | + | |colspan="2"| ROM select, active low. Pulled low to start a ROM transfer. |
| |- | | |- |
| | 5 | | | 5 |
| | RST | | | RST |
− | | Reset, active low. | + | |colspan="2"| Reset, active low. |
| |- | | |- |
| | 6 | | | 6 |
| | ECS | | | ECS |
− | | Savegame chip select, active low. Pulled low to start a savegame SPI transfer. | + | |colspan="2"| Savegame chip select, active low. Pulled low to start a savegame SPI transfer. |
| |- | | |- |
| | 7 | | | 7 |
| | IRQ | | | IRQ |
− | | Removal detection. | + | |colspan="2"| Removal detection. |
| |- | | |- |
| | 8 | | | 8 |
| | VCC | | | VCC |
− | | Powersupply 3.3V. | + | |colspan="2"| Powersupply 3.3V. |
| + | |- |
| + | ! |
| + | ! |
| + | ! ROM bus (selected by RCS) |
| + | ! Savegame bus (selected by ECS) |
| |- | | |- |
| | 9 | | | 9 |
| | DAT0 | | | DAT0 |
− | | Bidirectional data bus. | + | |rowspan="8"| Bidirectional data bus. |
| + | |rowspan="4"| NC |
| |- | | |- |
| | 10 | | | 10 |
| | DAT1 | | | DAT1 |
− | | Bidirectional data bus.
| |
| |- | | |- |
| | 11 | | | 11 |
| | DAT2 | | | DAT2 |
− | | Bidirectional data bus.
| |
| |- | | |- |
| | 12 | | | 12 |
| | DAT3 | | | DAT3 |
− | | Bidirectional data bus.
| |
| |- | | |- |
| | 13 | | | 13 |
| | DAT4 | | | DAT4 |
− | | Bidirectional data bus. | + | | NC/SIO3 |
| |- | | |- |
| | 14 | | | 14 |
| | DAT5 | | | DAT5 |
− | | Bidirectional data bus. | + | | WP#/SIO2 |
| |- | | |- |
| | 15 | | | 15 |
| | DAT6 | | | DAT6 |
− | | Bidirectional data bus / SPI data from savegame chip. | + | | SO/SIO1 |
| |- | | |- |
| | 16 | | | 16 |
| | DAT7 | | | DAT7 |
− | | Bidirectional data bus / SPI data to savegame chip. | + | | SI/SIO0 |
| |- | | |- |
| | 17 | | | 17 |
| | GND | | | GND |
− | | Ground | + | |colspan="2"| Ground |
| + | |} |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! |
| + | ! 3DS |
| + | ! DS and DSi |
| + | |- |
| + | | VCC |
| + | | Only enabled when the power supply bits of [[CONFIG9_Registers#CFG9_CARDSTATUS|CFG9_CARDSTATUS]] are set to <tt>10</tt> |
| + | | Always available when card is detected |
| + | |- |
| + | | Card-detect |
| + | | Physical insertion switch, readable through [[CONFIG9_Registers#CFG9_CARDSTATUS|CFG9_CARDSTATUS]] bit 0 |
| + | | IRQ pin |
| + | |- |
| + | | Time to first clock pulse |
| + | | ~280ms |
| + | | ~166ms |
| |} | | |} |
| | | |
| + | ===SPI flash=== |
| + | Savegame SPI flash transfers use CPOL=1 and CPHA=1. So far, only one savegame FLASH chip has been identified. The chip identifies as <tt>0xC22211</tt>. The JEDEC manufacturer ID is Macronix, and despite the chip label saying 25L1001, the JEDEC ID matches the MX25L1021E. Datasheet at:<br> |
| + | [https://www.macronix.com/Lists/Datasheet/Attachments/8796/MX25L1021E,%203V,%201Mb,%20v1.3.pdf Macronix (Rev. 1.3, nov. 11, 2013)] <br> |
| + | [https://web.archive.org/web/20160307235354/http://www.beilenet.com/download/MX25L1021E,%203V,%201Mb,%20v0.01.pdf Old version mirror (Rev. 0.01, apr. 07, 2010)] <br> |
| + | However, the MX25L1021E doesn't support the 4 bit wide transmission that the 3DS uses to talk to the SPI flash. It is thus likely that this is a custom flash chip. |
| + | |
| + | ===Format=== |
| + | Cartridges can come in several sizes and include system updates in a region reserved for this. In ROMs less than 1GB the update region can be found with: |
| + | CART_SIZE_MAX-( 0x280000*(CART_SIZE_MAX/CART_SIZE_128MB) )-0x2000000. The region is then 0x2000000 bytes. |
| | | |
| ===Protocol=== | | ===Protocol=== |
− | The communication protocol between the 3DS system and the 3DS gamecard has changed almost completely in comparison with the 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. |
| | | |
− | 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 94: |
Line 125: |
| ! Size | | ! Size |
| ! Command | | ! Command |
| + | ! Decrypted command |
| ! Description | | ! Description |
| |- | | |- |
− | |2000 | + | |<tt>2000</tt> |
− | |9F00000000000000 | + | |<tt>9F00000000000000</tt> |
− | | Reset | + | |<tt>9F00000000000000</tt> |
| + | |Reset |
| |- | | |- |
− | |0000 | + | |<tt>0000</tt> |
− | |71C93FE9BB0A3B18 | + | |<tt>71C93FE9BB0A3B18</tt> |
− | | Unknown | + | |<tt>71C93FE9BB0A3B18</tt> |
| + | |Signal that the gamecard should act as a 3DS gamecard |
| |- | | |- |
− | |0004 | + | |<tt>0004</tt> |
− | |9000000000000000 | + | |<tt>9000000000000000</tt> |
− | | Get gamecard ID, response=9000FEC2 | + | |<tt>9000000000000000</tt> |
| + | |Get gamecard ID1, response=9000FEC2 |
| |- | | |- |
− | |0004 | + | |<tt>0004</tt> |
− | |9000000000000000 | + | |<tt>9000000000000000</tt> |
− | | Get gamecard ID, response=9000FEC2 | + | |<tt>9000000000000000</tt> |
| + | |Get gamecard ID1, response=9000FEC2 |
| |- | | |- |
− | |0004 | + | |<tt>0004</tt> |
− | |A000000000000000 | + | |<tt>A000000000000000</tt> |
− | | Unknown, response=00000000 | + | |<tt>A000000000000000</tt> |
| + | |Get gamecard ID2, response=00000000 |
| |- | | |- |
− | |0000 | + | |<tt>0000</tt> |
− | |3E00000000000000 | + | |<tt>3E00000000000000</tt> |
− | | Enter 16-byte command mode. | + | |<tt>3E00000000000000</tt> |
| + | |Enter 16-byte command mode |
| |- | | |- |
− | |07EC | + | |<tt>0200</tt> |
− | |82000000000000000000000000000000 | + | |<tt>82000000000000000000000000000000</tt> |
− | | Get header | + | |<tt>82000000000000000000000000000000</tt> |
| + | |Get gamecard header and enable encryption |
| |- | | |- |
− | |05E3 | + | |<tt>0000</tt> |
− | |F32C92D85C9D44DED3E0E41DBE7C90D9 | + | |<tt>F32C92D85C9D44DED3E0E41DBE7C90D9</tt> |
− | | Encrypted, unknown | + | |<tt>8300000000000000708DF1A731717D0B</tt> |
| + | |Seed (rekey cryptography) |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |696B9D8582FB55D31B68CAFE70C74A95 | + | |<tt>696B9D8582FB55D31B68CAFE70C74A95</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |BAA4812CA0AC9C5D19399530E3ACCCAB | + | |<tt>BAA4812CA0AC9C5D19399530E3ACCCAB</tt> |
− | | Encrypted, unknown | + | |<tt>A300000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID2 (using cryptography) |
| |- | | |- |
− | |032E | + | |<tt>0000</tt> |
− | |178E427C22D87ADB86387249A97D321A | + | |<tt>178E427C22D87ADB86387249A97D321A</tt> |
− | | Encrypted, unknown | + | |<tt>C500000000000000708DF1A731717D0B</tt> |
| + | |Refresh cart NAND |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |E06019B1BD5C9130ED6A4D9F4A9E7193 | + | |<tt>E06019B1BD5C9130ED6A4D9F4A9E7193</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |4E0D224862523BBFE2E6255F80E15F37 | + | |<tt>4E0D224862523BBFE2E6255F80E15F37</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |4CDF93D319FB62D0DB632A45E3E8D84C | + | |<tt>4CDF93D319FB62D0DB632A45E3E8D84C</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |9AA5D80551002F955546D296A57F0FEF | + | |<tt>9AA5D80551002F955546D296A57F0FEF</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0332 | + | |<tt>0004</tt> |
− | |C12BA81AEF30DDDBD93FAD5D544C6334 | + | |<tt>C12BA81AEF30DDDBD93FAD5D544C6334</tt> |
− | | Encrypted, unknown | + | |<tt>A200000000000000708DF1A731717D0B</tt> |
| + | |Get gamecard ID1 (using cryptography), response=9000FEC2 |
| |- | | |- |
− | |0532 | + | |<tt>0200</tt> |
− | |62EC5FB7F420AE1DC6253AE18AFA5BB3 | + | |<tt>62EC5FB7F420AE1DC6253AE18AFA5BB3</tt> |
− | | Encrypted, read address 0 | + | |<tt>BF000000000000000000000000000000</tt> |
| + | |Read gamecard at address 0 |
| |- | | |- |
− | |0332 | + | |<tt>0200</tt> |
− | |E3FA23AA016BE0C93430D1F42FF41324 | + | |<tt>E3FA23AA016BE0C93430D1F42FF41324</tt> |
− | | Encrypted, read address 0x4000 | + | |<tt>BF000000000040000000000000000000</tt> |
| + | |Read gamecard at address 0x4000 |
| |} | | |} |
| | | |
− | The header command has some initial dummy bytes, and eventually responds with a 0x200 byte header. Here's an example for Lego Starwars 3: | + | The header command has some initial dummy bytes, and eventually responds with the 0x200 byte [[NCSD#InitialData|InitialData]]. Here's an example for Lego Starwars 3: |
| 0000000: 00 8c 03 00 00 00 04 00 00 00 00 00 00 00 00 00 ................ | | 0000000: 00 8c 03 00 00 00 04 00 00 00 00 00 00 00 00 00 ................ |
| 0000010: b3 cf fb c6 6a b1 cb 20 32 af ce 35 d4 1c 74 c9 ....j.. 2..5..t. | | 0000010: b3 cf fb c6 6a b1 cb 20 32 af ce 35 d4 1c 74 c9 ....j.. 2..5..t. |
Line 202: |
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: |
| + | |
| + | # Set the [[AES_Registers|AES keyslot 0x3b keyY]] to the values at 0x000:0x010. The corresponding keyX is set in [[Bootloader|Boot9]]. |
| + | # 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. |
| + | # Split the primary seed into two halves: left and right. |
| + | # 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. |
| + | # Call the SNOW 2.0 stream cipher 32 times to obtain 1024 bits (32 words) of output. Discard them. |
| + | # 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. |
| + | # 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: |
| + | |
| + | # 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. |
| + | # Call the SNOW 2.0 stream cipher 32 times to obtain 1024 bits (32 words) of output. Discard them. |
| + | # 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. |
| + | # 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. |