vfs: ensure key area keys are validated

This commit is contained in:
Liam 2023-08-28 22:22:00 -04:00
parent 1615a86375
commit 5a09ba7255
1 changed files with 13 additions and 4 deletions

View File

@ -22,6 +22,10 @@
namespace FileSys { namespace FileSys {
static u8 MasterKeyIdForKeyGeneration(u8 key_generation) {
return std::max<u8>(key_generation, 1) - 1;
}
NCA::NCA(VirtualFile file_, const NCA* base_nca) NCA::NCA(VirtualFile file_, const NCA* base_nca)
: file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { : file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
if (file == nullptr) { if (file == nullptr) {
@ -41,12 +45,17 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
return; return;
} }
// Ensure we have the proper key area keys to continue.
const u8 master_key_id = MasterKeyIdForKeyGeneration(reader->GetKeyGeneration());
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, reader->GetKeyIndex())) {
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
return;
}
RightsId rights_id{}; RightsId rights_id{};
reader->GetRightsId(rights_id.data(), rights_id.size()); reader->GetRightsId(rights_id.data(), rights_id.size());
if (rights_id != RightsId{}) { if (rights_id != RightsId{}) {
// External decryption key required; provide it here. // External decryption key required; provide it here.
const auto key_generation = std::max<s32>(reader->GetKeyGeneration(), 1) - 1;
u128 rights_id_u128; u128 rights_id_u128;
std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id)); std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id));
@ -57,12 +66,12 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
return; return;
} }
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, key_generation)) { if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
status = Loader::ResultStatus::ErrorMissingTitlekek; status = Loader::ResultStatus::ErrorMissingTitlekek;
return; return;
} }
auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, key_generation); auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id);
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB); Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB);
cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(),
Core::Crypto::Op::Decrypt); Core::Crypto::Op::Decrypt);