mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-08 11:51:48 +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,47 +902,87 @@ static bool _ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we're supposed to read a hash layer without encryption. */
|
/* 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 || \
|
if (ctx->skip_hash_layer_crypto)
|
||||||
(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))))
|
|
||||||
{
|
{
|
||||||
/* 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)
|
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);
|
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, \
|
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);
|
nca_ctx->content_id_str, ctx->section_num);
|
||||||
goto end;
|
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)) || \
|
||||||
/* Long, tedious route. Calculate offsets and block sizes. */
|
(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)))
|
||||||
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_size = (block_end_offset - block_start_offset);
|
|
||||||
|
|
||||||
if (offset < ctx->last_layer_offset)
|
|
||||||
{
|
{
|
||||||
/* Read plaintext area. */
|
/* Handle reads that span across both plaintext hash layers and encrypted FS area. */
|
||||||
if (!ncaReadContentFile(nca_ctx, out, block_size, block_start_offset))
|
bool plaintext_first = (offset < ctx->last_layer_offset);
|
||||||
|
|
||||||
|
/* Calculate offsets and block sizes. */
|
||||||
|
block_start_offset = content_offset;
|
||||||
|
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 (plaintext_first)
|
||||||
{
|
{
|
||||||
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, \
|
/* 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, \
|
||||||
|
nca_ctx->content_id_str, ctx->section_num);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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. Use FS-section-relative offset. */
|
||||||
|
if (!_ncaReadFsSection(ctx, out, block_size, offset)) goto end;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
nca_ctx->content_id_str, ctx->section_num);
|
||||||
goto end;
|
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);
|
out_u8 += block_size;
|
||||||
} else {
|
block_start_offset = ctx->last_layer_offset;
|
||||||
/* Read encrypted area. */
|
block_size = ctx->last_layer_size;
|
||||||
if (!_ncaReadFsSection(ctx, out, block_size, offset)) goto end;
|
|
||||||
|
|
||||||
/* Read plaintext area. */
|
if (!_ncaReadFsSection(ctx, out_u8, block_size, block_start_offset)) goto end;
|
||||||
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, \
|
/* Read plaintext area. Use NCA-relative offset. */
|
||||||
block_end_offset, nca_ctx->content_id_str, ctx->section_num);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Optimization for reads from plaintext FS sections or reads that are aligned to the AES-CTR / AES-XTS sector size. */
|
/* 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