summaryrefslogtreecommitdiffstats
path: root/src/core/crypto/partition_data_manager.cpp
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2018-09-29 17:48:51 +0200
committerZach Hilman <zachhilman@gmail.com>2018-10-07 19:16:23 +0200
commit3ec054643e50f2845fb6a1a924b83bd71a0e2234 (patch)
tree313f2bcfba3610aa9bad98c3a7995d475712adc2 /src/core/crypto/partition_data_manager.cpp
parentqt: Add rederive keyset menu option (diff)
downloadyuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar.gz
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar.bz2
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar.lz
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar.xz
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.tar.zst
yuzu-3ec054643e50f2845fb6a1a924b83bd71a0e2234.zip
Diffstat (limited to 'src/core/crypto/partition_data_manager.cpp')
-rw-r--r--src/core/crypto/partition_data_manager.cpp89
1 files changed, 52 insertions, 37 deletions
diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp
index 60128b0e1..d1c04e98d 100644
--- a/src/core/crypto/partition_data_manager.cpp
+++ b/src/core/crypto/partition_data_manager.cpp
@@ -7,20 +7,24 @@
// hash the new keyblob source and master key and add the hashes to
// the arrays below.
+#include <algorithm>
#include <array>
+#include <cctype>
+#include <cstring>
#include <boost/optional/optional.hpp>
#include <mbedtls/sha256.h>
#include "common/assert.h"
+#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
+#include "core/crypto/ctr_encryption_layer.h"
#include "core/crypto/key_manager.h"
#include "core/crypto/partition_data_manager.h"
+#include "core/crypto/xts_encryption_layer.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_offset.h"
-#include "ctr_encryption_layer.h"
-#include "xts_encryption_layer.h"
using namespace Common;
@@ -72,7 +76,7 @@ struct KIPHeader {
};
static_assert(sizeof(KIPHeader) == 0x100, "KIPHeader has incorrect size.");
-const static std::array<SHA256Hash, 0x10> source_hashes{
+const std::array<SHA256Hash, 0x10> source_hashes{
"B24BD293259DBC7AC5D63F88E60C59792498E6FC5443402C7FFE87EE8B61A3F0"_array32, // keyblob_mac_key_source
"7944862A3A5C31C6720595EFD302245ABD1B54CCDCF33000557681E65C5664A4"_array32, // master_key_source
"21E2DF100FC9E094DB51B47B9B1D6E94ED379DB8B547955BEF8FE08D8DD35603"_array32, // package2_key_source
@@ -91,7 +95,7 @@ const static std::array<SHA256Hash, 0x10> source_hashes{
"FC02B9D37B42D7A1452E71444F1F700311D1132E301A83B16062E72A78175085"_array32, // rsa_kek_mask0
};
-const static std::array<SHA256Hash, 0x20> keyblob_source_hashes{
+const std::array<SHA256Hash, 0x20> keyblob_source_hashes{
"8A06FE274AC491436791FDB388BCDD3AB9943BD4DEF8094418CDAC150FD73786"_array32, // keyblob_key_source_00
"2D5CAEB2521FEF70B47E17D6D0F11F8CE2C1E442A979AD8035832C4E9FBCCC4B"_array32, // keyblob_key_source_01
"61C5005E713BAE780641683AF43E5F5C0E03671117F702F401282847D2FC6064"_array32, // keyblob_key_source_02
@@ -129,7 +133,7 @@ const static std::array<SHA256Hash, 0x20> keyblob_source_hashes{
"0000000000000000000000000000000000000000000000000000000000000000"_array32, // keyblob_key_source_1F
};
-const static std::array<SHA256Hash, 0x20> master_key_hashes{
+const std::array<SHA256Hash, 0x20> master_key_hashes{
"0EE359BE3C864BB0782E1D70A718A0342C551EED28C369754F9C4F691BECF7CA"_array32, // master_key_00
"4FE707B7E4ABDAF727C894AAF13B1351BFE2AC90D875F73B2E20FA94B9CC661E"_array32, // master_key_01
"79277C0237A2252EC3DFAC1F7C359C2B3D121E9DB15BB9AB4C2B4408D2F3AE09"_array32, // master_key_02
@@ -167,7 +171,7 @@ const static std::array<SHA256Hash, 0x20> master_key_hashes{
"0000000000000000000000000000000000000000000000000000000000000000"_array32, // master_key_1F
};
-std::vector<u8> DecompressBLZ(const std::vector<u8>& in) {
+static std::vector<u8> DecompressBLZ(const std::vector<u8>& in) {
const auto data_size = in.size() - 0xC;
u32 compressed_size{};
@@ -226,10 +230,10 @@ std::vector<u8> DecompressBLZ(const std::vector<u8>& in) {
return out;
}
-u8 CalculateMaxKeyblobSourceHash() {
+static u8 CalculateMaxKeyblobSourceHash() {
for (s8 i = 0x1F; i >= 0; --i) {
if (keyblob_source_hashes[i] != SHA256Hash{})
- return i + 1;
+ return static_cast<u8>(i + 1);
}
return 0;
@@ -238,10 +242,12 @@ u8 CalculateMaxKeyblobSourceHash() {
const u8 PartitionDataManager::MAX_KEYBLOB_SOURCE_HASH = CalculateMaxKeyblobSourceHash();
template <size_t key_size = 0x10>
-std::array<u8, key_size> FindKeyFromHex(const std::vector<u8>& binary, std::array<u8, 0x20> hash) {
- std::array<u8, 0x20> temp{};
+std::array<u8, key_size> FindKeyFromHex(const std::vector<u8>& binary,
+ const std::array<u8, 0x20>& hash) {
if (binary.size() < key_size)
return {};
+
+ std::array<u8, 0x20> temp{};
for (size_t i = 0; i < binary.size() - key_size; ++i) {
mbedtls_sha256(binary.data() + i, key_size, temp.data(), 0);
@@ -256,19 +262,24 @@ std::array<u8, key_size> FindKeyFromHex(const std::vector<u8>& binary, std::arra
return {};
}
-std::array<Key128, 0x20> FindEncryptedMasterKeyFromHex(const std::vector<u8>& binary, Key128 key) {
- SHA256Hash temp{};
- Key128 dec_temp{};
+std::array<u8, 16> FindKeyFromHex16(const std::vector<u8>& binary, std::array<u8, 32> hash) {
+ return FindKeyFromHex<0x10>(binary, hash);
+}
+
+static std::array<Key128, 0x20> FindEncryptedMasterKeyFromHex(const std::vector<u8>& binary,
+ const Key128& key) {
if (binary.size() < 0x10)
return {};
+ SHA256Hash temp{};
+ Key128 dec_temp{};
std::array<Key128, 0x20> out{};
AESCipher<Key128> cipher(key, Mode::ECB);
for (size_t i = 0; i < binary.size() - 0x10; ++i) {
cipher.Transcode(binary.data() + i, dec_temp.size(), dec_temp.data(), Op::Decrypt);
mbedtls_sha256(dec_temp.data(), dec_temp.size(), temp.data(), 0);
- for (size_t k = 0; k < 0x20; ++k) {
+ for (size_t k = 0; k < out.size(); ++k) {
if (temp == master_key_hashes[k]) {
out[k] = dec_temp;
break;
@@ -282,7 +293,7 @@ std::array<Key128, 0x20> FindEncryptedMasterKeyFromHex(const std::vector<u8>& bi
FileSys::VirtualFile FindFileInDirWithNames(const FileSys::VirtualDir& dir,
const std::string& name) {
auto upper = name;
- std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
+ std::transform(upper.begin(), upper.end(), upper.begin(), [](u8 c) { return std::toupper(c); });
for (const auto& fname : {name, name + ".bin", upper, upper + ".BIN"}) {
if (dir->GetFile(fname) != nullptr)
return dir->GetFile(fname);
@@ -303,14 +314,16 @@ PartitionDataManager::PartitionDataManager(FileSys::VirtualDir sysdata_dir)
FindFileInDirWithNames(sysdata_dir, "BCPKG2-5-Repair-Main"),
FindFileInDirWithNames(sysdata_dir, "BCPKG2-6-Repair-Sub"),
}),
- secure_monitor(FindFileInDirWithNames(sysdata_dir, "sm")),
- package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg_decr")),
+ secure_monitor(FindFileInDirWithNames(sysdata_dir, "secmon")),
+ package1_decrypted(FindFileInDirWithNames(sysdata_dir, "pkg1_decr")),
secure_monitor_bytes(secure_monitor == nullptr ? std::vector<u8>{}
: secure_monitor->ReadAllBytes()),
package1_decrypted_bytes(package1_decrypted == nullptr ? std::vector<u8>{}
: package1_decrypted->ReadAllBytes()),
prodinfo(FindFileInDirWithNames(sysdata_dir, "PRODINFO")) {}
+PartitionDataManager::~PartitionDataManager() = default;
+
bool PartitionDataManager::HasBoot0() const {
return boot0 != nullptr;
}
@@ -417,6 +430,22 @@ FileSys::VirtualFile PartitionDataManager::GetPackage2Raw(Package2Type type) con
return package2.at(static_cast<size_t>(type));
}
+bool AttemptDecrypt(const std::array<u8, 16>& key, Package2Header& header) {
+
+ const std::vector<u8> iv(header.header_ctr.begin(), header.header_ctr.end());
+ Package2Header temp = header;
+ AESCipher<Key128> cipher(key, Mode::CTR);
+ cipher.SetIV(iv);
+ cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr,
+ Op::Decrypt);
+ if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) {
+ header = temp;
+ return true;
+ }
+
+ return false;
+}
+
void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20> package2_keys,
Package2Type type) {
FileSys::VirtualFile file = std::make_shared<FileSys::OffsetVfsFile>(
@@ -429,18 +458,9 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20>
u8 revision = 0xFF;
if (header.magic != Common::MakeMagic('P', 'K', '2', '1')) {
- for (size_t i = 0; i < 0x20; ++i) {
- const std::vector<u8> iv(header.header_ctr.begin(), header.header_ctr.end());
- Package2Header temp = header;
- AESCipher<Key128> cipher(package2_keys[i], Mode::CTR);
- cipher.SetIV(iv);
- cipher.Transcode(&temp.header_ctr, sizeof(Package2Header) - 0x100, &temp.header_ctr,
- Op::Decrypt);
- if (temp.magic == Common::MakeMagic('P', 'K', '2', '1')) {
- header = temp;
+ for (size_t i = 0; i < package2_keys.size(); ++i) {
+ if (AttemptDecrypt(package2_keys[i], header))
revision = i;
- break;
- }
}
}
@@ -460,7 +480,7 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20>
// package2_decrypted[static_cast<size_t>(type)] = s1;
- INIHeader ini{};
+ INIHeader ini;
std::memcpy(&ini, c.data(), sizeof(INIHeader));
if (ini.magic != Common::MakeMagic('I', 'N', 'I', '1'))
return;
@@ -468,7 +488,7 @@ void PartitionDataManager::DecryptPackage2(std::array<std::array<u8, 16>, 0x20>
std::map<u64, KIPHeader> kips{};
u64 offset = sizeof(INIHeader);
for (size_t i = 0; i < ini.process_count; ++i) {
- KIPHeader kip{};
+ KIPHeader kip;
std::memcpy(&kip, c.data() + offset, sizeof(KIPHeader));
if (kip.magic != Common::MakeMagic('K', 'I', 'P', '1'))
return;
@@ -565,16 +585,11 @@ FileSys::VirtualFile PartitionDataManager::GetProdInfoRaw() const {
return prodinfo;
}
-void PartitionDataManager::DecryptProdInfo(std::array<u8, 16> bis_crypt,
- std::array<u8, 16> bis_tweak) {
+void PartitionDataManager::DecryptProdInfo(std::array<u8, 0x20> bis_key) {
if (prodinfo == nullptr)
return;
- Key256 final_key{};
- std::memcpy(final_key.data(), bis_crypt.data(), bis_crypt.size());
- std::memcpy(final_key.data() + sizeof(Key128), bis_tweak.data(), bis_tweak.size());
-
- prodinfo_decrypted = std::make_shared<XTSEncryptionLayer>(prodinfo, final_key);
+ prodinfo_decrypted = std::make_shared<XTSEncryptionLayer>(prodinfo, bis_key);
}
std::array<u8, 576> PartitionDataManager::GetETicketExtendedKek() const {