[fs] Fix integrity check validation for new updates #395

Merged
crueter merged 16 commits from improve-integrity-check into master 2025-09-12 16:02:13 +02:00
3 changed files with 17 additions and 40 deletions

View file

@ -34,12 +34,9 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
}
reader = std::make_shared<NcaReader>();
if (Result rc =
reader->Initialize(file, GetCryptoConfiguration(), GetNcaCompressionConfiguration());
R_FAILED(rc)) {
if (Result rc = reader->Initialize(file, GetCryptoConfiguration(), GetNcaCompressionConfiguration()); R_FAILED(rc)) {
if (rc != ResultInvalidNcaSignature) {
LOG_ERROR(Loader, "File reader errored out during header read: {:#x}",
rc.GetInnerValue());
LOG_ERROR(Loader, "File reader errored out during header read: {:#x}", rc.GetInnerValue());
}
status = Loader::ResultStatus::ErrorBadNCAHeader;
return;
@ -84,10 +81,8 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
std::vector<VirtualFile> filesystems(fs_count);
for (s32 i = 0; i < fs_count; i++) {
NcaFsHeaderReader header_reader;
const Result rc = fs.OpenStorage(&filesystems[i], &header_reader, i);
if (R_FAILED(rc)) {
LOG_ERROR(Loader, "File reader errored out during read of section {}: {:#x}", i,
rc.GetInnerValue());
if (Result rc = fs.OpenStorage(&filesystems[i], &header_reader, i); R_FAILED(rc)) {
LOG_DEBUG(Loader, "File reader errored out during read of section {}: {:#x}", i, rc.GetInnerValue());
status = Loader::ResultStatus::ErrorBadNCAHeader;
return;
}

View file

@ -4,23 +4,18 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
#include "common/alignment.h"
#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
namespace FileSys {
constexpr inline u32 ILog2(u32 val)
{
constexpr inline u32 ILog2(u32 val) {
ASSERT(val > 0);
return static_cast<u32>((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val));
}
void IntegrityVerificationStorage::Initialize(VirtualFile hs,
VirtualFile ds,
s64 verif_block_size,
s64 upper_layer_verif_block_size,
bool is_real_data)
{
void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size,
s64 upper_layer_verif_block_size, bool is_real_data) {
// Validate preconditions.
ASSERT(verif_block_size >= HashSize);
@ -40,28 +35,22 @@ void IntegrityVerificationStorage::Initialize(VirtualFile hs,
ASSERT(m_upper_layer_verification_block_size == 1ll << m_upper_layer_verification_block_order);
// Validate sizes.
if (m_data_storage != nullptr) {
{
s64 hash_size = m_hash_storage->GetSize();
s64 data_size = m_data_storage->GetSize();
ASSERT(((hash_size / HashSize) * m_verification_block_size) >= data_size);
} else {
LOG_ERROR(Loader,
"Failed to initialize integrity verification store. Game, update, or DLC may not "
"work.");
}
// Set data.
m_is_real_data = is_real_data;
}
void IntegrityVerificationStorage::Finalize()
{
void IntegrityVerificationStorage::Finalize() {
m_hash_storage = VirtualFile();
m_data_storage = VirtualFile();
}
size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const
{
size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const {
// Succeed if zero size.
if (size == 0) {
return size;
@ -70,13 +59,7 @@ size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset
// Validate arguments.
ASSERT(buffer != nullptr);
if (m_data_storage == nullptr) {
LOG_ERROR(Loader,
"Integrity verification store failed read operation. Game, update or DLC may not "
"work.");
return 0;
}
// Validate the offset.
s64 data_size = m_data_storage->GetSize();
ASSERT(offset <= static_cast<size_t>(data_size));
@ -104,8 +87,7 @@ size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset
return m_data_storage->Read(buffer, read_size, offset);
}
size_t IntegrityVerificationStorage::GetSize() const
{
size_t IntegrityVerificationStorage::GetSize() const {
return m_data_storage->GetSize();
}

View file

@ -1051,8 +1051,8 @@ Result NcaFileSystemDriver::CreatePatchMetaStorage(
ASSERT(out_aes_ctr_ex_meta != nullptr);
ASSERT(out_indirect_meta != nullptr);
ASSERT(base_storage != nullptr);
ASSERT(patch_info.HasAesCtrExTable());
MaranBr marked this conversation as resolved

What's this for?

What's this for?

These two asserts are not needed at this point in the code.

These two asserts are not needed at this point in the code.
ASSERT(patch_info.HasIndirectTable());
//ASSERT(patch_info.HasAesCtrExTable());
//ASSERT(patch_info.HasIndirectTable());
ASSERT(Common::IsAligned<s64>(patch_info.aes_ctr_ex_size, NcaHeader::XtsBlockSize));
// Validate patch info extents.
@ -1334,8 +1334,8 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl(
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));
storage_info[level_hash_info.max_layers - 1] = std::make_shared<OffsetVfsFile>(
MaranBr marked this conversation as resolved

Seems interesting, what's in SetDataStorage that caused issues?

Seems interesting, what's in SetDataStorage that caused issues?

This is something I will look into further when I have more time. It's safe for now.

This is something I will look into further when I have more time. It's safe for now.
std::move(base_storage), layer_info.size, last_layer_info_offset);
// Make the integrity romfs storage.
auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();