From 4aad010f7adbcf7d524b245139cd35869c7799f2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 23 Sep 2018 21:05:01 -0400 Subject: key_manager: Add support for loading keys from partition data --- src/core/crypto/key_manager.cpp | 86 +++++++++++++++++++++++++++++++++++++++++ src/core/crypto/key_manager.h | 2 + 2 files changed, 88 insertions(+) diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 1328cdd47..027643654 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -870,6 +870,92 @@ void KeyManager::SetKeyWrapped(S256KeyType id, Key256 key, u64 field1, u64 field SetKey(id, key, field1, field2); } +void KeyManager::PopulateFromPartitionData(PartitionDataManager data) { + if (!BaseDeriveNecessary()) + return; + + if (!data.HasBoot0()) + return; + + for (size_t i = 0; i < 0x20; ++i) { + if (encrypted_keyblobs[i] != std::array{}) + continue; + encrypted_keyblobs[i] = data.GetEncryptedKeyblob(i); + WriteKeyToFile<0xB0>(KeyCategory::Console, fmt::format("encrypted_keyblob_{:02X}", i), + encrypted_keyblobs[i]); + } + + SetKeyWrapped(S128KeyType::Source, data.GetPackage2KeySource(), + static_cast(SourceKeyType::Package2)); + SetKeyWrapped(S128KeyType::Source, data.GetAESKekGenerationSource(), + static_cast(SourceKeyType::AESKekGeneration)); + SetKeyWrapped(S128KeyType::Source, data.GetTitlekekSource(), + static_cast(SourceKeyType::Titlekek)); + SetKeyWrapped(S128KeyType::Source, data.GetMasterKeySource(), + static_cast(SourceKeyType::Master)); + SetKeyWrapped(S128KeyType::Source, data.GetKeyblobMACKeySource(), + static_cast(SourceKeyType::KeyblobMAC)); + + for (size_t i = 0; i < PartitionDataManager::MAX_KEYBLOB_SOURCE_HASH; ++i) { + SetKeyWrapped(S128KeyType::Source, data.GetKeyblobKeySource(i), + static_cast(SourceKeyType::Keyblob), i); + } + + if (data.HasFuses()) + SetKeyWrapped(S128KeyType::SecureBoot, data.GetSecureBootKey()); + + DeriveBase(); + + Key128 latest_master{}; + for (s8 i = 0x1F; i > 0; --i) { + if (GetKey(S128KeyType::Master, i) != Key128{}) { + latest_master = GetKey(S128KeyType::Master, i); + break; + } + } + + const auto masters = data.GetTZMasterKeys(latest_master); + for (size_t i = 0; i < 0x20; ++i) { + if (masters[i] != Key128{} && !HasKey(S128KeyType::Master, i)) + SetKey(S128KeyType::Master, masters[i], i); + } + + DeriveBase(); + + if (!data.HasPackage2()) + return; + + std::array package2_keys{}; + for (size_t i = 0; i < 0x20; ++i) { + if (HasKey(S128KeyType::Package2, i)) + package2_keys[i] = GetKey(S128KeyType::Package2, i); + } + data.DecryptPackage2(package2_keys, Package2Type::NormalMain); + + SetKeyWrapped(S128KeyType::Source, data.GetKeyAreaKeyApplicationSource(), + static_cast(SourceKeyType::KeyAreaKey), + static_cast(KeyAreaKeyType::Application)); + SetKeyWrapped(S128KeyType::Source, data.GetKeyAreaKeyOceanSource(), + static_cast(SourceKeyType::KeyAreaKey), + static_cast(KeyAreaKeyType::Ocean)); + SetKeyWrapped(S128KeyType::Source, data.GetKeyAreaKeySystemSource(), + static_cast(SourceKeyType::KeyAreaKey), + static_cast(KeyAreaKeyType::System)); + SetKeyWrapped(S128KeyType::Source, data.GetSDKekSource(), + static_cast(SourceKeyType::SDKek)); + SetKeyWrapped(S256KeyType::SDKeySource, data.GetSDSaveKeySource(), + static_cast(SDKeyType::Save)); + SetKeyWrapped(S256KeyType::SDKeySource, data.GetSDNCAKeySource(), + static_cast(SDKeyType::NCA)); + SetKeyWrapped(S128KeyType::Source, data.GetHeaderKekSource(), + static_cast(SourceKeyType::HeaderKek)); + SetKeyWrapped(S256KeyType::HeaderSource, data.GetHeaderKeySource()); + SetKeyWrapped(S128KeyType::Source, data.GetAESKeyGenerationSource(), + static_cast(SourceKeyType::AESKeyGeneration)); + + DeriveBase(); +} + const boost::container::flat_map> KeyManager::s128_file_id = { {"eticket_rsa_kek", {S128KeyType::ETicketRSAKek, 0, 0}}, {"eticket_rsa_kek_source", diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 58afcdcac..d26aa59b6 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -158,6 +158,8 @@ public: void DeriveBase(); void DeriveETicket(PartitionDataManager data); + void PopulateFromPartitionData(PartitionDataManager data); + private: std::map, Key128> s128_keys; std::map, Key256> s256_keys; -- cgit v1.2.3