NCSD: Difference between revisions
→InitialData: Fix struct being too large caused by having redundant data |
|||
(12 intermediate revisions by 7 users not shown) | |||
Line 64: | 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 102: | Line 102: | ||
| Partition ID table | | Partition ID table | ||
|- | |- | ||
| | | 0x1D0 | ||
| | | 0x20 | ||
| Reserved | | Reserved | ||
|- | |- | ||
Line 136: | 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 197: | Line 201: | ||
|- | |- | ||
| 0x208 | | 0x208 | ||
| | | 0xF8 | ||
| | | 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 | ||
| 0x200 | |||
| InitialData | |||
|} | |||
=== InitialData === | |||
This data is returned by [[Gamecards|16-byte cartridge command]] 0x82. | |||
{| class="wikitable" border="1" | |||
|- | |||
! OFFSET | |||
! SIZE | |||
! DESCRIPTION | |||
|- | |||
| 0x00 | |||
| 0x10 | | 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 | ||
| | | 0x10 | ||
| TitleKey (AES-CCM encrypted) | |||
|- | |- | ||
| | | 0x20 | ||
| 0x10 | | 0x10 | ||
| | | AES-CCM MAC | ||
|- | |- | ||
| | | 0x30 | ||
| 0xC | | 0xC | ||
| | | AES-CCM nonce | ||
|- | |- | ||
| | | 0x3C | ||
| 0xC4 | | 0xC4 | ||
| Reserved | | Reserved (normally all-zero) | ||
|- | |- | ||
| 0x100 | | 0x100 | ||
| | | 0x100 | ||
| NcchHeader (copy of the first NCCH header, excluding the RSA signature) | |||
|} | |} | ||
Line 238: | Line 289: | ||
| 0x1400 | | 0x1400 | ||
| 0x10 | | 0x10 | ||
| | | TitleKeyData | ||
|- | |- | ||
| 0x1410 | | 0x1410 | ||
| | | 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 == |