mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 04:02:11 +00:00
nca: fix bugs in plaintext hash layer reading.
SHA3-256 support is still missing.
This commit is contained in:
parent
2c4ddac4c6
commit
4b2cd46785
1 changed files with 66 additions and 26 deletions
|
@ -902,27 +902,30 @@ static bool _ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size
|
|||
}
|
||||
|
||||
/* Check if we're supposed to read a hash layer without encryption. */
|
||||
if (ctx->skip_hash_layer_crypto && ((offset + read_size) <= ctx->last_layer_offset || (ctx->last_layer_offset + ctx->last_layer_size) <= offset || \
|
||||
(offset < ctx->last_layer_offset && (offset + read_size) > ctx->last_layer_offset) || \
|
||||
(ctx->last_layer_offset < offset && (ctx->last_layer_offset + ctx->last_layer_size) < (offset + read_size))))
|
||||
if (ctx->skip_hash_layer_crypto)
|
||||
{
|
||||
/* Easy route. Just read the plaintext data we need and bail out. */
|
||||
if ((offset + read_size) <= ctx->last_layer_offset || (ctx->last_layer_offset + ctx->last_layer_size) <= offset)
|
||||
{
|
||||
/* Easy route. Just read the plaintext data we need and bail out. */
|
||||
ret = ncaReadContentFile(nca_ctx, out, read_size, content_offset);
|
||||
if (!ret) LOG_MSG("Failed to read 0x%lX bytes data block at offset 0x%lX from NCA \"%s\" FS section #%u! (plaintext hash layer) (#1).", read_size, content_offset, \
|
||||
nca_ctx->content_id_str, ctx->section_num);
|
||||
goto end;
|
||||
}
|
||||
} else
|
||||
if ((offset < ctx->last_layer_offset && (offset + read_size) > ctx->last_layer_offset && (offset + read_size) <= (ctx->last_layer_offset + ctx->last_layer_size)) || \
|
||||
(ctx->last_layer_offset < offset && (ctx->last_layer_offset + ctx->last_layer_size) > offset && (ctx->last_layer_offset + ctx->last_layer_size) < (offset + read_size)))
|
||||
{
|
||||
/* Handle reads that span across both plaintext hash layers and encrypted FS area. */
|
||||
bool plaintext_first = (offset < ctx->last_layer_offset);
|
||||
|
||||
/* Long, tedious route. Calculate offsets and block sizes. */
|
||||
/* Calculate offsets and block sizes. */
|
||||
block_start_offset = content_offset;
|
||||
block_end_offset = ((block_start_offset + read_size) - (offset < ctx->last_layer_offset ? ctx->last_layer_offset : (ctx->last_layer_offset + ctx->last_layer_size)));
|
||||
block_end_offset = (ctx->section_offset + (plaintext_first ? ctx->last_layer_offset : (ctx->last_layer_offset + ctx->last_layer_size)));
|
||||
block_size = (block_end_offset - block_start_offset);
|
||||
|
||||
if (offset < ctx->last_layer_offset)
|
||||
if (plaintext_first)
|
||||
{
|
||||
/* Read plaintext area. */
|
||||
/* Read plaintext area. Use NCA-relative offset. */
|
||||
if (!ncaReadContentFile(nca_ctx, out, block_size, block_start_offset))
|
||||
{
|
||||
LOG_MSG("Failed to read 0x%lX bytes data block at offset 0x%lX from NCA \"%s\" FS section #%u! (plaintext hash layer) (#2).", block_size, block_start_offset, \
|
||||
|
@ -930,19 +933,56 @@ static bool _ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* Read encrypted area. */
|
||||
/* Read encrypted area. Use FS-section-relative offset. */
|
||||
ret = _ncaReadFsSection(ctx, (u8*)out + block_size, read_size - block_size, offset + block_size);
|
||||
} else {
|
||||
/* Read encrypted area. */
|
||||
/* Read encrypted area. Use FS-section-relative offset. */
|
||||
if (!_ncaReadFsSection(ctx, out, block_size, offset)) goto end;
|
||||
|
||||
/* Read plaintext area. */
|
||||
/* Read plaintext area. Use NCA-relative offset. */
|
||||
ret = ncaReadContentFile(nca_ctx, (u8*)out + block_size, read_size - block_size, block_end_offset);
|
||||
if (!ret) LOG_MSG("Failed to read 0x%lX bytes data block at offset 0x%lX from NCA \"%s\" FS section #%u! (plaintext hash layer) (#3).", read_size - block_size, \
|
||||
block_end_offset, nca_ctx->content_id_str, ctx->section_num);
|
||||
}
|
||||
|
||||
return ret;
|
||||
goto end;
|
||||
} else
|
||||
if (offset < ctx->last_layer_offset && (offset + read_size) > (ctx->last_layer_offset + ctx->last_layer_size))
|
||||
{
|
||||
/* Handle plaintext hash layer + encrypted FS area + plaintext hash layer reads. */
|
||||
u8 *out_u8 = (u8*)out;
|
||||
|
||||
/* Read plaintext area. Use NCA-relative offset. */
|
||||
block_start_offset = content_offset;
|
||||
block_end_offset = (ctx->section_offset + ctx->last_layer_offset);
|
||||
block_size = (block_end_offset - block_start_offset);
|
||||
|
||||
if (!ncaReadContentFile(nca_ctx, out_u8, block_size, block_start_offset))
|
||||
{
|
||||
LOG_MSG("Failed to read 0x%lX bytes data block at offset 0x%lX from NCA \"%s\" FS section #%u! (plaintext hash layer) (#4).", block_size, block_start_offset, \
|
||||
nca_ctx->content_id_str, ctx->section_num);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Read encrypted area. Use FS-section-relative offset. */
|
||||
out_u8 += block_size;
|
||||
block_start_offset = ctx->last_layer_offset;
|
||||
block_size = ctx->last_layer_size;
|
||||
|
||||
if (!_ncaReadFsSection(ctx, out_u8, block_size, block_start_offset)) goto end;
|
||||
|
||||
/* Read plaintext area. Use NCA-relative offset. */
|
||||
out_u8 += block_size;
|
||||
block_start_offset = (block_end_offset + block_size);
|
||||
block_end_offset = (content_offset + read_size);
|
||||
block_size = (block_end_offset - block_start_offset);
|
||||
|
||||
ret = ncaReadContentFile(nca_ctx, out_u8, block_size, block_start_offset);
|
||||
if (!ret) LOG_MSG("Failed to read 0x%lX bytes data block at offset 0x%lX from NCA \"%s\" FS section #%u! (plaintext hash layer) (#5).", block_size, block_start_offset, \
|
||||
nca_ctx->content_id_str, ctx->section_num);
|
||||
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optimization for reads from plaintext FS sections or reads that are aligned to the AES-CTR / AES-XTS sector size. */
|
||||
|
|
Loading…
Reference in a new issue