Difference between revisions of "DSi cartridge header"
m (NDSHeader moved to NDS Format) |
Hallowizer (talk | contribs) m (Hallowizer moved page DSi Cartridge Header to DSi cartridge header: Proper casing) |
||
(18 intermediate revisions by 5 users not shown) | |||
Line 5: | Line 5: | ||
! OFFSET | ! OFFSET | ||
! SIZE | ! SIZE | ||
− | ! DESCRIPTION | + | ! DESCRIPTION - ORIGINAL NDS ENTRIES |
|- | |- | ||
| 0x000 | | 0x000 | ||
Line 21: | Line 21: | ||
| 0x012 | | 0x012 | ||
| 1 | | 1 | ||
− | | Unitcode | + | | Unitcode (00h=NDS, 02h=NDS+DSi, 03h=DSi) (bit1=DSi) |
+ | |||
|- | |- | ||
| 0x013 | | 0x013 | ||
Line 32: | Line 33: | ||
|- | |- | ||
| 0x015 | | 0x015 | ||
− | | | + | | 7 |
| Reserved | | Reserved | ||
+ | |- | ||
+ | | 0x01C | ||
+ | | 2 | ||
+ | | Game Revision (used by DSi titles) | ||
|- | |- | ||
| 0x01E | | 0x01E | ||
Line 101: | Line 106: | ||
| 0x058 | | 0x058 | ||
| 4 | | 4 | ||
− | | | + | | ARM7 overlay offset |
|- | |- | ||
| 0x05C | | 0x05C | ||
| 4 | | 4 | ||
− | | | + | | ARM7 overlay length |
|- | |- | ||
| 0x060 | | 0x060 | ||
Line 117: | Line 122: | ||
| 0x068 | | 0x068 | ||
| 4 | | 4 | ||
− | | Icon Banner offset | + | | Icon Banner offset (same as NDS, but with new extra entries) |
+ | |||
|- | |- | ||
| 0x06C | | 0x06C | ||
Line 141: | Line 147: | ||
| 0x080 | | 0x080 | ||
| 4 | | 4 | ||
− | | NTR region ROM size | + | | NTR region ROM size (excluding DSi area) |
|- | |- | ||
| 0x084 | | 0x084 | ||
Line 149: | Line 155: | ||
| 0x088 | | 0x088 | ||
| 56 | | 56 | ||
− | | Reserved | + | | Reserved (0x88, 0x8C, 0x90 = Unknown, used by DSi) |
|- | |- | ||
| 0x0C0 | | 0x0C0 | ||
Line 166: | Line 172: | ||
| 32 | | 32 | ||
| Debugger reserved | | Debugger reserved | ||
+ | |- | ||
+ | ! OFFSET | ||
+ | ! SIZE | ||
+ | ! DESCRIPTION - EXTENDED DSi ENTRIES | ||
|- | |- | ||
| 0x180 | | 0x180 | ||
− | | | + | | 20 |
− | | | + | | Global MBK1..MBK5 Settings |
+ | |- | ||
+ | | 0x194 | ||
+ | | 12 | ||
+ | | Local MBK6..MBK8 Settings for ARM9 | ||
+ | |- | ||
+ | | 0x1A0 | ||
+ | | 12 | ||
+ | | Local MBK6..MBK8 Settings for ARM7 | ||
+ | |- | ||
+ | | 0x1AC | ||
+ | | 4 | ||
+ | | Global MBK9 Setting | ||
+ | |- | ||
+ | | 0x1B0 | ||
+ | | 4 | ||
+ | | Region Flags | ||
|- | |- | ||
| 0x1B4 | | 0x1B4 | ||
Line 181: | Line 207: | ||
| 0x1BC | | 0x1BC | ||
| 4 | | 4 | ||
− | | Reserved | + | | Reserved/flags? When bit2 of byte 0x1bf is set, usage of banner.sav from the title data dir is enabled.(additional banner data) |
|- | |- | ||
| 0x1C0 | | 0x1C0 | ||
Line 205: | Line 231: | ||
| 0x1D4 | | 0x1D4 | ||
| 4 | | 4 | ||
− | | | + | | Pointer to [[base address where various structures and parameters are passed to the title]] - what is that??? |
|- | |- | ||
| 0x1D8 | | 0x1D8 | ||
Line 256: | Line 282: | ||
|- | |- | ||
| 0x208 | | 0x208 | ||
− | | | + | | 4 |
− | | | + | | Icon Banner Size (usually 0x23C0) |
+ | |- | ||
+ | | 0x20C | ||
+ | | 4 | ||
+ | | Unknown (used by DSi) | ||
+ | |- | ||
+ | | 0x210 | ||
+ | | 4 | ||
+ | | NTR+TWL region ROM size (total size including DSi area) | ||
+ | |- | ||
+ | | 0x214 | ||
+ | | 12 | ||
+ | | Unknown (used by DSi) | ||
+ | |- | ||
+ | | 0x220 | ||
+ | | 4 | ||
+ | | Modcrypt area 1 offset | ||
+ | |- | ||
+ | | 0x224 | ||
+ | | 4 | ||
+ | | Modcrypt area 1 size | ||
+ | |- | ||
+ | | 0x228 | ||
+ | | 4 | ||
+ | | Modcrypt area 2 offset | ||
+ | |- | ||
+ | | 0x22C | ||
+ | | 4 | ||
+ | | Modcrypt area 2 size | ||
|- | |- | ||
| 0x230 | | 0x230 | ||
Line 264: | Line 318: | ||
|- | |- | ||
| 0x238 | | 0x238 | ||
− | | | + | | 4 |
− | | Reserved | + | | DSiWare: "public.sav" size |
+ | |- | ||
+ | | 0x23C | ||
+ | | 4 | ||
+ | | DSiWare: "private.sav" size | ||
+ | |- | ||
+ | | 0x240 | ||
+ | | 176 | ||
+ | | Reserved (zero) | ||
+ | |- | ||
+ | | 0x2F0 | ||
+ | | 16 | ||
+ | | Unknown (used by DSi) | ||
|- | |- | ||
| 0x300 | | 0x300 | ||
Line 277: | Line 343: | ||
| 0x328 | | 0x328 | ||
| 20 | | 20 | ||
− | | Digest | + | | Digest master SHA1 HMAC hash |
|- | |- | ||
| 0x33C | | 0x33C | ||
Line 297: | Line 363: | ||
| 0x3A0 | | 0x3A0 | ||
| 20 | | 20 | ||
− | | | + | | ARM9 (without secure area) SHA1 HMAC hash |
|- | |- | ||
| 0x3B4 | | 0x3B4 | ||
Line 309: | Line 375: | ||
| 0xF80 | | 0xF80 | ||
| 0x80 | | 0x80 | ||
− | | RSA signature | + | | RSA signature (the first 0xE00 bytes of the header are signed with an 1024-bit RSA signature). |
|} | |} | ||
− | The first | + | = Modcrypt = |
+ | Modcrypt is a new additional way of encrypting parts of the NDS ROM executable binary modules using AES CTR. It is mostly being used to encrypt the ARM9i and ARM7i binaries. For example, DSi hybrid card based games have only the ARM9i binary encrypted, while NAND based applications have both the ARM9i and ARM7i binaries encrypted. The modcrypt areas can span over any of the ARM9/ARM7/ARM9i/ARM7i areas. | ||
+ | |||
+ | The AES counter used for modcrypt area 1 is the first 16 bytes of the ARM9 SHA1 HMAC hash (0x300), and for area 2 the first 16 bytes of the ARM7 SHA1 HMAC hash (0x314). The AES key used is a little more complicated. The header can specify to use a secure or insecure key: | ||
+ | |||
+ | if ( (header[0x1C] & 4) || (header[0x1BF] & 0x80) ) | ||
+ | keytype = INSECURE; | ||
+ | else | ||
+ | keytype = SECURE; | ||
+ | |||
+ | The insecure key is simply the first 16 bytes of the header. The secure key is constructed from a scrambled key pair, where one part is based on an 8-byte shared secret between all DSi's and an 8-byte expanded gamecode, and the other part is based on the first 16 bytes of the ARM9i SHA1 HMAC hash (0x350). The key pair is scrambled in an unknown way to form the final secure key. | ||
+ | |||
+ | It is likely that the insecure key is only used for a debug version of an application, since most card based and NAND based applications are using the secure key. | ||
+ | |||
+ | |||
+ | = Digests = | ||
+ | The NDS format has been extended with a hash tree to verify the entire contents of an NDS ROM. The NDS ROM is divided into sectors, and each sector will be hashed and have its hash stored in the digest sector hashtable. The size of a sector is defined in the header aswell. Furthermore, the sector hashtable is partitioned and hashed again to form block hashes. This block hashtable is hashed again into a single hash called the digest master hash. These hashtables can be used to verify that the sectors of a NDS ROM have not been tampered with, since the integrity of a sector hash can be verified by a block hash, which in turn can be verified by the master hash. And this hash is part of the header, which is signed with RSA. | ||
+ | |||
+ | The sector hashtable reaches over the NTR and TWL regions, respectively. | ||
+ | |||
+ | = See Also = | ||
+ | |||
+ | * [[Card hardware]] - cartridge bus protocol | ||
+ | * [[Bootloader]] - boot procedure |
Latest revision as of 22:34, 19 August 2021
The following tries to document the structure of the NDS ROM format and its DSi extended version.
OFFSET | SIZE | DESCRIPTION - ORIGINAL NDS ENTRIES |
---|---|---|
0x000 | 12 | Game Title |
0x00C | 4 | Gamecode |
0x010 | 2 | Makercode |
0x012 | 1 | Unitcode (00h=NDS, 02h=NDS+DSi, 03h=DSi) (bit1=DSi) |
0x013 | 1 | Encryption seed select |
0x014 | 1 | Devicecapacity |
0x015 | 7 | Reserved |
0x01C | 2 | Game Revision (used by DSi titles) |
0x01E | 1 | ROM Version |
0x01F | 1 | Internal flags, (Bit2: Autostart) |
0x020 | 4 | ARM9 rom offset |
0x024 | 4 | ARM9 entry address |
0x028 | 4 | ARM9 load address |
0x02C | 4 | ARM9 size |
0x030 | 4 | ARM7 rom offset |
0x034 | 4 | ARM7 entry address |
0x038 | 4 | ARM7 load address |
0x03C | 4 | ARM7 size |
0x040 | 4 | File Name Table (FNT) offset |
0x044 | 4 | File Name Table (FNT) length |
0x048 | 4 | File Allocation Table (FAT) offset |
0x04C | 4 | File Allocation Table (FAT) length |
0x050 | 4 | ARM9 overlay offset |
0x054 | 4 | ARM9 overlay length |
0x058 | 4 | ARM7 overlay offset |
0x05C | 4 | ARM7 overlay length |
0x060 | 4 | Normal card control register settings |
0x064 | 4 | Secure card control register settings |
0x068 | 4 | Icon Banner offset (same as NDS, but with new extra entries) |
0x06C | 2 | Secure area (2K) CRC |
0x06E | 2 | Secure transfer timeout |
0x070 | 4 | ARM9 autoload |
0x074 | 4 | ARM7 autoload |
0x078 | 8 | Secure disable |
0x080 | 4 | NTR region ROM size (excluding DSi area) |
0x084 | 4 | Header size |
0x088 | 56 | Reserved (0x88, 0x8C, 0x90 = Unknown, used by DSi) |
0x0C0 | 156 | Nintendo Logo |
0x15C | 2 | Nintendo Logo CRC |
0x15E | 2 | Header CRC |
0x160 | 32 | Debugger reserved |
OFFSET | SIZE | DESCRIPTION - EXTENDED DSi ENTRIES |
0x180 | 20 | Global MBK1..MBK5 Settings |
0x194 | 12 | Local MBK6..MBK8 Settings for ARM9 |
0x1A0 | 12 | Local MBK6..MBK8 Settings for ARM7 |
0x1AC | 4 | Global MBK9 Setting |
0x1B0 | 4 | Region Flags |
0x1B4 | 4 | Access control |
0x1B8 | 4 | ARM7 SCFG EXT mask (controls which devices to enable) |
0x1BC | 4 | Reserved/flags? When bit2 of byte 0x1bf is set, usage of banner.sav from the title data dir is enabled.(additional banner data) |
0x1C0 | 4 | ARM9i rom offset |
0x1C4 | 4 | Reserved |
0x1C8 | 4 | ARM9i load address |
0x1CC | 4 | ARM9i size |
0x1D0 | 4 | ARM7i rom offset |
0x1D4 | 4 | Pointer to base address where various structures and parameters are passed to the title - what is that??? |
0x1D8 | 4 | ARM7i load address |
0x1DC | 4 | ARM7i size |
0x1E0 | 4 | Digest NTR region offset |
0x1E4 | 4 | Digest NTR region length |
0x1E8 | 4 | Digest TWL region offset |
0x1EC | 4 | Digest TWL region length |
0x1F0 | 4 | Digest Sector Hashtable offset |
0x1F4 | 4 | Digest Sector Hashtable length |
0x1F8 | 4 | Digest Block Hashtable offset |
0x1FC | 4 | Digest Block Hashtable length |
0x200 | 4 | Digest Sector size |
0x204 | 4 | Digest Block sectorcount |
0x208 | 4 | Icon Banner Size (usually 0x23C0) |
0x20C | 4 | Unknown (used by DSi) |
0x210 | 4 | NTR+TWL region ROM size (total size including DSi area) |
0x214 | 12 | Unknown (used by DSi) |
0x220 | 4 | Modcrypt area 1 offset |
0x224 | 4 | Modcrypt area 1 size |
0x228 | 4 | Modcrypt area 2 offset |
0x22C | 4 | Modcrypt area 2 size |
0x230 | 8 | Title ID |
0x238 | 4 | DSiWare: "public.sav" size |
0x23C | 4 | DSiWare: "private.sav" size |
0x240 | 176 | Reserved (zero) |
0x2F0 | 16 | Unknown (used by DSi) |
0x300 | 20 | ARM9 (with encrypted secure area) SHA1 HMAC hash |
0x314 | 20 | ARM7 SHA1 HMAC hash |
0x328 | 20 | Digest master SHA1 HMAC hash |
0x33C | 20 | Banner SHA1 HMAC hash |
0x350 | 20 | ARM9i (decrypted) SHA1 HMAC hash |
0x364 | 20 | ARM7i (decrypted) SHA1 HMAC hash |
0x378 | 40 | Reserved |
0x3A0 | 20 | ARM9 (without secure area) SHA1 HMAC hash |
0x3B4 | 2636 | Reserved |
0xE00 | 0x180 | Reserved and unchecked region, always zero. Used for passing arguments in debug environment. |
0xF80 | 0x80 | RSA signature (the first 0xE00 bytes of the header are signed with an 1024-bit RSA signature). |
Modcrypt
Modcrypt is a new additional way of encrypting parts of the NDS ROM executable binary modules using AES CTR. It is mostly being used to encrypt the ARM9i and ARM7i binaries. For example, DSi hybrid card based games have only the ARM9i binary encrypted, while NAND based applications have both the ARM9i and ARM7i binaries encrypted. The modcrypt areas can span over any of the ARM9/ARM7/ARM9i/ARM7i areas.
The AES counter used for modcrypt area 1 is the first 16 bytes of the ARM9 SHA1 HMAC hash (0x300), and for area 2 the first 16 bytes of the ARM7 SHA1 HMAC hash (0x314). The AES key used is a little more complicated. The header can specify to use a secure or insecure key:
if ( (header[0x1C] & 4) || (header[0x1BF] & 0x80) ) keytype = INSECURE; else keytype = SECURE;
The insecure key is simply the first 16 bytes of the header. The secure key is constructed from a scrambled key pair, where one part is based on an 8-byte shared secret between all DSi's and an 8-byte expanded gamecode, and the other part is based on the first 16 bytes of the ARM9i SHA1 HMAC hash (0x350). The key pair is scrambled in an unknown way to form the final secure key.
It is likely that the insecure key is only used for a debug version of an application, since most card based and NAND based applications are using the secure key.
Digests
The NDS format has been extended with a hash tree to verify the entire contents of an NDS ROM. The NDS ROM is divided into sectors, and each sector will be hashed and have its hash stored in the digest sector hashtable. The size of a sector is defined in the header aswell. Furthermore, the sector hashtable is partitioned and hashed again to form block hashes. This block hashtable is hashed again into a single hash called the digest master hash. These hashtables can be used to verify that the sectors of a NDS ROM have not been tampered with, since the integrity of a sector hash can be verified by a block hash, which in turn can be verified by the master hash. And this hash is part of the header, which is signed with RSA.
The sector hashtable reaches over the NTR and TWL regions, respectively.
See Also
- Card hardware - cartridge bus protocol
- Bootloader - boot procedure