Savegames: Difference between revisions
No edit summary |
No edit summary |
||
| Line 2: | Line 2: | ||
=== | === Savegame Encryption === | ||
On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing. | On the 3DS savegames are stored much like on the DS, that is on a FLASH chip in the gamecart. On the DS these savegames were stored in plain-text but on the 3DS a layer of encryption was added. This is AES-CTR, as the contents of several savegames exhibit the odd behavior that xor-ing certain parts of the savegame together will result in the plain-text appearing. | ||
| Line 57: | Line 57: | ||
* each byte is the checksum of an encrypted 0x200 bytes large block | * each byte is the checksum of an encrypted 0x200 bytes large block | ||
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum | * to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum | ||
=== MAC header === | |||
{| class="wikitable" | |||
|- | |||
! Image offset | |||
! Length | |||
! Description | |||
|- | |||
| 0x00 | |||
| 0x10 | |||
| AES-CCM MAC over a SHA256 hash, with an all-zero nonce | |||
|- | |||
| 0x10 | |||
| 0xF0 | |||
| Zero padding | |||
|} | |||
The [[AES]] engine keyslot used for crypting the image seems to be the same one used for this MAC. This MAC is used to verify the DISA/DIFF header. SHA256_Update() is used to calculate the hash with the blocks described below. | |||
==== Extdata SHA256 blocks ==== | |||
{| class="wikitable" | |||
|- | |||
! Block Size | |||
! Description | |||
|- | |||
| 0x8 | |||
| Savegame type, "CTR-EXT0" | |||
|- | |||
| 0x8 | |||
| First word is the hex ID from image filename, second word is the hex ID of the sub-dir under the <ExtdataIDLow> directory (all-zero for Quota.dat) | |||
|- | |||
| 0x4 | |||
| 1 for Quota.dat, 0 otherwise | |||
|- | |||
| 0x8 | |||
| Same as the previous u64 | |||
|- | |||
| 0x100 | |||
| 0x100-byte header from offset 0x100 in image (DIFF for extdata) | |||
|} | |||
=== Partitions === | === Partitions === | ||
There can be multiple partitions on the chip. | There can be multiple partitions on the chip. | ||
The partitions are represented by tables of DIFI blobs inside a DISA structure. | The partitions are represented by tables of DIFI blobs inside a DISA/DIFF structure. | ||
The order of the DIFI blobs is the order of the partitions in the chip. | The order of the DIFI blobs is the order of the partitions in the chip. | ||
'''DISA''' | '''DISA''' | ||
* If the uint32 @ 0x168 | * This is located @ 0x100 in the image, following the MAC header. | ||
* If the uint32 @ 0x168 in the image in the DISA(the low 8-bits) is non-zero, then first table is is hashed, otherwise the second DIFI table is hashed. | |||
* If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE). | * If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE). | ||
{| class="wikitable" | {| class="wikitable" | ||
| Line 155: | Line 196: | ||
'''DIFF''' | '''DIFF''' | ||
* This is the [[extdata]] equivalent of DISA, for extdata which use FS. DIFF is | * This is the [[extdata]] equivalent of DISA, for extdata which use FS. DIFF is only used for extdata. | ||
* When the active-table field low 8-bits is non-zero, the primary partition is used. Otherwise, the secondary partition is used. | * When the active-table field low 8-bits is non-zero, the primary partition is used. Otherwise, the secondary partition is used. | ||