summaryrefslogtreecommitdiff
path: root/src/core/file_sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys')
-rw-r--r--src/core/file_sys/card_image.cpp15
-rw-r--r--src/core/file_sys/content_archive.cpp48
-rw-r--r--src/core/file_sys/content_archive.h5
-rw-r--r--src/core/file_sys/vfs.cpp7
4 files changed, 30 insertions, 45 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 5ff09a362..3c1dbf46c 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -30,8 +30,8 @@ XCI::XCI(VirtualFile file_) : file(std::move(file_)), partitions(0x4) {
30 return; 30 return;
31 } 31 }
32 32
33 const static std::array<std::string, 0x4> partition_names = {"update", "normal", "secure", 33 static constexpr std::array<const char*, 0x4> partition_names = {"update", "normal", "secure",
34 "logo"}; 34 "logo"};
35 35
36 for (XCIPartition partition : 36 for (XCIPartition partition :
37 {XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) { 37 {XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) {
@@ -93,12 +93,9 @@ VirtualDir XCI::GetLogoPartition() const {
93} 93}
94 94
95std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { 95std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const {
96 for (const auto& nca : ncas) { 96 auto iter = std::find_if(ncas.begin(), ncas.end(),
97 if (nca->GetType() == type) 97 [type](std::shared_ptr<NCA> nca) { return nca->GetType() == type; });
98 return nca; 98 return iter == ncas.end() ? nullptr : *iter;
99 }
100
101 return nullptr;
102} 99}
103 100
104VirtualFile XCI::GetNCAFileByType(NCAContentType type) const { 101VirtualFile XCI::GetNCAFileByType(NCAContentType type) const {
@@ -133,7 +130,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
133 return Loader::ResultStatus::ErrorInvalidFormat; 130 return Loader::ResultStatus::ErrorInvalidFormat;
134 } 131 }
135 132
136 for (VirtualFile file : partitions[static_cast<size_t>(part)]->GetFiles()) { 133 for (const VirtualFile& file : partitions[static_cast<size_t>(part)]->GetFiles()) {
137 if (file->GetExtension() != "nca") 134 if (file->GetExtension() != "nca")
138 continue; 135 continue;
139 auto nca = std::make_shared<NCA>(file); 136 auto nca = std::make_shared<NCA>(file);
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index add01974e..952dc7068 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -9,10 +9,9 @@
9#include "core/crypto/aes_util.h" 9#include "core/crypto/aes_util.h"
10#include "core/crypto/ctr_encryption_layer.h" 10#include "core/crypto/ctr_encryption_layer.h"
11#include "core/file_sys/content_archive.h" 11#include "core/file_sys/content_archive.h"
12#include "core/file_sys/romfs.h"
12#include "core/file_sys/vfs_offset.h" 13#include "core/file_sys/vfs_offset.h"
13#include "core/loader/loader.h" 14#include "core/loader/loader.h"
14#include "mbedtls/cipher.h"
15#include "romfs.h"
16 15
17namespace FileSys { 16namespace FileSys {
18 17
@@ -77,7 +76,7 @@ bool IsValidNCA(const NCAHeader& header) {
77 return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); 76 return header.magic == Common::MakeMagic('N', 'C', 'A', '3');
78} 77}
79 78
80Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) { 79Core::Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) {
81 u8 master_key_id = header.crypto_type; 80 u8 master_key_id = header.crypto_type;
82 if (header.crypto_type_2 > master_key_id) 81 if (header.crypto_type_2 > master_key_id)
83 master_key_id = header.crypto_type_2; 82 master_key_id = header.crypto_type_2;
@@ -85,16 +84,12 @@ Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) {
85 --master_key_id; 84 --master_key_id;
86 85
87 std::vector<u8> key_area(header.key_area.begin(), header.key_area.end()); 86 std::vector<u8> key_area(header.key_area.begin(), header.key_area.end());
88 if (!Crypto::keys.ValidateKey(Crypto::S128KeyType::KEY_AREA, master_key_id, header.key_index)) { 87 Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
89 status = Loader::ResultStatus::ErrorEncrypted; 88 keys.GetKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index),
90 return {}; 89 Core::Crypto::Mode::ECB);
91 } 90 cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Core::Crypto::Op::Decrypt);
92 Crypto::AESCipher<Crypto::Key128> cipher(
93 Crypto::keys.GetKey(Crypto::S128KeyType::KEY_AREA, master_key_id, header.key_index),
94 Crypto::Mode::ECB);
95 cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Crypto::Op::DECRYPT);
96 91
97 Crypto::Key128 out; 92 Core::Crypto::Key128 out;
98 if (type == NCASectionCryptoType::XTS) 93 if (type == NCASectionCryptoType::XTS)
99 std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin()); 94 std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin());
100 else if (type == NCASectionCryptoType::CTR) 95 else if (type == NCASectionCryptoType::CTR)
@@ -102,8 +97,8 @@ Crypto::Key128 NCA::GetKeyAreaKey(NCASectionCryptoType type) {
102 else 97 else
103 LOG_CRITICAL(Crypto, "Called GetKeyAreaKey on invalid NCASectionCryptoType type={:02X}", 98 LOG_CRITICAL(Crypto, "Called GetKeyAreaKey on invalid NCASectionCryptoType type={:02X}",
104 static_cast<u8>(type)); 99 static_cast<u8>(type));
105 100 u128 out_128{};
106 u128 out_128 = *reinterpret_cast<u128*>(&out); 101 memcpy(out_128.data(), out.data(), 16);
107 LOG_DEBUG(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}", 102 LOG_DEBUG(Crypto, "called with crypto_rev={:02X}, kak_index={:02X}, key={:016X}{:016X}",
108 master_key_id, header.key_index, out_128[1], out_128[0]); 103 master_key_id, header.key_index, out_128[1], out_128[0]);
109 104
@@ -121,9 +116,9 @@ VirtualFile NCA::Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_o
121 case NCASectionCryptoType::CTR: 116 case NCASectionCryptoType::CTR:
122 LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset); 117 LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
123 { 118 {
124 auto out = std::make_shared<Crypto::CTREncryptionLayer>( 119 auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(
125 std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset); 120 std::move(in), GetKeyAreaKey(NCASectionCryptoType::CTR), starting_offset);
126 std::vector<u8> iv(16, 0); 121 std::vector<u8> iv(16);
127 for (u8 i = 0; i < 8; ++i) 122 for (u8 i = 0; i < 8; ++i)
128 iv[i] = header.raw.section_ctr[0x8 - i - 1]; 123 iv[i] = header.raw.section_ctr[0x8 - i - 1];
129 out->SetIV(iv); 124 out->SetIV(iv);
@@ -146,13 +141,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
146 141
147 if (!IsValidNCA(header)) { 142 if (!IsValidNCA(header)) {
148 NCAHeader dec_header{}; 143 NCAHeader dec_header{};
149 if (!Crypto::keys.ValidateKey(Crypto::S256KeyType::HEADER)) { 144 Core::Crypto::AESCipher<Core::Crypto::Key256> cipher(
150 status = Loader::ResultStatus::ErrorEncrypted; 145 keys.GetKey(Core::Crypto::S256KeyType::Header), Core::Crypto::Mode::XTS);
151 return; 146 cipher.XTSTranscode(&header, sizeof(NCAHeader), &dec_header, 0, 0x200,
152 } 147 Core::Crypto::Op::Decrypt);
153 Crypto::AESCipher<Crypto::Key256> cipher(Crypto::keys.GetKey(Crypto::S256KeyType::HEADER),
154 Crypto::Mode::XTS);
155 cipher.XTSTranscode(&header, sizeof(NCAHeader), &dec_header, 0, 0x200, Crypto::Op::DECRYPT);
156 if (IsValidNCA(dec_header)) { 148 if (IsValidNCA(dec_header)) {
157 header = dec_header; 149 header = dec_header;
158 encrypted = true; 150 encrypted = true;
@@ -171,14 +163,10 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
171 163
172 if (encrypted) { 164 if (encrypted) {
173 auto raw = file->ReadBytes(length_sections, SECTION_HEADER_OFFSET); 165 auto raw = file->ReadBytes(length_sections, SECTION_HEADER_OFFSET);
174 if (!Crypto::keys.ValidateKey(Crypto::S256KeyType::HEADER)) { 166 Core::Crypto::AESCipher<Core::Crypto::Key256> cipher(
175 status = Loader::ResultStatus::ErrorEncrypted; 167 keys.GetKey(Core::Crypto::S256KeyType::Header), Core::Crypto::Mode::XTS);
176 return;
177 }
178 Crypto::AESCipher<Crypto::Key256> cipher(Crypto::keys.GetKey(Crypto::S256KeyType::HEADER),
179 Crypto::Mode::XTS);
180 cipher.XTSTranscode(raw.data(), length_sections, sections.data(), 2, SECTION_HEADER_SIZE, 168 cipher.XTSTranscode(raw.data(), length_sections, sections.data(), 2, SECTION_HEADER_SIZE,
181 Crypto::Op::DECRYPT); 169 Core::Crypto::Op::Decrypt);
182 } else { 170 } else {
183 file->ReadBytes(sections.data(), length_sections, SECTION_HEADER_OFFSET); 171 file->ReadBytes(sections.data(), length_sections, SECTION_HEADER_OFFSET);
184 } 172 }
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index d9ad3bf7e..153142b06 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -9,12 +9,12 @@
9#include <string> 9#include <string>
10#include <vector> 10#include <vector>
11 11
12#include "core/loader/loader.h"
13#include "common/common_funcs.h" 12#include "common/common_funcs.h"
14#include "common/common_types.h" 13#include "common/common_types.h"
15#include "common/swap.h" 14#include "common/swap.h"
16#include "core/crypto/key_manager.h" 15#include "core/crypto/key_manager.h"
17#include "core/file_sys/partition_filesystem.h" 16#include "core/file_sys/partition_filesystem.h"
17#include "core/loader/loader.h"
18 18
19namespace FileSys { 19namespace FileSys {
20enum class NCAContentType : u8 { 20enum class NCAContentType : u8 {
@@ -107,7 +107,8 @@ private:
107 107
108 bool encrypted; 108 bool encrypted;
109 109
110 Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type); 110 Core::Crypto::KeyManager keys;
111 Core::Crypto::Key128 GetKeyAreaKey(NCASectionCryptoType type);
111 112
112 VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset); 113 VirtualFile Decrypt(NCASectionHeader header, VirtualFile in, u64 starting_offset);
113}; 114};
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 57d0aeb85..dae1c16ef 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -297,10 +297,9 @@ bool DeepEquals(const VirtualFile& file1, const VirtualFile& file2, size_t block
297 297
298 if (f1_vs != f2_vs) 298 if (f1_vs != f2_vs)
299 return false; 299 return false;
300 for (size_t j = 0; j < f1_vs; ++j) { 300 auto iters = std::mismatch(f1_v.begin(), f1_v.end(), f2_v.begin(), f2_v.end());
301 if (f1_v[j] != f2_v[j]) 301 if (iters.first != f1_v.end() && iters.second != f2_v.end())
302 return false; 302 return false;
303 }
304 } 303 }
305 304
306 return true; 305 return true;