Savegames: Difference between revisions
→Gamecard savegame Encryption: Add summary table for encryption |
|||
Line 13: | Line 13: | ||
! Old3DS | ! Old3DS | ||
! [[AES#Keyslot|AES Keyslots]] (Encryotion / CMAC) | ! [[AES#Keyslot|AES Keyslots]] (Encryotion / CMAC) | ||
! | ! KeyY generation method | ||
! Repeating CTR | ! Repeating CTR | ||
|- | |- | ||
Line 54: | Line 54: | ||
So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame. | So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame. | ||
=== KeyY Generation methid === | |||
The [[ | The [[NCSD]] partition flags determine the method used to generate this keyY. | ||
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY | ==== v1 ==== | ||
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY is the following: | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 80: | Line 81: | ||
|} | |} | ||
==== | ==== v2 ==== | ||
Key Y is the first 0x10 bytes of SHA-256 calculated over the following data | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature. | |||
|- | |||
| 0x8 | |||
| 0x40 | |||
| read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]], which is the gamecard-uniqueID) | |||
|} | |||
This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn't implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards. | This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn't implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards. | ||
==== | ==== v3 ==== | ||
[[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. | ||
First, a SHA-256 hash is calculated over the following data | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| First 8-bytes from the plaintext [[NCCH#CXI|CXI]] accessdesc signature. | |||
|- | |||
| 0x8 | |||
| 0x40 | |||
| Same ID as [[Process_Services_PXI|GetRomId]] | |||
|- | |||
| 0x48 | |||
| 0x8 | |||
| CXI Program ID | |||
|- | |||
| 0x50 | |||
| 0x20 | |||
| ExeFS:/.code hash from the decrypted [[ExeFS]] header | |||
|} | |||
Then an [[AES]]-CMAC is calculated over this hash. The output CMAC is used for keyY. The key slot for this CMAC is 0x2F. | |||
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. | The 0x2F keyY used for calculating this AES-CMAC (not to be confused with the final keyY for decrypting/signing savegames) 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. |