Browse Source

add toggle for nca verification

pull/298/head
Maufeat 7 months ago
committed by crueter
parent
commit
55f0b40dc3
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 7
      src/common/settings.h
  2. 6
      src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
  3. 104
      src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp
  4. 4
      src/core/hle/service/am/service/library_applet_creator.cpp
  5. 5
      src/yuzu/configuration/shared_translation.cpp

7
src/common/settings.h

@ -217,7 +217,8 @@ struct Values {
true,
true,
&use_speed_limit};
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default};
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core,
Specialization::Default};
// Memory
#ifdef HAS_NCE
@ -624,7 +625,9 @@ struct Values {
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
true, true, &rng_seed_enabled};
Setting<std::string> device_name{
linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true};
linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true};
SwitchableSetting<bool> disable_nca_verification{linkage, true, "disable_nca_verification",
Category::System, Specialization::Default};
Setting<s32> current_user{linkage, 0, "current_user", Category::System};

6
src/core/file_sys/fssystem/fssystem_bucket_tree.cpp

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
@ -236,7 +237,10 @@ Result BucketTree::Initialize(VirtualFile node_storage, VirtualFile entry_storag
void BucketTree::Initialize(size_t node_size, s64 end_offset) {
ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
ASSERT(Common::IsPowerOfTwo(node_size));
//TODO: ASSERT(end_offset > 0);
if (!Settings::values.disable_nca_verification.GetValue()) {
ASSERT(end_offset > 0);
}
ASSERT(!this->IsInitialized());
m_node_size = node_size;

104
src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
@ -1289,42 +1290,97 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageForMeta(
Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl(
VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info, s64 layer_info_offset,
int /*max_data_cache_entries*/, int /*max_hash_cache_entries*/, s8 /*buffer_level*/) {
int max_data_cache_entries, int max_hash_cache_entries, s8 buffer_level) {
// Preconditions
ASSERT(out != nullptr);
ASSERT(base_storage != nullptr);
ASSERT(layer_info_offset >= 0);
// Read IVFC layout
HierarchicalIntegrityVerificationInformation lhi{};
std::memcpy(std::addressof(lhi), std::addressof(meta_info.level_hash_info), sizeof(lhi));
if (!Settings::values.disable_nca_verification.GetValue()) {
// Define storage types.
using VerificationStorage = HierarchicalIntegrityVerificationStorage;
using StorageInfo = VerificationStorage::HierarchicalStorageInformation;
// Validate the meta info.
HierarchicalIntegrityVerificationInformation level_hash_info;
std::memcpy(std::addressof(level_hash_info), std::addressof(meta_info.level_hash_info),
sizeof(level_hash_info));
R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(level_hash_info.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
// Get the base storage size.
s64 base_storage_size = base_storage->GetSize();
// Create storage info.
StorageInfo storage_info;
for (s32 i = 0; i < static_cast<s32>(level_hash_info.max_layers - 2); ++i) {
const auto& layer_info = level_hash_info.info[i];
R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
storage_info[i + 1] = std::make_shared<OffsetVfsFile>(
base_storage, layer_info.size, layer_info_offset + layer_info.offset);
}
R_UNLESS(IntegrityMinLayerCount <= lhi.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(lhi.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
// Set the last layer info.
const auto& layer_info = level_hash_info.info[level_hash_info.max_layers - 2];
const s64 last_layer_info_offset = layer_info_offset > 0 ? 0LL : layer_info.offset.Get();
R_UNLESS(last_layer_info_offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
storage_info.SetDataStorage(std::make_shared<OffsetVfsFile>(
std::move(base_storage), layer_info.size, last_layer_info_offset));
const auto& data_li = lhi.info[lhi.max_layers - 2];
// Make the integrity romfs storage.
auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();
R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
const s64 base_size = base_storage->GetSize();
// Initialize the integrity storage.
R_TRY(integrity_storage->Initialize(level_hash_info, meta_info.master_hash, storage_info,
max_data_cache_entries, max_hash_cache_entries,
buffer_level));
// Compute the data layer window
const s64 data_off = (layer_info_offset > 0) ? 0LL : data_li.offset.Get();
R_UNLESS(data_off + data_li.size <= base_size, ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(data_off + data_li.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
// Set the output.
*out = std::move(integrity_storage);
R_SUCCEED();
} else {
// Read IVFC layout
HierarchicalIntegrityVerificationInformation lhi{};
std::memcpy(std::addressof(lhi), std::addressof(meta_info.level_hash_info), sizeof(lhi));
// TODO: Passthrough (temporary compatibility: integrity disabled)
auto data_view = std::make_shared<OffsetVfsFile>(base_storage, data_li.size, data_off);
R_UNLESS(data_view != nullptr, ResultAllocationMemoryFailedAllocateShared);
R_UNLESS(IntegrityMinLayerCount <= lhi.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(lhi.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
auto passthrough = std::make_shared<PassthroughStorage>(std::move(data_view));
R_UNLESS(passthrough != nullptr, ResultAllocationMemoryFailedAllocateShared);
const auto& data_li = lhi.info[lhi.max_layers - 2];
*out = std::move(passthrough);
R_SUCCEED();
const s64 base_size = base_storage->GetSize();
// Compute the data layer window
const s64 data_off = (layer_info_offset > 0) ? 0LL : data_li.offset.Get();
R_UNLESS(data_off + data_li.size <= base_size, ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(data_off + data_li.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
// TODO: Passthrough (temporary compatibility: integrity disabled)
auto data_view = std::make_shared<OffsetVfsFile>(base_storage, data_li.size, data_off);
R_UNLESS(data_view != nullptr, ResultAllocationMemoryFailedAllocateShared);
auto passthrough = std::make_shared<PassthroughStorage>(std::move(data_view));
R_UNLESS(passthrough != nullptr, ResultAllocationMemoryFailedAllocateShared);
*out = std::move(passthrough);
R_SUCCEED();
}
}
Result NcaFileSystemDriver::CreateRegionSwitchStorage(VirtualFile* out,

4
src/core/hle/service/am/service/library_applet_creator.cpp

@ -113,9 +113,11 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
Firmware1700 = 17,
Firmware1800 = 18,
Firmware1900 = 19,
Firmware2000 = 20,
Firmware2100 = 21,
};
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1900);
auto process = CreateProcess(system, program_id, Firmware1400, Firmware2100);
if (!process) {
// Couldn't initialize the guest process
return {};

5
src/yuzu/configuration/shared_translation.cpp

@ -409,6 +409,11 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
"their resolution, details and supported controllers and depending on this setting.\n"
"Setting to Handheld can help improve performance for low end systems."));
INSERT(Settings, current_user, QString(), QString());
INSERT(Settings, disable_nca_verification, tr("Disable NCA Verification"),
tr("Disables integrity verification of NCA content archives."
"\nThis may improve loading speed but risks data corruption or invalid files going "
"undetected.\n"
"Is necessary to make games and updates work that needs firmware 20+."));
// Controls

Loading…
Cancel
Save