Преглед изворни кода

Merge pull request #1486 from lioncash/file

key_manager/partition_data_manager: Minor changes
bunnei пре 7 година
родитељ
комит
b3cca34f50

+ 26 - 13
src/core/crypto/key_manager.cpp

@@ -98,7 +98,7 @@ std::array<u8, 144> DecryptKeyblob(const std::array<u8, 176>& encrypted_keyblob,
     return keyblob;
     return keyblob;
 }
 }
 
 
-void KeyManager::DeriveGeneralPurposeKeys(u8 crypto_revision) {
+void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
     const auto kek_generation_source =
     const auto kek_generation_source =
         GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration));
         GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration));
     const auto key_generation_source =
     const auto key_generation_source =
@@ -147,31 +147,38 @@ boost::optional<Key128> DeriveSDSeed() {
                                    "rb+");
                                    "rb+");
     if (!save_43.IsOpen())
     if (!save_43.IsOpen())
         return boost::none;
         return boost::none;
+
     const FileUtil::IOFile sd_private(
     const FileUtil::IOFile sd_private(
         FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
         FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
     if (!sd_private.IsOpen())
     if (!sd_private.IsOpen())
         return boost::none;
         return boost::none;
 
 
-    sd_private.Seek(0, SEEK_SET);
     std::array<u8, 0x10> private_seed{};
     std::array<u8, 0x10> private_seed{};
-    if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != 0x10)
+    if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
         return boost::none;
         return boost::none;
+    }
 
 
     std::array<u8, 0x10> buffer{};
     std::array<u8, 0x10> buffer{};
     std::size_t offset = 0;
     std::size_t offset = 0;
     for (; offset + 0x10 < save_43.GetSize(); ++offset) {
     for (; offset + 0x10 < save_43.GetSize(); ++offset) {
-        save_43.Seek(offset, SEEK_SET);
+        if (!save_43.Seek(offset, SEEK_SET)) {
+            return boost::none;
+        }
+
         save_43.ReadBytes(buffer.data(), buffer.size());
         save_43.ReadBytes(buffer.data(), buffer.size());
-        if (buffer == private_seed)
+        if (buffer == private_seed) {
             break;
             break;
+        }
     }
     }
 
 
-    if (offset + 0x10 >= save_43.GetSize())
+    if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
         return boost::none;
         return boost::none;
+    }
 
 
     Key128 seed{};
     Key128 seed{};
-    save_43.Seek(offset + 0x10, SEEK_SET);
-    save_43.ReadBytes(seed.data(), seed.size());
+    if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
+        return boost::none;
+    }
     return seed;
     return seed;
 }
 }
 
 
@@ -234,7 +241,9 @@ std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) {
         return {};
         return {};
 
 
     std::vector<u8> buffer(ticket_save.GetSize());
     std::vector<u8> buffer(ticket_save.GetSize());
-    ticket_save.ReadBytes(buffer.data(), buffer.size());
+    if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
+        return {};
+    }
 
 
     std::vector<TicketRaw> out;
     std::vector<TicketRaw> out;
     u32 magic{};
     u32 magic{};
@@ -261,6 +270,9 @@ static std::array<u8, size> operator^(const std::array<u8, size>& lhs,
 
 
 template <size_t target_size, size_t in_size>
 template <size_t target_size, size_t in_size>
 static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
 static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
+    // Avoids truncation overflow within the loop below.
+    static_assert(target_size <= 0xFF);
+
     std::array<u8, in_size + 4> seed_exp{};
     std::array<u8, in_size + 4> seed_exp{};
     std::memcpy(seed_exp.data(), seed.data(), in_size);
     std::memcpy(seed_exp.data(), seed.data(), in_size);
 
 
@@ -268,7 +280,7 @@ static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
     size_t i = 0;
     size_t i = 0;
     while (out.size() < target_size) {
     while (out.size() < target_size) {
         out.resize(out.size() + 0x20);
         out.resize(out.size() + 0x20);
-        seed_exp[in_size + 3] = i;
+        seed_exp[in_size + 3] = static_cast<u8>(i);
         mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0);
         mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0);
         ++i;
         ++i;
     }
     }
@@ -299,10 +311,11 @@ boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
     std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority));
     std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority));
     if (cert_authority == 0)
     if (cert_authority == 0)
         return boost::none;
         return boost::none;
-    if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't'))
+    if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) {
         LOG_INFO(Crypto,
         LOG_INFO(Crypto,
                  "Attempting to parse ticket with non-standard certificate authority {:08X}.",
                  "Attempting to parse ticket with non-standard certificate authority {:08X}.",
                  cert_authority);
                  cert_authority);
+    }
 
 
     Key128 rights_id;
     Key128 rights_id;
     std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
     std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
@@ -871,9 +884,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
                                      "/system/save/80000000000000e2",
                                      "/system/save/80000000000000e2",
                                  "rb+");
                                  "rb+");
 
 
+    const auto blob2 = GetTicketblob(save2);
     auto res = GetTicketblob(save1);
     auto res = GetTicketblob(save1);
-    const auto res2 = GetTicketblob(save2);
-    std::copy(res2.begin(), res2.end(), std::back_inserter(res));
+    res.insert(res.end(), blob2.begin(), blob2.end());
 
 
     for (const auto& raw : res) {
     for (const auto& raw : res) {
         const auto pair = ParseTicket(raw, rsa_key);
         const auto pair = ParseTicket(raw, rsa_key);

+ 1 - 1
src/core/crypto/key_manager.h

@@ -175,7 +175,7 @@ private:
     void WriteKeyToFile(KeyCategory category, std::string_view keyname,
     void WriteKeyToFile(KeyCategory category, std::string_view keyname,
                         const std::array<u8, Size>& key);
                         const std::array<u8, Size>& key);
 
 
-    void DeriveGeneralPurposeKeys(u8 crypto_revision);
+    void DeriveGeneralPurposeKeys(std::size_t crypto_revision);
 
 
     void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
     void SetKeyWrapped(S128KeyType id, Key128 key, u64 field1 = 0, u64 field2 = 0);
     void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);
     void SetKeyWrapped(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0);

+ 34 - 42
src/core/crypto/partition_data_manager.cpp

@@ -11,7 +11,6 @@
 #include <array>
 #include <array>
 #include <cctype>
 #include <cctype>
 #include <cstring>
 #include <cstring>
-#include <boost/optional/optional.hpp>
 #include <mbedtls/sha256.h>
 #include <mbedtls/sha256.h>
 #include "common/assert.h"
 #include "common/assert.h"
 #include "common/common_funcs.h"
 #include "common/common_funcs.h"
@@ -19,7 +18,7 @@
 #include "common/hex_util.h"
 #include "common/hex_util.h"
 #include "common/logging/log.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
 #include "common/string_util.h"
-#include "core/crypto/ctr_encryption_layer.h"
+#include "common/swap.h"
 #include "core/crypto/key_manager.h"
 #include "core/crypto/key_manager.h"
 #include "core/crypto/partition_data_manager.h"
 #include "core/crypto/partition_data_manager.h"
 #include "core/crypto/xts_encryption_layer.h"
 #include "core/crypto/xts_encryption_layer.h"
@@ -302,7 +301,7 @@ FileSys::VirtualFile FindFileInDirWithNames(const FileSys::VirtualDir& dir,
     return nullptr;
     return nullptr;
 }
 }
 
 
-PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir)
+PartitionDataManager::PartitionDataManager(const FileSys::VirtualDir& sysdata_dir)
     : boot0(FindFileInDirWithNames(sysdata_dir, "BOOT0")),
     : boot0(FindFileInDirWithNames(sysdata_dir, "BOOT0")),
       fuses(FindFileInDirWithNames(sysdata_dir, "fuse")),
       fuses(FindFileInDirWithNames(sysdata_dir, "fuse")),
       kfuses(FindFileInDirWithNames(sysdata_dir, "kfuse")),
       kfuses(FindFileInDirWithNames(sysdata_dir, "kfuse")),
@@ -314,13 +313,14 @@ PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir)
           FindFileInDirWithNames(sysdata_dir, "BCPKG2-5-Repair-Main"),
           FindFileInDirWithNames(sysdata_dir, "BCPKG2-5-Repair-Main"),
           FindFileInDirWithNames(sysdata_dir, "BCPKG2-6-Repair-Sub"),
           FindFileInDirWithNames(sysdata_dir, "BCPKG2-6-Repair-Sub"),
       }),
       }),
