Savegames: Difference between revisions

CMAC is used for MAC computations
Line 15: Line 15:
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]' keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.
All gamecard and SD savegames are encrypted with AES-CTR. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslots]]' keyY(these savegame keyslots use the hardware key-generator) is unique for each region and for each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used.


The [[AES]]-MAC(which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated MAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).
The [[AES]]-CMAC (which uses a hardware key-generator keyslot, as mentioned above) at the the beginning of the savegame must match the calculated CMAC using the DISA/DIFF data, otherwise the savegame is considered corrupted(see below).


When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY(original keyY method used with saves where the CTR repeats within the image) is the following:
Line 47: Line 47:
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method.


A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-MAC(the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output MAC is used for the savegame keyY.
A SHA-256 hash is calculated over the same data used with the above hashed keyY method, after hashing the above data the following data is hashed: the CXI programID, and the ExeFS:/.code hash from the decrypted [[ExeFS]] header. An [[AES]]-CMAC (the keyslot used for this uses the hardware key-scrambler) is then calculated over this hash, the output CMAC is used for the savegame keyY.


The keyY used for calculating this AES MAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten during system boot. This RSA slot0 key-data gets overwritten with the RSA key-data used for verifying RSA signatures, every time Process9 verifies any RSA signatures except for [[NCCH|NCCH]] accessdesc signatures. Starting with [[7.0.0-13]] this key-init function used at boot is also used to initialize a separate keyslot used for the new [[NCCH]] encryption method.


This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.
This [[FIRM|Process9]] key-init function first checks if a certain 0x10-byte block in the 0x01FF8000 region is all-zero. When all-zero it immediately returns, otherwise it clears that block then continues to do the key generation. This is likely for supporting launching a v6.0+ NATIVE_FIRM under this FIRM.
Line 97: Line 97:
* 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


=== AES MAC header ===
=== AES CMAC header ===


{| class="wikitable"
{| class="wikitable"
Line 107: Line 107:
| 0x00
| 0x00
| 0x10
| 0x10
| [[AES]] MAC over a 0x20-byte SHA256 hash(the keyslot used here uses the hardware key-scrambler).
| [[AES]]-CMAC over a 0x20-byte SHA256 hash(the keyslot used here uses the hardware key-scrambler).
|-
|-
| 0x10
| 0x10
Line 114: Line 114:
|}
|}


This AES MAC is used to "sign" the DISA/DIFF header. Each time the savegame is updated the hash stored in the DISA/DIFF is updated, therefore the MAC must be updated each time the save is modified as well. SHA256_Update() is used to calculate the hash with the blocks described below.
This AES CMAC is used to "sign" the DISA/DIFF header. Each time the savegame is updated the hash stored in the DISA/DIFF is updated, therefore the CMAC must be updated each time the save is modified as well. SHA256_Update() is used to calculate the hash with the blocks described below.


==== Savegame Types ====
==== Savegame Types ====
Line 205: Line 205:
|}
|}


For gamecard savegames the output hash from this is used with the MAC. This save-type is also used for SD savegames, for SD saves the input data is the 0x100-byte DISA header. For SD savegames, the calculated output hash is used with CTR-SIGN.
For gamecard savegames the output hash from this is used with the CMAC. This save-type is also used for SD savegames, for SD saves the input data is the 0x100-byte DISA header. For SD savegames, the calculated output hash is used with CTR-SIGN.


==== CTR-SIGN SHA256 Blocks ====
==== CTR-SIGN SHA256 Blocks ====
Line 222: Line 222:
| SHA-256 hash from CTR-SAV0
| SHA-256 hash from CTR-SAV0
|}
|}
This is used for SD savegames, the calculated hash from this is used with the MAC.
This is used for SD savegames, the calculated hash from this is used with the CMAC.


==== CTR-9DB0 SHA256 Blocks ====
==== CTR-9DB0 SHA256 Blocks ====
Line 240: Line 240:
|}
|}


This is used for the SD/NAND /[[Title_Database|dbs]] .db extdata images, see [[Title_Database]] regarding AES-MAC keyslots used here.
This is used for the SD/NAND /[[Title_Database|dbs]] .db extdata images, see [[Title_Database]] regarding AES-CMAC keyslots used here.


=== Partitions ===
=== Partitions ===
Line 250: Line 250:
==== DISA ====
==== DISA ====


* This is located @ 0x100 in the image, following the MAC header.
* This is located @ 0x100 in the image, following the CMAC header.
* If the uint32 @ 0x68 in the DISA(the low 8-bits) is non-zero, then the secondary table is is used, otherwise the primary table is used.  
* If the uint32 @ 0x68 in the DISA(the low 8-bits) is non-zero, then the secondary table is is used, otherwise the primary table is used.  
* 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).
Line 807: Line 807:
=== Tools ===
=== Tools ===


* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the MAC must be used with /clean.sav, prior to writing output.sav to a gamecard.
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] supports reading and modifying savegames. In the mounted FUSE filesystem, the /output.sav is the raw FLASH save-image. When the save was modified, a separate tool to update the CMAC must be used with /clean.sav, prior to writing output.sav to a gamecard.
* [[3DSExplorer]] supports reading of savegames, it doesn't support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).
* [[3DSExplorer]] supports reading of savegames, it doesn't support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented).
[[セーブデータ|Japanese]]
[[セーブデータ|Japanese]]