diff options
| author | 2023-08-28 22:22:00 -0400 | |
|---|---|---|
| committer | 2023-08-28 22:22:00 -0400 | |
| commit | 5a09ba7255dc4428137bd2f51fb1bb197ef36957 (patch) | |
| tree | 653a6fff417e36c1f20a1371a27c0cbf82d8b687 | |
| parent | Merge pull request #11390 from FearlessTobi/hwopus-multi (diff) | |
| download | yuzu-5a09ba7255dc4428137bd2f51fb1bb197ef36957.tar.gz yuzu-5a09ba7255dc4428137bd2f51fb1bb197ef36957.tar.xz yuzu-5a09ba7255dc4428137bd2f51fb1bb197ef36957.zip | |
vfs: ensure key area keys are validated
| -rw-r--r-- | src/core/file_sys/content_archive.cpp | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 44e6852fe..7d2f0abb8 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -22,6 +22,10 @@ | |||
| 22 | 22 | ||
| 23 | namespace FileSys { | 23 | namespace FileSys { |
| 24 | 24 | ||
| 25 | static u8 MasterKeyIdForKeyGeneration(u8 key_generation) { | ||
| 26 | return std::max<u8>(key_generation, 1) - 1; | ||
| 27 | } | ||
| 28 | |||
| 25 | NCA::NCA(VirtualFile file_, const NCA* base_nca) | 29 | NCA::NCA(VirtualFile file_, const NCA* base_nca) |
| 26 | : file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { | 30 | : file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { |
| 27 | if (file == nullptr) { | 31 | if (file == nullptr) { |
| @@ -41,12 +45,17 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) | |||
| 41 | return; | 45 | return; |
| 42 | } | 46 | } |
| 43 | 47 | ||
| 48 | // Ensure we have the proper key area keys to continue. | ||
| 49 | const u8 master_key_id = MasterKeyIdForKeyGeneration(reader->GetKeyGeneration()); | ||
| 50 | if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, reader->GetKeyIndex())) { | ||
| 51 | status = Loader::ResultStatus::ErrorMissingKeyAreaKey; | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | |||
| 44 | RightsId rights_id{}; | 55 | RightsId rights_id{}; |
| 45 | reader->GetRightsId(rights_id.data(), rights_id.size()); | 56 | reader->GetRightsId(rights_id.data(), rights_id.size()); |
| 46 | if (rights_id != RightsId{}) { | 57 | if (rights_id != RightsId{}) { |
| 47 | // External decryption key required; provide it here. | 58 | // External decryption key required; provide it here. |
| 48 | const auto key_generation = std::max<s32>(reader->GetKeyGeneration(), 1) - 1; | ||
| 49 | |||
| 50 | u128 rights_id_u128; | 59 | u128 rights_id_u128; |
| 51 | std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id)); | 60 | std::memcpy(rights_id_u128.data(), rights_id.data(), sizeof(rights_id)); |
| 52 | 61 | ||
| @@ -57,12 +66,12 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) | |||
| 57 | return; | 66 | return; |
| 58 | } | 67 | } |
| 59 | 68 | ||
| 60 | if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, key_generation)) { | 69 | if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) { |
| 61 | status = Loader::ResultStatus::ErrorMissingTitlekek; | 70 | status = Loader::ResultStatus::ErrorMissingTitlekek; |
| 62 | return; | 71 | return; |
| 63 | } | 72 | } |
| 64 | 73 | ||
| 65 | auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, key_generation); | 74 | auto titlekek = keys.GetKey(Core::Crypto::S128KeyType::Titlekek, master_key_id); |
| 66 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB); | 75 | Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(titlekek, Core::Crypto::Mode::ECB); |
| 67 | cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), | 76 | cipher.Transcode(titlekey.data(), titlekey.size(), titlekey.data(), |
| 68 | Core::Crypto::Op::Decrypt); | 77 | Core::Crypto::Op::Decrypt); |