+      prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")),
       secure_monitor(FindFileInDirWithNames(sysdata_dir, "secmon")),
       secure_monitor(FindFileInDirWithNames(sysdata_dir, "secmon")),
       package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg1_decr")),
       package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg1_decr")),
       secure_monitor_bytes(secure_monitor == nullptr ? std::vector<u8>{}
       secure_monitor_bytes(secure_monitor == nullptr ? std::vector<u8>{}
                                                      : secure_monitor->ReadAllBytes()),
                                                      : secure_monitor->ReadAllBytes()),
       package1_decrypted_bytes(package1_decrypted == nullptr ? std::vector<u8>{}
       package1_decrypted_bytes(package1_decrypted == nullptr ? std::vector<u8>{}
-                                                             : package1_decrypted->ReadAllBytes()),
-      prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")) {}
+                                                             : package1_decrypted->ReadAllBytes()) {
+}
 
 
 PartitionDataManager::~PartitionDataManager() = default;
 PartitionDataManager::~PartitionDataManager() = default;
 
 
@@ -332,18 +332,19 @@ FileSys::VirtualFile PartitionDataManager::GetBoot0Raw() const {
     return boot0;
     return boot0;
 }
 }
 
 
-std::array<u8, 176> PartitionDataManager::GetEncryptedKeyblob(u8 index) const {
-    if (HasBoot0() && index < 32)
+PartitionDataManager::EncryptedKeyBlob PartitionDataManager::GetEncryptedKeyblob(
+    std::size_t index) const {
+    if (HasBoot0() && index < NUM_ENCRYPTED_KEYBLOBS)
         return GetEncryptedKeyblobs()[index];
         return GetEncryptedKeyblobs()[index];
     return {};
     return {};
 }
 }
 
 
-std::array<std::array<u8, 176>, 32> PartitionDataManager::GetEncryptedKeyblobs() const {
+PartitionDataManager::EncryptedKeyBlobs PartitionDataManager::GetEncryptedKeyblobs() const {
     if (!HasBoot0())
     if (!HasBoot0())
         return {};
         return {};
 
 
-    std::array<std::array<u8, 176>, 32> out{};
-    for (size_t i = 0; i < 0x20; ++i)
+    EncryptedKeyBlobs out{};
+    for (size_t i = 0; i < out.size(); ++i)
         boot0->Read(out[i].data(), out[i].size(), 0x180000 + i * 0x200);
         boot0->Read(out[i].data(), out[i].size(), 0x180000 + i * 0x200);
     return out;
     return out;
 }
 }
@@ -389,7 +390,7 @@ std::array<u8, 16> PartitionDataManager::GetKeyblobMACKeySource() const {
     return FindKeyFromHex(package1_decrypted_bytes, source_hashes[0]);
     return FindKeyFromHex(package1_decrypted_bytes, source_hashes[0]);
 }
 }
 
 
