summaryrefslogtreecommitdiff
path: root/src/core/crypto/key_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/crypto/key_manager.cpp')
-rw-r--r--src/core/crypto/key_manager.cpp39
1 files changed, 26 insertions, 13 deletions
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index a59a7e1f5..fd0786068 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -98,7 +98,7 @@ std::array<u8, 144> DecryptKeyblob(const std::array<u8, 176>& encrypted_keyblob,
98 return keyblob; 98 return keyblob;
99} 99}
100 100
101void KeyManager::DeriveGeneralPurposeKeys(u8 crypto_revision) { 101void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
102 const auto kek_generation_source = 102 const auto kek_generation_source =
103 GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration)); 103 GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::AESKekGeneration));
104 const auto key_generation_source = 104 const auto key_generation_source =
@@ -147,31 +147,38 @@ boost::optional<Key128> DeriveSDSeed() {
147 "rb+"); 147 "rb+");
148 if (!save_43.IsOpen()) 148 if (!save_43.IsOpen())
149 return boost::none; 149 return boost::none;
150
150 const FileUtil::IOFile sd_private( 151 const FileUtil::IOFile sd_private(
151 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+"); 152 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
152 if (!sd_private.IsOpen()) 153 if (!sd_private.IsOpen())
153 return boost::none; 154 return boost::none;
154 155
155 sd_private.Seek(0, SEEK_SET);
156 std::array<u8, 0x10> private_seed{}; 156 std::array<u8, 0x10> private_seed{};
157 if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != 0x10) 157 if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
158 return boost::none; 158 return boost::none;
159 }
159 160
160 std::array<u8, 0x10> buffer{}; 161 std::array<u8, 0x10> buffer{};
161 std::size_t offset = 0; 162 std::size_t offset = 0;
162 for (; offset + 0x10 < save_43.GetSize(); ++offset) { 163 for (; offset + 0x10 < save_43.GetSize(); ++offset) {
163 save_43.Seek(offset, SEEK_SET); 164 if (!save_43.Seek(offset, SEEK_SET)) {
165 return boost::none;
166 }
167
164 save_43.ReadBytes(buffer.data(), buffer.size()); 168 save_43.ReadBytes(buffer.data(), buffer.size());
165 if (buffer == private_seed) 169 if (buffer == private_seed) {
166 break; 170 break;
171 }
167 } 172 }
168 173
169 if (offset + 0x10 >= save_43.GetSize()) 174 if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
170 return boost::none; 175 return boost::none;
176 }
171 177
172 Key128 seed{}; 178 Key128 seed{};
173 save_43.Seek(offset + 0x10, SEEK_SET); 179 if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
174 save_43.ReadBytes(seed.data(), seed.size()); 180 return boost::none;
181 }
175 return seed; 182 return seed;
176} 183}
177 184
@@ -234,7 +241,9 @@ std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) {
234 return {}; 241 return {};
235 242
236 std::vector<u8> buffer(ticket_save.GetSize()); 243 std::vector<u8> buffer(ticket_save.GetSize());
237 ticket_save.ReadBytes(buffer.data(), buffer.size()); 244 if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
245 return {};
246 }
238 247
239 std::vector<TicketRaw> out; 248 std::vector<TicketRaw> out;
240 u32 magic{}; 249 u32 magic{};
@@ -261,6 +270,9 @@ static std::array<u8, size> operator^(const std::array<u8, size>& lhs,
261 270
262template <size_t target_size, size_t in_size> 271template <size_t target_size, size_t in_size>
263static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) { 272static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
273 // Avoids truncation overflow within the loop below.
274 static_assert(target_size <= 0xFF);
275
264 std::array<u8, in_size + 4> seed_exp{}; 276 std::array<u8, in_size + 4> seed_exp{};
265 std::memcpy(seed_exp.data(), seed.data(), in_size); 277 std::memcpy(seed_exp.data(), seed.data(), in_size);
266 278
@@ -268,7 +280,7 @@ static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
268 size_t i = 0; 280 size_t i = 0;
269 while (out.size() < target_size) { 281 while (out.size() < target_size) {
270 out.resize(out.size() + 0x20); 282 out.resize(out.size() + 0x20);
271 seed_exp[in_size + 3] = i; 283 seed_exp[in_size + 3] = static_cast<u8>(i);
272 mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0); 284 mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0);
273 ++i; 285 ++i;
274 } 286 }
@@ -299,10 +311,11 @@ boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
299 std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority)); 311 std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority));
300 if (cert_authority == 0) 312 if (cert_authority == 0)
301 return boost::none; 313 return boost::none;
302 if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) 314 if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) {
303 LOG_INFO(Crypto, 315 LOG_INFO(Crypto,
304 "Attempting to parse ticket with non-standard certificate authority {:08X}.", 316 "Attempting to parse ticket with non-standard certificate authority {:08X}.",
305 cert_authority); 317 cert_authority);
318 }
306 319
307 Key128 rights_id; 320 Key128 rights_id;
308 std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128)); 321 std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
@@ -871,9 +884,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
871 "/system/save/80000000000000e2", 884 "/system/save/80000000000000e2",
872 "rb+"); 885 "rb+");
873 886
887 const auto blob2 = GetTicketblob(save2);
874 auto res = GetTicketblob(save1); 888 auto res = GetTicketblob(save1);
875 const auto res2 = GetTicketblob(save2); 889 res.insert(res.end(), blob2.begin(), blob2.end());
876 std::copy(res2.begin(), res2.end(), std::back_inserter(res));
877 890
878 for (const auto& raw : res) { 891 for (const auto& raw : res) {
879 const auto pair = ParseTicket(raw, rsa_key); 892 const auto pair = ParseTicket(raw, rsa_key);