XCI: Difference between revisions
RE'd from GameCardWriter |
No edit summary |
||
Line 1: | Line 1: | ||
= Header = | Known internally as "XCI" (NX Card Image), this is the format used for storing the contents of a Nintendo Switch Gamecard. | ||
= Gamecard Header = | |||
This header is 0x200 bytes and is located at offset 0 in the Gamecard. | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 10: | Line 12: | ||
| 0x0 | | 0x0 | ||
| 0x100 | | 0x100 | ||
| RSA-2048 PKCS #1 signature over the | | RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200) | ||
|- | |- | ||
| 0x100 | | 0x100 | ||
Line 26: | Line 28: | ||
| 0x10C | | 0x10C | ||
| 0x1 | | 0x1 | ||
| | | KEK Index | ||
|- | |- | ||
| 0x10D | | 0x10D | ||
Line 42: | Line 44: | ||
| 0x110 | | 0x110 | ||
| 0x8 | | 0x8 | ||
| | | Random value for challenge–response authentication | ||
|- | |- | ||
| 0x118 | | 0x118 | ||
Line 50: | Line 52: | ||
| 0x120 | | 0x120 | ||
| 0x10 | | 0x10 | ||
| Gamecard | | Gamecard Info IV (reversed) | ||
|- | |- | ||
| 0x130 | | 0x130 | ||
Line 62: | Line 64: | ||
| 0x140 | | 0x140 | ||
| 0x20 | | 0x20 | ||
| | | SHA-256 hash of the [[#HFS0 Header|HFS0 Header]] | ||
|- | |- | ||
| 0x160 | | 0x160 | ||
| 0x20 | | 0x20 | ||
| | | SHA-256 hash of the [[#Initial Data|Initial Data]] | ||
|- | |- | ||
| 0x180 | | 0x180 | ||
| 0x4 | | 0x4 | ||
| | | Secure Mode Flag (0x01 means Secure Mode is available) | ||
|- | |- | ||
| 0x184 | | 0x184 | ||
Line 86: | Line 88: | ||
| 0x190 | | 0x190 | ||
| 0x70 | | 0x70 | ||
| Gamecard | | [[#Gamecard Info|Gamecard Info]] (AES-128-CBC encrypted) | ||
|} | |} | ||
= | == Gamecard Info == | ||
When decrypted, this 0x70 byte region is as follows: | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x4 | |||
| Version (0x01 for old Gamecards, 0x02 for new Gamecards with the "logo" partition) | |||
|- | |||
| 0x4 | |||
| 0x4 | |||
| Empty | |||
|- | |||
| 0x8 | |||
| 0x4 | |||
| Always 0x00A10010 (unfinalized Gamecard) or 0x00A10011 (finalized Gamecard) | |||
|- | |||
| 0xC | |||
| 0x4 | |||
| Always 0x1388 | |||
|- | |||
| 0x10 | |||
| 0xC | |||
| Empty | |||
|- | |||
| 0x1C | |||
| 0x4 | |||
| ? | |||
|- | |||
| 0x20 | |||
| 0x4 | |||
| ? | |||
|- | |||
| 0x24 | |||
| 0x4 | |||
| Empty | |||
|- | |||
| 0x28 | |||
| 0x8 | |||
| Random ID? | |||
|- | |||
| 0x30 | |||
| 0x8 | |||
| Always 0x0100000000000816 (title-listing data archive's title ID) | |||
|- | |||
| 0x38 | |||
| 0x38 | |||
| Empty | |||
|} | |||
= Gamecard Certificate = | |||
This is the Gamecard's unique certificate and is located at offset 0x7000. | |||
[[Filesystem_services|FS]] IDeviceOperator cmd 206 "GetGameCardDeviceCertificate" retrieves this data. | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 100: | Line 158: | ||
| 0x0 | | 0x0 | ||
| 0x100 | | 0x100 | ||
| RSA-2048 PKCS #1 signature over the data from 0x100 | | RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200 | ||
|- | |- | ||
| 0x100 | | 0x100 | ||
Line 108: | Line 166: | ||
| 0x110 | | 0x110 | ||
| 0x10 | | 0x10 | ||
| ? | |||
|- | |||
| 0x120 | |||
| 0xA | |||
| ? | | ? | ||
|- | |- | ||
Line 115: | Line 177: | ||
|} | |} | ||
The data between the | The data between the Gamecard Certificate and the start of the HFS0 region is all 0xFF. | ||
= Initial Data = | |||
This data is used for challenge–response authentication when changing to the Gamecard's secure mode. | |||
[[Filesystem_services|FS]] calculates a SHA-256 hash over the whole 0x200 bytes and compares it with the hash stored at offset 0x160 in the [[#Gamecard Header|Gamecard Header]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| Random value from [[#Gamecard Header|Gamecard Header]] at offset 0x110 | |||
|- | |||
| 0x8 | |||
| 0x8 | |||
| Empty | |||
|- | |||
| 0x10 | |||
| 0x2C | |||
| Challenge–response authentication data | |||
|- | |||
| 0x3C | |||
| 0x1C4 | |||
| Reserved (must be empty) | |||
|} | |||
= HFS0 = | = HFS0 = | ||
This is the | This is the Gamecard file system which starts with magicnum "HFS0". | ||
== Header == | |||
The "SHA-256 File System" or "HFS0" starts at offset 0xF000 in the Gamecard. The first 0x200 bytes act as a global header and represent the root partition which points to the other partitions ("normal", "logo", "update" and "secure). | |||
A hash for this header is stored at offset 0x140 in the [[#Gamecard Header|Gamecard Header]]. | |||
== File System == | |||
The actual file system is as follows (also valid for the root partition): | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 128: | Line 226: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| HFS0 | | Magicnum "HFS0" | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
Line 177: | Line 275: | ||
| 0x14 | | 0x14 | ||
| 0x4 | | 0x4 | ||
| Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200) | | Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200) | ||
|- | |- | ||
| 0x18 | | 0x18 | ||
Line 185: | Line 283: | ||
| 0x20 | | 0x20 | ||
| 0x20 | | 0x20 | ||
| | | SHA-256 hash of the first (size of hashed region) bytes of filedata | ||
|} | |} | ||
The string table is 00-padded to align the start of raw filedata with a sector/media unit boundary (usually?). | The string table is 00-padded to align the start of raw filedata with a sector/media unit boundary (usually?). | ||
= | = Cartridge Layout = | ||
Observed gamecards contain three partitions: "update", "normal", and "secure". | Observed gamecards contain three partitions: "update", "normal", and "secure". | ||
Line 199: | Line 297: | ||
The secure partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. | The secure partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. | ||
The entire rest of the | The entire rest of the Gamecard after the secure partition ends is all FF padding. | ||
[4.0.0+] The "normal" partition is now empty and a new partition "logo" was added. | [4.0.0+] The "normal" partition is now empty and a new partition "logo" was added. |