fs: revise NcaFileSystemDriver for latest semantics

This commit is contained in:
Michael Scire
2021-12-13 22:42:32 -08:00
committed by SciresM
parent ccf29a1302
commit 52296fc2dd
37 changed files with 1612 additions and 1026 deletions

View File

@@ -150,7 +150,7 @@ namespace ams::fssystem::save {
m_storage = fs::SubStorage();
}
Result HierarchicalIntegrityVerificationStorage::Initialize(const HierarchicalIntegrityVerificationInformation &info, HierarchicalStorageInformation storage, FileSystemBufferManagerSet *bufs, os::SdkRecursiveMutex *mtx, fs::StorageType storage_type) {
Result HierarchicalIntegrityVerificationStorage::Initialize(const HierarchicalIntegrityVerificationInformation &info, HierarchicalStorageInformation storage, FileSystemBufferManagerSet *bufs, IHash256GeneratorFactory *hgf, os::SdkRecursiveMutex *mtx, fs::StorageType storage_type) {
/* Validate preconditions. */
AMS_ASSERT(bufs != nullptr);
AMS_ASSERT(IntegrityMinLayerCount <= info.max_layers && info.max_layers <= IntegrityMaxLayerCount);
@@ -168,7 +168,7 @@ namespace ams::fssystem::save {
{
fs::HashSalt mac;
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[0].key, KeyArray[0].size);
m_verify_storages[0].Initialize(storage[HierarchicalStorageInformation::MasterStorage], storage[HierarchicalStorageInformation::Layer1Storage], static_cast<s64>(1) << info.info[0].block_order, HashSize, m_buffers->buffers[m_max_layers - 2], mac, false, storage_type);
m_verify_storages[0].Initialize(storage[HierarchicalStorageInformation::MasterStorage], storage[HierarchicalStorageInformation::Layer1Storage], static_cast<s64>(1) << info.info[0].block_order, HashSize, m_buffers->buffers[m_max_layers - 2], hgf, mac, false, storage_type);
}
/* Ensure we don't leak state if further initialization goes wrong. */
@@ -203,7 +203,7 @@ namespace ams::fssystem::save {
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
fs::HashSalt mac;
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], mac, false, storage_type);
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], hgf, mac, false, storage_type);
}
/* Initialize the buffer storage. */
@@ -217,7 +217,7 @@ namespace ams::fssystem::save {
fs::SubStorage buffer_storage(std::addressof(m_buffer_storages[level]), 0, info.info[level].size);
fs::HashSalt mac;
crypto::GenerateHmacSha256Mac(mac.value, sizeof(mac), info.seed.value, sizeof(info.seed), KeyArray[level + 1].key, KeyArray[level + 1].size);
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], mac, true, storage_type);
m_verify_storages[level + 1].Initialize(buffer_storage, storage[level + 2], static_cast<s64>(1) << info.info[level + 1].block_order, static_cast<s64>(1) << info.info[level].block_order, m_buffers->buffers[m_max_layers - 2], hgf, mac, true, storage_type);
}
/* Initialize the buffer storage. */

View File

@@ -17,15 +17,19 @@
namespace ams::fssystem::save {
Result IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, IBufferManager *bm, const fs::HashSalt &salt, bool is_real_data, fs::StorageType storage_type) {
Result IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const fs::HashSalt &salt, bool is_real_data, fs::StorageType storage_type) {
/* Validate preconditions. */
AMS_ASSERT(verif_block_size >= HashSize);
AMS_ASSERT(bm != nullptr);
AMS_ASSERT(hgf != nullptr);
/* Set storages. */
m_hash_storage = hs;
m_data_storage = ds;
/* Set hash generator factory. */
m_hash_generator_factory = hgf;
/* Set verification block sizes. */
m_verification_block_size = verif_block_size;
m_verification_block_order = ILog2(static_cast<u32>(verif_block_size));
@@ -111,14 +115,17 @@ namespace ams::fssystem::save {
clear_guard.Cancel();
}
/* Verify the signatures. */
Result verify_hash_result = ResultSuccess();
/* Create hash generator. */
auto generator = m_hash_generator_factory->Create();
/* Prepare to validate the signatures. */
const auto signature_count = size >> m_verification_block_order;
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
/* Verify the signatures. */
Result verify_hash_result = ResultSuccess();
size_t verified_count = 0;
while (verified_count < signature_count) {
/* Read the current signatures. */
@@ -132,7 +139,7 @@ namespace ams::fssystem::save {
for (size_t i = 0; i < cur_count && R_SUCCEEDED(cur_result); ++i) {
const auto verified_size = (verified_count + i) << m_verification_block_order;
u8 *cur_buf = static_cast<u8 *>(buffer) + verified_size;
cur_result = this->VerifyHash(cur_buf, reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i);
cur_result = this->VerifyHash(cur_buf, reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i, generator);
/* If the data is corrupted, clear the corrupted parts. */
if (fs::ResultIntegrityVerificationStorageCorrupted::Includes(cur_result)) {
@@ -211,6 +218,8 @@ namespace ams::fssystem::save {
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
auto generator = m_hash_generator_factory->Create();
while (updated_count < signature_count) {
const auto cur_count = std::min(buffer_count, signature_count - updated_count);
@@ -220,7 +229,7 @@ namespace ams::fssystem::save {
for (size_t i = 0; i < cur_count; ++i) {
const auto updated_size = (updated_count + i) << m_verification_block_order;
this->CalcBlockHash(reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i, reinterpret_cast<const u8 *>(buffer) + updated_size);
this->CalcBlockHash(reinterpret_cast<BlockHash *>(signature_buffer.GetBuffer()) + i, reinterpret_cast<const u8 *>(buffer) + updated_size, generator);
}
}
@@ -360,19 +369,18 @@ namespace ams::fssystem::save {
}
}
void IntegrityVerificationStorage::CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size) const {
/* Create a sha256 generator. */
crypto::Sha256Generator sha;
sha.Initialize();
void IntegrityVerificationStorage::CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size, std::unique_ptr<fssystem::IHash256Generator> &generator) const {
/* Initialize the generator. */
generator->Initialize();
/* If calculating for save data, hash the salt. */
if (m_storage_type == fs::StorageType_SaveData) {
sha.Update(m_salt.value, sizeof(m_salt));
generator->Update(m_salt.value, sizeof(m_salt));
}
/* Update with the buffer and get the hash. */
sha.Update(buffer, block_size);
sha.GetHash(out, sizeof(*out));
generator->Update(buffer, block_size);
generator->GetHash(out, sizeof(*out));
/* Set the validation bit, if the hash is for save data. */
if (m_storage_type == fs::StorageType_SaveData) {
@@ -428,7 +436,7 @@ namespace ams::fssystem::save {
return ResultSuccess();
}
Result IntegrityVerificationStorage::VerifyHash(const void *buf, BlockHash *hash) {
Result IntegrityVerificationStorage::VerifyHash(const void *buf, BlockHash *hash, std::unique_ptr<fssystem::IHash256Generator> &generator) {
/* Validate preconditions. */
AMS_ASSERT(buf != nullptr);
AMS_ASSERT(hash != nullptr);
@@ -445,7 +453,7 @@ namespace ams::fssystem::save {
/* Get the calculated hash. */
BlockHash calc_hash;
this->CalcBlockHash(std::addressof(calc_hash), buf);
this->CalcBlockHash(std::addressof(calc_hash), buf, generator);
/* Check that the signatures are equal. */
if (!crypto::IsSameBytes(std::addressof(cmp_hash), std::addressof(calc_hash), sizeof(BlockHash))) {