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
|
@ -31,13 +31,12 @@ constexpr std::array<u8, 10> KeyTypes{{
|
|||
HW::AES::APTWrap,
|
||||
HW::AES::BOSSDataKey,
|
||||
0x32, // unknown
|
||||
HW::AES::DLPDataKey,
|
||||
HW::AES::DLPNFCDataKey,
|
||||
HW::AES::CECDDataKey,
|
||||
0, // invalid
|
||||
HW::AES::FRDKey,
|
||||
// Note: According to 3dbrew the KeyY is overridden by Process9 when using this key type.
|
||||
// TODO: implement this behaviour?
|
||||
HW::AES::NFCKey,
|
||||
HW::AES::DLPNFCDataKey,
|
||||
}};
|
||||
|
||||
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.
|
||||
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])) {
|
||||
LOG_ERROR(Service_PS,
|
||||
"Key 0x{:2X} is not available, encryption/decryption will not be correct",
|
||||
|
|
|
@ -55,6 +55,15 @@ AESKey HexToKey(const std::string& hex) {
|
|||
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 {
|
||||
std::optional<AESKey> x;
|
||||
std::optional<AESKey> y;
|
||||
|
@ -91,6 +100,9 @@ struct KeySlot {
|
|||
|
||||
std::array<KeySlot, KeySlotID::MaxKeySlotID> key_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 {
|
||||
ARM9 = 0, // uses NDMA
|
||||
|
@ -440,6 +452,12 @@ void LoadPresetKeys() {
|
|||
while (!file.eof()) {
|
||||
std::string line;
|
||||
std::getline(file, line);
|
||||
|
||||
// Ignore empty or commented lines.
|
||||
if (line.empty() || line.starts_with("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> parts;
|
||||
Common::SplitString(line, '=', parts);
|
||||
if (parts.size() != 2) {
|
||||
|
@ -448,6 +466,24 @@ void LoadPresetKeys() {
|
|||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
key = HexToKey(parts[1]);
|
||||
|
@ -466,6 +502,21 @@ void LoadPresetKeys() {
|
|||
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;
|
||||
char key_type;
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace HW::AES {
|
||||
|
@ -27,8 +28,8 @@ enum KeySlotID : std::size_t {
|
|||
// AES Keyslot used to encrypt the BOSS container data.
|
||||
BOSSDataKey = 0x38,
|
||||
|
||||
// AES Keyslot used to calculate DLP data frame checksum.
|
||||
DLPDataKey = 0x39,
|
||||
// AES Keyslot used to calculate DLP data frame checksum and encrypt Amiibo key data.
|
||||
DLPNFCDataKey = 0x39,
|
||||
|
||||
// AES Keyslot used to generate the StreetPass CCMP key.
|
||||
CECDDataKey = 0x2E,
|
||||
|
@ -36,9 +37,6 @@ enum KeySlotID : std::size_t {
|
|||
// AES Keyslot used by the friends module.
|
||||
FRDKey = 0x36,
|
||||
|
||||
// AES Keyslot used by the NFC module.
|
||||
NFCKey = 0x39,
|
||||
|
||||
// AES keyslot used for APT:Wrap/Unwrap functions
|
||||
APTWrap = 0x31,
|
||||
|
||||
|
@ -48,11 +46,28 @@ enum KeySlotID : std::size_t {
|
|||
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 NumDlpNfcKeyYs = 2;
|
||||
constexpr std::size_t NumNfcSecrets = 2;
|
||||
|
||||
constexpr std::size_t AES_BLOCK_SIZE = 16;
|
||||
|
||||
using AESKey = std::array<u8, AES_BLOCK_SIZE>;
|
||||
using AESIV = std::array<u8, AES_BLOCK_SIZE>;
|
||||
|
||||
void InitKeys(bool force = false);
|
||||
|
||||
|
@ -65,5 +80,9 @@ bool IsNormalKeyAvailable(std::size_t slot_id);
|
|||
AESKey GetNormalKey(std::size_t slot_id);
|
||||
|
||||
void SelectCommonKeyIndex(u8 index);
|
||||
void SelectDlpNfcKeyYIndex(u8 index);
|
||||
|
||||
const NfcSecret& GetNfcSecret(u8 index);
|
||||
const AESIV& GetNfcIv();
|
||||
|
||||
} // namespace HW::AES
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue