From 1b48e3ec0888275fbcd2854a81385e7c963b7ec5 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 08:33:45 -0400 Subject: partition_data_manager: Remove unused includes Gets unused includes out of the headers and moves them into the cpp file if they're used there instead. --- src/core/crypto/partition_data_manager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index d1c04e98df..4baf8ccc5c 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "common/assert.h" #include "common/common_funcs.h" @@ -19,7 +18,7 @@ #include "common/hex_util.h" #include "common/logging/log.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/partition_data_manager.h" #include "core/crypto/xts_encryption_layer.h" -- cgit v1.2.3 From 0581db975afb7a9793205e39d38ef9c1a8bf7772 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 08:36:23 -0400 Subject: partition_data_manager: Amend constructor initializer list order Orders the members in the exact order they would be initialized. This also prevents compiler warnings about this sort of thing. --- src/core/crypto/partition_data_manager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 4baf8ccc5c..7c3d9661d4 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -313,13 +313,14 @@ PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir) FindFileInDirWithNames(sysdata_dir, "BCPKG2-5-Repair-Main"), FindFileInDirWithNames(sysdata_dir, "BCPKG2-6-Repair-Sub"), }), + prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")), secure_monitor(FindFileInDirWithNames(sysdata_dir, "secmon")), package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg1_decr")), secure_monitor_bytes(secure_monitor == nullptr ? std::vector{} : secure_monitor->ReadAllBytes()), package1_decrypted_bytes(package1_decrypted == nullptr ? std::vector{} - : package1_decrypted->ReadAllBytes()), - prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")) {} + : package1_decrypted->ReadAllBytes()) { +} PartitionDataManager::~PartitionDataManager() = default; -- cgit v1.2.3 From 49f255e0b50779f1d4d16fbf6451a570b656998b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 08:39:02 -0400 Subject: partition_data_manager: Take VirtualFile by const reference in constructor Given the VirtualFile instance isn't stored into the class as a data member, or written to, this can just be turned into a const reference, as the constructor doesn't need to make a copy of it. --- src/core/crypto/partition_data_manager.cpp | 2 +- src/core/crypto/partition_data_manager.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 7c3d9661d4..ff46aad7c4 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -301,7 +301,7 @@ FileSys::VirtualFile FindFileInDirWithNames(const FileSys::VirtualDir& dir, return nullptr; } -PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir) +PartitionDataManager::PartitionDataManager(const FileSys::VirtualDir& sysdata_dir) : boot0(FindFileInDirWithNames(sysdata_dir, "BOOT0")), fuses(FindFileInDirWithNames(sysdata_dir, "fuse")), kfuses(FindFileInDirWithNames(sysdata_dir, "kfuse")), diff --git a/src/core/crypto/partition_data_manager.h b/src/core/crypto/partition_data_manager.h index 0822a949c7..c5a492a92b 100644 --- a/src/core/crypto/partition_data_manager.h +++ b/src/core/crypto/partition_data_manager.h @@ -23,7 +23,7 @@ class PartitionDataManager { public: static const u8 MAX_KEYBLOB_SOURCE_HASH; - explicit PartitionDataManager(FileSys::VirtualDir sysdata_dir); + explicit PartitionDataManager(const FileSys::VirtualDir& sysdata_dir); ~PartitionDataManager(); // BOOT0 -- cgit v1.2.3 From 8e8fbbc19b4faed97b9168b314e401f194865349 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 08:52:34 -0400 Subject: partition_data_manager: Dehardcode array bounds Instead, we can make it part of the type and make named variables for them, so they only require one definition (and if they ever change for whatever reason, they only need to be changed in one spot). --- src/core/crypto/partition_data_manager.cpp | 10 +++++----- src/core/crypto/partition_data_manager.h | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index ff46aad7c4..bef8cdaf00 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -332,18 +332,18 @@ FileSys::VirtualFile PartitionDataManager::GetBoot0Raw() const { return boot0; } -std::array PartitionDataManager::GetEncryptedKeyblob(u8 index) const { - if (HasBoot0() && index < 32) +PartitionDataManager::EncryptedKeyBlob PartitionDataManager::GetEncryptedKeyblob(u8 index) const { + if (HasBoot0() && index < NUM_ENCRYPTED_KEYBLOBS) return GetEncryptedKeyblobs()[index]; return {}; } -std::array, 32> PartitionDataManager::GetEncryptedKeyblobs() const { +PartitionDataManager::EncryptedKeyBlobs PartitionDataManager::GetEncryptedKeyblobs() const { if (!HasBoot0()) return {}; - std::array, 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); return out; } diff --git a/src/core/crypto/partition_data_manager.h b/src/core/crypto/partition_data_manager.h index c5a492a92b..7c9c4410a9 100644 --- a/src/core/crypto/partition_data_manager.h +++ b/src/core/crypto/partition_data_manager.h @@ -22,6 +22,11 @@ enum class Package2Type { class PartitionDataManager { public: 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; + + using EncryptedKeyBlob = std::array; + using EncryptedKeyBlobs = std::array; explicit PartitionDataManager(const FileSys::VirtualDir& sysdata_dir); ~PartitionDataManager(); @@ -29,8 +34,8 @@ public: // BOOT0 bool HasBoot0() const; FileSys::VirtualFile GetBoot0Raw() const; - std::array GetEncryptedKeyblob(u8 index) const; - std::array, 0x20> GetEncryptedKeyblobs() const; + EncryptedKeyBlob GetEncryptedKeyblob(u8 index) const; + EncryptedKeyBlobs GetEncryptedKeyblobs() const; std::vector GetSecureMonitor() const; std::array GetPackage2KeySource() const; std::array GetAESKekGenerationSource() const; -- cgit v1.2.3 From e21cda8767466211fdc41fb15ea05f3eb26d9d6a Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:13:19 -0400 Subject: key_manager/partition_data_manager: Silence truncation compiler warnings --- src/core/crypto/key_manager.cpp | 7 +++++-- src/core/crypto/key_manager.h | 2 +- src/core/crypto/partition_data_manager.cpp | 12 +++++++----- src/core/crypto/partition_data_manager.h | 4 ++-- 4 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index d2ce4f5bf5..fd07860684 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -98,7 +98,7 @@ std::array DecryptKeyblob(const std::array& encrypted_keyblob, return keyblob; } -void KeyManager::DeriveGeneralPurposeKeys(u8 crypto_revision) { +void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) { const auto kek_generation_source = GetKey(S128KeyType::Source, static_cast(SourceKeyType::AESKekGeneration)); const auto key_generation_source = @@ -270,6 +270,9 @@ static std::array operator^(const std::array& lhs, template static std::array MGF1(const std::array& seed) { + // Avoids truncation overflow within the loop below. + static_assert(target_size <= 0xFF); + std::array seed_exp{}; std::memcpy(seed_exp.data(), seed.data(), in_size); @@ -277,7 +280,7 @@ static std::array MGF1(const std::array& seed) { size_t i = 0; while (out.size() < target_size) { out.resize(out.size() + 0x20); - seed_exp[in_size + 3] = i; + seed_exp[in_size + 3] = static_cast(i); mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0); ++i; } diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index a41abbdfcd..cccb3c0aec 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -175,7 +175,7 @@ private: void WriteKeyToFile(KeyCategory category, std::string_view keyname, const std::array& 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(S256KeyType id, Key256 key, u64 field1 = 0, u64 field2 = 0); diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index bef8cdaf00..51d89508bd 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -332,7 +332,8 @@ FileSys::VirtualFile PartitionDataManager::GetBoot0Raw() const { return boot0; } -PartitionDataManager::EncryptedKeyBlob PartitionDataManager::GetEncryptedKeyblob(u8 index) const { +PartitionDataManager::EncryptedKeyBlob PartitionDataManager::GetEncryptedKeyblob( + std::size_t index) const { if (HasBoot0() && index < NUM_ENCRYPTED_KEYBLOBS) return GetEncryptedKeyblobs()[index]; return {}; @@ -389,7 +390,7 @@ std::array PartitionDataManager::GetKeyblobMACKeySource() const { return FindKeyFromHex(package1_decrypted_bytes, source_hashes[0]); } -std::array PartitionDataManager::GetKeyblobKeySource(u8 revision) const { +std::array PartitionDataManager::GetKeyblobKeySource(std::size_t revision) const { if (keyblob_source_hashes[revision] == SHA256Hash{}) { LOG_WARNING(Crypto, "No keyblob source hash for crypto revision {:02X}! Cannot derive keys...", @@ -456,11 +457,12 @@ void PartitionDataManager::DecryptPackage2(std::array, 0x20> if (file->ReadObject(&header) != sizeof(Package2Header)) return; - u8 revision = 0xFF; + std::size_t revision = 0xFF; 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; + } } } diff --git a/src/core/crypto/partition_data_manager.h b/src/core/crypto/partition_data_manager.h index 7c9c4410a9..9e448f7205 100644 --- a/src/core/crypto/partition_data_manager.h +++ b/src/core/crypto/partition_data_manager.h @@ -34,7 +34,7 @@ public: // BOOT0 bool HasBoot0() const; FileSys::VirtualFile GetBoot0Raw() const; - EncryptedKeyBlob GetEncryptedKeyblob(u8 index) const; + EncryptedKeyBlob GetEncryptedKeyblob(std::size_t index) const; EncryptedKeyBlobs GetEncryptedKeyblobs() const; std::vector GetSecureMonitor() const; std::array GetPackage2KeySource() const; @@ -46,7 +46,7 @@ public: std::vector GetPackage1Decrypted() const; std::array GetMasterKeySource() const; std::array GetKeyblobMACKeySource() const; - std::array GetKeyblobKeySource(u8 revision) const; + std::array GetKeyblobKeySource(std::size_t revision) const; // Fuses bool HasFuses() const; -- cgit v1.2.3 From 7095c2fa42a100c17438b9e374166fe621c774d4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:16:27 -0400 Subject: partition_data_manager: Remove commented out code Commented out code shouldn't be left in without a reason indicating why in a comment. --- src/core/crypto/partition_data_manager.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 51d89508bd..056119c042 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -480,8 +480,6 @@ void PartitionDataManager::DecryptPackage2(std::array, 0x20> cipher.SetIV(s1_iv); cipher.Transcode(c.data(), c.size(), c.data(), Op::Decrypt); - // package2_decrypted[static_cast(type)] = s1; - INIHeader ini; std::memcpy(&ini, c.data(), sizeof(INIHeader)); if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1')) -- cgit v1.2.3 From 461cd4b81cc90d1b2da3f98033247b0a1d406935 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:20:19 -0400 Subject: partition_data_manager: Move IV data to where it's needed in DecryptPackage2() Given it's only used in one spot and has a fairly generic name, we can just specify it directly in the function call. This also the benefit of automatically moving it. --- src/core/crypto/partition_data_manager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 056119c042..e364affbac 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -469,15 +469,13 @@ void PartitionDataManager::DecryptPackage2(std::array, 0x20> if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) return; - const std::vector s1_iv(header.section_ctr[1].begin(), header.section_ctr[1].end()); - const auto a = std::make_shared( file, header.section_size[1], header.section_size[0] + sizeof(Package2Header)); auto c = a->ReadAllBytes(); AESCipher 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); INIHeader ini; -- cgit v1.2.3 From 283f111f7df7ba241d20100b919f112507d98729 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:23:34 -0400 Subject: partition_data_manager: Take package2_keys by const reference These are only ever read from, so we don't need to make a copy of all the keys here. --- src/core/crypto/partition_data_manager.cpp | 2 +- src/core/crypto/partition_data_manager.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index e364affbac..6862a08842 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -447,7 +447,7 @@ bool AttemptDecrypt(const std::array& key, Package2Header& header) { return false; } -void PartitionDataManager::DecryptPackage2(std::array, 0x20> package2_keys, +void PartitionDataManager::DecryptPackage2(const std::array& package2_keys, Package2Type type) { FileSys::VirtualFile file = std::make_shared( package2[static_cast(type)], diff --git a/src/core/crypto/partition_data_manager.h b/src/core/crypto/partition_data_manager.h index 9e448f7205..0ad007c727 100644 --- a/src/core/crypto/partition_data_manager.h +++ b/src/core/crypto/partition_data_manager.h @@ -60,7 +60,8 @@ public: // Package2 bool HasPackage2(Package2Type type = Package2Type::NormalMain) const; FileSys::VirtualFile GetPackage2Raw(Package2Type type = Package2Type::NormalMain) const; - void DecryptPackage2(std::array, 0x20> package2, Package2Type type); + void DecryptPackage2(const std::array, 0x20>& package2_keys, + Package2Type type); const std::vector& GetPackage2FSDecompressed( Package2Type type = Package2Type::NormalMain) const; std::array GetKeyAreaKeyApplicationSource( -- cgit v1.2.3 From 20a95f7e909f28df7a0abd78094981db3da97b25 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:27:07 -0400 Subject: partition_data_manager: Remove unused std::map instance within DecryptPackage2() Aside from emplacing elements into the map, the map itself is never actually queried for contained data. --- src/core/crypto/partition_data_manager.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 6862a08842..a311ad8465 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -483,14 +483,12 @@ void PartitionDataManager::DecryptPackage2(const std::array& packa if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1')) return; - std::map kips{}; u64 offset = sizeof(INIHeader); for (size_t i = 0; i < ini.process_count; ++i) { KIPHeader kip; std::memcpy(&kip, c.data() + offset, sizeof(KIPHeader)); if (kip.magic != Common::MakeMagic('K', 'I', 'P', '1')) return; - kips.emplace(offset, kip); const auto name = Common::StringFromFixedZeroTerminatedBuffer(kip.name.data(), kip.name.size()); -- cgit v1.2.3 From 18db0f11077e0eb69342d3c17a44f5bdcff968ed Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Oct 2018 09:30:09 -0400 Subject: partition_data_manager: Reserve and insert data within output vector in DecryptPackage2() We can just reserve the memory then perform successive insertions instead of needing to use memcpy. This also avoids the need to zero out the output vector's memory before performing the insertions. We can also std::move the output std::vector into the destination so that we don't need to make a completely new copy of the vector, getting rid of an unnecessary allocation. Additionally, we can use iterators to determine the beginning and end ranges of the std::vector instances that comprise the output vector, as the end of one range just becomes the beginning for the next successive range, and since std::vector's iterator constructor copies data within the range [begin, end), this is more straightforward and gets rid of the need to have an offset variable that keeps getting incremented to determine where to do the next std::memcpy. --- src/core/crypto/partition_data_manager.cpp | 36 +++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'src/core/crypto/partition_data_manager.cpp') diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index a311ad8465..ed5e2b145f 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -499,33 +499,29 @@ void PartitionDataManager::DecryptPackage2(const std::array& packa continue; } - std::vector text(kip.sections[0].size_compressed); - std::vector rodata(kip.sections[1].size_compressed); - std::vector 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 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 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 data = DecompressBLZ({rodata_end, data_end}); - text = DecompressBLZ(text); - rodata = DecompressBLZ(rodata); - data = DecompressBLZ(data); + std::vector 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 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") - package2_fs[static_cast(type)] = out; + package2_fs[static_cast(type)] = std::move(out); else if (name == "spl") - package2_spl[static_cast(type)] = out; + package2_spl[static_cast(type)] = std::move(out); } } -- cgit v1.2.3