mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Add consolidated GodMode9 key dumping script. (#6396)
This commit is contained in:
		
							parent
							
								
									8d19483b7e
								
							
						
					
					
						commit
						b6e73f0d49
					
				
					 5 changed files with 396 additions and 8 deletions
				
			
		
							
								
								
									
										291
									
								
								dist/dumpkeys/DumpKeys.gm9
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								dist/dumpkeys/DumpKeys.gm9
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,291 @@ | ||||||
|  | set PREVIEW_MODE "Key Dumper\n \nWorking..." | ||||||
|  | 
 | ||||||
|  | # Boot9 | ||||||
|  | 
 | ||||||
|  | set BOOT9_BIN "M:/boot9.bin" | ||||||
|  | 
 | ||||||
|  | fget $[BOOT9_BIN]@D9D0:10 KEYX_2C | ||||||
|  | set KEYX_2D $[KEYX_2C] | ||||||
|  | set KEYX_2E $[KEYX_2C] | ||||||
|  | set KEYX_2F $[KEYX_2C] | ||||||
|  | fget $[BOOT9_BIN]@D9E0:10 KEYX_30 | ||||||
|  | set KEYX_31 $[KEYX_30] | ||||||
|  | set KEYX_32 $[KEYX_30] | ||||||
|  | set KEYX_33 $[KEYX_30] | ||||||
|  | fget $[BOOT9_BIN]@D9F0:10 KEYX_34 | ||||||
|  | set KEYX_35 $[KEYX_34] | ||||||
|  | set KEYX_36 $[KEYX_34] | ||||||
|  | set KEYX_37 $[KEYX_34] | ||||||
|  | fget $[BOOT9_BIN]@DA00:10 KEYX_38 | ||||||
|  | set KEYX_39 $[KEYX_38] | ||||||
|  | set KEYX_3A $[KEYX_38] | ||||||
|  | set KEYX_3B $[KEYX_38] | ||||||
|  | fget $[BOOT9_BIN]@DA10:10 KEYX_3C | ||||||
|  | fget $[BOOT9_BIN]@DA20:10 KEYX_3D | ||||||
|  | fget $[BOOT9_BIN]@DA30:10 KEYX_3E | ||||||
|  | fget $[BOOT9_BIN]@DA40:10 KEYX_3F | ||||||
|  | 
 | ||||||
|  | fget $[BOOT9_BIN]@DA50:10 KEYY_04 | ||||||
|  | fget $[BOOT9_BIN]@DA60:10 KEYY_05 | ||||||
|  | fget $[BOOT9_BIN]@DA70:10 KEYY_06 | ||||||
|  | fget $[BOOT9_BIN]@DA80:10 KEYY_07 | ||||||
|  | fget $[BOOT9_BIN]@DA90:10 KEYY_08 | ||||||
|  | fget $[BOOT9_BIN]@DAA0:10 KEYY_09 | ||||||
|  | fget $[BOOT9_BIN]@DAB0:10 KEYY_0A | ||||||
|  | fget $[BOOT9_BIN]@DAC0:10 KEYY_0B | ||||||
|  | 
 | ||||||
|  | fget $[BOOT9_BIN]@DAD0:10 KEYN_0D | ||||||
|  | fget $[BOOT9_BIN]@DBA0:10 KEYN_2D | ||||||
|  | fget $[BOOT9_BIN]@DBB0:10 KEYN_32 | ||||||
|  | fget $[BOOT9_BIN]@DBC0:10 KEYN_36 | ||||||
|  | fget $[BOOT9_BIN]@DBD0:10 KEYN_38 | ||||||
|  | 
 | ||||||
|  | # NATIVE_FIRM | ||||||
|  | 
 | ||||||
|  | if chk $[ONTYPE] "N3DS" | ||||||
|  |     if not find 1:/title/00040138/20000002/content/????????.app NATIVE_FIRM_APP | ||||||
|  |         echo "New 3DS NATIVE_FIRM not found." | ||||||
|  |         goto Exit | ||||||
|  |     end | ||||||
|  |     set EXPECTED_NATIVE_FIRM_VER "1F00" | ||||||
|  |     set KEYY_2E_OFFSET "66504" | ||||||
|  |     set KEYY_39_NFC_OFFSET "66524" | ||||||
|  |     set COMMON_0_OFFSET "6CE51" | ||||||
|  |     set COMMON_1_OFFSET "6CE65" | ||||||
|  |     set COMMON_2_OFFSET "6CE79" | ||||||
|  |     set COMMON_3_OFFSET "6CE8D" | ||||||
|  |     set COMMON_4_OFFSET "6CEA1" | ||||||
|  |     set COMMON_5_OFFSET "6CEB5" | ||||||
|  | else | ||||||
|  |     if not find 1:/title/00040138/00000002/content/????????.app NATIVE_FIRM_APP | ||||||
|  |         echo "Old 3DS NATIVE_FIRM not found." | ||||||
|  |         goto Exit | ||||||
|  |     end | ||||||
|  |     set EXPECTED_NATIVE_FIRM_VER "1F00" | ||||||
|  |     set KEYY_2E_OFFSET "66488" | ||||||
|  |     set KEYY_39_NFC_OFFSET "664A8" | ||||||
|  |     set COMMON_0_OFFSET "6CDC1" | ||||||
|  |     set COMMON_1_OFFSET "6CDD5" | ||||||
|  |     set COMMON_2_OFFSET "6CDE9" | ||||||
|  |     set COMMON_3_OFFSET "6CDFD" | ||||||
|  |     set COMMON_4_OFFSET "6CE11" | ||||||
|  |     set COMMON_5_OFFSET "6CE25" | ||||||
|  | end | ||||||
|  | set NATIVE_FIRM_EXTHEADER "G:/extheader.bin" | ||||||
|  | set NATIVE_FIRM_ENCRYPTED "G:/exefs/.firm" | ||||||
|  | set NATIVE_FIRM_DECRYPTED "$[GM9OUT]/native.firm" | ||||||
|  | set PROCESS9_CODE "G:/0004013000003000.Process9/exefs/.code" | ||||||
|  | 
 | ||||||
|  | imgmount $[NATIVE_FIRM_APP] | ||||||
|  | 
 | ||||||
|  | fget $[NATIVE_FIRM_EXTHEADER]@E:2 NATIVE_FIRM_VER | ||||||
|  | if not chk $[NATIVE_FIRM_VER] $[EXPECTED_NATIVE_FIRM_VER] | ||||||
|  |     echo "Unsupported NATIVE_FIRM version.\nThis script requires the latest 3DS firmware.\n\nExpected $[EXPECTED_NATIVE_FIRM_VER], got $[NATIVE_FIRM_VER]" | ||||||
|  |     goto Exit | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | cp -w $[NATIVE_FIRM_ENCRYPTED] $[NATIVE_FIRM_DECRYPTED] | ||||||
|  | decrypt $[NATIVE_FIRM_DECRYPTED] | ||||||
|  | 
 | ||||||
|  | imgumount | ||||||
|  | 
 | ||||||
|  | imgmount $[NATIVE_FIRM_DECRYPTED] | ||||||
|  | 
 | ||||||
|  | fget $[PROCESS9_CODE]@$[KEYY_2E_OFFSET]:10 KEYY_2E | ||||||
|  | set KEYY_31 $[KEYY_2E] | ||||||
|  | set KEYY_39_DLP $[KEYY_2E] | ||||||
|  | fget $[PROCESS9_CODE]@$[KEYY_39_NFC_OFFSET]:10 KEYY_39_NFC | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_0_OFFSET]:10 COMMON_0 | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_1_OFFSET]:10 COMMON_1 | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_2_OFFSET]:10 COMMON_2 | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_3_OFFSET]:10 COMMON_3 | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_4_OFFSET]:10 COMMON_4 | ||||||
|  | fget $[PROCESS9_CODE]@$[COMMON_5_OFFSET]:10 COMMON_5 | ||||||
|  | 
 | ||||||
