Add consolidated GodMode9 key dumping script. (#6396)
This commit is contained in:
parent
8d19483b7e
commit
b6e73f0d49
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Reference in New Issue