Difference between revisions of "XCI"
(RE'd from GameCardWriter) |
|||
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. |
Revision as of 21:14, 1 June 2018
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.
Offset | Size | Description |
---|---|---|
0x0 | 0x100 | RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200) |
0x100 | 0x4 | Magicnum "HEAD" |
0x104 | 0x4 | Write Size (size of non-secure data in Media Units which are 0x200 bytes) |
0x108 | 0x4 | 0xFFFFFFFF |
0x10C | 0x1 | KEK Index |
0x10D | 0x1 | Gamecard Type (0xFA = 1GB, 0xF8 = 2GB, 0xF0 = 4GB, 0xE0 = 8GB, 0xE1 = 16GB, 0xE2 = 32GB) |
0x10E | 0x1 | ? |
0x10F | 0x1 | Gamecard Options (bit0 = AutoBoot, bit1 = HistoryErase) |
0x110 | 0x8 | Random value for challenge–response authentication |
0x118 | 0x8 | Gamecard Size (in Media Units which are 0x200 bytes) |
0x120 | 0x10 | Gamecard Info IV (reversed) |
0x130 | 0x8 | HFS0 partition offset |
0x138 | 0x8 | HFS0 header size |
0x140 | 0x20 | SHA-256 hash of the HFS0 Header |
0x160 | 0x20 | SHA-256 hash of the Initial Data |
0x180 | 0x4 | Secure Mode Flag (0x01 means Secure Mode is available) |
0x184 | 0x4 | 2? |
0x188 | 0x4 | 0? |
0x18C | 0x4 | Duplicate Write Size (size of non-secure data in Media Units which are 0x200 bytes) |
0x190 | 0x70 | Gamecard Info (AES-128-CBC encrypted) |
Gamecard Info
When decrypted, this 0x70 byte region is as follows:
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.
FS IDeviceOperator cmd 206 "GetGameCardDeviceCertificate" retrieves this data.
Offset | Size | Description |
---|---|---|
0x0 | 0x100 | RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200 |
0x100 | 0x4 | Magicnum "CERT" |
0x110 | 0x10 | ? |
0x120 | 0xA | ? |
0x12A | 0xD6 | Encrypted data. Some kind of key? |
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.
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.
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Random value from Gamecard Header at offset 0x110 |
0x8 | 0x8 | Empty |
0x10 | 0x2C | Challenge–response authentication data |
0x3C | 0x1C4 | Reserved (must be empty) |
HFS0
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.
File System
The actual file system is as follows (also valid for the root partition):
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Magicnum "HFS0" |
0x4 | 0x4 | Number of files |
0x8 | 0x4 | Size of the string table |
0xC | 0x4 | Zero/Reserved |
0x10 | X | File Entry Table |
0x10 + X | Y | String Table |
0x10 + X + Y | Z | Raw File Data |
Where File Entry Table consists of Number of Files FileEntries:
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Offset of file in Data |
0x8 | 0x8 | Size of file in Data |
0x10 | 0x4 | Offset of filename in String Table |
0x14 | 0x4 | Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200) |
0x18 | 8 | Zero/Reserved |
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?).
Cartridge Layout
Observed gamecards contain three partitions: "update", "normal", and "secure".
The update partition (Gamecard partition 0 for fsp-srv cmd 31) contains .cnmt.nca + .nca files for the entire system update required to play the game. Launch day carts contain a full copy of 1.0 ncas, newer carts contain newer sysupdate NCAs etc.
The normal partition contains the .cnmt.nca and the game icondata nca. This is presumably for future compatibility so that if a future update changes the cryptographic protocol for the secure partition, Game icon data can still be shown in the home menu on old firmwares.
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 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.