Difference between revisions of "NAX0"

From Nintendo Switch Brew
Jump to navigation Jump to search
(Created page with "This is the format on the files stored on SD, unknown if this is used elsewhere. The data between this header and offset 0x4000 is unused/uninitialized it a...")
 
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This is the format on the files stored on [[SD_Filesystem|SD]], unknown if this is used elsewhere.
+
This is the format on the files stored on [[SD_Filesystem|SD]] (Nintendo Aes Xts -- official name is AesXtsFilesystem/AesXtsFile).
  
 
The data between this header and offset 0x4000 is unused/uninitialized it appears. The actual content which is encrypted, starts at offset 0x4000 with the size from the header.
 
The data between this header and offset 0x4000 is unused/uninitialized it appears. The actual content which is encrypted, starts at offset 0x4000 with the size from the header.
  
When a title is redownloaded/reinstalled, the header and raw content in NAX0 are completely different except for the magicnum and size-field.
+
When a NAX0 file is recreated, the header and raw content in NAX0 are completely different except for the magicnum and size-field. This is the case when a title is redownloaded/reinstalled, and when "save/" files are recreated after manual deletion.
 +
 
 +
[[Error_codes|Error]] 0x250E02 is returned by NCM when attempting to access a NcaId where the NAX0 header HMAC validation fails.
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 13: Line 15:
 
| 0x0
 
| 0x0
 
| 0x20
 
| 0x20
| Data appears to be random.
+
| Header HMAC
 
|-
 
|-
 
| 0x20
 
| 0x20
Line 21: Line 23:
 
| 0x28
 
| 0x28
 
| 0x20
 
| 0x20
| Data appears to be random.
+
| Encrypted AES-XTS Keys
 
|-
 
|-
 
| 0x48
 
| 0x48
| 0x8?
+
| 0x8
 
| Size of the file relative to offset 0x4000.
 
| Size of the file relative to offset 0x4000.
 +
|-
 +
| 0x50
 +
| 0x30
 +
| Padding
 
|}
 
|}
 +
 +
= Encryption =
 +
 +
The actual content uses AES-XTS with the same non-standard tweak (endianness swap) as usual, and sector size 0x4000.
 +
 +
Key derivation is as follows:
 +
 +
First, FS retrieves the 16-byte console-unique seed that NS registered (data originates from the ns_appman:/private [[Flash_Filesystem#System_Savegames|system savegame]]). Next, FS calculates encryptedSeedKeys = <0x20 hardcoded keydata depending on if this NAX0 is a save or an NCA> XORed with the system seed, calculates kek = [[SPL_services#GenerateAesKek|GenerateAesKek]](<hardcoded keydata>, 0, 0), and then calculates decryptedSeedKeys by doing decryptedSeedKeys[i] = [[SPL_services#GenerateAesKey|GenerateAesKey]](kek, encryptedSeedKeys[i]); for both keys.
 +
 +
 +
Once the decryptedSeedKeys are calculated, FS calculates naxSpecificKeys = hmac-sha256(key=decryptedSeedKeys[0], data=<NAX0 path, relative to /Nintendo/Contents>); (example path: '/registered/000000FF/cafebabecafebabecafebabecafebabe.nca'). Then, FS does the following decryptions in place: aes128_ecb_decrypt(key=naxSpecificKeys[0], data=Header + 0x28); aes128_ecb_decrypt(key=naxSpecificKeys[1], data=Header + 0x38); Finally, hmac-sha256(key=Header[0x20:0x60], data=decryptedSeedKeys[1]) is calculated, and compared using a constant-time memcmp to the hmac stored at Header + 0x0. If it matches, decryption proceeds using the two decrypted keys at Header + 0x28 as an AES-XTS keypair.

Latest revision as of 08:34, 16 April 2018

This is the format on the files stored on SD (Nintendo Aes Xts -- official name is AesXtsFilesystem/AesXtsFile).

The data between this header and offset 0x4000 is unused/uninitialized it appears. The actual content which is encrypted, starts at offset 0x4000 with the size from the header.

When a NAX0 file is recreated, the header and raw content in NAX0 are completely different except for the magicnum and size-field. This is the case when a title is redownloaded/reinstalled, and when "save/" files are recreated after manual deletion.

Error 0x250E02 is returned by NCM when attempting to access a NcaId where the NAX0 header HMAC validation fails.

Offset Size Description
0x0 0x20 Header HMAC
0x20 0x8 Magicnum "NAX0"
0x28 0x20 Encrypted AES-XTS Keys
0x48 0x8 Size of the file relative to offset 0x4000.
0x50 0x30 Padding

Encryption

The actual content uses AES-XTS with the same non-standard tweak (endianness swap) as usual, and sector size 0x4000.

Key derivation is as follows:

First, FS retrieves the 16-byte console-unique seed that NS registered (data originates from the ns_appman:/private system savegame). Next, FS calculates encryptedSeedKeys = <0x20 hardcoded keydata depending on if this NAX0 is a save or an NCA> XORed with the system seed, calculates kek = GenerateAesKek(<hardcoded keydata>, 0, 0), and then calculates decryptedSeedKeys by doing decryptedSeedKeys[i] = GenerateAesKey(kek, encryptedSeedKeys[i]); for both keys.


Once the decryptedSeedKeys are calculated, FS calculates naxSpecificKeys = hmac-sha256(key=decryptedSeedKeys[0], data=<NAX0 path, relative to /Nintendo/Contents>); (example path: '/registered/000000FF/cafebabecafebabecafebabecafebabe.nca'). Then, FS does the following decryptions in place: aes128_ecb_decrypt(key=naxSpecificKeys[0], data=Header + 0x28); aes128_ecb_decrypt(key=naxSpecificKeys[1], data=Header + 0x38); Finally, hmac-sha256(key=Header[0x20:0x60], data=decryptedSeedKeys[1]) is calculated, and compared using a constant-time memcmp to the hmac stored at Header + 0x0. If it matches, decryption proceeds using the two decrypted keys at Header + 0x28 as an AES-XTS keypair.