|  | imgumount | ||||||
|  | rm -o -s $[NATIVE_FIRM_DECRYPTED] | ||||||
|  | 
 | ||||||
|  | # NFC | ||||||
|  | 
 | ||||||
|  | if chk $[ONTYPE] "N3DS" | ||||||
|  |     if not find 1:/title/00040130/20004002/content/????????.app NFC_APP | ||||||
|  |         echo "New 3DS NFC not found." | ||||||
|  |         goto Exit | ||||||
|  |     end | ||||||
|  |     set EXPECTED_NFC_VER "0700" | ||||||
|  |     set NFC_PHRASE_0_OFFSET "355EE" | ||||||
|  |     set NFC_SEED_0_OFFSET "355FC" | ||||||
|  |     set NFC_HMAC_KEY_0_OFFSET "3560A" | ||||||
|  |     set NFC_PHRASE_1_OFFSET "3561A" | ||||||
|  |     set NFC_SEED_1_OFFSET "35628" | ||||||
|  |     set NFC_HMAC_KEY_1_OFFSET "35638" | ||||||
|  |     set NFC_IV_OFFSET "35648" | ||||||
|  | else | ||||||
|  |     if not find 1:/title/00040130/00004002/content/????????.app NFC_APP | ||||||
|  |         echo "Old 3DS NFC not found." | ||||||
|  |         goto Exit | ||||||
|  |     end | ||||||
|  |     set EXPECTED_NFC_VER "0800" | ||||||
|  |     set NFC_PHRASE_0_OFFSET "17382" | ||||||
|  |     set NFC_SEED_0_OFFSET "17390" | ||||||
|  |     set NFC_HMAC_KEY_0_OFFSET "1739E" | ||||||
|  |     set NFC_PHRASE_1_OFFSET "173AE" | ||||||
|  |     set NFC_SEED_1_OFFSET "173BC" | ||||||
|  |     set NFC_HMAC_KEY_1_OFFSET "173CC" | ||||||
|  |     set NFC_IV_OFFSET "173DC" | ||||||
|  | end | ||||||
|  | set NFC_EXTHEADER "G:/extheader.bin" | ||||||
|  | set NFC_CODE "$[GM9OUT]/nfc_code.bin" | ||||||
|  | 
 | ||||||
