XCI: Difference between revisions
PKCS1 signatures |
mNo edit summary |
||
(37 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
This is the format used for storing the contents of a Nintendo Switch Gamecard. | |||
= Structure = | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 9: | Line 9: | ||
|- | |- | ||
| 0x0 | | 0x0 | ||
| 0x1000 | |||
| [[#CardKeyArea]] | |||
|- | |||
| 0x1000 | |||
| 0x200 | |||
| [[#CardHeader]] | |||
|- | |||
| 0x1200 | |||
| 0x200 | |||
| [11.0.0+] [[#NewCardHeader]] | |||
|- | |||
| 0x1400 | |||
| 0x400 | |||
| [11.0.0+] [[#NewCardHeaderCertArea]] | |||
|- | |||
| 0x1800 | |||
| 0x100 | | 0x100 | ||
| RSA-2048 PKCS #1 signature over the data from 0x100 | | [11.0.0+] NewCardHeaderCertAreaModulus | ||
|- | |||
| 0x1900 | |||
| 0x6700 | |||
| Reserved | |||
|- | |||
| 0x8000 | |||
| 0x8000 | |||
| [[#CertArea]] | |||
|- | |||
| 0x10000 | |||
| Variable | |||
| [[#NormalArea]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#RomArea]] | |||
|- | |||
| Invalid | |||
| Invalid | |||
| BackupArea | |||
|} | |||
== CardKeyArea == | |||
This region cannot be read directly once written to the Gamecard. Therefore, it is hidden away during read/write operations on the raw Gamecard data. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x200 | |||
| [[#InitialData]] | |||
|- | |||
| 0x200 | |||
| 0xD00 | |||
| [[#TitleKeyArea]] | |||
|- | |||
| 0xF00 | |||
| 0x100 | |||
| Reserved | |||
|} | |||
=== InitialData === | |||
This region 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 [[#CardHeader]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| Package ID from [[#CardHeader]] at offset 0x110 | |||
|- | |||
| 0x8 | |||
| 0x8 | |||
| Reserved | |||
|- | |||
| 0x10 | |||
| 0x10 | |||
| Challenge–response authentication data | |||
|- | |||
| 0x20 | |||
| 0x10 | |||
| Challenge–response authentication MAC | |||
|- | |||
| 0x30 | |||
| 0xC | |||
| Challenge–response authentication Nonce | |||
|- | |||
| 0x3C | |||
| 0x1C4 | |||
| Reserved (must be empty) | |||
|} | |||
=== TitleKeyArea === | |||
This region is stored encrypted and contains the title keys used by the [[#InitialData]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| TitleKey1 | |||
|- | |||
| 0x8 | |||
| 0x8 | |||
| TitleKey2 | |||
|- | |||
| 0x10 | |||
| 0xCF0 | |||
| Reserved | |||
|} | |||
== CardHeader == | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x100 | |||
| RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200) | |||
|- | |- | ||
| 0x100 | | 0x100 | ||
| 0x4 | | 0x4 | ||
| | | Magic ("HEAD") | ||
|- | |- | ||
| 0x104 | | 0x104 | ||
| 0x4 | | 0x4 | ||
| | | RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes) | ||
|- | |- | ||
| 0x108 | | 0x108 | ||
| 0x4 | | 0x4 | ||
| 0xFFFFFFFF | | BackupAreaStartPageAddress (always 0xFFFFFFFF) | ||
|- | |- | ||
| 0x10C | | 0x10C | ||
| 0x1 | | 0x1 | ||
| | | TitleKeyDecIndex (high nibble) and KekIndex (low nibble) | ||
|- | |- | ||
| 0x10D | | 0x10D | ||
| 0x1 | | 0x1 | ||
| | | [[#RomSize]] | ||
|- | |- | ||
| 0x10E | | 0x10E | ||
| 0x1 | | 0x1 | ||
| | | [[#Version]] | ||
|- | |- | ||
| 0x10F | | 0x10F | ||
| 0x1 | | 0x1 | ||
| | | [[#Flags]] | ||
|- | |- | ||
| 0x110 | | 0x110 | ||
| 0x8 | | 0x8 | ||
| | | PackageId (used for challenge–response authentication) | ||
|- | |- | ||
| 0x118 | | 0x118 | ||
| 0x4 | |||
| ValidDataEndAddress (in Gamecard page units, which are 0x200 bytes) | |||
|- | |||
| 0x11C | |||
| 0x4 | |||
| Reserved | |||
|- | |||
| 0x120 | |||
| 0x10 | |||
| Iv (reversed) | |||
|- | |||
| 0x130 | |||
| 0x8 | |||
| PartitionFsHeaderAddress | |||
|- | |||
| 0x138 | |||
| 0x8 | |||
| PartitionFsHeaderSize | |||
|- | |||
| 0x140 | |||
| 0x20 | |||
| PartitionFsHeaderHash (SHA-256 hash of the [[#PartitionFsHeader]]) | |||
|- | |||
| 0x160 | |||
| 0x20 | |||
| InitialDataHash (SHA-256 hash of the [[#InitialData]]) | |||
|- | |||
| 0x180 | |||
| 0x4 | |||
| [[#SelSec]] | |||
|- | |||
| 0x184 | |||
| 0x4 | |||
| SelT1Key (always 2) | |||
|- | |||
| 0x188 | |||
| 0x4 | |||
| SelKey (always 0) | |||
|- | |||
| 0x18C | |||
| 0x4 | |||
| LimArea (in Gamecard page units, which are 0x200 bytes) | |||
|- | |||
| 0x190 | |||
| 0x70 | |||
| [[#CardHeaderEncryptedData]] | |||
|} | |||
=== RomSize === | |||
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardSize|GameCardSize]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 0xFA | |||
| 1GB | |||
|- | |||
| 0xF8 | |||
| 2GB | |||
|- | |||
| 0xF0 | |||
| 4GB | |||
|- | |||
| 0xE0 | |||
| 8GB | |||
|- | |||
| 0xE1 | |||
| 16GB | |||
|- | |||
| 0xE2 | |||
| 32GB | |||
|} | |||
=== Version === | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 0 | |||
| Default | |||
|- | |||
| 1 | |||
| | |||
|- | |||
| 2 | |||
| | |||
|- | |||
| 3 | |||
| [20.0.0+] T2Supported | |||
|} | |||
=== Flags === | |||
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Bits | |||
! Description | |||
|- | |||
| 0 | |||
| AutoBoot | |||
|- | |||
| 1 | |||
| HistoryErase | |||
|- | |||
| 2 | |||
| [4.0.0+] RepairTool | |||
|- | |||
| 3 | |||
| [9.0.0+] DifferentRegionCupToTerraDevice | |||
|- | |||
| 4 | |||
| [9.0.0+] DifferentRegionCupToGlobalDevice | |||
|- | |||
| 7 | |||
| [11.0.0+] CardHeaderSignKey | |||
|} | |||
=== SelSec === | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 1 | |||
| T1 | |||
|- | |||
| 2 | |||
| T2 | |||
|} | |||
=== CardHeaderEncryptedData === | |||
This region is stored encrypted (AES-128-CBC). | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| [[#FwVersion]] | |||
|- | |||
| 0x8 | |||
| 0x4 | |||
| [[#AccCtrl1]] | |||
|- | |||
| 0xC | |||
| 0x4 | |||
| Wait1TimeRead (always 0x1388) | |||
|- | |||
| 0x10 | |||
| 0x4 | |||
| Wait2TimeRead (always 0) | |||
|- | |||
| 0x14 | |||
| 0x4 | |||
| Wait1TimeWrite (always 0) | |||
|- | |||
| 0x18 | |||
| 0x4 | |||
| Wait2TimeWrite (always 0) | |||
|- | |||
| 0x1C | |||
| 0x4 | |||
| FwMode (the current SdkAddonVersion) | |||
|- | |||
| 0x20 | |||
| 0x4 | |||
| UppVersion | |||
|- | |||
| 0x24 | |||
| 0x1 | |||
| [9.0.0+] [[#CompatibilityType]] | |||
|- | |||
| 0x25 | |||
| 0x3 | |||
| Reserved | |||
|- | |||
| 0x28 | |||
| 0x8 | |||
| UppHash (SHA-256 hash of the [[#UpdatePartition]]) | |||
|- | |||
| 0x30 | |||
| 0x8 | |||
| UppId (always 0x0100000000000816) | |||
|- | |||
| 0x38 | |||
| 0x38 | |||
| Reserved | |||
|} | |||
==== FwVersion ==== | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 0 | |||
| Development | |||
|- | |||
| 1 | |||
| Retail | |||
|- | |||
| 2 | |||
| [4.0.0+] Retail | |||
|- | |||
| 3 | |||
| [11.0.0+] Development | |||
|- | |||
| 4 | |||
| [11.0.0+] Retail | |||
|- | |||
| 5 | |||
| [12.0.0+] Retail | |||
|} | |||
==== AccCtrl1 ==== | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 0x00A10011 | |||
| 25MHz | |||
|- | |||
| 0x00A10010 | |||
| 50MHz | |||
|} | |||
==== CompatibilityType ==== | |||
{| class="wikitable" border="1" | |||
|- | |||
! Value | |||
! Description | |||
|- | |||
| 0 | |||
| Normal | |||
|- | |||
| 1 | |||
| Terra | |||
|} | |||
== NewCardHeader == | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x100 | |||
| RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200) | |||
|- | |||
| 0x100 | |||
| 0x4 | |||
| Magic ("HEAD") | |||
|- | |||
| 0x104 | |||
| 0x4 | |||
| RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes) | |||
|- | |||
| 0x108 | |||
| 0x4 | |||
| BackupAreaStartPageAddress (always 0xFFFFFFFF) | |||
|- | |||
| 0x10C | |||
| 0x1 | |||
| TitleKeyDecIndex (high nibble) and KekIndex (low nibble) | |||
|- | |||
| 0x10D | |||
| 0x1 | |||
| [[#RomSize]] | |||
|- | |||
| 0x10E | |||
| 0x1 | |||
| [[#Version]] | |||
|- | |||
| 0x10F | |||
| 0x1 | |||
| [[#Flags]] | |||
|- | |||
| 0x110 | |||
| 0x8 | | 0x8 | ||
| | | PackageId (used for challenge–response authentication) | ||
|- | |||
| 0x118 | |||
| 0x4 | |||
| ValidDataEndAddress (in Gamecard page units, which are 0x200 bytes) | |||
|- | |||
| 0x11C | |||
| 0x1 | |||
| [20.0.0+] CardHeaderSignKeyIndex ([1.0.0-19.0.1] Reserved) | |||
|- | |||
| 0x11D | |||
| 0x1 | |||
| [18.0.0+] [[#Flags2]] ([1.0.0-17.0.1] Reserved) | |||
|- | |||
| 0x11E | |||
| 0x2 | |||
| [19.0.0+] [[#NumberOfApplicationIds]] ([1.0.0-18.1.0] Reserved) | |||
|- | |- | ||
| 0x120 | | 0x120 | ||
| 0x10 | | 0x10 | ||
| | | Iv (reversed) | ||
|- | |- | ||
| 0x130 | | 0x130 | ||
| 0x8 | | 0x8 | ||
| | | PartitionFsHeaderAddress | ||
|- | |- | ||
| 0x138 | | 0x138 | ||
| | | 0x8 | ||
| | | PartitionFsHeaderSize | ||
|- | |- | ||
| 0x140 | | 0x140 | ||
| 0x20 | | 0x20 | ||
| | | PartitionFsHeaderHash (SHA-256 hash of the [[#PartitionFsHeader]]) | ||
|- | |- | ||
| 0x160 | | 0x160 | ||
| 0x20 | | 0x20 | ||
| | | InitialDataHash (SHA-256 hash of the [[#InitialData]]) | ||
|- | |- | ||
| 0x180 | | 0x180 | ||
| 0x4 | | 0x4 | ||
| | | [[#SelSec]] | ||
|- | |- | ||
| 0x184 | | 0x184 | ||
| 0x4 | | 0x4 | ||
| 2 | | SelT1Key (always 2) | ||
|- | |- | ||
| 0x188 | | 0x188 | ||
| 0x4 | | 0x4 | ||
| 0 | | SelKey (always 0) | ||
|- | |- | ||
| 0x18C | | 0x18C | ||
| 0x4 | | 0x4 | ||
| | | LimArea (in Gamecard page units, which are 0x200 bytes) | ||
|- | |- | ||
| 0x190 | | 0x190 | ||
| 0x70 | | 0x70 | ||
| | | [[#NewCardHeaderEncryptedData]] | ||
|} | |} | ||
=== Flags2 === | |||
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute2|GameCardAttribute2]]. | |||
= | === NumberOfApplicationIds === | ||
This is the number of entries in the ApplicationIdList located right before ValidDataEndAddress. | |||
This is | === NewCardHeaderEncryptedData === | ||
This region is stored encrypted (AES-128-CBC). | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| [[#FwVersion]] | |||
|- | |||
| 0x8 | |||
| 0x4 | |||
| [[#AccCtrl1]] | |||
|- | |||
| 0xC | |||
| 0x4 | |||
| Wait1TimeRead (always 0x1388) | |||
|- | |||
| 0x10 | |||
| 0x4 | |||
| Wait2TimeRead (always 0) | |||
|- | |||
| 0x14 | |||
| 0x4 | |||
| Wait1TimeWrite (always 0) | |||
|- | |||
| 0x18 | |||
| 0x4 | |||
| Wait2TimeWrite (always 0) | |||
|- | |||
| 0x1C | |||
| 0x4 | |||
| FwMode (the current SdkAddonVersion) | |||
|- | |||
| 0x20 | |||
| 0x4 | |||
| UppVersion | |||
|- | |||
| 0x24 | |||
| 0x1 | |||
| [[#CompatibilityType]] | |||
|- | |||
| 0x25 | |||
| 0x3 | |||
| Reserved | |||
|- | |||
| 0x28 | |||
| 0x8 | |||
| UppHash (SHA-256 hash of the [[#UpdatePartition]]) | |||
|- | |||
| 0x30 | |||
| 0x8 | |||
| UppId (always 0x0100000000000816) | |||
|- | |||
| 0x38 | |||
| 0x8 | |||
| Reserved | |||
|- | |||
| 0x40 | |||
| 0x20 | |||
| RelatedCardHeaderHash (SHA-256 hash of [[#CardHeader]]) | |||
|- | |||
| 0x60 | |||
| 0x10 | |||
| Reserved | |||
|} | |||
== NewCardHeaderCertArea == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 102: | Line 605: | ||
| 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 0x400 | ||
|- | |- | ||
| 0x100 | | 0x100 | ||
| 0x4 | | 0x4 | ||
| | | Magic | ||
|- | |||
| 0x104 | |||
| 0x4 | |||
| Version | |||
|- | |||
| 0x108 | |||
| 0x8 | |||
| | |||
|- | |||
| 0x110 | |||
| 0x1 | |||
| CardHeaderSignKeyIndex | |||
|- | |||
| 0x111 | |||
| 0x1F | |||
| Reserved | |||
|- | |||
| 0x130 | |||
| 0x100 | |||
| Modulus | |||
|- | |||
| 0x230 | |||
| 0x3 | |||
| PublicExponent | |||
|- | |||
| 0x233 | |||
| 0x1CD | |||
| Reserved | |||
|} | |||
== CertArea == | |||
This is the Gamecard's unique certificate. | |||
[[Filesystem_services|FS]] retrieves this data with [[Filesystem_services#GetGameCardDeviceCertificate|GetGameCardDeviceCertificate]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x100 | |||
| RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200 | |||
|- | |||
| 0x100 | |||
| 0x4 | |||
| Magic ("CERT") | |||
|- | |||
| 0x104 | |||
| 0x4 | |||
| Version | |||
|- | |||
| 0x108 | |||
| 0x1 | |||
| KekIndex | |||
|- | |||
| 0x109 | |||
| 0x7 | |||
| Reserved | |||
|- | |- | ||
| 0x110 | | 0x110 | ||
| 0x10 | | 0x10 | ||
| | | T1CardDeviceId | ||
|- | |||
| 0x120 | |||
| 0x10 | |||
| Iv | |||
|- | |||
| 0x130 | |||
| 0x10 | |||
| HwKey (encrypted) | |||
|- | |||
| 0x140 | |||
| 0xC0 | |||
| Reserved (encrypted) | |||
|- | |||
| 0x200 | |||
| 0x7E00 | |||
| Reserved | |||
|} | |||
== NormalArea == | |||
This region contains all non-secure partitions of the Gamecard file system. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#PartitionFsHeader|RootPartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#PartitionFsHeader|UpdatePartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#UpdatePartition|UpdatePartition]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [4.0.0+] [[#PartitionFsHeader|LogoPartitionHeader]] | |||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [4.0.0+] [[#LogoPartition|LogoPartition]] | ||
|- | |||
| Variable | |||
| Variable | |||
| [[#PartitionFsHeader|NormalPartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#NormalPartition|NormalPartition]] | |||
|} | |} | ||
=== UpdatePartition === | |||
This partition 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. | |||
= | === NormalPartition === | ||
This is the | This 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. | ||
[4.0.0+] This partition is now empty. | |||
=== LogoPartition === | |||
[4.0.0+] This partition now contains the contents of the [[#NormalPartition]]. | |||
== RomArea == | |||
This region contains all secure partitions of the Gamecard file system. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#PartitionFsHeader|SecurePartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#SecurePartition|SecurePartition]] | |||
|} | |||
=== SecurePartition === | |||
This partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. | |||
== PartitionFs == | |||
This is the Gamecard file system which starts with magicnum "HFS0". | |||
=== PartitionFsHeader === | |||
The "SHA-256 File System" or "HFS0" starts at offset 0x10000 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 [[#CardHeader]]. | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 130: | Line 778: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| HFS0 | | Magic ("HFS0") | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
| 0x4 | | 0x4 | ||
| | | FileCount | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
| 0x4 | | 0x4 | ||
| | | StringTableSize | ||
|- | |- | ||
| 0xC | | 0xC | ||
| 0x4 | | 0x4 | ||
| | | Reserved | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
| X | | X | ||
| | | [[#FileEntryTable]] | ||
|- | |- | ||
| 0x10 + X | | 0x10 + X | ||
| Y | | Y | ||
| | | StringTable | ||
|- | |- | ||
| 0x10 + X + Y | | 0x10 + X + Y | ||
| Z | | Z | ||
| | | RawFileData | ||
|} | |} | ||
==== FileEntryTable ==== | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 179: | Line 826: | ||
| 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 187: | Line 834: | ||
| 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?). | ||