summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2018-09-24 02:56:02 +0200
committerZach Hilman <zachhilman@gmail.com>2018-10-07 19:15:11 +0200
commitd6a0d5d43263be84959ab74e8e6570c1b9a28693 (patch)
tree0a34564611279f9a55f91d6ee8a3d7a8a0d8a0e9
parentkey_manager: Add keyblob support (diff)
downloadyuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar.gz
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar.bz2
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar.lz
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar.xz
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.tar.zst
yuzu-d6a0d5d43263be84959ab74e8e6570c1b9a28693.zip
-rw-r--r--src/core/crypto/key_manager.cpp68
-rw-r--r--src/core/crypto/key_manager.h34
2 files changed, 99 insertions, 3 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 0f1a86d1e..2a0b0b574 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -152,6 +152,12 @@ KeyManager::KeyManager() {
AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, "console.keys_autogenerated", false);
}
+static bool ValidCryptoRevisionString(const std::string& base, size_t begin, size_t length) {
+ if (base.size() < begin + length)
+ return false;
+ return std::all_of(base.begin() + begin, base.begin() + begin + length, ::isdigit);
+}
+
void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
std::ifstream file(filename);
if (!file.is_open())
@@ -190,6 +196,59 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
const auto index = s256_file_id.at(out[0]);
Key256 key = Common::HexStringToArray<32>(out[1]);
s256_keys[{index.type, index.field1, index.field2}] = key;
+ } else if (out[0].compare(0, 8, "keyblob_") == 0 &&
+ out[0].compare(0, 9, "keyblob_k") != 0) {
+ if (!ValidCryptoRevisionString(out[0], 8, 2))
+ continue;
+
+ const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16);
+ keyblobs[index] = Common::HexStringToArray<0x90>(out[1]);
+ } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) {
+ if (!ValidCryptoRevisionString(out[0], 18, 2))
+ continue;
+
+ const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16);
+ encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]);
+ } else {
+ for (const auto& kv : std::map<std::pair<S128KeyType, u64>, std::string>{
+ {{S128KeyType::Master, 0}, "master_key_"},
+ {{S128KeyType::Package1, 0}, "package1_key_"},
+ {{S128KeyType::Package2, 0}, "package2_key_"},
+ {{S128KeyType::Titlekek, 0}, "titlekek_"},
+ {{S128KeyType::Source, static_cast<u64>(SourceKeyType::Keyblob)},
+ "keyblob_key_source_"},
+ {{S128KeyType::Keyblob, 0}, "keyblob_key_"},
+ {{S128KeyType::KeyblobMAC, 0}, "keyblob_mac_key_"},
+ }) {
+ if (!ValidCryptoRevisionString(out[0], kv.second.size(), 2))
+ continue;
+ if (out[0].compare(0, kv.second.size(), kv.second) == 0) {
+ const auto index =
+ std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16);
+ const auto sub = kv.first.second;
+ if (sub == 0) {
+ s128_keys[{kv.first.first, index, 0}] =
+ Common::HexStringToArray<16>(out[1]);
+ } else {
+ s128_keys[{kv.first.first, kv.first.second, index}] =
+ Common::HexStringToArray<16>(out[1]);
+ }
+
+ break;
+ }
+ }
+
+ const static std::array<const char*, 3> kak_names = {
+ "key_area_key_application_", "key_area_key_ocean_", "key_area_key_system_"};
+ for (size_t j = 0; j < 3; ++j) {
+ const auto& match = kak_names[j];
+ if (out[0].compare(0, std::strlen(match), match) == 0) {
+ const auto index =
+ std::stoul(out[0].substr(std::strlen(match), 2), nullptr, 16);
+ s128_keys[{S128KeyType::KeyArea, index, j}] =
+ Common::HexStringToArray<16>(out[1]);
+ }
+ }
}
}
}
@@ -255,8 +314,15 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
Key128 rights_id;
std::memcpy(rights_id.data(), &field2, sizeof(u64));
std::memcpy(rights_id.data() + sizeof(u64), &field1, sizeof(u64));
- WriteKeyToFile(true, Common::HexArrayToString(rights_id), key);
+ WriteKeyToFile(KeyCategory::Title, Common::HexArrayToString(rights_id), key);
}
+
+ auto category = KeyCategory::Standard;
+ if (id == S128KeyType::Keyblob || id == S128KeyType::KeyblobMAC || id == S128KeyType::TSEC ||
+ id == S128KeyType::SecureBoot || id == S128KeyType::SDSeed || id == S128KeyType::BIS) {
+ category = KeyCategory::Console;
+ }
+
const auto iter2 = std::find_if(
s128_file_id.begin(), s128_file_id.end(),
[&id, &field1, &field2](const std::pair<std::string, KeyIndex<S128KeyType>> elem) {
diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h
index b2c386bfb..1cb62c2dc 100644
--- a/src/core/crypto/key_manager.h
+++ b/src/core/crypto/key_manager.h
@@ -33,8 +33,10 @@ enum class KeyCategory : u8 {
};
enum class S256KeyType : u64 {
- Header, //
- SDKeySource, // f1=SDKeyType
+ SDKey, // f1=SDKeyType
+ Header, //
+ SDKeySource, // f1=SDKeyType
+ HeaderSource, //
};
enum class S128KeyType : u64 {
@@ -47,6 +49,14 @@ enum class S128KeyType : u64 {
SDSeed, //
Titlekey, // f1=rights id LSB f2=rights id MSB
Source, // f1=source type, f2= sub id
+ Keyblob, // f1=crypto revision
+ KeyblobMAC, // f1=crypto revision
+ TSEC, //
+ SecureBoot, //
+ BIS, // f1=partition (0-3), f2=type {crypt, tweak}
+ HeaderKek, //
+ SDKek, //
+ RSAKek, //
};
enum class KeyAreaKeyType : u8 {
@@ -59,6 +69,16 @@ enum class SourceKeyType : u8 {
SDKek, //
AESKekGeneration, //
AESKeyGeneration, //
+ RSAOaepKekGeneration, //
+ Master, //
+ Keyblob, // f2=crypto revision
+ KeyAreaKey, // f2=KeyAreaKeyType
+ Titlekek, //
+ Package2, //
+ HeaderKek, //
+ KeyblobMAC, //
+ ETicketKek, //
+ ETicketKekek, //
};
enum class SDKeyType : u8 {
@@ -66,6 +86,16 @@ enum class SDKeyType : u8 {
NCA,
};
+enum class BISKeyType : u8 {
+ Crypto,
+ Tweak,
+};
+
+enum class RSAKekType : u8 {
+ Mask0,
+ Seed3,
+};
+
template <typename KeyType>
struct KeyIndex {
KeyType type;