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)
|
||||
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 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
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,10 @@ namespace ams::fssystem {
|
|||
DecryptAesCtrFunction decrypt_aes_ctr;
|
||||
DecryptAesCtrFunction decrypt_aes_ctr_external;
|
||||
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);
|
||||
|
||||
|
@ -103,6 +107,7 @@ namespace ams::fssystem {
|
|||
DecryptAesCtrFunction m_decrypt_aes_ctr_external;
|
||||
bool m_is_software_aes_prioritized;
|
||||
NcaHeader::EncryptionType m_header_encryption_type;
|
||||
bool m_is_header_sign1_signature_valid;
|
||||
GetDecompressorFunction m_get_decompressor;
|
||||
IHash256GeneratorFactory *m_hash_generator_factory;
|
||||
public:
|
||||
|
@ -149,8 +154,10 @@ namespace ams::fssystem {
|
|||
GetDecompressorFunction GetDecompressor() const;
|
||||
IHash256GeneratorFactory *GetHashGeneratorFactory() const;
|
||||
|
||||
void GetHeaderSign2(void *dst, size_t size);
|
||||
void GetHeaderSign2TargetHash(void *dst, size_t size);
|
||||
bool GetHeaderSign1Valid() const;
|
||||
|
||||
void GetHeaderSign2(void *dst, size_t size) const;
|
||||
void GetHeaderSign2TargetHash(void *dst, size_t size) const;
|
||||
};
|
||||
|
||||
class NcaFsHeaderReader : public ::ams::fs::impl::Newable {
|
||||
|
@ -252,6 +259,13 @@ namespace ams::fssystem {
|
|||
/* Open the storage. */
|
||||
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:
|
||||
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);
|
||||
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
|
||||
|
||||
}
|
||||
|
|
|
@ -180,6 +180,11 @@ namespace ams::fssystem {
|
|||
cfg->decrypt_aes_ctr_external = DecryptAesCtrForPreparedKey;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -292,14 +292,6 @@ namespace ams::fssystem {
|
|||
using IntegrityLevelInfo = NcaFsHeader::HashData::IntegrityMetaInfo::LevelHashInfo;
|
||||
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) {
|
||||
|
@ -308,7 +300,7 @@ namespace ams::fssystem {
|
|||
|
||||
/* If we have a compressed storage, use it as splitter. */
|
||||
if (ctx->compressed_storage != nullptr) {
|
||||
*out_splitter = std::move(ctx->compressed_storage);
|
||||
*out_splitter = ctx->compressed_storage;
|
||||
} else {
|
||||
/* Otherwise, allocate a default splitter. */
|
||||
*out_splitter = fssystem::AllocateShared<DefaultAsynchronousAccessSplitter>();
|
||||
|
@ -447,21 +439,29 @@ namespace ams::fssystem {
|
|||
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. */
|
||||
switch (out_header_reader->GetHashType()) {
|
||||
switch (header_reader->GetHashType()) {
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
return fs::ResultInvalidNcaFsHeaderHashType();
|
||||
}
|
||||
|
||||
/* Process compression layer. */
|
||||
if (out_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()));
|
||||
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), header_reader->GetCompressionInfo()));
|
||||
}
|
||||
|
||||
/* 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 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);
|
||||
R_UNLESS(is_signature_valid, fs::ResultNcaHeaderSignature1VerificationFailed());
|
||||
m_is_header_sign1_signature_valid = crypto::VerifyRsa2048PssSha256(sig, sig_size, mod, mod_size, exp, exp_size, msg, msg_size);
|
||||
|
||||
#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. */
|
||||
|
@ -363,14 +368,22 @@ namespace ams::fssystem {
|
|||
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(size == NcaHeader::HeaderSignSize);
|
||||
|
||||
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(dst != nullptr);
|
||||
AMS_ASSERT(size == IHash256Generator::HashSize);
|
||||
|
|
Loading…
Reference in a new issue