-std::array<u8, 16> PartitionDataManager::GetKeyblobKeySource(u8 revision) const {
+std::array<u8, 16> PartitionDataManager::GetKeyblobKeySource(std::size_t revision) const {
     if (keyblob_source_hashes[revision] == SHA256Hash{}) {
     if (keyblob_source_hashes[revision] == SHA256Hash{}) {
         LOG_WARNING(Crypto,
         LOG_WARNING(Crypto,
                     "No keyblob source hash for crypto revision {:02X}! Cannot derive keys...",
                     "No keyblob source hash for crypto revision {:02X}! Cannot derive keys...",
@@ -446,7 +447,7 @@ bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) {
     return false;
     return false;
 }
 }
 
 
-void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20> package2_keys,
+void PartitionDataManager::DecryptPackage2(const std::array<Key128, 0x20>& package2_keys,
                                            Package2Type type) {
                                            Package2Type type) {
     FileSys::VirtualFile file = std::make_shared<FileSys::OffsetVfsFile>(
     FileSys::VirtualFile file = std::make_shared<FileSys::OffsetVfsFile>(
         package2[static_cast<size_t>(type)],
         package2[static_cast<size_t>(type)],
@@ -456,43 +457,38 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20>
     if (file->ReadObject(&header) != sizeof(Package2Header))
     if (file->ReadObject(&header) != sizeof(Package2Header))
         return;
         return;
 
 
-    u8 revision = 0xFF;
+    std::size_t revision = 0xFF;
     if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) {
     if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) {
-        for (size_t i = 0; i < package2_keys.size(); ++i) {
-            if (AttemptDecrypt(package2_keys[i], header))
+        for (std::size_t i = 0; i < package2_keys.size(); ++i) {
+            if (AttemptDecrypt(package2_keys[i], header)) {
                 revision = i;
                 revision = i;
+            }
         }
         }
     }
     }
 
 
     if (header.magic != Common::MakeMagic('P', 'K', '2', '1'))
     if (header.magic != Common::MakeMagic('P', 'K', '2', '1'))
         return;
         return;
 
 
-    const std::vector<u8> s1_iv(header.section_ctr[1].begin(), header.section_ctr[1].end());
-
     const auto a = std::make_shared<FileSys::OffsetVfsFile>(
     const auto a = std::make_shared<FileSys::OffsetVfsFile>(
         file, header.section_size[1], header.section_size[0] + sizeof(Package2Header));
         file, header.section_size[1], header.section_size[0] + sizeof(Package2Header));
 
 
     auto c = a->ReadAllBytes();
     auto c = a->ReadAllBytes();
 
 
     AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR);
     AESCipher<Key128> cipher(package2_keys[revision], Mode::CTR);
-    cipher.SetIV(s1_iv);
+    cipher.SetIV({header.section_ctr[1].begin(), header.section_ctr[1].end()});
     cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt);
     cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt);
 
 
-    // package2_decrypted[static_cast<size_t>(type)] = s1;
-
     INIHeader ini;
     INIHeader ini;
     std::memcpy(&ini, c.data(), sizeof(INIHeader));
     std::memcpy(&ini, c.data(), sizeof(INIHeader));
     if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1'))
     if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1'))
         return;
         return;
 
 
-    std::map<u64, KIPHeader> kips{};
     u64 offset = sizeof(INIHeader);
     u64 offset = sizeof(INIHeader);
     for (size_t i = 0; i < ini.process_count; ++i) {
     for (size_t i = 0; i < ini.process_count; ++i) {
         KIPHeader kip;
         KIPHeader kip;
         std::memcpy(&kip, c.data() + offset, sizeof(KIPHeader));
         std::memcpy(&kip, c.data() + offset, sizeof(KIPHeader));
         if (kip.magic != Common::MakeMagic('K', 'I', 'P', '1'))
         if (kip.magic != Common::MakeMagic('K', 'I', 'P', '1'))
             return;
             return;
-        kips.emplace(offset, kip);
 
 
         const auto name =
         const auto name =
             Common::StringFromFixedZeroTerminatedBuffer(kip.name.data(), kip.name.size());
             Common::StringFromFixedZeroTerminatedBuffer(kip.name.data(), kip.name.size());
@@ -503,33 +499,29 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20>
             continue;
             continue;
         }
         }
 
 
-        std::vector<u8> text(kip.sections[0].size_compressed);
-        std::vector<u8> rodata(kip.sections[1].size_compressed);
-        std::vector<u8> data(kip.sections[2].size_compressed);
+        const u64 initial_offset = sizeof(KIPHeader) + offset;
+        const auto text_begin = c.cbegin() + initial_offset;
+        const auto text_end = text_begin + kip.sections[0].size_compressed;
+        const std::vector<u8> text = DecompressBLZ({text_begin, text_end});
 
 
-        u64 offset_sec = sizeof(KIPHeader) + offset;
-        std::memcpy(text.data(), c.data() + offset_sec, text.size());
-        offset_sec += text.size();
-        std::memcpy(rodata.data(), c.data() + offset_sec, rodata.size());
-        offset_sec += rodata.size();
-        std::memcpy(data.data(), c.data() + offset_sec, data.size());
+        const auto rodata_end = text_end + kip.sections[1].size_compressed;
+        const std::vector<u8> rodata = DecompressBLZ({text_end, rodata_end});
 
 
-        offset += sizeof(KIPHeader) + kip.sections[0].size_compressed +
-                  kip.sections[1].size_compressed + kip.sections[2].size_compressed;
+        const auto data_end = rodata_end + kip.sections[2].size_compressed;
+        const std::vector<u8> data = DecompressBLZ({rodata_end, data_end});
 
 
-        text = DecompressBLZ(text);
-        rodata = DecompressBLZ(rodata);
-        data = DecompressBLZ(data);
+        std::vector<u8> out;
+        out.reserve(text.size() + rodata.size() + data.size());
+        out.insert(out.end(), text.begin(), text.end());
+        out.insert(out.end(), rodata.begin(), rodata.end());
+        out.insert(out.end(), data.begin(), data.end());
 
 
-        std::vector<u8> out(text.size() + rodata.size() + data.size());
-        std::memcpy(out.data(), text.data(), text.size());
-        std::memcpy(out.data() + text.size(), rodata.data(), rodata.size());
-        std::memcpy(out.data() + text.size() + rodata.size(), data.data(), data.size());
+        offset += sizeof(KIPHeader) + out.size();
 
 
         if (name == "FS")
         if (name == "FS")
-            package2_fs[static_cast<size_t>(type)] = out;
+            package2_fs[static_cast<size_t>(type)] = std::move(out);
         else if (name == "spl")
         else if (name == "spl")
-            package2_spl[static_cast<size_t>(type)] = out;
+            package2_spl[static_cast<size_t>(type)] = std::move(out);
     }
     }
 }
 }
 
 