|  | imgmount $[NFC_APP] | ||||||
|  | 
 | ||||||
|  | fget $[NFC_EXTHEADER]@E:2 NFC_VER | ||||||
|  | if not chk $[NFC_VER] $[EXPECTED_NFC_VER] | ||||||
|  |     echo "Unsupported NFC module version.\nThis script requires the latest 3DS firmware.\n\nExpected $[EXPECTED_NFC_VER], got $[NFC_VER]" | ||||||
|  |     goto Exit | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | imgumount | ||||||
|  | 
 | ||||||
|  | extrcode $[NFC_APP] $[NFC_CODE] | ||||||
|  | 
 | ||||||
|  | fget $[NFC_CODE]@$[NFC_PHRASE_0_OFFSET]:E NFC_PHRASE_0 | ||||||
|  | fget $[NFC_CODE]@$[NFC_SEED_0_OFFSET]:E NFC_SEED_0 | ||||||
|  | fget $[NFC_CODE]@$[NFC_HMAC_KEY_0_OFFSET]:10 NFC_HMAC_KEY_0 | ||||||
|  | 
 | ||||||
|  | fget $[NFC_CODE]@$[NFC_PHRASE_1_OFFSET]:E NFC_PHRASE_1 | ||||||
|  | fget $[NFC_CODE]@$[NFC_SEED_1_OFFSET]:10 NFC_SEED_1 | ||||||
|  | fget $[NFC_CODE]@$[NFC_HMAC_KEY_1_OFFSET]:10 NFC_HMAC_KEY_1 | ||||||
|  | 
 | ||||||
|  | fget $[NFC_CODE]@$[NFC_IV_OFFSET]:10 NFC_IV | ||||||
|  | 
 | ||||||
|  | rm -o -s $[NFC_CODE] | ||||||
|  | 
 | ||||||
|  | # GodMode9 Key Database | ||||||
|  | 
 | ||||||
