// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include "common/common_types.h" namespace Crypto { typedef std::array Key128; typedef std::array Key256; typedef std::array SHA256Hash; static_assert(sizeof(Key128) == 16, "Key128 must be 128 bytes big."); static_assert(sizeof(Key256) == 32, "Key128 must be 128 bytes big."); enum class S256KeyType : u64 { HEADER, // SD_SAVE, // SD_NCA, // }; enum class S128KeyType : u64 { MASTER, // f1=crypto revision PACKAGE1, // f1=crypto revision PACKAGE2, // f1=crypto revision TITLEKEK, // f1=crypto revision ETICKET_RSA_KEK, // KEY_AREA, // f1=crypto revision f2=type {app, ocean, system} SD_SEED, // TITLEKEY, // f1=rights id LSB f2=rights id MSB }; enum class KeyAreaKeyType : u8 { Application, Ocean, System, }; template struct KeyIndex { KeyType type; u64 field1; u64 field2; std::string DebugInfo() { u8 key_size = 16; if (std::is_same_v) key_size = 32; return fmt::format("key_size={:02X}, key={:02X}, field1={:016X}, field2={:016X}", key_size, static_cast(type), field1, field2); } }; // The following two (== and hash) are so KeyIndex can be a key in unordered_map template bool operator==(const KeyIndex& lhs, const KeyIndex& rhs) { return lhs.type == rhs.type && lhs.field1 == rhs.field1 && lhs.field2 == rhs.field2; } } // namespace Crypto namespace std { template struct hash> { size_t operator()(const Crypto::KeyIndex& k) const { using std::hash; return ((hash()(static_cast(k.type)) ^ (hash()(k.field1) << 1)) >> 1) ^ (hash()(k.field2) << 1); } }; } // namespace std namespace Crypto { std::array operator"" _array16(const char* str, size_t len); std::array operator"" _array32(const char* str, size_t len); struct KeyManager { void SetValidationMode(bool dev); void LoadFromFile(std::string_view filename, bool is_title_keys); bool HasKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0); bool HasKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0); Key128 GetKey(S128KeyType id, u64 field1 = 0, u64 field2 = 0); Key256 GetKey(S256KeyType id, u64 field1 = 0, u64 field2 = 0); void SetKey(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0); void SetKey(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); bool ValidateKey(S128KeyType key, u64 field1 = 0, u64 field2 = 0); bool ValidateKey(S256KeyType key, u64 field1 = 0, u64 field2 = 0); private: std::unordered_map, Key128> s128_keys; std::unordered_map, Key256> s256_keys; bool dev_mode = false; static std::unordered_map, SHA256Hash> s128_hash_prod; static std::unordered_map, SHA256Hash> s256_hash_prod; static std::unordered_map, SHA256Hash> s128_hash_dev; static std::unordered_map, SHA256Hash> s256_hash_dev; static std::unordered_map> s128_file_id; static std::unordered_map> s256_file_id; }; extern KeyManager keys; } // namespace Crypto