+ 11 - 7
src/core/crypto/partition_data_manager.h

@@ -5,9 +5,7 @@
 #pragma once
 #pragma once
 
 
 #include <vector>
 #include <vector>
-#include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/common_types.h"
-#include "common/swap.h"
 #include "core/file_sys/vfs_types.h"
 #include "core/file_sys/vfs_types.h"
 
 
 namespace Core::Crypto {
 namespace Core::Crypto {
@@ -24,15 +22,20 @@ enum class Package2Type {
 class PartitionDataManager {
 class PartitionDataManager {
 public:
 public:
     static const u8 MAX_KEYBLOB_SOURCE_HASH;
     static const u8 MAX_KEYBLOB_SOURCE_HASH;
+    static constexpr std::size_t NUM_ENCRYPTED_KEYBLOBS = 32;
+    static constexpr std::size_t ENCRYPTED_KEYBLOB_SIZE = 0xB0;
 
 
-    explicit PartitionDataManager(FileSys::VirtualDir sysdata_dir);
+    using EncryptedKeyBlob = std::array<u8, ENCRYPTED_KEYBLOB_SIZE>;
+    using EncryptedKeyBlobs = std::array<EncryptedKeyBlob, NUM_ENCRYPTED_KEYBLOBS>;
+
+    explicit PartitionDataManager(const FileSys::VirtualDir& sysdata_dir);
     ~PartitionDataManager();
     ~PartitionDataManager();
 
 
     // BOOT0
     // BOOT0
     bool HasBoot0() const;
     bool HasBoot0() const;
     FileSys::VirtualFile GetBoot0Raw() const;
     FileSys::VirtualFile GetBoot0Raw() const;
-    std::array<u8, 0xB0> GetEncryptedKeyblob(u8 index) const;
-    std::array<std::array<u8, 0xB0>, 0x20> GetEncryptedKeyblobs() const;
+    EncryptedKeyBlob GetEncryptedKeyblob(std::size_t index) const;
+    EncryptedKeyBlobs GetEncryptedKeyblobs() const;
     std::vector<u8> GetSecureMonitor() const;
     std::vector<u8> GetSecureMonitor() const;
     std::array<u8, 0x10> GetPackage2KeySource() const;
     std::array<u8, 0x10> GetPackage2KeySource() const;
     std::array<u8, 0x10> GetAESKekGenerationSource() const;
     std::array<u8, 0x10> GetAESKekGenerationSource() const;
@@ -43,7 +46,7 @@ public:
     std::vector<u8> GetPackage1Decrypted() const;
     std::vector<u8> GetPackage1Decrypted() const;
     std::array<u8, 0x10> GetMasterKeySource() const;
     std::array<u8, 0x10> GetMasterKeySource() const;
     std::array<u8, 0x10> GetKeyblobMACKeySource() const;
     std::array<u8, 0x10> GetKeyblobMACKeySource() const;
-    std::array<u8, 0x10> GetKeyblobKeySource(u8 revision) const;
+    std::array<u8, 0x10> GetKeyblobKeySource(std::size_t revision) const;
 
 
     // Fuses
     // Fuses
     bool HasFuses() const;
     bool HasFuses() const;
@@ -57,7 +60,8 @@ public:
     // Package2
     // Package2
     bool HasPackage2(Package2Type type = Package2Type::NormalMain) const;
     bool HasPackage2(Package2Type type = Package2Type::NormalMain) const;
     FileSys::VirtualFile GetPackage2Raw(Package2Type type = Package2Type::NormalMain) const;
     FileSys::VirtualFile GetPackage2Raw(Package2Type type = Package2Type::NormalMain) const;
-    void DecryptPackage2(std::array<std::array<u8, 16>, 0x20> package2, Package2Type type);
+    void DecryptPackage2(const std::array<std::array<u8, 16>, 0x20>& package2_keys,
+                         Package2Type type);
     const std::vector<u8>& GetPackage2FSDecompressed(
     const std::vector<u8>& GetPackage2FSDecompressed(
         Package2Type type = Package2Type::NormalMain) const;
         Package2Type type = Package2Type::NormalMain) const;
     std::array<u8, 0x10> GetKeyAreaKeyApplicationSource(
     std::array<u8, 0x10> GetKeyAreaKeyApplicationSource(