|  | set KEY_DB "V:/aeskeydb.bin" | ||||||
|  | set KEY_DB_18X "K:/slot0x18KeyX.ret.bin" | ||||||
|  | set KEY_DB_19X "K:/slot0x19KeyX.ret.bin" | ||||||
|  | set KEY_DB_1AX "K:/slot0x1AKeyX.ret.bin" | ||||||
|  | set KEY_DB_1BX "K:/slot0x1BKeyX.ret.bin" | ||||||
|  | set KEY_DB_1CX "K:/slot0x1CKeyX.ret.bin" | ||||||
|  | set KEY_DB_1DX "K:/slot0x1DKeyX.ret.bin" | ||||||
|  | set KEY_DB_1EX "K:/slot0x1EKeyX.ret.bin" | ||||||
|  | set KEY_DB_1FX "K:/slot0x1FKeyX.ret.bin" | ||||||
|  | set KEY_DB_25X "K:/slot0x25KeyX.ret.bin" | ||||||
|  | set KEY_DB_24Y "K:/slot0x24KeyY.bin" | ||||||
|  | set KEY_DB_2FY "K:/slot0x2FKeyY.ret.bin" | ||||||
|  | 
 | ||||||
|  | imgmount $[KEY_DB] | ||||||
|  | 
 | ||||||
|  | fget $[KEY_DB_18X]@0:10 KEYX_18 | ||||||
|  | fget $[KEY_DB_19X]@0:10 KEYX_19 | ||||||
|  | fget $[KEY_DB_1AX]@0:10 KEYX_1A | ||||||
|  | fget $[KEY_DB_1BX]@0:10 KEYX_1B | ||||||
|  | fget $[KEY_DB_1CX]@0:10 KEYX_1C | ||||||
|  | fget $[KEY_DB_1DX]@0:10 KEYX_1D | ||||||
|  | fget $[KEY_DB_1EX]@0:10 KEYX_1E | ||||||
|  | fget $[KEY_DB_1FX]@0:10 KEYX_1F | ||||||
|  | fget $[KEY_DB_25X]@0:10 KEYX_25 | ||||||
|  | 
 | ||||||
|  | fget $[KEY_DB_24Y]@0:10 KEYY_24 | ||||||
|  | fget $[KEY_DB_2FY]@0:10 KEYY_2F | ||||||
|  | 
 | ||||||
|  | imgumount | ||||||
|  | 
 | ||||||
|  | # Write Keys To File | ||||||
|  | 
 | ||||||
|  | set OUT "0:/gm9/aes_keys.txt" | ||||||
|  | 
 | ||||||
|  | dumptxt $[OUT] "# KeyX" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "slot0x18KeyX=$[KEYX_18]" | ||||||
|  | dumptxt -p $[OUT] "slot0x19KeyX=$[KEYX_19]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1AKeyX=$[KEYX_1A]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1BKeyX=$[KEYX_1B]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1CKeyX=$[KEYX_1C]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1DKeyX=$[KEYX_1D]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1EKeyX=$[KEYX_1E]" | ||||||
|  | dumptxt -p $[OUT] "slot0x1FKeyX=$[KEYX_1F]" | ||||||
|  | dumptxt -p $[OUT] "slot0x25KeyX=$[KEYX_25]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2CKeyX=$[KEYX_2C]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2DKeyX=$[KEYX_2D]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2EKeyX=$[KEYX_2E]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2FKeyX=$[KEYX_2F]" | ||||||
|  | dumptxt -p $[OUT] "slot0x30KeyX=$[KEYX_30]" | ||||||
|  | dumptxt -p $[OUT] "slot0x31KeyX=$[KEYX_31]" | ||||||
|  | dumptxt -p $[OUT] "slot0x32KeyX=$[KEYX_32]" | ||||||
|  | dumptxt -p $[OUT] "slot0x33KeyX=$[KEYX_33]" | ||||||
|  | dumptxt -p $[OUT] "slot0x34KeyX=$[KEYX_34]" | ||||||
|  | dumptxt -p $[OUT] "slot0x35KeyX=$[KEYX_35]" | ||||||
|  | dumptxt -p $[OUT] "slot0x36KeyX=$[KEYX_36]" | ||||||
|  | dumptxt -p $[OUT] "slot0x37KeyX=$[KEYX_37]" | ||||||
|  | dumptxt -p $[OUT] "slot0x38KeyX=$[KEYX_38]" | ||||||
|  | dumptxt -p $[OUT] "slot0x39KeyX=$[KEYX_39]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3AKeyX=$[KEYX_3A]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3BKeyX=$[KEYX_3B]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3CKeyX=$[KEYX_3C]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3DKeyX=$[KEYX_3D]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3EKeyX=$[KEYX_3E]" | ||||||
|  | dumptxt -p $[OUT] "slot0x3FKeyX=$[KEYX_3F]" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | dumptxt -p $[OUT] "# KeyY" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "slot0x04KeyY=$[KEYY_04]" | ||||||
|  | dumptxt -p $[OUT] "slot0x05KeyY=$[KEYY_05]" | ||||||
|  | dumptxt -p $[OUT] "slot0x06KeyY=$[KEYY_06]" | ||||||
|  | dumptxt -p $[OUT] "slot0x07KeyY=$[KEYY_07]" | ||||||
|  | dumptxt -p $[OUT] "slot0x08KeyY=$[KEYY_08]" | ||||||
|  | dumptxt -p $[OUT] "slot0x09KeyY=$[KEYY_09]" | ||||||
|  | dumptxt -p $[OUT] "slot0x0AKeyY=$[KEYY_0A]" | ||||||
|  | dumptxt -p $[OUT] "slot0x0BKeyY=$[KEYY_0B]" | ||||||
|  | dumptxt -p $[OUT] "slot0x24KeyY=$[KEYY_24]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2EKeyY=$[KEYY_2E]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2FKeyY=$[KEYY_2F]" | ||||||
|  | dumptxt -p $[OUT] "slot0x31KeyY=$[KEYY_31]" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | dumptxt -p $[OUT] "# DLP/NFC KeyY (slot 0x39)" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "dlpKeyY=$[KEYY_39_DLP]" | ||||||
|  | dumptxt -p $[OUT] "nfcKeyY=$[KEYY_39_NFC]" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | dumptxt -p $[OUT] "# Ticket Common KeyY (slot 0x3D)" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "common0=$[COMMON_0]" | ||||||
|  | dumptxt -p $[OUT] "common1=$[COMMON_1]" | ||||||
|  | dumptxt -p $[OUT] "common2=$[COMMON_2]" | ||||||
|  | dumptxt -p $[OUT] "common3=$[COMMON_3]" | ||||||
|  | dumptxt -p $[OUT] "common4=$[COMMON_4]" | ||||||
|  | dumptxt -p $[OUT] "common5=$[COMMON_5]" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | dumptxt -p $[OUT] "# KeyN" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "slot0x0DKeyN=$[KEYN_0D]" | ||||||
|  | dumptxt -p $[OUT] "slot0x2DKeyN=$[KEYN_2D]" | ||||||
|  | dumptxt -p $[OUT] "slot0x32KeyN=$[KEYN_32]" | ||||||
|  | dumptxt -p $[OUT] "slot0x36KeyN=$[KEYN_36]" | ||||||
|  | dumptxt -p $[OUT] "slot0x38KeyN=$[KEYN_38]" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | dumptxt -p $[OUT] "# NFC Secrets" | ||||||
|  | dumptxt -p $[OUT] "" | ||||||
|  | 
 | ||||||
|  | dumptxt -p $[OUT] "nfcSecret0Phrase=$[NFC_PHRASE_0]" | ||||||
|  | dumptxt -p $[OUT] "nfcSecret0Seed=$[NFC_SEED_0]" | ||||||
|  | dumptxt -p $[OUT] "nfcSecret0HmacKey=$[NFC_HMAC_KEY_0]" | ||||||
|  | dumptxt -p $[OUT] "nfcSecret1Phrase=$[NFC_PHRASE_1]" | ||||||
|  | dumptxt -p $[OUT] "nfcSecret1Seed=$[NFC_SEED_1]" | ||||||
|  | dumptxt -p $[OUT] "nfcSecret1HmacKey=$[NFC_HMAC_KEY_1]" | ||||||
|  | dumptxt -p $[OUT] "nfcIv=$[NFC_IV]" | ||||||
|  | 
 | ||||||
|  | @Exit | ||||||
|  | 
 | ||||||
							
								
								
									
										10
									
								
								dist/dumpkeys/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								dist/dumpkeys/README.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | # DumpKeys | ||||||
|  | 
 | ||||||
|  | This is a GodMode9 script that dumps all the keys and other related secrets that Citra needs from a real 3DS. | ||||||
|  | 
 | ||||||
|  | Usage: | ||||||
|  | 1. Copy "DumpKeys.gm9" into the "gm9/scripts/" directory on your SD card. | ||||||
|  | 2. Launch GodMode9, press the HOME button, select Scripts, and select "DumpKeys" from the list of scripts that appears. | ||||||
|  | 3. Wait for the script to complete and return you to the GodMode9 main menu. | ||||||
|  | 4. Power off your system and copy the "gm9/aes_keys.txt" file off of your SD card into "(Citra directory)/sysdata/". | ||||||
|  | 
 | ||||||
|  | @ -31,13 +31,12 @@ constexpr std::array<u8, 10> KeyTypes{{ | ||||||
|     HW::AES::APTWrap, |     HW::AES::APTWrap, | ||||||
|     HW::AES::BOSSDataKey, |     HW::AES::BOSSDataKey, | ||||||
|     0x32, // unknown
 |     0x32, // unknown
 | ||||||
|     HW::AES::DLPDataKey, |     HW::AES::DLPNFCDataKey, | ||||||
|     HW::AES::CECDDataKey, |     HW::AES::CECDDataKey, | ||||||
|     0, // invalid
 |     0, // invalid
 | ||||||
|     HW::AES::FRDKey, |     HW::AES::FRDKey, | ||||||
|     // Note: According to 3dbrew the KeyY is overridden by Process9 when using this key type.
 |     // Note: According to 3dbrew the KeyY is overridden by Process9 when using this key type.
 | ||||||
|     // TODO: implement this behaviour?
 |     HW::AES::DLPNFCDataKey, | ||||||
|     HW::AES::NFCKey, |  | ||||||
| }}; | }}; | ||||||
| 
 | 
 | ||||||
