mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nstool] Give reasons for why a NCA partition is unreadable.
This commit is contained in:
parent
ab1f092d75
commit
60eda9e42e
2 changed files with 75 additions and 50 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fnd/SimpleTextOutput.h>
|
#include <fnd/SimpleTextOutput.h>
|
||||||
#include <nx/NcaUtils.h>
|
#include <nx/NcaUtils.h>
|
||||||
|
@ -140,7 +141,7 @@ void NcaProcess::generateNcaBodyEncryptionKeys()
|
||||||
{
|
{
|
||||||
mBodyKeys.aes_xts = mKeyset->nca.manual_body_key_aesxts;
|
mBodyKeys.aes_xts = mKeyset->nca.manual_body_key_aesxts;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (mBodyKeys.aes_ctr.isSet)
|
if (mBodyKeys.aes_ctr.isSet)
|
||||||
{
|
{
|
||||||
printf("AES-CTR Key: ");
|
printf("AES-CTR Key: ");
|
||||||
|
@ -153,6 +154,7 @@ void NcaProcess::generateNcaBodyEncryptionKeys()
|
||||||
printf("AES-XTS Key1: ");
|
printf("AES-XTS Key1: ");
|
||||||
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[1], sizeof(mBodyKeys.aes_ctr.var));
|
fnd::SimpleTextOutput::hexDump(mBodyKeys.aes_xts.var.key[1], sizeof(mBodyKeys.aes_ctr.var));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void NcaProcess::generatePartitionConfiguration()
|
void NcaProcess::generatePartitionConfiguration()
|
||||||
|
@ -182,7 +184,7 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
if (fs_header.version.get() != nx::nca::kDefaultFsHeaderVersion)
|
if (fs_header.version.get() != nx::nca::kDefaultFsHeaderVersion)
|
||||||
{
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "NCA FS Header [" << partition.index << "] Version(" << fs_header.version.get() << "): UNSUPPORTED\n";
|
error << "NCA FS Header [" << partition.index << "] Version(" << fs_header.version.get() << "): UNSUPPORTED";
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +199,8 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
info.hash_type = (nx::nca::HashType)fs_header.hash_type;
|
info.hash_type = (nx::nca::HashType)fs_header.hash_type;
|
||||||
info.enc_type = (nx::nca::EncryptionType)fs_header.encryption_type;
|
info.enc_type = (nx::nca::EncryptionType)fs_header.encryption_type;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
// filter out unrecognised format types
|
// filter out unrecognised format types
|
||||||
switch (info.format_type)
|
switch (info.format_type)
|
||||||
{
|
{
|
||||||
|
@ -205,57 +209,72 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "NCA FS Header [" << partition.index << "] FormatType(" << info.format_type << "): UNKNOWN \n";
|
error << "FormatType(" << info.format_type << "): UNKNOWN";
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create reader based on encryption type0
|
// create reader based on encryption type0
|
||||||
switch(info.enc_type)
|
if (info.enc_type == nx::nca::CRYPT_NONE)
|
||||||
{
|
{
|
||||||
case (nx::nca::CRYPT_AESXTS):
|
|
||||||
case (nx::nca::CRYPT_AESCTREX):
|
|
||||||
info.reader = nullptr;
|
|
||||||
break;
|
|
||||||
case (nx::nca::CRYPT_AESCTR):
|
|
||||||
info.reader = mBodyKeys.aes_ctr.isSet? new OffsetAdjustedIFile(new AesCtrWrappedIFile(mReader, mBodyKeys.aes_ctr.var, info.aes_ctr), true, info.offset, info.size) : nullptr;
|
|
||||||
break;
|
|
||||||
case (nx::nca::CRYPT_NONE):
|
|
||||||
info.reader = new OffsetAdjustedIFile(mReader, info.offset, info.size);
|
info.reader = new OffsetAdjustedIFile(mReader, info.offset, info.size);
|
||||||
break;
|
}
|
||||||
default:
|
else if (info.enc_type == nx::nca::CRYPT_AESCTR)
|
||||||
|
{
|
||||||
|
if (mBodyKeys.aes_ctr.isSet == false)
|
||||||
|
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
|
||||||
|
info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mReader, mBodyKeys.aes_ctr.var, info.aes_ctr), true, info.offset, info.size);
|
||||||
|
}
|
||||||
|
else if (info.enc_type == nx::nca::CRYPT_AESXTS || info.enc_type == nx::nca::CRYPT_AESCTREX)
|
||||||
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "NCA FS Header [" << partition.index << "] EncryptionType(" << info.enc_type << "): UNKNOWN \n";
|
error << "EncryptionType(" << kEncryptionTypeStr[info.enc_type] << "): UNSUPPORTED";
|
||||||
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error.clear();
|
||||||
|
error << "EncryptionType(" << info.enc_type << "): UNKNOWN";
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter out unrecognised hash types, and get data offsets
|
// filter out unrecognised hash types, and hash based readers
|
||||||
switch (info.hash_type)
|
if (info.hash_type == nx::nca::HASH_HIERARCHICAL_SHA256 || info.hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||||
|
{
|
||||||
|
switch(info.hash_type)
|
||||||
{
|
{
|
||||||
case (nx::nca::HASH_NONE):
|
|
||||||
break;
|
|
||||||
case (nx::nca::HASH_HIERARCHICAL_SHA256):
|
case (nx::nca::HASH_HIERARCHICAL_SHA256):
|
||||||
info.hash_tree_meta.importHierarchicalSha256Header(nx::HierarchicalSha256Header(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
|
info.hash_tree_meta.importHierarchicalSha256Header(nx::HierarchicalSha256Header(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
|
||||||
//info.reader = (info.reader == nullptr) ? nullptr : new OffsetAdjustedIFile(info.reader, true, info.hash_tree_meta.getDataLayer().offset, info.hash_tree_meta.getDataLayer().size);
|
|
||||||
info.reader = (info.reader == nullptr) ? nullptr : new HashTreeWrappedIFile(info.reader, true, info.hash_tree_meta);
|
|
||||||
break;
|
break;
|
||||||
case (nx::nca::HASH_HIERARCHICAL_INTERGRITY):
|
case (nx::nca::HASH_HIERARCHICAL_INTERGRITY):
|
||||||
info.hash_tree_meta.importHierarchicalIntergityHeader(nx::HierarchicalIntegrityHeader(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
|
info.hash_tree_meta.importHierarchicalIntergityHeader(nx::HierarchicalIntegrityHeader(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
|
||||||
//info.reader = (info.reader == nullptr) ? nullptr : new OffsetAdjustedIFile(info.reader, true, info.hash_tree_meta.getDataLayer().offset, info.hash_tree_meta.getDataLayer().size);
|
|
||||||
info.reader = (info.reader == nullptr) ? nullptr : new HashTreeWrappedIFile(info.reader, true, info.hash_tree_meta);
|
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
error.clear();
|
|
||||||
error << "NCA FS Header [" << partition.index << "] HashType(" << info.hash_type << "): UNKNOWN \n";
|
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fnd::IFile* tmp = info.reader;
|
||||||
|
info.reader = nullptr;
|
||||||
|
info.reader = new HashTreeWrappedIFile(tmp, true, info.hash_tree_meta);
|
||||||
|
}
|
||||||
|
else if (info.hash_type != nx::nca::HASH_NONE)
|
||||||
|
{
|
||||||
|
error.clear();
|
||||||
|
error << "HashType(" << info.hash_type << "): UNKNOWN";
|
||||||
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception& e)
|
||||||
|
{
|
||||||
|
info.fail_reason = std::string(e.error());
|
||||||
|
if (info.reader != nullptr)
|
||||||
|
delete info.reader;
|
||||||
|
info.reader = nullptr;
|
||||||
|
info.hash_tree_meta = HashTreeMeta();
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
if (info.reader != nullptr)
|
if (info.reader != nullptr)
|
||||||
{
|
{
|
||||||
fnd::MemoryBlob sss;
|
fnd::MemoryBlob sss;
|
||||||
sss.alloc(info.reader->size());
|
sss.alloc(0x100);
|
||||||
info.reader->read(sss.getBytes(), sss.getSize());
|
info.reader->read(sss.getBytes(), 0x100);
|
||||||
printf("[%d] START\n", i);
|
printf("[%d] START\n", i);
|
||||||
fnd::SimpleTextOutput::hxdStyleDump(sss.getBytes(), 0x100);
|
fnd::SimpleTextOutput::hxdStyleDump(sss.getBytes(), 0x100);
|
||||||
printf("[%d] END\n", i);
|
printf("[%d] END\n", i);
|
||||||
|
@ -448,7 +467,12 @@ void NcaProcess::processPartitions()
|
||||||
// if the reader is null, skip
|
// if the reader is null, skip
|
||||||
if (partition.reader == nullptr)
|
if (partition.reader == nullptr)
|
||||||
{
|
{
|
||||||
printf("[WARNING] NCA Partition %d not readable\n", index);
|
printf("[WARNING] NCA Partition %d not readable.", index);
|
||||||
|
if (partition.fail_reason.empty() == false)
|
||||||
|
{
|
||||||
|
printf(" (%s)", partition.fail_reason.c_str());
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ private:
|
||||||
struct sPartitionInfo
|
struct sPartitionInfo
|
||||||
{
|
{
|
||||||
fnd::IFile* reader;
|
fnd::IFile* reader;
|
||||||
|
std::string fail_reason;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue