diff --git a/src/common/common_paths.h b/src/common/common_paths.h index d5b510cdb..8ce3769e1 100644 --- a/src/common/common_paths.h +++ b/src/common/common_paths.h @@ -46,3 +46,4 @@ // Sys files #define SHARED_FONT "shared_font.bin" #define AES_KEYS "aes_keys.txt" +#define AES_KEYS_DB "aeskeydb.bin" diff --git a/src/core/hw/aes/key.cpp b/src/core/hw/aes/key.cpp index 4e8a8a59a..91050189d 100644 --- a/src/core/hw/aes/key.cpp +++ b/src/core/hw/aes/key.cpp @@ -76,7 +76,30 @@ AESKey HexToKey(const std::string& hex) { return key; } -void LoadPresetKeys() { +void SetKeySlot(const AESKey& key, size_t slot_id, char key_type) { + switch (key_type) { + case 'X': + if (!key_slots.at(slot_id).x.is_initialized()) { + SetKeyX(slot_id, key); + } + break; + case 'Y': + if (!key_slots.at(slot_id).y.is_initialized()) { + SetKeyY(slot_id, key); + } + break; + case 'N': + if (!key_slots.at(slot_id).normal.is_initialized()) { + SetNormalKey(slot_id, key); + } + break; + default: + LOG_ERROR(HW_AES, "Invalid key type %c", key_type); + break; + } +} + +void LoadKeysFromText() { const std::string filepath = FileUtil::GetUserPath(D_SYSDATA_IDX) + AES_KEYS; FileUtil::CreateFullPath(filepath); // Create path if not already created std::ifstream file; @@ -121,22 +144,59 @@ void LoadPresetKeys() { continue; } - switch (key_type) { - case 'X': - key_slots.at(slot_id).SetKeyX(key); - break; - case 'Y': - key_slots.at(slot_id).SetKeyY(key); - break; - case 'N': - key_slots.at(slot_id).SetNormalKey(key); - break; - default: - LOG_ERROR(HW_AES, "Invalid key type %c", key_type); - break; - } + SetKeySlot(key, slot_id, key_type); } } +/** + * This is used to load the aeskeydb.bin file from the sysdata directory. + * This file comes from Decrypt9 and can be built using the Build Key Database option. + * It requires bin files containing the key data following the format slot0x??key?.bin. + * The wiki describes that this database can be encrypted or decrypted however as of right now only + * the decrypted format is supported. + */ +void LoadKeysFromDB() { + // aeskeydb.bin struct taken from https://git.io/vyzHF + struct AesKeyInfo { + u8 slot; // keyslot, 0x00...0x3F + char type; // type 'X' / 'Y' / 'N' for normalKey + std::array id; // key ID for special keys, all zero for standard keys + u8 reserved[2]; // reserved space + u8 is_devkitkey; // 0 for retail units / 1 for DevKit units + u8 is_encrypted; // 0 if not / anything else if it is + AESKey key; + }; + + const std::string filepath = FileUtil::GetUserPath(D_SYSDATA_IDX) + AES_KEYS_DB; + // Create path if not already created + FileUtil::CreateFullPath(filepath); + auto file = FileUtil::IOFile(filepath, "r"); + + if (!file) { + return; + } + AesKeyInfo key_info; + while (file.IsGood()) { + file.ReadArray(&key_info, 1); + + if (key_info.slot >= MaxKeySlotID) { + LOG_ERROR(HW_AES, "Out of range slot ID 0x%zX", key_info.slot); + continue; + } + if (key_info.is_encrypted) { + LOG_ERROR(HW_AES, "Key with slot ID 0x%zX is encrypted", key_info.slot); + continue; + } + if (key_info.id[0] != 0x00) { + LOG_WARNING(HW_AES, "Key with slot ID 0x%zX is a special key, ignoring", key_info.slot); + continue; + } + SetKeySlot(key_info.key, key_info.slot, key_info.type); + } +} +void LoadPresetKeys() { + LoadKeysFromText(); + LoadKeysFromDB(); +} } // namespace