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. |
− | The header is 0x200-bytes at offset 0 in the 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 XCI header (data from 0x100 to 0x200) | + | | 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 Initial Data IV (reversed) | + | | Gamecard Info IV (reversed) |
| |- | | |- |
| | 0x130 | | | 0x130 |
Line 62: |
Line 64: |
| | 0x140 | | | 0x140 |
| | 0x20 | | | 0x20 |
− | | SHA256 hash of the HFS0 Header | + | | SHA-256 hash of the [[#HFS0 Header|HFS0 Header]] |
| |- | | |- |
| | 0x160 | | | 0x160 |
| | 0x20 | | | 0x20 |
− | | SHA256 hash of the crypto header | + | | SHA-256 hash of the [[#Initial Data|Initial Data]] |
| |- | | |- |
| | 0x180 | | | 0x180 |
| | 0x4 | | | 0x4 |
− | | 1? | + | | Secure Mode Flag (0x01 means Secure Mode is available) |
| |- | | |- |
| | 0x184 | | | 0x184 |
Line 86: |
Line 88: |
| | 0x190 | | | 0x190 |
| | 0x70 | | | 0x70 |
− | | Gamecard Initial Data (AES-128-CBC encrypted) | + | | [[#Gamecard Info|Gamecard Info]] (AES-128-CBC encrypted) |
| |} | | |} |
| | | |
− | = Cert = | + | == Gamecard Info == |
− | This is for the CERT, located at Gamecard + 0x7000 (always?). This matches exactly the output from fsp-srv IDeviceOperator cmd 206 "GetGameCardDeviceCertificate".
| + | 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 - 0x200. | + | | 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 CERT and the start of the HFS0 is all 0xFF. | + | 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 FS which has magicnum "HFS0" at header+0. | + | 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 Magic | + | | 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 |
− | | SHA256 hash of the first (size of hashed region) bytes of filedata. | + | | 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?). |
| | | |
− | = Typical Cartridge Layout = | + | = 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 gamecard after the secure partition ends is all FF padding. | + | 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. |