mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
fs: add indirection to raw storage open, for hac2l
This commit is contained in:
parent
09a44fa680
commit
76910e8954
6 changed files with 70 additions and 20 deletions
|
@ -51,6 +51,8 @@ namespace ams::fssrv::fscreator {
|
||||||
#if !defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
#if !defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
Result CreateWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader, s32 index);
|
Result CreateWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader, s32 index);
|
||||||
Result CreateWithPatchWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> original_nca_reader, std::shared_ptr<fssystem::NcaReader> current_nca_reader, s32 index);
|
Result CreateWithPatchWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> original_nca_reader, std::shared_ptr<fssystem::NcaReader> current_nca_reader, s32 index);
|
||||||
|
|
||||||
|
Result CreateByRawStorage(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, const fssystem::NcaFsHeaderReader *header_reader, std::shared_ptr<fs::IStorage> raw_storage, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,10 @@ namespace ams::fssystem {
|
||||||
DecryptAesCtrFunction decrypt_aes_ctr;
|
DecryptAesCtrFunction decrypt_aes_ctr;
|
||||||
DecryptAesCtrFunction decrypt_aes_ctr_external;
|
DecryptAesCtrFunction decrypt_aes_ctr_external;
|
||||||
bool is_plaintext_header_available;
|
bool is_plaintext_header_available;
|
||||||
|
|
||||||
|
#if !defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
bool is_unsigned_header_available_for_host_tool;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static_assert(util::is_pod<NcaCryptoConfiguration>::value);
|
static_assert(util::is_pod<NcaCryptoConfiguration>::value);
|
||||||
|
|
||||||
|
@ -103,6 +107,7 @@ namespace ams::fssystem {
|
||||||
DecryptAesCtrFunction m_decrypt_aes_ctr_external;
|
DecryptAesCtrFunction m_decrypt_aes_ctr_external;
|
||||||
bool m_is_software_aes_prioritized;
|
bool m_is_software_aes_prioritized;
|
||||||
NcaHeader::EncryptionType m_header_encryption_type;
|
NcaHeader::EncryptionType m_header_encryption_type;
|
||||||
|
bool m_is_header_sign1_signature_valid;
|
||||||
GetDecompressorFunction m_get_decompressor;
|
GetDecompressorFunction m_get_decompressor;
|
||||||
IHash256GeneratorFactory *m_hash_generator_factory;
|
IHash256GeneratorFactory *m_hash_generator_factory;
|
||||||
public:
|
public:
|
||||||
|
@ -149,8 +154,10 @@ namespace ams::fssystem {
|
||||||
GetDecompressorFunction GetDecompressor() const;
|
GetDecompressorFunction GetDecompressor() const;
|
||||||
IHash256GeneratorFactory *GetHashGeneratorFactory() const;
|
IHash256GeneratorFactory *GetHashGeneratorFactory() const;
|
||||||
|
|
||||||
void GetHeaderSign2(void *dst, size_t size);
|
bool GetHeaderSign1Valid() const;
|
||||||
void GetHeaderSign2TargetHash(void *dst, size_t size);
|
|
||||||
|
void GetHeaderSign2(void *dst, size_t size) const;
|
||||||
|
void GetHeaderSign2TargetHash(void *dst, size_t size) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NcaFsHeaderReader : public ::ams::fs::impl::Newable {
|
class NcaFsHeaderReader : public ::ams::fs::impl::Newable {
|
||||||
|
@ -252,6 +259,13 @@ namespace ams::fssystem {
|
||||||
/* Open the storage. */
|
/* Open the storage. */
|
||||||
R_RETURN(OpenStorageWithContext(out, out_splitter, out_header_reader, fs_index, std::addressof(ctx)));
|
R_RETURN(OpenStorageWithContext(out, out_splitter, out_header_reader, fs_index, std::addressof(ctx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
private:
|
||||||
|
#else
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
|
Result CreateStorageByRawStorage(std::shared_ptr<fs::IStorage> *out, const NcaFsHeaderReader *header_reader, std::shared_ptr<fs::IStorage> raw_storage, StorageContext *ctx);
|
||||||
private:
|
private:
|
||||||
Result OpenStorageImpl(std::shared_ptr<fs::IStorage> *out, NcaFsHeaderReader *out_header_reader, s32 fs_index, StorageContext *ctx);
|
Result OpenStorageImpl(std::shared_ptr<fs::IStorage> *out, NcaFsHeaderReader *out_header_reader, s32 fs_index, StorageContext *ctx);
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,22 @@ namespace ams::fssrv::fscreator {
|
||||||
*out_splitter = std::move(splitter);
|
*out_splitter = std::move(splitter);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result StorageOnNcaCreator::CreateByRawStorage(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, const fssystem::NcaFsHeaderReader *header_reader, std::shared_ptr<fs::IStorage> raw_storage, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader) {
|
||||||
|
/* Create a fs driver. */
|
||||||
|
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||||
|
|
||||||
|
/* Open the storage. */
|
||||||
|
auto *storage_ctx = static_cast<fssystem::NcaFileSystemDriver::StorageContext *>(ctx);
|
||||||
|
R_TRY(nca_fs_driver.CreateStorageByRawStorage(out, header_reader, std::move(raw_storage), storage_ctx));
|
||||||
|
|
||||||
|
/* Update the splitter. */
|
||||||
|
if (storage_ctx->compressed_storage != nullptr) {
|
||||||
|
*out_splitter = storage_ctx->compressed_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,11 @@ namespace ams::fssystem {
|
||||||
cfg->decrypt_aes_ctr_external = DecryptAesCtrForPreparedKey;
|
cfg->decrypt_aes_ctr_external = DecryptAesCtrForPreparedKey;
|
||||||
cfg->is_plaintext_header_available = !prod;
|
cfg->is_plaintext_header_available = !prod;
|
||||||
|
|
||||||
|
/* TODO: Should this default to false for host tools with api to set explicitly? */
|
||||||
|
#if !defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
cfg->is_unsigned_header_available_for_host_tool = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,14 +292,6 @@ namespace ams::fssystem {
|
||||||
using IntegrityLevelInfo = NcaFsHeader::HashData::IntegrityMetaInfo::LevelHashInfo;
|
using IntegrityLevelInfo = NcaFsHeader::HashData::IntegrityMetaInfo::LevelHashInfo;
|
||||||
using IntegrityDataInfo = IntegrityLevelInfo::HierarchicalIntegrityVerificationLevelInformation;
|
using IntegrityDataInfo = IntegrityLevelInfo::HierarchicalIntegrityVerificationLevelInformation;
|
||||||
|
|
||||||
// inline const Sha256DataRegion &GetSha256DataRegion(const NcaFsHeader::HashData &hash_data) {
|
|
||||||
// return hash_data.hierarchical_sha256_data.hash_layer_region[1];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// inline const IntegrityDataInfo &GetIntegrityDataInfo(const NcaFsHeader::HashData &hash_data) {
|
|
||||||
// return hash_data.integrity_meta_info.level_hash_info.info[hash_data.integrity_meta_info.level_hash_info.max_layers - 2];
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result NcaFileSystemDriver::OpenStorageWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<IAsynchronousAccessSplitter> *out_splitter, NcaFsHeaderReader *out_header_reader, s32 fs_index, StorageContext *ctx) {
|
Result NcaFileSystemDriver::OpenStorageWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<IAsynchronousAccessSplitter> *out_splitter, NcaFsHeaderReader *out_header_reader, s32 fs_index, StorageContext *ctx) {
|
||||||
|
@ -308,7 +300,7 @@ namespace ams::fssystem {
|
||||||
|
|
||||||
/* If we have a compressed storage, use it as splitter. */
|
/* If we have a compressed storage, use it as splitter. */
|
||||||
if (ctx->compressed_storage != nullptr) {
|
if (ctx->compressed_storage != nullptr) {
|
||||||
*out_splitter = std::move(ctx->compressed_storage);
|
*out_splitter = ctx->compressed_storage;
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise, allocate a default splitter. */
|
/* Otherwise, allocate a default splitter. */
|
||||||
*out_splitter = fssystem::AllocateShared<DefaultAsynchronousAccessSplitter>();
|
*out_splitter = fssystem::AllocateShared<DefaultAsynchronousAccessSplitter>();
|
||||||
|
@ -447,21 +439,29 @@ namespace ams::fssystem {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the non-raw storage. */
|
||||||
|
R_RETURN(this->CreateStorageByRawStorage(out, out_header_reader, std::move(storage), ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result NcaFileSystemDriver::CreateStorageByRawStorage(std::shared_ptr<fs::IStorage> *out, const NcaFsHeaderReader *header_reader, std::shared_ptr<fs::IStorage> raw_storage, StorageContext *ctx) {
|
||||||
|
/* Initialize storage as raw storage. */
|
||||||
|
std::shared_ptr<fs::IStorage> storage = std::move(raw_storage);
|
||||||
|
|
||||||
/* Process hash/integrity layer. */
|
/* Process hash/integrity layer. */
|
||||||
switch (out_header_reader->GetHashType()) {
|
switch (header_reader->GetHashType()) {
|
||||||
case NcaFsHeader::HashType::HierarchicalSha256Hash:
|
case NcaFsHeader::HashType::HierarchicalSha256Hash:
|
||||||
R_TRY(this->CreateSha256Storage(std::addressof(storage), std::move(storage), out_header_reader->GetHashData().hierarchical_sha256_data));
|
R_TRY(this->CreateSha256Storage(std::addressof(storage), std::move(storage), header_reader->GetHashData().hierarchical_sha256_data));
|
||||||
break;
|
break;
|
||||||
case NcaFsHeader::HashType::HierarchicalIntegrityHash:
|
case NcaFsHeader::HashType::HierarchicalIntegrityHash:
|
||||||
R_TRY(this->CreateIntegrityVerificationStorage(std::addressof(storage), std::move(storage), out_header_reader->GetHashData().integrity_meta_info));
|
R_TRY(this->CreateIntegrityVerificationStorage(std::addressof(storage), std::move(storage), header_reader->GetHashData().integrity_meta_info));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return fs::ResultInvalidNcaFsHeaderHashType();
|
return fs::ResultInvalidNcaFsHeaderHashType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process compression layer. */
|
/* Process compression layer. */
|
||||||
if (out_header_reader->ExistsCompressionLayer()) {
|
if (header_reader->ExistsCompressionLayer()) {
|
||||||
R_TRY(this->CreateCompressedStorage(std::addressof(storage), ctx != nullptr ? std::addressof(ctx->compressed_storage) : nullptr, ctx != nullptr ? std::addressof(ctx->compressed_storage_meta_storage) : nullptr, std::move(storage), out_header_reader->GetCompressionInfo()));
|
R_TRY(this->CreateCompressedStorage(std::addressof(storage), ctx != nullptr ? std::addressof(ctx->compressed_storage) : nullptr, ctx != nullptr ? std::addressof(ctx->compressed_storage_meta_storage) : nullptr, std::move(storage), header_reader->GetCompressionInfo()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set output storage. */
|
/* Set output storage. */
|
||||||
|
|
|
@ -103,8 +103,13 @@ namespace ams::fssystem {
|
||||||
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(m_header.magic)));
|
const u8 *msg = static_cast<const u8 *>(static_cast<const void *>(std::addressof(m_header.magic)));
|
||||||
const size_t msg_size = NcaHeader::Size - NcaHeader::HeaderSignSize * NcaHeader::HeaderSignCount;
|
const size_t msg_size = NcaHeader::Size - NcaHeader::HeaderSignSize * NcaHeader::HeaderSignCount;
|
||||||
|
|
||||||
const bool is_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
m_is_header_sign1_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||||
R_UNLESS(is_signature_valid, fs::ResultNcaHeaderSignature1VerificationFailed());
|
|
||||||
|
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
R_UNLESS(m_is_header_sign1_signature_valid, fs::ResultNcaHeaderSignature1VerificationFailed());
|
||||||
|
#else
|
||||||
|
R_UNLESS(m_is_header_sign1_signature_valid || crypto_cfg.is_unsigned_header_available_for_host_tool, fs::ResultNcaHeaderSignature1VerificationFailed());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the sdk version. */
|
/* Validate the sdk version. */
|
||||||
|
@ -363,14 +368,22 @@ namespace ams::fssystem {
|
||||||
return m_header_storage->Read(offset, dst, sizeof(NcaFsHeader));
|
return m_header_storage->Read(offset, dst, sizeof(NcaFsHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaReader::GetHeaderSign2(void *dst, size_t size) {
|
bool NcaReader::GetHeaderSign1Valid() const {
|
||||||
|
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||||
|
AMS_ABORT_UNLESS(m_is_header_sign1_signature_valid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_is_header_sign1_signature_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NcaReader::GetHeaderSign2(void *dst, size_t size) const {
|
||||||
AMS_ASSERT(dst != nullptr);
|
AMS_ASSERT(dst != nullptr);
|
||||||
AMS_ASSERT(size == NcaHeader::HeaderSignSize);
|
AMS_ASSERT(size == NcaHeader::HeaderSignSize);
|
||||||
|
|
||||||
std::memcpy(dst, m_header.header_sign_2, size);
|
std::memcpy(dst, m_header.header_sign_2, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaReader::GetHeaderSign2TargetHash(void *dst, size_t size) {
|
void NcaReader::GetHeaderSign2TargetHash(void *dst, size_t size) const {
|
||||||
AMS_ASSERT(m_hash_generator_factory != nullptr);
|
AMS_ASSERT(m_hash_generator_factory != nullptr);
|
||||||
AMS_ASSERT(dst != nullptr);
|
AMS_ASSERT(dst != nullptr);
|
||||||
AMS_ASSERT(size == IHash256Generator::HashSize);
|
AMS_ASSERT(size == IHash256Generator::HashSize);
|
||||||
|
|
Loading…
Reference in a new issue