1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-09-20 14:03:26 +01:00

Verify NCA FS section header hash.

This commit is contained in:
Pablo Curiel 2021-04-26 01:51:01 -04:00
parent 17dd24bc92
commit 455b86179b

View file

@ -83,6 +83,8 @@ void ncaFreeCryptoBuffer(void)
bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, const NcmContentInfo *content_info, Ticket *tik) bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, const NcmContentInfo *content_info, Ticket *tik)
{ {
NcmContentStorage *ncm_storage = NULL; NcmContentStorage *ncm_storage = NULL;
u8 fs_header_hash_calc[SHA256_HASH_SIZE] = {0};
u8 valid_fs_section_cnt = 0;
if (!out || (storage_id != NcmStorageId_GameCard && !(ncm_storage = titleGetNcmStorageByStorageId(storage_id))) || \ if (!out || (storage_id != NcmStorageId_GameCard && !(ncm_storage = titleGetNcmStorageByStorageId(storage_id))) || \
(storage_id == NcmStorageId_GameCard && hfs_partition_type >= GameCardHashFileSystemPartitionType_Count) || !content_info || content_info->content_type > NcmContentType_DeltaFragment) (storage_id == NcmStorageId_GameCard && hfs_partition_type >= GameCardHashFileSystemPartitionType_Count) || !content_info || content_info->content_type > NcmContentType_DeltaFragment)
@ -151,11 +153,12 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
} }
} }
/* Parse sections. */ /* Parse NCA FS sections. */
for(u8 i = 0; i < NCA_FS_HEADER_COUNT; i++) for(u8 i = 0; i < NCA_FS_HEADER_COUNT; i++)
{ {
NcaFsInfo *fs_info = &(out->header.fs_info[i]); NcaFsInfo *fs_info = &(out->header.fs_info[i]);
NcaFsSectionContext *fs_ctx = &(out->fs_ctx[i]); NcaFsSectionContext *fs_ctx = &(out->fs_ctx[i]);
u8 *fs_header_hash = out->header.fs_header_hash[i].hash;
/* Fill section context. */ /* Fill section context. */
fs_ctx->nca_ctx = out; fs_ctx->nca_ctx = out;
@ -165,6 +168,12 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
/* Don't proceed if this NCA FS section isn't populated. */ /* Don't proceed if this NCA FS section isn't populated. */
if (!ncaIsFsInfoEntryValid(fs_info)) continue; if (!ncaIsFsInfoEntryValid(fs_info)) continue;
/* Calculate NCA FS section header hash. */
sha256CalculateHash(fs_header_hash_calc, &(fs_ctx->header), sizeof(NcaFsHeader));
/* Don't proceed if there's a checksum mismatch. */
if (memcmp(fs_header_hash_calc, fs_header_hash, SHA256_HASH_SIZE) != 0) continue;
/* Calculate section offset and size. */ /* Calculate section offset and size. */
fs_ctx->section_offset = NCA_FS_SECTOR_OFFSET(fs_info->start_sector); fs_ctx->section_offset = NCA_FS_SECTOR_OFFSET(fs_info->start_sector);
fs_ctx->section_size = (NCA_FS_SECTOR_OFFSET(fs_info->end_sector) - fs_ctx->section_offset); fs_ctx->section_size = (NCA_FS_SECTOR_OFFSET(fs_info->end_sector) - fs_ctx->section_offset);
@ -246,9 +255,14 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
/* Enable FS context if we got up to this point. */ /* Enable FS context if we got up to this point. */
fs_ctx->enabled = true; fs_ctx->enabled = true;
/* Increase valid NCA FS section count. */
valid_fs_section_cnt++;
} }
return true; if (!valid_fs_section_cnt) LOG_MSG("Unable to identify any valid FS sections in NCA \"%s\"!", out->content_id_str);
return (valid_fs_section_cnt > 0);
} }
bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset) bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset)
@ -425,7 +439,7 @@ bool ncaEncryptHeader(NcaContext *ctx)
NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]); NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]);
/* Don't proceed if this NCA FS section isn't populated. */ /* Don't proceed if this NCA FS section isn't populated. */
if (ctx->format_version != NcaVersion_Nca3 && !ncaIsFsInfoEntryValid(fs_info)) continue; if (!ncaIsFsInfoEntryValid(fs_info)) continue;
/* The AES-XTS sector number for each NCA FS header varies depending on the NCA format version. */ /* The AES-XTS sector number for each NCA FS header varies depending on the NCA format version. */
/* NCA3 uses sector number 0 for the NCA header, then increases it with each new sector (e.g. making the first NCA FS section header use sector number 2, and so on). */ /* NCA3 uses sector number 0 for the NCA header, then increases it with each new sector (e.g. making the first NCA FS section header use sector number 2, and so on). */
@ -577,7 +591,7 @@ static bool ncaReadDecryptedHeader(NcaContext *ctx)
NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]); NcaFsSectionContext *fs_ctx = &(ctx->fs_ctx[i]);
/* Don't proceed if this NCA FS section isn't populated. */ /* Don't proceed if this NCA FS section isn't populated. */
if (ctx->format_version != NcaVersion_Nca3 && !ncaIsFsInfoEntryValid(fs_info)) continue; if (!ncaIsFsInfoEntryValid(fs_info)) continue;
/* Read NCA FS section header. */ /* Read NCA FS section header. */
u64 fs_header_offset = (ctx->format_version != NcaVersion_Nca0 ? (sizeof(NcaHeader) + (i * sizeof(NcaFsHeader))) : NCA_FS_SECTOR_OFFSET(fs_info->start_sector)); u64 fs_header_offset = (ctx->format_version != NcaVersion_Nca0 ? (sizeof(NcaHeader) + (i * sizeof(NcaFsHeader))) : NCA_FS_SECTOR_OFFSET(fs_info->start_sector));