mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-15 22:01:41 -06:00
core: Add CMAKE option to disable built-in keyblob (#2024)
* core: Add CMAKE option to disable built-in keyblob * Additional assurance against accidental inclusion of default_keys.h * default_keys.h: Make default_keys_enc constexpr * default_keys.h: Make default_keys_enc_size constexpr --------- Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
parent
e8c75b4107
commit
336d871a7f
@ -137,6 +137,8 @@ option(ENABLE_SSE42 "Enable SSE4.2 optimizations on x86_64" ON)
|
||||
|
||||
option(ENABLE_DEVELOPER_OPTIONS "Enable functionality targeted at emulator developers" OFF)
|
||||
|
||||
option(ENABLE_BUILTIN_KEYBLOB "Enable the inclusion of the default crypto keys blob" ON)
|
||||
|
||||
# Compile options
|
||||
CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ${IS_DEBUG_BUILD} "MINGW" OFF)
|
||||
option(ENABLE_LTO "Enable link time optimization" ${DEFAULT_ENABLE_LTO})
|
||||
|
||||
@ -183,6 +183,9 @@ endif()
|
||||
if(ENABLE_DEVELOPER_OPTIONS)
|
||||
add_compile_definitions(ENABLE_DEVELOPER_OPTIONS)
|
||||
endif()
|
||||
if(ENABLE_BUILTIN_KEYBLOB)
|
||||
add_compile_definitions(ENABLE_BUILTIN_KEYBLOB)
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(core)
|
||||
|
||||
@ -670,12 +670,16 @@ void ConfigureSystem::RefreshSecureDataStatus() {
|
||||
return tr("Status: Loaded (Invalid Signature)");
|
||||
case HW::UniqueData::SecureDataLoadStatus::RegionChanged:
|
||||
return tr("Status: Loaded (Region Changed)");
|
||||
case HW::UniqueData::SecureDataLoadStatus::CannotValidateSignature:
|
||||
return tr("Status: Loaded (Cannot Validate Signature)");
|
||||
case HW::UniqueData::SecureDataLoadStatus::NotFound:
|
||||
return tr("Status: Not Found");
|
||||
case HW::UniqueData::SecureDataLoadStatus::Invalid:
|
||||
return tr("Status: Invalid");
|
||||
case HW::UniqueData::SecureDataLoadStatus::IOError:
|
||||
return tr("Status: IO Error");
|
||||
case HW::UniqueData::SecureDataLoadStatus::NoCryptoKeys:
|
||||
return tr("Status: Missing Crypto Keys");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
|
||||
@ -464,7 +464,6 @@ add_library(citra_core STATIC
|
||||
hw/aes/key.h
|
||||
hw/ecc.cpp
|
||||
hw/ecc.h
|
||||
hw/default_keys.h
|
||||
hw/rsa/rsa.cpp
|
||||
hw/rsa/rsa.h
|
||||
hw/unique_data.cpp
|
||||
@ -502,6 +501,10 @@ add_library(citra_core STATIC
|
||||
tracer/recorder.h
|
||||
)
|
||||
|
||||
if (ENABLE_BUILTIN_KEYBLOB)
|
||||
target_sources(citra_core PRIVATE hw/default_keys.h)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(citra_core)
|
||||
|
||||
target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core)
|
||||
|
||||
@ -18,7 +18,9 @@
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/hw/aes/arithmetic128.h"
|
||||
#include "core/hw/aes/key.h"
|
||||
#ifdef ENABLE_BUILTIN_KEYBLOB
|
||||
#include "core/hw/default_keys.h"
|
||||
#endif // ENABLE_BUILTIN_KEYBLOB
|
||||
#include "core/hw/rsa/rsa.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
@ -130,8 +132,8 @@ std::array<std::optional<AESKey>, NumDlpNfcKeyYs> dlp_nfc_key_y_slots;
|
||||
std::array<NfcSecret, NumNfcSecrets> nfc_secrets;
|
||||
AESIV nfc_iv;
|
||||
|
||||
AESKey otp_key;
|
||||
AESIV otp_iv;
|
||||
AESKey otp_key{};
|
||||
AESIV otp_iv{};
|
||||
|
||||
// gets xor'd with the mac address to produce the final iv
|
||||
AESIV dlp_checksum_mod_iv;
|
||||
@ -297,6 +299,7 @@ std::istringstream GetKeysStream() {
|
||||
if (file.is_open()) {
|
||||
return std::istringstream(std::string(std::istreambuf_iterator<char>(file), {}));
|
||||
} else {
|
||||
#ifdef ENABLE_BUILTIN_KEYBLOB
|
||||
// The key data is encrypted in the source to prevent easy access to it for unintended
|
||||
// purposes.
|
||||
std::vector<u8> kiv(16);
|
||||
@ -304,6 +307,9 @@ std::istringstream GetKeysStream() {
|
||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption(kiv.data(), kiv.size(), kiv.data())
|
||||
.ProcessData(reinterpret_cast<u8*>(s.data()), default_keys_enc, s.size());
|
||||
return std::istringstream(s);
|
||||
#else
|
||||
return std::istringstream("");
|
||||
#endif // ENABLE_BUILTIN_KEYBLOB
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,13 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
unsigned char default_keys_enc[] = {
|
||||
#pragma once
|
||||
|
||||
#ifndef ENABLE_BUILTIN_KEYBLOB
|
||||
#error Attempting to include default_keys.h, but ENABLE_BUILTIN_KEYBLOB is disabled.
|
||||
#endif
|
||||
|
||||
constexpr unsigned char default_keys_enc[] = {
|
||||
0x4E, 0x81, 0xE9, 0x54, 0xCC, 0xDE, 0xFD, 0x56, 0x7D, 0xD2, 0x72, 0xE6, 0xD9, 0xCD, 0x8E, 0x11,
|
||||
0xE1, 0x7F, 0x74, 0xF4, 0xFC, 0x54, 0xA6, 0xA4, 0x27, 0xC2, 0xD7, 0x50, 0xEA, 0xE7, 0xBE, 0xC9,
|
||||
0xA7, 0x5E, 0xE0, 0x2E, 0x4A, 0xBE, 0xF5, 0xD5, 0x0D, 0x22, 0x76, 0x2E, 0xB6, 0x80, 0xD8, 0x54,
|
||||
@ -468,4 +474,4 @@ unsigned char default_keys_enc[] = {
|
||||
0x14, 0x79, 0xD0, 0xA8, 0x3C, 0xB3, 0x46, 0xC3, 0xDA, 0x6C, 0x0C, 0xEC, 0x2A, 0xB2, 0x9B, 0x21,
|
||||
0xB2, 0xAD, 0x8C, 0x0C, 0x85, 0x9A, 0x8D, 0x7C, 0x10, 0xEA, 0x51, 0x1D, 0x2D, 0xDE, 0x7D, 0x8F};
|
||||
|
||||
const long int default_keys_enc_size = sizeof(default_keys_enc);
|
||||
constexpr long int default_keys_enc_size = sizeof(default_keys_enc);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -14,7 +14,8 @@ class RsaSlot {
|
||||
public:
|
||||
RsaSlot() = default;
|
||||
RsaSlot(std::vector<u8> exponent, std::vector<u8> modulus)
|
||||
: init(true), exponent(std::move(exponent)), modulus(std::move(modulus)) {}
|
||||
: init_exponent(true), init_modulus(true), exponent(std::move(exponent)),
|
||||
modulus(std::move(modulus)) {}
|
||||
|
||||
std::vector<u8> ModularExponentiation(std::span<const u8> message,
|
||||
int out_size_bytes = -1) const;
|
||||
@ -25,11 +26,12 @@ public:
|
||||
|
||||
explicit operator bool() const {
|
||||
// TODO(B3N30): Maybe check if exponent and modulus are vailid
|
||||
return init;
|
||||
return init_exponent && init_modulus;
|
||||
}
|
||||
|
||||
void SetExponent(const std::vector<u8>& e) {
|
||||
exponent = e;
|
||||
init_exponent = true;
|
||||
}
|
||||
|
||||
const std::vector<u8>& GetExponent() const {
|
||||
@ -38,6 +40,7 @@ public:
|
||||
|
||||
void SetModulus(const std::vector<u8>& m) {
|
||||
modulus = m;
|
||||
init_modulus = true;
|
||||
}
|
||||
|
||||
const std::vector<u8>& GetModulus() const {
|
||||
@ -46,6 +49,7 @@ public:
|
||||
|
||||
void SetPrivateD(const std::vector<u8>& d) {
|
||||
private_d = d;
|
||||
init_private_d = true;
|
||||
}
|
||||
|
||||
const std::vector<u8>& GetPrivateD() const {
|
||||
@ -53,7 +57,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool init = false;
|
||||
bool init_exponent = false;
|
||||
bool init_modulus = false;
|
||||
bool init_private_d = false;
|
||||
std::vector<u8> exponent;
|
||||
std::vector<u8> modulus;
|
||||
std::vector<u8> private_d;
|
||||
|
||||
@ -27,13 +27,17 @@ static MovableSedFull movable;
|
||||
static bool movable_signature_valid = false;
|
||||
|
||||
bool SecureInfoA::VerifySignature() const {
|
||||
return HW::RSA::GetSecureInfoSlot().Verify(
|
||||
std::span<const u8>(reinterpret_cast<const u8*>(&body), sizeof(body)), signature);
|
||||
auto sec_info_slot = HW::RSA::GetSecureInfoSlot();
|
||||
return sec_info_slot &&
|
||||
sec_info_slot.Verify(
|
||||
std::span<const u8>(reinterpret_cast<const u8*>(&body), sizeof(body)), signature);
|
||||
}
|
||||
|
||||
bool LocalFriendCodeSeedB::VerifySignature() const {
|
||||
return HW::RSA::GetLocalFriendCodeSeedSlot().Verify(
|
||||
std::span<const u8>(reinterpret_cast<const u8*>(&body), sizeof(body)), signature);
|
||||
auto lfcs_slot = HW::RSA::GetLocalFriendCodeSeedSlot();
|
||||
return lfcs_slot &&
|
||||
HW::RSA::GetLocalFriendCodeSeedSlot().Verify(
|
||||
std::span<const u8>(reinterpret_cast<const u8*>(&body), sizeof(body)), signature);
|
||||
}
|
||||
|
||||
bool MovableSed::VerifySignature() const {
|
||||
@ -42,6 +46,9 @@ bool MovableSed::VerifySignature() const {
|
||||
|
||||
SecureDataLoadStatus LoadSecureInfoA() {
|
||||
if (secure_info_a.IsValid()) {
|
||||
if (!HW::RSA::GetSecureInfoSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
return secure_info_a_signature_valid
|
||||
? SecureDataLoadStatus::Loaded
|
||||
: (secure_info_a_region_changed ? SecureDataLoadStatus::RegionChanged
|
||||
@ -63,8 +70,11 @@ SecureDataLoadStatus LoadSecureInfoA() {
|
||||
return SecureDataLoadStatus::IOError;
|
||||
}
|
||||
|
||||
HW::AES::InitKeys();
|
||||
secure_info_a_region_changed = false;
|
||||
HW::AES::InitKeys();
|
||||
if (!HW::RSA::GetSecureInfoSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
secure_info_a_signature_valid = secure_info_a.VerifySignature();
|
||||
if (!secure_info_a_signature_valid) {
|
||||
// Check if the file has been region changed
|
||||
@ -93,6 +103,9 @@ SecureDataLoadStatus LoadSecureInfoA() {
|
||||
|
||||
SecureDataLoadStatus LoadLocalFriendCodeSeedB() {
|
||||
if (local_friend_code_seed_b.IsValid()) {
|
||||
if (!HW::RSA::GetLocalFriendCodeSeedSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
return local_friend_code_seed_b_signature_valid ? SecureDataLoadStatus::Loaded
|
||||
: SecureDataLoadStatus::InvalidSignature;
|
||||
}
|
||||
@ -114,6 +127,9 @@ SecureDataLoadStatus LoadLocalFriendCodeSeedB() {
|
||||
}
|
||||
|
||||
HW::AES::InitKeys();
|
||||
if (!HW::RSA::GetLocalFriendCodeSeedSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
local_friend_code_seed_b_signature_valid = local_friend_code_seed_b.VerifySignature();
|
||||
if (!local_friend_code_seed_b_signature_valid) {
|
||||
LOG_WARNING(HW, "LocalFriendCodeSeed_B signature check failed");
|
||||
@ -128,10 +144,17 @@ SecureDataLoadStatus LoadOTP() {
|
||||
return SecureDataLoadStatus::Loaded;
|
||||
}
|
||||
|
||||
auto is_all_zero = [](const auto& arr) {
|
||||
return std::all_of(arr.begin(), arr.end(), [](auto x) { return x == 0; });
|
||||
};
|
||||
|
||||
const std::string filepath = GetOTPPath();
|
||||
|
||||
HW::AES::InitKeys();
|
||||
auto otp_keyiv = HW::AES::GetOTPKeyIV();
|
||||
if (is_all_zero(otp_keyiv.first) || is_all_zero(otp_keyiv.second)) {
|
||||
return SecureDataLoadStatus::NoCryptoKeys;
|
||||
}
|
||||
|
||||
auto loader_status = otp.Load(filepath, otp_keyiv.first, otp_keyiv.second);
|
||||
if (loader_status != Loader::ResultStatus::Success) {
|
||||
@ -169,6 +192,9 @@ SecureDataLoadStatus LoadOTP() {
|
||||
|
||||
SecureDataLoadStatus LoadMovable() {
|
||||
if (movable.IsValid()) {
|
||||
if (!HW::RSA::GetLocalFriendCodeSeedSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
return movable_signature_valid ? SecureDataLoadStatus::Loaded
|
||||
: SecureDataLoadStatus::InvalidSignature;
|
||||
}
|
||||
@ -193,6 +219,9 @@ SecureDataLoadStatus LoadMovable() {
|
||||
}
|
||||
|
||||
HW::AES::InitKeys();
|
||||
if (!HW::RSA::GetLocalFriendCodeSeedSlot()) {
|
||||
return SecureDataLoadStatus::CannotValidateSignature;
|
||||
}
|
||||
movable_signature_valid = movable.VerifySignature();
|
||||
if (!movable_signature_valid) {
|
||||
LOG_WARNING(HW, "movable.sed signature check failed");
|
||||
|
||||
@ -136,10 +136,12 @@ enum class SecureDataLoadStatus {
|
||||
Loaded = 0,
|
||||
InvalidSignature = 1,
|
||||
RegionChanged = 2,
|
||||
CannotValidateSignature = 3,
|
||||
|
||||
NotFound = -1,
|
||||
Invalid = -2,
|
||||
IOError = -3,
|
||||
NoCryptoKeys = -4,
|
||||
};
|
||||
|
||||
SecureDataLoadStatus LoadSecureInfoA();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user