| void PS_PS::EncryptDecryptAes(Kernel::HLERequestContext& ctx) { | void PS_PS::EncryptDecryptAes(Kernel::HLERequestContext& ctx) { | ||||||
|  | @ -60,6 +59,12 @@ void PS_PS::EncryptDecryptAes(Kernel::HLERequestContext& ctx) { | ||||||
|     // and encrypted data is actually returned, but the key used is unknown.
 |     // and encrypted data is actually returned, but the key used is unknown.
 | ||||||
|     ASSERT_MSG(key_type != 7 && key_type < 10, "Key type is invalid"); |     ASSERT_MSG(key_type != 7 && key_type < 10, "Key type is invalid"); | ||||||
| 
 | 
 | ||||||
|  |     if (key_type == 0x5) { | ||||||
|  |         HW::AES::SelectDlpNfcKeyYIndex(HW::AES::DlpNfcKeyY::Dlp); | ||||||
|  |     } else if (key_type == 0x9) { | ||||||
|  |         HW::AES::SelectDlpNfcKeyYIndex(HW::AES::DlpNfcKeyY::Nfc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (!HW::AES::IsNormalKeyAvailable(KeyTypes[key_type])) { |     if (!HW::AES::IsNormalKeyAvailable(KeyTypes[key_type])) { | ||||||
|         LOG_ERROR(Service_PS, |         LOG_ERROR(Service_PS, | ||||||
|                   "Key 0x{:2X} is not available, encryption/decryption will not be correct", |                   "Key 0x{:2X} is not available, encryption/decryption will not be correct", | ||||||
|  |  | ||||||
|  | @ -55,6 +55,15 @@ AESKey HexToKey(const std::string& hex) { | ||||||
|     return key; |     return key; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::vector<u8> HexToVector(const std::string& hex) { | ||||||
|  |     std::vector<u8> vector(hex.size() / 2); | ||||||
|  |     for (std::size_t i = 0; i < vector.size(); ++i) { | ||||||
|  |         vector[i] = static_cast<u8>(std::stoi(hex.substr(i * 2, 2), nullptr, 16)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return vector; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct KeySlot { | struct KeySlot { | ||||||
|     std::optional<AESKey> x; |     std::optional<AESKey> x; | ||||||
|     std::optional<AESKey> y; |     std::optional<AESKey> y; | ||||||
|  | @ -91,6 +100,9 @@ struct KeySlot { | ||||||
| 
 | 
 | ||||||
| std::array<KeySlot, KeySlotID::MaxKeySlotID> key_slots; | std::array<KeySlot, KeySlotID::MaxKeySlotID> key_slots; | ||||||
| std::array<std::optional<AESKey>, MaxCommonKeySlot> common_key_y_slots; | std::array<std::optional<AESKey>, MaxCommonKeySlot> common_key_y_slots; | ||||||
|  | std::array<std::optional<AESKey>, NumDlpNfcKeyYs> dlp_nfc_key_y_slots; | ||||||
|  | std::array<NfcSecret, NumNfcSecrets> nfc_secrets; | ||||||
|  | AESIV nfc_iv; | ||||||
| 
 | 
 | ||||||
| enum class FirmwareType : u32 { | enum class FirmwareType : u32 { | ||||||
|     ARM9 = 0,  // uses NDMA
 |     ARM9 = 0,  // uses NDMA
 | ||||||
|  | @ -440,6 +452,12 @@ void LoadPresetKeys() { | ||||||
|     while (!file.eof()) { |     while (!file.eof()) { | ||||||
|         std::string line; |         std::string line; | ||||||
|         std::getline(file, line); |         std::getline(file, line); | ||||||
|  | 
 | ||||||
|  |         // Ignore empty or commented lines.
 | ||||||
|  |         if (line.empty() || line.starts_with("#")) { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         std::vector<std::string> parts; |         std::vector<std::string> parts; | ||||||
|         Common::SplitString(line, '=', parts); |         Common::SplitString(line, '=', parts); | ||||||
|         if (parts.size() != 2) { |         if (parts.size() != 2) { | ||||||
|  | @ -448,6 +466,24 @@ void LoadPresetKeys() { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const std::string& name = parts[0]; |         const std::string& name = parts[0]; | ||||||
|  | 
 | ||||||
|  |         std::size_t nfc_secret_index; | ||||||
|  |         if (std::sscanf(name.c_str(), "nfcSecret%zd", &nfc_secret_index) == 1) { | ||||||
|  |             auto value = HexToVector(parts[1]); | ||||||
|  |             if (nfc_secret_index >= nfc_secrets.size()) { | ||||||
|  |                 LOG_ERROR(HW_AES, "Invalid NFC secret index {}", nfc_secret_index); | ||||||
|  |             } else if (name.ends_with("Phrase")) { | ||||||
|  |                 nfc_secrets[nfc_secret_index].phrase = value; | ||||||
|  |             } else if (name.ends_with("Seed")) { | ||||||
|  |                 nfc_secrets[nfc_secret_index].seed = value; | ||||||
|  |             } else if (name.ends_with("HmacKey")) { | ||||||
|  |                 nfc_secrets[nfc_secret_index].hmac_key = value; | ||||||
|  |             } else { | ||||||
|  |                 LOG_ERROR(HW_AES, "Invalid NFC secret {}", name); | ||||||
|  |             } | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         AESKey key; |         AESKey key; | ||||||
|         try { |         try { | ||||||
|             key = HexToKey(parts[1]); |             key = HexToKey(parts[1]); | ||||||
|  | @ -466,6 +502,21 @@ void LoadPresetKeys() { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if (name == "dlpKeyY") { | ||||||
|  |             dlp_nfc_key_y_slots[DlpNfcKeyY::Dlp] = key; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (name == "nfcKeyY") { | ||||||
|  |             dlp_nfc_key_y_slots[DlpNfcKeyY::Nfc] = key; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (name == "nfcIv") { | ||||||
|  |             nfc_iv = key; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         std::size_t slot_id; |         std::size_t slot_id; | ||||||
|         char key_type; |         char key_type; | ||||||
|         if (std::sscanf(name.c_str(), "slot0x%zXKey%c", &slot_id, &key_type) != 2) { |         if (std::sscanf(name.c_str(), "slot0x%zXKey%c", &slot_id, &key_type) != 2) { | ||||||
|  | @ -534,4 +585,16 @@ void SelectCommonKeyIndex(u8 index) { | ||||||
|     key_slots[KeySlotID::TicketCommonKey].SetKeyY(common_key_y_slots.at(index)); |     key_slots[KeySlotID::TicketCommonKey].SetKeyY(common_key_y_slots.at(index)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SelectDlpNfcKeyYIndex(u8 index) { | ||||||
|  |     key_slots[KeySlotID::DLPNFCDataKey].SetKeyY(dlp_nfc_key_y_slots.at(index)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const NfcSecret& GetNfcSecret(u8 index) { | ||||||
|  |     return nfc_secrets[index]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const AESIV& GetNfcIv() { | ||||||
|  |     return nfc_iv; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace HW::AES
 | } // namespace HW::AES
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
|  | #include <vector> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| namespace HW::AES { | namespace HW::AES { | ||||||
|  | @ -27,8 +28,8 @@ enum KeySlotID : std::size_t { | ||||||
|     // AES Keyslot used to encrypt the BOSS container data.
 |     // AES Keyslot used to encrypt the BOSS container data.
 | ||||||
|     BOSSDataKey = 0x38, |     BOSSDataKey = 0x38, | ||||||
| 
 | 
 | ||||||
|     // AES Keyslot used to calculate DLP data frame checksum.
 |     // AES Keyslot used to calculate DLP data frame checksum and encrypt Amiibo key data.
 | ||||||
|     DLPDataKey = 0x39, |     DLPNFCDataKey = 0x39, | ||||||
| 
 | 
 | ||||||
|     // AES Keyslot used to generate the StreetPass CCMP key.
 |     // AES Keyslot used to generate the StreetPass CCMP key.
 | ||||||
|     CECDDataKey = 0x2E, |     CECDDataKey = 0x2E, | ||||||
|  | @ -36,9 +37,6 @@ enum KeySlotID : std::size_t { | ||||||
|     // AES Keyslot used by the friends module.
 |     // AES Keyslot used by the friends module.
 | ||||||
|     FRDKey = 0x36, |     FRDKey = 0x36, | ||||||
| 
 | 
 | ||||||
|     // AES Keyslot used by the NFC module.
 |  | ||||||
|     NFCKey = 0x39, |  | ||||||
| 
 |  | ||||||
|     // AES keyslot used for APT:Wrap/Unwrap functions
 |     // AES keyslot used for APT:Wrap/Unwrap functions
 | ||||||
|     APTWrap = 0x31, |     APTWrap = 0x31, | ||||||
| 
 | 
 | ||||||
|  | @ -48,11 +46,28 @@ enum KeySlotID : std::size_t { | ||||||
|     MaxKeySlotID = 0x40, |     MaxKeySlotID = 0x40, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum DlpNfcKeyY : std::size_t { | ||||||
|  |     // Download Play KeyY
 | ||||||
|  |     Dlp = 0, | ||||||
|  | 
 | ||||||
|  |     // NFC (Amiibo) KeyY
 | ||||||
|  |     Nfc = 1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct NfcSecret { | ||||||
|  |     std::vector<u8> phrase; | ||||||
|  |     std::vector<u8> seed; | ||||||
|  |     std::vector<u8> hmac_key; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| constexpr std::size_t MaxCommonKeySlot = 6; | constexpr std::size_t MaxCommonKeySlot = 6; | ||||||
|  | constexpr std::size_t NumDlpNfcKeyYs = 2; | ||||||
|  | constexpr std::size_t NumNfcSecrets = 2; | ||||||
| 
 | 
 | ||||||
| constexpr std::size_t AES_BLOCK_SIZE = 16; | constexpr std::size_t AES_BLOCK_SIZE = 16; | ||||||
| 
 | 
 | ||||||
| using AESKey = std::array<u8, AES_BLOCK_SIZE>; | using AESKey = std::array<u8, AES_BLOCK_SIZE>; | ||||||
|  | using AESIV = std::array<u8, AES_BLOCK_SIZE>; | ||||||
| 
 | 
 | ||||||
| void InitKeys(bool force = false); | void InitKeys(bool force = false); | ||||||
| 
 | 
 | ||||||
|  | @ -65,5 +80,9 @@ bool IsNormalKeyAvailable(std::size_t slot_id); | ||||||
| AESKey GetNormalKey(std::size_t slot_id); | AESKey GetNormalKey(std::size_t slot_id); | ||||||
| 
 | 
 | ||||||
| void SelectCommonKeyIndex(u8 index); | void SelectCommonKeyIndex(u8 index); | ||||||
|  | void SelectDlpNfcKeyYIndex(u8 index); | ||||||
|  | 
 | ||||||
|  | const NfcSecret& GetNfcSecret(u8 index); | ||||||
|  | const AESIV& GetNfcIv(); | ||||||
| 
 | 
 | ||||||
| } // namespace HW::AES
 | } // namespace HW::AES
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue