Changes

Jump to navigation Jump to search
5,060 bytes added ,  2 June
→‎InitialData: Fix struct being too large caused by having redundant data
Line 25: Line 25:  
| 2
 
| 2
 
| [[Download Play]] Child container ([[NCCH#CFA|CFA]])
 
| [[Download Play]] Child container ([[NCCH#CFA|CFA]])
 +
|-
 +
| 6
 +
| New3DS [[System_Update_CFA|Update Data]] ([[NCCH#CFA|CFA]])
 
|-
 
|-
 
| 7
 
| 7
Line 61: Line 64:  
|  0x118
 
|  0x118
 
|  8
 
|  8
|  Partitions crypt type  
+
|  Partitions crypt type (each byte corresponds to a partition in the partition table)
 
|-
 
|-
 
|  0x120
 
|  0x120
Line 100: Line 103:  
|-
 
|-
 
|  0x1D0
 
|  0x1D0
0x30
+
0x20
 
|  Reserved
 
|  Reserved
 +
|-
 +
| 0x1F0
 +
| 0xE
 +
| Reserved?
 +
|-
 +
| 0x1FE
 +
| 0x1
 +
| Support for this was implemented with [[9.6.0-24|9.6.0-X]] FIRM. Bit0=1 enables using bits 1-2, it's unknown what these two bits are actually used for(the value of these two bits get compared with some other value during NCSD verification/loading). This appears to enable a new, likely hardware-based, antipiracy check on cartridges.
 +
|-
 +
| 0x1FF
 +
| 0x1
 +
| Support for this was implemented with [[9.6.0-24|9.6.0-X]] FIRM, see below regarding save crypto.
 
|}
 
|}
   Line 121: Line 136:  
|}
 
|}
    +
=== NCSD Signature ===
 +
The RSA public key used for gamecard NCSD is stored in [[Memory_layout|ITCM]]. The separate public key used for NAND NCSD is stored in Process9 .(ro)data instead of ITCM, and in [[Bootloader|boot ROM]].
 +
 +
For the boot ROM check, sighax may be used to fake-sign NAND headers.  Process9's check will fail, however, unless patched.
    
=== Partition Flags ===
 
=== Partition Flags ===
Line 154: Line 173:  
|-
 
|-
 
| 1
 
| 1
| Starting with [[6.0.0-11]] NATIVE_FIRM will use this flag to determine the gamecard [[Savegames|savegame]] keyY method, when flag[3] is set. 0 = [[2.0.0-2]] hashed keyY, 1 = [[Savegames|new]] keyY method implemented with [[6.0.0-11]].
+
| Starting with [[6.0.0-11]] NATIVE_FIRM will use this flag to determine the gamecard [[Savegames|savegame]] keyY method, when flag[3] is set. 0 = [[2.0.0-2]] hashed keyY, 1 = [[Savegames|new]] keyY method implemented with [[6.0.0-11]]. 0x0A = implemented with [[9.3.0-21|9.3.0-X]]. On Old3DS this is identical to the [[2.2.0-4]] crypto. On New3DS this is identical to the [[2.2.0-4]] crypto, except with New3DS-only gamecard savedata [[AES|keyslots]].
 +
Starting with [[9.6.0-24|9.6.0-X]] FIRM, Process9 now sets <savecrypto_stateval> to partitionflag[1] + <the u8 value from NCSD+0x1FF>, instead of just setting it to partitionflag[1].
 
|-
 
|-
 
| 3
 
| 3
 
| Support for this flag was implemented in NATIVE_FIRM with [[2.0.0-2]]. When this flag is set the hashed gamecard [[Savegames|savegame]] keyY method is used, this likely still uses the repeating-CTR however. With [[6.0.0-11]] the system will determine the gamecard savegame keyY method via flag[1], instead of just using the hashed keyY via this flag.
 
| Support for this flag was implemented in NATIVE_FIRM with [[2.0.0-2]]. When this flag is set the hashed gamecard [[Savegames|savegame]] keyY method is used, this likely still uses the repeating-CTR however. With [[6.0.0-11]] the system will determine the gamecard savegame keyY method via flag[1], instead of just using the hashed keyY via this flag.
|-
+
|-th
 
| 7
 
| 7
 
| This flag enables using the hashed gamecard [[Savegames|savegame]] keyY method, support for this flag was implemented in NATIVE_FIRM with [[2.2.0-4]]. All games with the NCSD image finalized since [[2.2.0-4]](and contains [[2.2.0-4]]+ in the system update partition) have this flag set, this flag also enables using new CTR method as well.
 
| This flag enables using the hashed gamecard [[Savegames|savegame]] keyY method, support for this flag was implemented in NATIVE_FIRM with [[2.2.0-4]]. All games with the NCSD image finalized since [[2.2.0-4]](and contains [[2.2.0-4]]+ in the system update partition) have this flag set, this flag also enables using new CTR method as well.
 
|}
 
|}
 +
 +
Starting with [[9.6.0-24|9.6.0-X]] FIRM, Process9 will just write val0 to a state field then return 0, instead of returning an error when the save crypto type isn't recognized. This was the *only* actual functionality change in the Old3DS Process9 function for gamecard savedata crypto init.
    
== Card Info Header ==
 
== Card Info Header ==
Line 179: Line 201:  
|-
 
|-
 
|  0x208
 
|  0x208
0xDF8
+
0xF8
Reserved1
+
Reserved
 +
|-
 +
|  0x300
 +
|  4
 +
|  Filled size of cartridge
 +
|-
 +
|  0x304
 +
|  0xC
 +
|  Reserved
 +
|-
 +
|  0x310
 +
|  2
 +
|  Title version
 +
|-
 +
|  0x312
 +
|  2
 +
|  Card revision
 +
|-
 +
|  0x314
 +
|  0xC
 +
|  Reserved
 +
|-
 +
|  0x320
 +
|  8
 +
|  Title ID of [[CVer]] in included update partition
 +
|-
 +
|  0x328
 +
|  2
 +
|  Version number of [[CVer]] in included update partition
 +
|-
 +
|  0x32A
 +
|  0xCD6
 +
|  Reserved
 
|-
 
|-
 
|  0x1000
 
|  0x1000
8
+
0x200
Media ID (same as first NCCH partitionId)
+
InitialData
 +
|}
 +
 
 +
=== InitialData ===
 +
 
 +
This data is returned by [[Gamecards|16-byte cartridge command]] 0x82.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x00
 +
|  0x10
 +
|  Seed (keyY used to decrypt the title key - keyX is keyslot 0x3B for production cards, or a key of all zeroes for development cards), consisting of the title ID (little-endian) followed by reserved data (normally all-zero)
 +
|-
 +
|  0x10
 +
|  0x10
 +
|  TitleKey (AES-CCM encrypted)
 
|-
 
|-
0x1008
+
0x20
8
+
0x10
Reserved2
+
AES-CCM MAC
 
|-
 
|-
|  0x1010
   
|  0x30
 
|  0x30
Initial Data
+
0xC
 +
|  AES-CCM nonce
 
|-
 
|-
0x1040
+
0x3C
0xC0
+
0xC4
|  Reserved
+
|  Reserved (normally all-zero)
 
|-
 
|-
|  0x1100
   
|  0x100
 
|  0x100
Copy of first NCCH header (excluding RSA signature)
+
0x100
 +
|  NcchHeader (copy of the first NCCH header, excluding the RSA signature)
 
|}
 
|}
   Line 216: Line 289:  
|  0x1400
 
|  0x1400
 
|  0x10
 
|  0x10
TitleKey
+
TitleKeyData
 
|-
 
|-
 
|  0x1410
 
|  0x1410
0xF0
+
0x1BF0
 
|  CardDeviceReserved2
 
|  CardDeviceReserved2
 +
|-
 +
|  0x3000
 +
|  0x1000
 +
|  TestData
 
|}
 
|}
 +
 +
TitleKeyData contains the decrypted version of the title key found in the InitialData. This field appears to be what development--and maybe production?--cards read to know what card encryption seed to use in the CTR protocol.
 +
 +
The CardDeviceReserved areas have random-looking data whose purpose is unknown, other than perhaps to hide the TitleKey.
 +
 +
Note that a particular flashcard vendor, namely Gateway, puts what many refer to as "private headers" at CardDeviceReserved1 in place of actual development card information. This header consists of:
 +
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x40
 +
|  Unique cartridge ID; only the first 0x10 bytes are meaningful, the rest are 0xff; obtainable using encrypted [[Gamecards|16-byte cartridge command]] 0xc6; the first 0x10 bytes can also be obtained in userland via [[Process_Services_PXI|pxi:ps9::GetRomId]]
 +
|-
 +
|  0x40
 +
|  0x4
 +
|  Cartridge ID1; obtainable using 8-byte cartridge command 0x90 or 16-byte cartridge command 0xa2
 +
|-
 +
|  0x44
 +
|  0x4
 +
|  Cartridge ID2; obtainable using 8-byte cartridge command 0xa0 or 16-byte cartridge command 0xa4
 +
|-
 +
|  0x48
 +
|  0x8
 +
|  Padding (all-0xff)
 +
|}
 +
 +
The legitimacy of the unique cartridge ID can be validated by online services.
 +
 +
Some dumping tools, notably GodMode9 as of 2024-05-26, erroneously always write 0x00000000 into the position of the Cartridge ID2. This is presumably because the cartridge ID2 is always zero for retail carts.
 +
 +
=== TestData ===
 +
The test data is the same one encountered in development DS/DSi cartridges. Its layout is as follows:
 +
{| class="wikitable" border="1"
 +
|-
 +
!  OFFSET
 +
!  SIZE
 +
!  DESCRIPTION
 +
|-
 +
|  0x0
 +
|  0x8
 +
|  The bytes FF 00 FF 00 AA 55 AA 55.
 +
|-
 +
|  0x8
 +
|  0x1F8
 +
|  An ascending byte sequence equal to the offset mod 256 (08 09 0A ... FE FF 00 01 ... FF).
 +
|-
 +
|  0x200
 +
|  0x200
 +
|  A descending byte sequence equal to 255 minus the offset mod 256 (FF FE FD ... 00 FF DE ... 00).
 +
|-
 +
|  0x400
 +
|  0x200
 +
|  Filled with 00 (0b00000000) bytes.
 +
|-
 +
|  0x600
 +
|  0x200
 +
|  Filled with FF (0b11111111) bytes.
 +
|-
 +
|  0x800
 +
|  0x200
 +
|  Filled with 0F (0b00001111) bytes.
 +
|-
 +
|  0xA00
 +
|  0x200
 +
|  Filled with F0 (0b11110000) bytes.
 +
|-
 +
|  0xC00
 +
|  0x200
 +
|  Filled with 55 (0b01010101) bytes.
 +
|-
 +
|  0xE00
 +
|  0x1FF
 +
|  Filled with AA (0b10101010) bytes.
 +
|-
 +
|  0xFFF
 +
|  0x1
 +
|  The final byte is 00 (0b00000000).
 +
|}
 +
 +
Production cards always return FF when attempting to read 0x1200-0x3FFF. They probably actually have the same data as development cards, but there's no way to read it.
    
== Tools ==
 
== Tools ==

Navigation menu