[nstool] Give reasons for why a NCA partition is unreadable.

This commit is contained in:
jakcron 2018-05-22 14:38:14 +08:00
parent ab1f092d75
commit 60eda9e42e
2 changed files with 75 additions and 50 deletions

View file

@ -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,65 +199,82 @@ 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;
// filter out unrecognised format types try
switch (info.format_type)
{ {
case (nx::nca::FORMAT_PFS0): // filter out unrecognised format types
case (nx::nca::FORMAT_ROMFS): switch (info.format_type)
break; {
default: case (nx::nca::FORMAT_PFS0):
error.clear(); case (nx::nca::FORMAT_ROMFS):
error << "NCA FS Header [" << partition.index << "] FormatType(" << info.format_type << "): UNKNOWN \n"; break;
throw fnd::Exception(kModuleName, error.str()); default:
} error.clear();
error << "FormatType(" << info.format_type << "): UNKNOWN";
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()); throw fnd::Exception(kModuleName, error.str());
} }
else
{
error.clear();
error << "EncryptionType(" << info.enc_type << "): UNKNOWN";
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_HIERARCHICAL_SHA256):
info.hash_tree_meta.importHierarchicalSha256Header(nx::HierarchicalSha256Header(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
break;
case (nx::nca::HASH_HIERARCHICAL_INTERGRITY):
info.hash_tree_meta.importHierarchicalIntergityHeader(nx::HierarchicalIntegrityHeader(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen));
break;
}
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)
{ {
case (nx::nca::HASH_NONE): info.fail_reason = std::string(e.error());
break; if (info.reader != nullptr)
case (nx::nca::HASH_HIERARCHICAL_SHA256): delete info.reader;
info.hash_tree_meta.importHierarchicalSha256Header(nx::HierarchicalSha256Header(fs_header.hash_superblock, nx::nca::kFsHeaderHashSuperblockLen)); info.reader = nullptr;
//info.reader = (info.reader == nullptr) ? nullptr : new OffsetAdjustedIFile(info.reader, true, info.hash_tree_meta.getDataLayer().offset, info.hash_tree_meta.getDataLayer().size); info.hash_tree_meta = HashTreeMeta();
info.reader = (info.reader == nullptr) ? nullptr : new HashTreeWrappedIFile(info.reader, true, info.hash_tree_meta);
break;
case (nx::nca::HASH_HIERARCHICAL_INTERGRITY):
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;
default:
error.clear();
error << "NCA FS Header [" << partition.index << "] HashType(" << info.hash_type << "): UNKNOWN \n";
throw fnd::Exception(kModuleName, error.str());
} }
/* /*
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;
} }

View file

@ -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;