NCA

From Nintendo Switch Brew
Revision as of 13:30, 18 July 2017 by Jakcron (talk | contribs) (Add information about encryption.)
Jump to navigation Jump to search

The entire raw NCAs are encrypted.

The only known area which is not encrypted in the raw NCA is the logo section, when the NCA includes that section. Everything else documented on this page is for the plaintext version of that data.

Encryption

The first 0xC00 bytes are encrypted with AES-XTS with sector size 0x200, 6 sectors in total.

Offset XTS Sector Key Description
0x0 0 NcaHeaderKey NCA Header Signatures
0x200 1 NcaHeaderKey NCA Header Data
0x400 2 ? NCA Section 0 Data
0x600 3 ? NCA Section 1 Data
0x800 4 ? NCA Section 2 Data
0xA00 5 ? NCA Section 3 Data

Header

Offset Size Description
0x0 0x100 RSA-2048 signature over the 0x200-bytes starting at offset 0x200 using fixed key.
0x100 0x100 RSA-2048 signature over the 0x200-bytes starting at offset 0x200 using key from NPDM, or zeroes if not a program.
0x200 0x4 Magicnum "NCA3"
0x204 0x1 ?
0x205 0x1 Type value?
0x206 0x1 Crypto flags? Normally 0. With 3.0.0+ ncatype1(not used for ncatype0, unknown for others) content this is 2: new keydata is used for this content, this field seems to control that.
0x207 0x1 Key index
0x208 0x8 Size of the entire NCA.
0x210 0x8 titleID
0x230 0x10 Rights ID (Ticket)
0x240 0x10*0x4(0x40) Table for each section, see below.
0x280 0x20*0x4(0x80) Table of SHA256 hashes, over each 0x200-byte Section Header Block.
0x300 0x10*0x4(0x40) Key area

The header is 0x400-bytes, at NCA+0.

Section Table Entry

Offset Size Description
0x0 0x4 Media offset
0x4 0x4 Media end-offset
0x8 0x4 Unknown
0xC 0x4 Unknown

Entry size is 0x10-bytes.

Media offset is absoluteoffset/{mediasize}, where mediasize is hard-coded to 0x200.

Section Header Block

Offset Size Description
0x0 0x1 ?
0x1 0x1 ?
0x2 0x1 ?
0x3 0x1 ?
0x4 0x1 Crypto type. 0 and >4 are invalid. 1 = none(plaintext from raw NCA). 2 = other crypto. 3 = regular crypto. 4 = unknown.
0x5 0x1 Padding?
0x8 FS-specific superblock.

The Section Header Block for each section is at absoluteoffset+0x400+(sectionid*0x200), where sectionid corresponds to the index used with the entry/hash tables.

The total size is 0x200-bytes.

PFS0 superblock

Offset Size Description
0x8 0x20 SHA256 hash over the hash-table at section-start+0 with the below hash-table size.
0x28 0x4 Block size in bytes.
0x2C 0x4 ?
0x38 0x8? Size of hash-table.
0x40 0x8? Offset relative to section-start where the PFS0 header is located.
0x48 0x8 Actual byte-size of the PFS0 filesystem relative to the PFS0 header.
0x50 0xF4 Normally zeros.
0x144 ? 0x1?
0x148 0xB8 Normally zeros.

This documents the structure of Section Header Block +0 for PFS0.

RomFS superblock

Offset Size Description
0x8 IVFC header

This documents the structure of Section Header Block +0 for RomFS.

Logo section

This is a PFS0. See here for the mounted-FS logo contents.

ExeFS section

This is a PFS0.

See here for mounted-FS ExeFS contents.

PFS0

Offset Size Description
0x0 X Table of SHA256 hashes.
X Y Zeros for alignment to {alignment size}.
X+Y Start of the PFS0 header.

This is the FS which has magicnum "PFS0" at header+0.

The hash table is hashes for every {Block size from superblock} starting at the PFS0 header. The size used for the last hash is {PFS0 filesystem size from superblock} - offset_relativeto_header.

See also the PFS0 superblock above.