mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
Merge branch 'master' of github.com:jakcron/nstool
This commit is contained in:
commit
7962c8cb0b
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
bin/*
|
bin/*
|
||||||
|
data/*
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so.*
|
*.so.*
|
||||||
|
|
|
@ -45,20 +45,33 @@ pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes)
|
||||||
|
|
||||||
; NCA Keys
|
; NCA Keys
|
||||||
nca_header_key : AES128-XTS Key (0x20 bytes)
|
nca_header_key : AES128-XTS Key (0x20 bytes)
|
||||||
nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
nca_header_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||||
nca_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
nca_header_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||||
nca_body_keak_application_## : AES128 Key (0x10 bytes)
|
nca_body_keak_application_## : AES128 Key (0x10 bytes)
|
||||||
nca_body_keak_ocean_## : AES128 Key (0x10 bytes)
|
nca_body_keak_ocean_## : AES128 Key (0x10 bytes)
|
||||||
nca_body_keak_system_## : AES128 Key (0x10 bytes)
|
nca_body_keak_system_## : AES128 Key (0x10 bytes)
|
||||||
|
|
||||||
|
; NRR Keys
|
||||||
|
nrr_certificate_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||||
|
nrr_certificate_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||||
|
|
||||||
; XCI Keys
|
; XCI Keys
|
||||||
xci_header_key : AES128 Key (0x10 bytes)
|
xci_header_key : AES128 Key (0x10 bytes)
|
||||||
xci_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
xci_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||||
xci_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
xci_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
||||||
|
|
||||||
; ACID Keys
|
; ACID Keys
|
||||||
acid_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
acid_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||||
acid_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
acid_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Legacy Keynames
|
||||||
|
Since firmware `9.0.0+` support for signature key generations was retroactively added for RSA-PSS signatures in NRR, ACID and NCA. The old names for these keys are still valid:
|
||||||
|
```
|
||||||
|
nca_header_sign_key_modulus : alias for nca_header_sign_key_00_modulus
|
||||||
|
nca_header_sign_key_private : alias for nca_header_sign_key_00_private
|
||||||
|
acid_sign_key_modulus : alias for acid_sign_key_00_modulus
|
||||||
|
acid_sign_key_private : alias for acid_sign_key_00_private
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compatibility with hactool keyset files
|
## Compatibility with hactool keyset files
|
||||||
|
|
2
deps/libfnd
vendored
2
deps/libfnd
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 98a6f623361781e5bf4efbec0477efa9729de2cd
|
Subproject commit 234c81d864e53cd208bb93bce69a1f5ff7e44161
|
2
deps/libnintendo-hac
vendored
2
deps/libnintendo-hac
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 112f9b59a3914dcc06a2713de8c7cd67112c57bb
|
Subproject commit 9372cb34d8ffdf4c84cc7a25ec9e675fdaff32c6
|
|
@ -60,42 +60,59 @@ void CnmtProcess::importCnmt()
|
||||||
|
|
||||||
void CnmtProcess::displayCnmt()
|
void CnmtProcess::displayCnmt()
|
||||||
{
|
{
|
||||||
#define _SPLIT_VER(ver) (uint32_t)((ver>>26) & 0x3f) << "." << (uint32_t)((ver>>20) & 0x3f) << "." << (uint32_t)((ver>>16) & 0xf) << "." << (uint32_t)(ver & 0xffff)
|
|
||||||
|
|
||||||
std::cout << "[ContentMeta]" << std::endl;
|
std::cout << "[ContentMeta]" << std::endl;
|
||||||
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getTitleId() << std::endl;
|
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getTitleId() << std::endl;
|
||||||
std::cout << " Version: v" << std::dec << mCnmt.getTitleVersion() << " (" << _SPLIT_VER(mCnmt.getTitleVersion()) << ")"<< std::endl;
|
std::cout << " Version: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()) << " (v" << std::dec << mCnmt.getTitleVersion() << ")"<< std::endl;
|
||||||
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()) << " (" << std::dec << mCnmt.getContentMetaType() << ")" << std::endl;
|
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()) << " (" << std::dec << (uint32_t)mCnmt.getContentMetaType() << ")" << std::endl;
|
||||||
std::cout << " Attributes: 0x" << std::hex << (uint32_t)mCnmt.getAttributes() << std::endl;
|
std::cout << " Attributes: 0x" << std::hex << mCnmt.getAttribute().to_ullong();
|
||||||
if (mCnmt.getAttributes() != 0)
|
if (mCnmt.getAttribute().any())
|
||||||
{
|
{
|
||||||
for (size_t bit = 0; bit < (sizeof(byte_t)*8); bit++)
|
std::vector<std::string> attribute_list;
|
||||||
|
|
||||||
|
for (size_t flag = 0; flag < mCnmt.getAttribute().size(); flag++)
|
||||||
{
|
{
|
||||||
if (_HAS_BIT(mCnmt.getAttributes(), bit))
|
|
||||||
|
if (mCnmt.getAttribute().test(flag))
|
||||||
{
|
{
|
||||||
std::cout << " > " << nn::hac::ContentMetaUtil::getContentMetaAttributeAsString((nn::hac::cnmt::ContentMetaAttribute)bit) << std::endl;
|
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(flag)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << " [";
|
||||||
|
for (auto itr = attribute_list.begin(); itr != attribute_list.end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << *itr;
|
||||||
|
if ((itr + 1) != attribute_list.end())
|
||||||
|
{
|
||||||
|
std::cout << ", ";
|
||||||
}
|
}
|
||||||
std::cout << " RequiredDownloadSystemVersion: v" << mCnmt.getRequiredDownloadSystemVersion() << " (" << _SPLIT_VER(mCnmt.getRequiredDownloadSystemVersion()) << ")"<< std::endl;
|
}
|
||||||
|
std::cout << "]";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::cout << " StorageId: " << nn::hac::ContentMetaUtil::getStorageIdAsString(mCnmt.getStorageId()) << " (" << std::dec << (uint32_t)mCnmt.getStorageId() << ")" << std::endl;
|
||||||
|
std::cout << " ContentInstallType: " << nn::hac::ContentMetaUtil::getContentInstallTypeAsString(mCnmt.getContentInstallType()) << " (" << std::dec << (uint32_t)mCnmt.getContentInstallType() << ")" << std::endl;
|
||||||
|
std::cout << " RequiredDownloadSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getRequiredDownloadSystemVersion()) << " (v" << mCnmt.getRequiredDownloadSystemVersion() << ")"<< std::endl;
|
||||||
switch(mCnmt.getContentMetaType())
|
switch(mCnmt.getContentMetaType())
|
||||||
{
|
{
|
||||||
case (nn::hac::cnmt::METATYPE_APPLICATION):
|
case (nn::hac::cnmt::ContentMetaType::Application):
|
||||||
std::cout << " ApplicationExtendedHeader:" << std::endl;
|
std::cout << " ApplicationExtendedHeader:" << std::endl;
|
||||||
std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion() << " (" << _SPLIT_VER(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()) << ")"<< std::endl;
|
std::cout << " RequiredApplicationVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion()) << " (v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredApplicationVersion() << ")"<< std::endl;
|
||||||
|
std::cout << " RequiredSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()) << " (v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion() << ")"<< std::endl;
|
||||||
std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().getPatchId() << std::endl;
|
std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().getPatchId() << std::endl;
|
||||||
break;
|
break;
|
||||||
case (nn::hac::cnmt::METATYPE_PATCH):
|
case (nn::hac::cnmt::ContentMetaType::Patch):
|
||||||
std::cout << " PatchMetaExtendedHeader:" << std::endl;
|
std::cout << " PatchMetaExtendedHeader:" << std::endl;
|
||||||
std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion() << " (" << _SPLIT_VER(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()) << ")"<< std::endl;
|
std::cout << " RequiredSystemVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion()) << " (v" << std::dec << mCnmt.getPatchMetaExtendedHeader().getRequiredSystemVersion() << ")"<< std::endl;
|
||||||
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getPatchMetaExtendedHeader().getApplicationId() << std::endl;
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getPatchMetaExtendedHeader().getApplicationId() << std::endl;
|
||||||
break;
|
break;
|
||||||
case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT):
|
case (nn::hac::cnmt::ContentMetaType::AddOnContent):
|
||||||
std::cout << " AddOnContentMetaExtendedHeader:" << std::endl;
|
std::cout << " AddOnContentMetaExtendedHeader:" << std::endl;
|
||||||
std::cout << " RequiredApplicationVersion: v" << std::dec << mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion() << " (" << _SPLIT_VER(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()) << ")" << std::endl;
|
std::cout << " RequiredApplicationVersion: " << nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion()) << " (v" << std::dec << mCnmt.getAddOnContentMetaExtendedHeader().getRequiredApplicationVersion() << ")" << std::endl;
|
||||||
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId() << std::endl;
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getAddOnContentMetaExtendedHeader().getApplicationId() << std::endl;
|
||||||
break;
|
break;
|
||||||
case (nn::hac::cnmt::METATYPE_DELTA):
|
case (nn::hac::cnmt::ContentMetaType::Delta):
|
||||||
std::cout << " DeltaMetaExtendedHeader:" << std::endl;
|
std::cout << " DeltaMetaExtendedHeader:" << std::endl;
|
||||||
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().getApplicationId() << std::endl;
|
std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().getApplicationId() << std::endl;
|
||||||
break;
|
break;
|
||||||
|
@ -109,8 +126,8 @@ void CnmtProcess::displayCnmt()
|
||||||
{
|
{
|
||||||
const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
|
const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i];
|
||||||
std::cout << " " << std::dec << i << std::endl;
|
std::cout << " " << std::dec << i << std::endl;
|
||||||
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()) << " (" << std::dec << info.getContentType() << ")" << std::endl;
|
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()) << " (" << std::dec << (uint32_t)info.getContentType() << ")" << std::endl;
|
||||||
std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.getContentId().data, nn::hac::cnmt::kContentIdLen, false, "") << std::endl;
|
std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.getContentId().data(), info.getContentId().size(), false, "") << std::endl;
|
||||||
std::cout << " Size: 0x" << std::hex << info.getContentSize() << std::endl;
|
std::cout << " Size: 0x" << std::hex << info.getContentSize() << std::endl;
|
||||||
std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(info.getContentHash().bytes, sizeof(info.getContentHash()), false, "") << std::endl;
|
std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(info.getContentHash().bytes, sizeof(info.getContentHash()), false, "") << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -118,33 +135,88 @@ void CnmtProcess::displayCnmt()
|
||||||
if (mCnmt.getContentMetaInfo().size() > 0)
|
if (mCnmt.getContentMetaInfo().size() > 0)
|
||||||
{
|
{
|
||||||
std::cout << " ContentMetaInfo:" << std::endl;
|
std::cout << " ContentMetaInfo:" << std::endl;
|
||||||
for (size_t i = 0; i < mCnmt.getContentMetaInfo().size(); i++)
|
displayContentMetaInfoList(mCnmt.getContentMetaInfo(), " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// print extended data
|
||||||
|
if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Patch && mCnmt.getPatchMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||||
|
{
|
||||||
|
// this is stubbed as the raw output is for development purposes
|
||||||
|
//std::cout << " PatchMetaExtendedData:" << std::endl;
|
||||||
|
//fnd::SimpleTextOutput::hxdStyleDump(mCnmt.getPatchMetaExtendedData().data(), mCnmt.getPatchMetaExtendedData().size());
|
||||||
|
}
|
||||||
|
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::Delta && mCnmt.getDeltaMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||||
|
{
|
||||||
|
// this is stubbed as the raw output is for development purposes
|
||||||
|
//std::cout << " DeltaMetaExtendedData:" << std::endl;
|
||||||
|
//fnd::SimpleTextOutput::hxdStyleDump(mCnmt.getDeltaMetaExtendedData().data(), mCnmt.getDeltaMetaExtendedData().size());
|
||||||
|
}
|
||||||
|
else if (mCnmt.getContentMetaType() == nn::hac::cnmt::ContentMetaType::SystemUpdate && mCnmt.getSystemUpdateMetaExtendedHeader().getExtendedDataSize() != 0)
|
||||||
|
{
|
||||||
|
std::cout << " SystemUpdateMetaExtendedData:" << std::endl;
|
||||||
|
std::cout << " FormatVersion: " << std::dec << mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion() << std::endl;
|
||||||
|
std::cout << " FirmwareVariation:" << std::endl;
|
||||||
|
auto variation_info = mCnmt.getSystemUpdateMetaExtendedData().getFirmwareVariationInfo();
|
||||||
|
for (size_t i = 0; i < mCnmt.getSystemUpdateMetaExtendedData().getFirmwareVariationInfo().size(); i++)
|
||||||
|
{
|
||||||
|
std::cout << " " << std::dec << i << std::endl;
|
||||||
|
std::cout << " FirmwareVariationId: 0x" << std::hex << variation_info[i].variation_id << std::endl;
|
||||||
|
if (mCnmt.getSystemUpdateMetaExtendedData().getFormatVersion() == 2)
|
||||||
|
{
|
||||||
|
std::cout << " ReferToBase: " << std::boolalpha << variation_info[i].meta.empty() << std::endl;
|
||||||
|
if (variation_info[i].meta.empty() == false)
|
||||||
|
{
|
||||||
|
std::cout << " ContentMeta:" << std::endl;
|
||||||
|
displayContentMetaInfoList(variation_info[i].meta, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data(), mCnmt.getDigest().size(), false, "") << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix)
|
||||||
|
{
|
||||||
|
std::cout << prefix << "Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << content_meta_info.getTitleId() << std::endl;
|
||||||
|
std::cout << prefix << "Version: " << nn::hac::ContentMetaUtil::getVersionAsString(content_meta_info.getTitleVersion()) << " (v" << std::dec << content_meta_info.getTitleVersion() << ")"<< std::endl;
|
||||||
|
std::cout << prefix << "Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(content_meta_info.getContentMetaType()) << " (" << std::dec << (uint32_t)content_meta_info.getContentMetaType() << ")" << std::endl;
|
||||||
|
std::cout << prefix << "Attributes: 0x" << std::hex << content_meta_info.getAttribute().to_ullong();
|
||||||
|
if (content_meta_info.getAttribute().any())
|
||||||
|
{
|
||||||
|
std::vector<std::string> attribute_list;
|
||||||
|
|
||||||
|
for (size_t flag = 0; flag < content_meta_info.getAttribute().size(); flag++)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (content_meta_info.getAttribute().test(flag))
|
||||||
|
{
|
||||||
|
attribute_list.push_back(nn::hac::ContentMetaUtil::getContentMetaAttributeFlagAsString(nn::hac::cnmt::ContentMetaAttributeFlag(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " [";
|
||||||
|
for (auto itr = attribute_list.begin(); itr != attribute_list.end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << *itr;
|
||||||
|
if ((itr + 1) != attribute_list.end())
|
||||||
|
{
|
||||||
|
std::cout << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CnmtProcess::displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < content_meta_info_list.size(); i++)
|
||||||
{
|
{
|
||||||
const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i];
|
||||||
std::cout << " " << std::dec << i << std::endl;
|
std::cout << prefix << std::dec << i << std::endl;
|
||||||
std::cout << " Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << info.getTitleId() << std::endl;
|
displayContentMetaInfo(info, prefix + " ");
|
||||||
std::cout << " Version: v" << std::dec << info.getTitleVersion() << " (" << _SPLIT_VER(info.getTitleVersion()) << ")"<< std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(info.getContentMetaType()) << " (" << std::dec << info.getContentMetaType() << ")" << std::endl;
|
|
||||||
std::cout << " Attributes: 0x" << std::hex << (uint32_t)info.getAttributes() << std::endl;
|
|
||||||
if (info.getAttributes() != 0)
|
|
||||||
{
|
|
||||||
for (size_t bit = 0; bit < (sizeof(byte_t)*8); bit++)
|
|
||||||
{
|
|
||||||
if (_HAS_BIT(info.getAttributes(), bit))
|
|
||||||
{
|
|
||||||
std::cout << " > " << nn::hac::ContentMetaUtil::getContentMetaAttributeAsString((nn::hac::cnmt::ContentMetaAttribute)bit) << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data, nn::hac::cnmt::kDigestLen, false, "") << std::endl;
|
|
||||||
|
|
||||||
#undef _SPLIT_VER
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* CnmtProcess::getBoolStr(bool state) const
|
|
||||||
{
|
|
||||||
return state? "TRUE" : "FALSE";
|
|
||||||
}
|
|
|
@ -32,5 +32,6 @@ private:
|
||||||
void importCnmt();
|
void importCnmt();
|
||||||
void displayCnmt();
|
void displayCnmt();
|
||||||
|
|
||||||
const char* getBoolStr(bool state) const;
|
void displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix);
|
||||||
|
void displayContentMetaInfoList(const std::vector<nn::hac::ContentMetaInfo>& content_meta_info_list, const std::string& prefix);
|
||||||
};
|
};
|
|
@ -3,6 +3,8 @@
|
||||||
#include <fnd/SimpleTextOutput.h>
|
#include <fnd/SimpleTextOutput.h>
|
||||||
#include <fnd/OffsetAdjustedIFile.h>
|
#include <fnd/OffsetAdjustedIFile.h>
|
||||||
#include <nn/hac/GameCardUtil.h>
|
#include <nn/hac/GameCardUtil.h>
|
||||||
|
#include <nn/hac/ContentMetaUtil.h>
|
||||||
|
#include <nn/hac/ContentArchiveUtil.h>
|
||||||
#include "GameCardProcess.h"
|
#include "GameCardProcess.h"
|
||||||
|
|
||||||
GameCardProcess::GameCardProcess() :
|
GameCardProcess::GameCardProcess() :
|
||||||
|
@ -138,9 +140,9 @@ void GameCardProcess::displayHeader()
|
||||||
}
|
}
|
||||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
{
|
{
|
||||||
std::cout << " InitialData:" << std::endl;
|
|
||||||
std::cout << " KekIndex: " << nn::hac::GameCardUtil::getKekIndexAsString((nn::hac::gc::KekIndex)mHdr.getKekIndex()) << " (" << std::dec << (uint32_t)mHdr.getKekIndex() << ")" << std::endl;
|
std::cout << " KekIndex: " << nn::hac::GameCardUtil::getKekIndexAsString((nn::hac::gc::KekIndex)mHdr.getKekIndex()) << " (" << std::dec << (uint32_t)mHdr.getKekIndex() << ")" << std::endl;
|
||||||
std::cout << " TitleKeyDecIndex: " << std::dec << (uint32_t)mHdr.getTitleKeyDecIndex() << std::endl;
|
std::cout << " TitleKeyDecIndex: " << std::dec << (uint32_t)mHdr.getTitleKeyDecIndex() << std::endl;
|
||||||
|
std::cout << " InitialData:" << std::endl;
|
||||||
std::cout << " Hash:" << std::endl;
|
std::cout << " Hash:" << std::endl;
|
||||||
std::cout << " " << fnd::SimpleTextOutput::arrayToString(mHdr.getInitialDataHash().bytes, 0x10, true, ":") << std::endl;
|
std::cout << " " << fnd::SimpleTextOutput::arrayToString(mHdr.getInitialDataHash().bytes, 0x10, true, ":") << std::endl;
|
||||||
std::cout << " " << fnd::SimpleTextOutput::arrayToString(mHdr.getInitialDataHash().bytes+0x10, 0x10, true, ":") << std::endl;
|
std::cout << " " << fnd::SimpleTextOutput::arrayToString(mHdr.getInitialDataHash().bytes+0x10, 0x10, true, ":") << std::endl;
|
||||||
|
@ -197,27 +199,40 @@ void GameCardProcess::displayHeader()
|
||||||
std::cout << " Wait2TimeRead: 0x" << std::hex << mHdr.getWait2TimeRead() << std::endl;
|
std::cout << " Wait2TimeRead: 0x" << std::hex << mHdr.getWait2TimeRead() << std::endl;
|
||||||
std::cout << " Wait1TimeWrite: 0x" << std::hex << mHdr.getWait1TimeWrite() << std::endl;
|
std::cout << " Wait1TimeWrite: 0x" << std::hex << mHdr.getWait1TimeWrite() << std::endl;
|
||||||
std::cout << " Wait2TimeWrite: 0x" << std::hex << mHdr.getWait2TimeWrite() << std::endl;
|
std::cout << " Wait2TimeWrite: 0x" << std::hex << mHdr.getWait2TimeWrite() << std::endl;
|
||||||
std::cout << " FwMode: 0x" << std::hex << mHdr.getFwMode() << std::endl;
|
std::cout << " SdkAddon Version: " << nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getFwMode()) << " (v" << std::dec << mHdr.getFwMode() << ")" << std::endl;
|
||||||
std::cout << " CompatibilityType: " << nn::hac::GameCardUtil::getCompatibilityTypeAsString((nn::hac::gc::CompatibilityType)mHdr.getCompatibilityType()) << "(" << std::dec << mHdr.getCompatibilityType() << ")" << std::endl;
|
std::cout << " CompatibilityType: " << nn::hac::GameCardUtil::getCompatibilityTypeAsString((nn::hac::gc::CompatibilityType)mHdr.getCompatibilityType()) << " (" << std::dec << (uint32_t) mHdr.getCompatibilityType() << ")" << std::endl;
|
||||||
std::cout << " Update Partition Info:" << std::endl;
|
std::cout << " Update Partition Info:" << std::endl;
|
||||||
#define _SPLIT_VER(ver) std::dec << ((ver>>26) & 0x3f) << "." << ((ver>>20) & 0x3f) << "." << ((ver>>16) & 0xf) << "." << (ver & 0xffff)
|
std::cout << " CUP Version: " << nn::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()) << " (v" << std::dec << mHdr.getUppVersion() << ")" << std::endl;
|
||||||
std::cout << " CUP Version: v" << std::dec << mHdr.getUppVersion() << " (" << _SPLIT_VER(mHdr.getUppVersion()) << ")" << std::endl;
|
|
||||||
#undef _SPLIT_VER
|
|
||||||
std::cout << " CUP TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getUppId() << std::endl;
|
std::cout << " CUP TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getUppId() << std::endl;
|
||||||
std::cout << " CUP Digest: " << fnd::SimpleTextOutput::arrayToString(mHdr.getUppHash(), 8, true, ":") << std::endl;
|
std::cout << " CUP Digest: " << fnd::SimpleTextOutput::arrayToString(mHdr.getUppHash(), 8, true, ":") << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash)
|
bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash, bool use_salt, byte_t salt)
|
||||||
{
|
{
|
||||||
fnd::Vec<byte_t> scratch;
|
fnd::Vec<byte_t> scratch;
|
||||||
fnd::sha::sSha256Hash calc_hash;
|
fnd::sha::sSha256Hash calc_hash;
|
||||||
|
if (use_salt)
|
||||||
|
{
|
||||||
|
scratch.alloc(len + 1);
|
||||||
|
scratch.data()[len] = salt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
scratch.alloc(len);
|
scratch.alloc(len);
|
||||||
(*mFile)->read(scratch.data(), offset, scratch.size());
|
}
|
||||||
|
|
||||||
|
(*mFile)->read(scratch.data(), offset, len);
|
||||||
fnd::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes);
|
fnd::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes);
|
||||||
|
|
||||||
return calc_hash.compare(test_hash);
|
return calc_hash.compare(test_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash)
|
||||||
|
{
|
||||||
|
return validateRegionOfFile(offset, len, test_hash, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void GameCardProcess::validateXciSignature()
|
void GameCardProcess::validateXciSignature()
|
||||||
{
|
{
|
||||||
fnd::rsa::sRsa2048Key header_sign_key;
|
fnd::rsa::sRsa2048Key header_sign_key;
|
||||||
|
@ -231,7 +246,7 @@ void GameCardProcess::validateXciSignature()
|
||||||
|
|
||||||
void GameCardProcess::processRootPfs()
|
void GameCardProcess::processRootPfs()
|
||||||
{
|
{
|
||||||
if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes) == false)
|
if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes, mHdr.getCompatibilityType() != nn::hac::gc::COMPAT_GLOBAL, mHdr.getCompatibilityType()) == false)
|
||||||
{
|
{
|
||||||
std::cout << "[WARNING] GameCard Root HFS0: FAIL (bad hash)" << std::endl;
|
std::cout << "[WARNING] GameCard Root HFS0: FAIL (bad hash)" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ private:
|
||||||
|
|
||||||
void importHeader();
|
void importHeader();
|
||||||
void displayHeader();
|
void displayHeader();
|
||||||
|
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash, bool use_salt, byte_t salt);
|
||||||
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);
|
bool validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash);
|
||||||
void validateXciSignature();
|
void validateXciSignature();
|
||||||
void processRootPfs();
|
void processRootPfs();
|
||||||
|
|
|
@ -16,9 +16,7 @@ KeyConfiguration::KeyConfiguration(const KeyConfiguration& other)
|
||||||
|
|
||||||
void KeyConfiguration::operator=(const KeyConfiguration& other)
|
void KeyConfiguration::operator=(const KeyConfiguration& other)
|
||||||
{
|
{
|
||||||
mAcidSignKey = other.mAcidSignKey;
|
|
||||||
mPkg2SignKey = other.mPkg2SignKey;
|
mPkg2SignKey = other.mPkg2SignKey;
|
||||||
mContentArchiveHeader0SignKey = other.mContentArchiveHeader0SignKey;
|
|
||||||
mXciHeaderSignKey = other.mXciHeaderSignKey;
|
mXciHeaderSignKey = other.mXciHeaderSignKey;
|
||||||
|
|
||||||
mContentArchiveHeaderKey = other.mContentArchiveHeaderKey;
|
mContentArchiveHeaderKey = other.mContentArchiveHeaderKey;
|
||||||
|
@ -26,6 +24,9 @@ void KeyConfiguration::operator=(const KeyConfiguration& other)
|
||||||
|
|
||||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
{
|
{
|
||||||
|
mAcidSignKey[i] = other.mAcidSignKey[i];
|
||||||
|
mContentArchiveHeader0SignKey[i] = other.mContentArchiveHeader0SignKey[i];
|
||||||
|
mNrrCertificateSignKey[i] = other.mNrrCertificateSignKey[i];
|
||||||
mPkg2Key[i] = other.mPkg2Key[i];
|
mPkg2Key[i] = other.mPkg2Key[i];
|
||||||
mPkg1Key[i] = other.mPkg1Key[i];
|
mPkg1Key[i] = other.mPkg1Key[i];
|
||||||
mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i];
|
mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i];
|
||||||
|
@ -69,6 +70,7 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
||||||
|
|
||||||
#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2))
|
#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2))
|
||||||
#define _CONCAT_3_STRINGS(str1, str2, str3) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3)
|
#define _CONCAT_3_STRINGS(str1, str2, str3) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3)
|
||||||
|
#define _CONCAT_4_STRINGS(str1, str2, str3, str4) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3), str4)
|
||||||
|
|
||||||
std::string key,val;
|
std::string key,val;
|
||||||
fnd::Vec<byte_t> dec_array;
|
fnd::Vec<byte_t> dec_array;
|
||||||
|
@ -93,8 +95,8 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kSourceStr), key_area_key_source[2].key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kSourceStr), key_area_key_source[2].key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kKekGenBase[nameidx], kSourceStr), aes_kek_generation_source.key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kKekGenBase[nameidx], kSourceStr), aes_kek_generation_source.key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kKeyGenBase[nameidx], kSourceStr), aes_key_generation_source.key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kKeyGenBase[nameidx], kSourceStr), aes_key_generation_source.key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20);
|
||||||
|
|
||||||
// Store Key Variants/Derivatives
|
// Store Key Variants/Derivatives
|
||||||
for (size_t mkeyidx = 0; mkeyidx < kMasterKeyNum; mkeyidx++)
|
for (size_t mkeyidx = 0; mkeyidx < kMasterKeyNum; mkeyidx++)
|
||||||
|
@ -110,6 +112,13 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[0][mkeyidx].key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[0][mkeyidx].key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[1][mkeyidx].key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[1][mkeyidx].key, 0x10);
|
||||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[2][mkeyidx].key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[2][mkeyidx].key, 0x10);
|
||||||
|
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mContentArchiveHeader0SignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mContentArchiveHeader0SignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kAcidBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mAcidSignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kAcidBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mAcidSignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kNrrCertBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mNrrCertificateSignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kNrrCertBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mNrrCertificateSignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store nca header key
|
// store nca header key
|
||||||
|
@ -119,20 +128,23 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10);
|
||||||
|
|
||||||
// store rsa keys
|
// store rsa keys
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyPrivate), mContentArchiveHeader0SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyModulus), mContentArchiveHeader0SignKey.modulus, fnd::rsa::kRsa2048Size);
|
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyPrivate), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
// legacy header nca key name
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyModulus), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kPrivateStr), mContentArchiveHeader0SignKey[0].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kModulusStr), mContentArchiveHeader0SignKey[0].modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kPrivateStr), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.modulus, fnd::rsa::kRsa2048Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kModulusStr), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
// legacy acid header key name
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kAcidBase[nameidx], kSignKey, kPrivateStr), mAcidSignKey[0].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kAcidBase[nameidx], kSignKey, kModulusStr), mAcidSignKey[0].modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyPrivate), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kPrivateStr), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyModulus), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size);
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kModulusStr), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||||
|
|
||||||
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkiRootBase[nameidx], kSignKey, kPrivateStr), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkiRootBase[nameidx], kSignKey, kModulusStr), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _SAVE_KEYDATA
|
#undef _SAVE_KEYDATA
|
||||||
|
@ -193,9 +205,9 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
||||||
|
|
||||||
void KeyConfiguration::clearGeneralKeyConfiguration()
|
void KeyConfiguration::clearGeneralKeyConfiguration()
|
||||||
{
|
{
|
||||||
mAcidSignKey = kNullRsa2048Key;
|
|
||||||
mPkg2SignKey = kNullRsa2048Key;
|
mPkg2SignKey = kNullRsa2048Key;
|
||||||
mContentArchiveHeader0SignKey = kNullRsa2048Key;
|
|
||||||
mXciHeaderSignKey = kNullRsa2048Key;
|
mXciHeaderSignKey = kNullRsa2048Key;
|
||||||
mPkiRootKeyList.clear();
|
mPkiRootKeyList.clear();
|
||||||
|
|
||||||
|
@ -204,6 +216,9 @@ void KeyConfiguration::clearGeneralKeyConfiguration()
|
||||||
|
|
||||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
{
|
{
|
||||||
|
mAcidSignKey[i] = kNullRsa2048Key;
|
||||||
|
mContentArchiveHeader0SignKey[i] = kNullRsa2048Key;
|
||||||
|
mNrrCertificateSignKey[i] = kNullRsa2048Key;
|
||||||
mPkg1Key[i] = kNullAesKey;
|
mPkg1Key[i] = kNullAesKey;
|
||||||
mPkg2Key[i] = kNullAesKey;
|
mPkg2Key[i] = kNullAesKey;
|
||||||
mETicketCommonKey[i] = kNullAesKey;
|
mETicketCommonKey[i] = kNullAesKey;
|
||||||
|
@ -225,14 +240,26 @@ bool KeyConfiguration::getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key)
|
||||||
return copyOutKeyResourceIfExists(mContentArchiveHeaderKey, key, kNullAesXtsKey);
|
return copyOutKeyResourceIfExists(mContentArchiveHeaderKey, key, kNullAesXtsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyConfiguration::getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key) const
|
bool KeyConfiguration::getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||||
{
|
{
|
||||||
return copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey, key, kNullRsa2048Key);
|
// TODO: This needs to be changed to support multiple keys
|
||||||
|
if (key_generation >= kMasterKeyNum)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key) const
|
return copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey[key_generation], key, kNullRsa2048Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||||
{
|
{
|
||||||
return copyOutKeyResourceIfExists(mAcidSignKey, key, kNullRsa2048Key);
|
// TODO: This needs to be changed to support multiple keys
|
||||||
|
if (key_generation >= kMasterKeyNum)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return copyOutKeyResourceIfExists(mAcidSignKey[key_generation], key, kNullRsa2048Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyConfiguration::getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const
|
bool KeyConfiguration::getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const
|
||||||
|
@ -284,6 +311,17 @@ bool KeyConfiguration::getNcaExternalContentKey(const byte_t rights_id[nn::hac::
|
||||||
return res_exists;
|
return res_exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyConfiguration::getNrrCertificateSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||||
|
{
|
||||||
|
// TODO: This needs to be changed to support multiple keys
|
||||||
|
if (key_generation >= kMasterKeyNum)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return copyOutKeyResourceIfExists(mNrrCertificateSignKey[key_generation], key, kNullRsa2048Key);
|
||||||
|
}
|
||||||
|
|
||||||
bool KeyConfiguration::getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const
|
bool KeyConfiguration::getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const
|
||||||
{
|
{
|
||||||
if (masterkey_index >= kMasterKeyNum)
|
if (masterkey_index >= kMasterKeyNum)
|
||||||
|
|
|
@ -25,8 +25,8 @@ public:
|
||||||
|
|
||||||
// nca keys
|
// nca keys
|
||||||
bool getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) const;
|
bool getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) const;
|
||||||
bool getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key) const;
|
bool getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const;
|
||||||
bool getAcidSignKey(fnd::rsa::sRsa2048Key& key) const;
|
bool getAcidSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const;
|
||||||
bool getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const;
|
bool getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const;
|
||||||
bool getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const;
|
bool getNcaKeyAreaEncryptionKeyHw(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const;
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ public:
|
||||||
void addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key);
|
void addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key);
|
||||||
bool getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const;
|
bool getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const;
|
||||||
|
|
||||||
|
// nrr key
|
||||||
|
bool getNrrCertificateSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const;
|
||||||
|
|
||||||
// pkg1/pkg2
|
// pkg1/pkg2
|
||||||
bool getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
bool getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
||||||
bool getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
bool getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
||||||
|
@ -73,6 +76,7 @@ private:
|
||||||
const std::string kXciHeaderBase[kNameVariantNum] = { "xci_header", "xci_header", "xci_header" };
|
const std::string kXciHeaderBase[kNameVariantNum] = { "xci_header", "xci_header", "xci_header" };
|
||||||
const std::string kContentArchiveHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" };
|
const std::string kContentArchiveHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" };
|
||||||
const std::string kAcidBase[kNameVariantNum] = { "acid", "acid", "acid" };
|
const std::string kAcidBase[kNameVariantNum] = { "acid", "acid", "acid" };
|
||||||
|
const std::string kNrrCertBase[kNameVariantNum] = { "nrr_certificate", "nrr_certificate", "nrr_certificate" };
|
||||||
const std::string kPkiRootBase[kNameVariantNum] = { "pki_root", "pki_root", "pki_root" };
|
const std::string kPkiRootBase[kNameVariantNum] = { "pki_root", "pki_root", "pki_root" };
|
||||||
const std::string kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" };
|
const std::string kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" };
|
||||||
const std::string kNcaKeyAreaEncKeyBase[kNameVariantNum] = { "nca_key_area_key", "key_area_key", "nca_body_keak" };
|
const std::string kNcaKeyAreaEncKeyBase[kNameVariantNum] = { "nca_key_area_key", "key_area_key", "nca_body_keak" };
|
||||||
|
@ -84,8 +88,9 @@ private:
|
||||||
const std::string kKeyStr = "key";
|
const std::string kKeyStr = "key";
|
||||||
const std::string kKekStr = "kek";
|
const std::string kKekStr = "kek";
|
||||||
const std::string kSourceStr = "source";
|
const std::string kSourceStr = "source";
|
||||||
const std::string kRsaKeyModulus = "sign_key_modulus";
|
const std::string kSignKey = "sign_key";
|
||||||
const std::string kRsaKeyPrivate = "sign_key_private";
|
const std::string kModulusStr = "modulus";
|
||||||
|
const std::string kPrivateStr = "private";
|
||||||
const std::string kNcaKeyAreaKeyIndexStr[kNcaKeakNum] = { "application", "ocean", "system" };
|
const std::string kNcaKeyAreaKeyIndexStr[kNcaKeakNum] = { "application", "ocean", "system" };
|
||||||
const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"};
|
const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"};
|
||||||
|
|
||||||
|
@ -167,7 +172,7 @@ private:
|
||||||
|
|
||||||
/* general key config */
|
/* general key config */
|
||||||
// acid
|
// acid
|
||||||
fnd::rsa::sRsa2048Key mAcidSignKey;
|
fnd::rsa::sRsa2048Key mAcidSignKey[kMasterKeyNum];
|
||||||
|
|
||||||
// pkg1 and pkg2
|
// pkg1 and pkg2
|
||||||
fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum];
|
fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum];
|
||||||
|
@ -175,11 +180,14 @@ private:
|
||||||
fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum];
|
fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum];
|
||||||
|
|
||||||
// nca
|
// nca
|
||||||
fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey;
|
fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey[kMasterKeyNum];
|
||||||
fnd::aes::sAesXts128Key mContentArchiveHeaderKey;
|
fnd::aes::sAesXts128Key mContentArchiveHeaderKey;
|
||||||
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum];
|
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum];
|
||||||
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum];
|
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum];
|
||||||
|
|
||||||
|
// nrr
|
||||||
|
fnd::rsa::sRsa2048Key mNrrCertificateSignKey[kMasterKeyNum];
|
||||||
|
|
||||||
// xci
|
// xci
|
||||||
fnd::rsa::sRsa2048Key mXciHeaderSignKey;
|
fnd::rsa::sRsa2048Key mXciHeaderSignKey;
|
||||||
fnd::aes::sAes128Key mXciHeaderKey;
|
fnd::aes::sAes128Key mXciHeaderKey;
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include <fnd/Vec.h>
|
#include <fnd/Vec.h>
|
||||||
|
|
||||||
#include <nn/hac/KernelCapabilityUtil.h>
|
#include <nn/hac/KernelCapabilityUtil.h>
|
||||||
#include <nn/hac/KernelInitialProcessUtil.h>
|
|
||||||
|
|
||||||
|
|
||||||
KipProcess::KipProcess():
|
KipProcess::KipProcess():
|
||||||
mFile(),
|
mFile(),
|
||||||
|
@ -147,10 +145,10 @@ void KipProcess::displayHeader()
|
||||||
std::cout << " Meta:" << std::endl;
|
std::cout << " Meta:" << std::endl;
|
||||||
std::cout << " Name: " << mHdr.getName() << std::endl;
|
std::cout << " Name: " << mHdr.getName() << std::endl;
|
||||||
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getTitleId() << std::endl;
|
std::cout << " TitleId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getTitleId() << std::endl;
|
||||||
std::cout << " ProcessCategory: " << nn::hac::KernelInitialProcessUtil::getProcessCategoryAsString(mHdr.getProcessCategory()) << std::endl;
|
std::cout << " Version: v" << std::dec << mHdr.getVersion() << std::endl;
|
||||||
std::cout << " InstructionType: " << getInstructionTypeStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_INSTRUCTION_64BIT)) << std::endl;
|
std::cout << " Is64BitInstruction: " << std::boolalpha << mHdr.getIs64BitInstructionFlag() << std::endl;
|
||||||
std::cout << " AddrSpaceWidth: " << getAddressSpaceStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_ADDR_SPACE_64BIT)) << std::endl;
|
std::cout << " Is64BitAddressSpace: " << std::boolalpha << mHdr.getIs64BitAddressSpaceFlag() << std::endl;
|
||||||
std::cout << " MemoryPool: " << getMemoryPoolStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_USE_SYSTEM_POOL_PARTITION)) << std::endl;
|
std::cout << " UseSecureMemory: " << std::boolalpha << mHdr.getUseSecureMemoryFlag() << std::endl;
|
||||||
std::cout << " Program Sections:" << std::endl;
|
std::cout << " Program Sections:" << std::endl;
|
||||||
std::cout << " .text:" << std::endl;
|
std::cout << " .text:" << std::endl;
|
||||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT))
|
||||||
|
@ -197,25 +195,15 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
|
|
||||||
if (kern.getSystemCalls().isSet())
|
if (kern.getSystemCalls().isSet())
|
||||||
{
|
{
|
||||||
fnd::List<nn::hac::kc::SystemCall> syscalls = kern.getSystemCalls().getSystemCalls();
|
auto syscall_ids = kern.getSystemCalls().getSystemCallIds();
|
||||||
std::cout << " SystemCalls:" << std::endl;
|
std::cout << " SystemCalls:" << std::endl;
|
||||||
std::cout << " ";
|
std::vector<std::string> syscall_names;
|
||||||
size_t lineLen = 0;
|
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
|
||||||
for (size_t i = 0; i < syscalls.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (lineLen > 60)
|
if (syscall_ids.test(syscall_id))
|
||||||
{
|
syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
|
||||||
lineLen = 0;
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " ";
|
|
||||||
}
|
}
|
||||||
std::string syscall_string = nn::hac::KernelCapabilityUtil::getSystemCallAsString(syscalls[i]);
|
fnd::SimpleTextOutput::dumpStringList(syscall_names, 60, 4);
|
||||||
std::cout << syscall_string;
|
|
||||||
if (syscalls[i] != syscalls.atBack())
|
|
||||||
std::cout << ", ";
|
|
||||||
lineLen += syscall_string.length();
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
if (kern.getMemoryMaps().isSet())
|
if (kern.getMemoryMaps().isSet())
|
||||||
{
|
{
|
||||||
|
@ -225,12 +213,12 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
std::cout << " MemoryMaps:" << std::endl;
|
std::cout << " MemoryMaps:" << std::endl;
|
||||||
for (size_t i = 0; i < maps.size(); i++)
|
for (size_t i = 0; i < maps.size(); i++)
|
||||||
{
|
{
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(maps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(maps[i].type) << ")" << std::endl;
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(maps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(maps[i].type) << ")" << std::endl;
|
||||||
}
|
}
|
||||||
//std::cout << " IoMaps:" << std::endl;
|
//std::cout << " IoMaps:" << std::endl;
|
||||||
for (size_t i = 0; i < ioMaps.size(); i++)
|
for (size_t i = 0; i < ioMaps.size(); i++)
|
||||||
{
|
{
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(ioMaps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(ioMaps[i].type) << ")" << std::endl;
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(ioMaps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(ioMaps[i].type) << ")" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kern.getInterupts().isSet())
|
if (kern.getInterupts().isSet())
|
||||||
|
@ -253,7 +241,7 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
}
|
}
|
||||||
if (kern.getMiscParams().isSet())
|
if (kern.getMiscParams().isSet())
|
||||||
{
|
{
|
||||||
std::cout << " ProgramType: " << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << std::endl;
|
std::cout << " ProgramType: " << nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()) << " (" << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
if (kern.getKernelVersion().isSet())
|
if (kern.getKernelVersion().isSet())
|
||||||
{
|
{
|
||||||
|
@ -265,36 +253,14 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
}
|
}
|
||||||
if (kern.getMiscFlags().isSet())
|
if (kern.getMiscFlags().isSet())
|
||||||
{
|
{
|
||||||
fnd::List<nn::hac::kc::MiscFlags> flagList = kern.getMiscFlags().getFlagList();
|
auto misc_flags = kern.getMiscFlags().getMiscFlags();
|
||||||
|
|
||||||
std::cout << " Misc Flags:" << std::endl;
|
std::cout << " Misc Flags:" << std::endl;
|
||||||
for (uint32_t i = 0; i < flagList.size(); i++)
|
std::vector<std::string> misc_flags_names;
|
||||||
|
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
|
||||||
{
|
{
|
||||||
if (i % 10 == 0)
|
if (misc_flags.test(misc_flags_bit))
|
||||||
{
|
misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||||
if (i != 0)
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " ";
|
|
||||||
}
|
}
|
||||||
std::cout << nn::hac::KernelCapabilityUtil::getMiscFlagAsString(flagList[i]);
|
fnd::SimpleTextOutput::dumpStringList(misc_flags_names, 60, 4);
|
||||||
if (flagList[i] != flagList.atBack())
|
|
||||||
std::cout << ", ";
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const char* KipProcess::getInstructionTypeStr(bool is64Bit) const
|
|
||||||
{
|
|
||||||
return is64Bit? "64Bit" : "32Bit";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* KipProcess::getAddressSpaceStr(bool is64Bit) const
|
|
||||||
{
|
|
||||||
return is64Bit? "64Bit" : "32Bit";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* KipProcess::getMemoryPoolStr(bool isSystemPool) const
|
|
||||||
{
|
|
||||||
return isSystemPool? "System" : "Application";
|
|
||||||
}
|
|
|
@ -32,8 +32,4 @@ private:
|
||||||
void importCodeSegments();
|
void importCodeSegments();
|
||||||
void displayHeader();
|
void displayHeader();
|
||||||
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
void displayKernelCap(const nn::hac::KernelCapabilityControl& kern);
|
||||||
|
|
||||||
const char* getInstructionTypeStr(bool is64Bit) const;
|
|
||||||
const char* getAddressSpaceStr(bool is64Bit) const;
|
|
||||||
const char* getMemoryPoolStr(bool isSystemPool) const;
|
|
||||||
};
|
};
|
|
@ -8,6 +8,8 @@
|
||||||
#include <nn/hac/KernelCapabilityUtil.h>
|
#include <nn/hac/KernelCapabilityUtil.h>
|
||||||
#include <nn/hac/MetaUtil.h>
|
#include <nn/hac/MetaUtil.h>
|
||||||
|
|
||||||
|
#include <fnd/SimpleTextOutput.h>
|
||||||
|
|
||||||
MetaProcess::MetaProcess() :
|
MetaProcess::MetaProcess() :
|
||||||
mFile(),
|
mFile(),
|
||||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
|
@ -21,8 +23,8 @@ void MetaProcess::process()
|
||||||
|
|
||||||
if (mVerify)
|
if (mVerify)
|
||||||
{
|
{
|
||||||
validateAcidSignature(mMeta.getAcid());
|
validateAcidSignature(mMeta.getAccessControlInfoDesc(), mMeta.getAccessControlInfoDescKeyGeneration());
|
||||||
validateAciFromAcid(mMeta.getAci(), mMeta.getAcid());
|
validateAciFromAcid(mMeta.getAccessControlInfo(), mMeta.getAccessControlInfoDesc());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
@ -31,18 +33,18 @@ void MetaProcess::process()
|
||||||
displayMetaHeader(mMeta);
|
displayMetaHeader(mMeta);
|
||||||
|
|
||||||
// aci binary
|
// aci binary
|
||||||
displayAciHdr(mMeta.getAci());
|
displayAciHdr(mMeta.getAccessControlInfo());
|
||||||
displayFac(mMeta.getAci().getFileSystemAccessControl());
|
displayFac(mMeta.getAccessControlInfo().getFileSystemAccessControl());
|
||||||
displaySac(mMeta.getAci().getServiceAccessControl());
|
displaySac(mMeta.getAccessControlInfo().getServiceAccessControl());
|
||||||
displayKernelCap(mMeta.getAci().getKernelCapabilities());
|
displayKernelCap(mMeta.getAccessControlInfo().getKernelCapabilities());
|
||||||
|
|
||||||
// acid binary
|
// acid binary
|
||||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
{
|
{
|
||||||
displayAciDescHdr(mMeta.getAcid());
|
displayAciDescHdr(mMeta.getAccessControlInfoDesc());
|
||||||
displayFac(mMeta.getAcid().getFileSystemAccessControl());
|
displayFac(mMeta.getAccessControlInfoDesc().getFileSystemAccessControl());
|
||||||
displaySac(mMeta.getAcid().getServiceAccessControl());
|
displaySac(mMeta.getAccessControlInfoDesc().getServiceAccessControl());
|
||||||
displayKernelCap(mMeta.getAcid().getKernelCapabilities());
|
displayKernelCap(mMeta.getAccessControlInfoDesc().getKernelCapabilities());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,11 +89,11 @@ void MetaProcess::importMeta()
|
||||||
mMeta.fromBytes(scratch.data(), scratch.size());
|
mMeta.fromBytes(scratch.data(), scratch.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid)
|
void MetaProcess::validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
fnd::rsa::sRsa2048Key acid_sign_key;
|
fnd::rsa::sRsa2048Key acid_sign_key;
|
||||||
if (mKeyCfg.getAcidSignKey(acid_sign_key) != true)
|
if (mKeyCfg.getAcidSignKey(acid_sign_key, key_generation) != true)
|
||||||
throw fnd::Exception();
|
throw fnd::Exception();
|
||||||
|
|
||||||
acid.validateSignature(acid_sign_key);
|
acid.validateSignature(acid_sign_key);
|
||||||
|
@ -114,19 +116,13 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl;
|
std::cout << "[WARNING] ACI ProgramId: FAIL (Outside Legal Range)" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < aci.getFileSystemAccessControl().getFsaRightsList().size(); i++)
|
auto fs_access = aci.getFileSystemAccessControl().getFsAccess();
|
||||||
|
auto desc_fs_access = acid.getFileSystemAccessControl().getFsAccess();
|
||||||
|
for (size_t i = 0; i < fs_access.size(); i++)
|
||||||
{
|
{
|
||||||
bool fsaRightFound = false;
|
if (fs_access.test(i) && desc_fs_access.test(i) == false)
|
||||||
for (size_t j = 0; j < acid.getFileSystemAccessControl().getFsaRightsList().size() && fsaRightFound == false; j++)
|
|
||||||
{
|
{
|
||||||
if (aci.getFileSystemAccessControl().getFsaRightsList()[i] == acid.getFileSystemAccessControl().getFsaRightsList()[j])
|
std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(i)) << " not permitted)" << std::endl;
|
||||||
fsaRightFound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsaRightFound == false)
|
|
||||||
{
|
|
||||||
|
|
||||||
std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << nn::hac::FileSystemAccessUtil::getFsaRightAsString(aci.getFileSystemAccessControl().getFsaRightsList()[i]) << " not permitted)" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,18 +193,13 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
std::cout << "[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinPriority() << " not permitted)" << std::endl;
|
std::cout << "[WARNING] ACI/KC ThreadInfo/MinPriority: FAIL (" << std::dec << (uint32_t)aci.getKernelCapabilities().getThreadInfo().getMinPriority() << " not permitted)" << std::endl;
|
||||||
}
|
}
|
||||||
// check system calls
|
// check system calls
|
||||||
for (size_t i = 0; i < aci.getKernelCapabilities().getSystemCalls().getSystemCalls().size(); i++)
|
auto syscall_ids = aci.getKernelCapabilities().getSystemCalls().getSystemCallIds();
|
||||||
|
auto desc_syscall_ids = acid.getKernelCapabilities().getSystemCalls().getSystemCallIds();
|
||||||
|
for (size_t i = 0; i < syscall_ids.size(); i++)
|
||||||
{
|
{
|
||||||
bool rightFound = false;
|
if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false)
|
||||||
for (size_t j = 0; j < acid.getKernelCapabilities().getSystemCalls().getSystemCalls().size() && rightFound == false; j++)
|
|
||||||
{
|
{
|
||||||
if (aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i] == acid.getKernelCapabilities().getSystemCalls().getSystemCalls()[j])
|
std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)) << " not permitted)" << std::endl;
|
||||||
rightFound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rightFound == false)
|
|
||||||
{
|
|
||||||
std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << nn::hac::KernelCapabilityUtil::getSystemCallAsString(aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i]) << " not permitted)" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check memory maps
|
// check memory maps
|
||||||
|
@ -223,9 +214,9 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
|
|
||||||
if (rightFound == false)
|
if (rightFound == false)
|
||||||
{
|
{
|
||||||
const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i];
|
auto map = aci.getKernelCapabilities().getMemoryMaps().getMemoryMaps()[i];
|
||||||
|
|
||||||
std::cout << "[WARNING] ACI/KC MemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(map.type) << ") not permitted)" << std::endl;
|
std::cout << "[WARNING] ACI/KC MemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type) << ") not permitted)" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++)
|
for (size_t i = 0; i < aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps().size(); i++)
|
||||||
|
@ -239,9 +230,9 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
|
|
||||||
if (rightFound == false)
|
if (rightFound == false)
|
||||||
{
|
{
|
||||||
const nn::hac::MemoryMappingHandler::sMemoryMapping& map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i];
|
auto map = aci.getKernelCapabilities().getMemoryMaps().getIoMemoryMaps()[i];
|
||||||
|
|
||||||
std::cout << "[WARNING] ACI/KC IoMemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(map.type) << ") not permitted)" << std::endl;
|
std::cout << "[WARNING] ACI/KC IoMemoryMap: FAIL (0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)map.addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(map.addr + map.size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(map.perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(map.type) << ") not permitted)" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check interupts
|
// check interupts
|
||||||
|
@ -277,18 +268,13 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
std::cout << "[WARNING] ACI/KC HandleTableSize: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() << " too large)" << std::endl;
|
std::cout << "[WARNING] ACI/KC HandleTableSize: FAIL (0x" << std::hex << (uint32_t)aci.getKernelCapabilities().getHandleTableSize().getHandleTableSize() << " too large)" << std::endl;
|
||||||
}
|
}
|
||||||
// check misc flags
|
// check misc flags
|
||||||
for (size_t i = 0; i < aci.getKernelCapabilities().getMiscFlags().getFlagList().size(); i++)
|
auto misc_flags = aci.getKernelCapabilities().getMiscFlags().getMiscFlags();
|
||||||
|
auto desc_misc_flags = acid.getKernelCapabilities().getMiscFlags().getMiscFlags();
|
||||||
|
for (size_t i = 0; i < misc_flags.size(); i++)
|
||||||
{
|
{
|
||||||
bool rightFound = false;
|
if (misc_flags.test(i) && desc_misc_flags.test(i) == false)
|
||||||
for (size_t j = 0; j < acid.getKernelCapabilities().getMiscFlags().getFlagList().size() && rightFound == false; j++)
|
|
||||||
{
|
{
|
||||||
if (aci.getKernelCapabilities().getMiscFlags().getFlagList()[i] == acid.getKernelCapabilities().getMiscFlags().getFlagList()[j])
|
std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)) << " not permitted)" << std::endl;
|
||||||
rightFound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rightFound == false)
|
|
||||||
{
|
|
||||||
std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << nn::hac::KernelCapabilityUtil::getMiscFlagAsString(aci.getKernelCapabilities().getMiscFlags().getFlagList()[i]) << " not permitted)" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,10 +282,12 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con
|
||||||
void MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
|
void MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr)
|
||||||
{
|
{
|
||||||
std::cout << "[Meta Header]" << std::endl;
|
std::cout << "[Meta Header]" << std::endl;
|
||||||
std::cout << " ACID KeyGeneration: " << std::dec << hdr.getAcidKeyGeneration() << std::endl;
|
std::cout << " ACID KeyGeneration: " << std::dec << (uint32_t)hdr.getAccessControlInfoDescKeyGeneration() << std::endl;
|
||||||
std::cout << " Process Architecture Params:" << std::endl;
|
std::cout << " Flags:" << std::endl;
|
||||||
std::cout << " Ins. Type: " << nn::hac::MetaUtil::getInstructionTypeAsString(hdr.getInstructionType()) << std::endl;
|
std::cout << " Is64BitInstruction: " << std::boolalpha << hdr.getIs64BitInstructionFlag() << std::endl;
|
||||||
std::cout << " Addr Space: " << nn::hac::MetaUtil::getProcAddressSpaceTypeAsString(hdr.getProcAddressSpaceType()) << std::endl;
|
std::cout << " ProcessAddressSpace: " << nn::hac::MetaUtil::getProcessAddressSpaceAsString(hdr.getProcessAddressSpace()) << std::endl;
|
||||||
|
std::cout << " OptimizeMemoryAllocation: " << std::boolalpha << hdr.getOptimizeMemoryAllocationFlag() << std::endl;
|
||||||
|
std::cout << " SystemResourceSize: 0x" << std::hex << hdr.getSystemResourceSize() << std::endl;
|
||||||
std::cout << " Main Thread Params:" << std::endl;
|
std::cout << " Main Thread Params:" << std::endl;
|
||||||
std::cout << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl;
|
std::cout << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl;
|
||||||
std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl;
|
std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl;
|
||||||
|
@ -322,14 +310,9 @@ void MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci)
|
||||||
void MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid)
|
void MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid)
|
||||||
{
|
{
|
||||||
std::cout << "[Access Control Info Desc]" << std::endl;
|
std::cout << "[Access Control Info Desc]" << std::endl;
|
||||||
if (acid.getFlagList().size() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " Flags: " << std::endl;
|
std::cout << " Flags: " << std::endl;
|
||||||
for (size_t i = 0; i < acid.getFlagList().size(); i++)
|
std::cout << " Production: " << std::boolalpha << acid.getProductionFlag() << std::endl;
|
||||||
{
|
std::cout << " Unqualified Approval: " << std::boolalpha << acid.getUnqualifiedApprovalFlag() << std::endl;
|
||||||
std::cout << " " << nn::hac::AccessControlInfoUtil::getAcidFlagAsString(acid.getFlagList()[i]) << " (" << std::dec << (uint32_t)acid.getFlagList()[i] << ")" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << " Memory Region: " << nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()) << " (" << std::dec << (uint32_t)acid.getMemoryRegion() << ")" << std::endl;
|
std::cout << " Memory Region: " << nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()) << " (" << std::dec << (uint32_t)acid.getMemoryRegion() << ")" << std::endl;
|
||||||
std::cout << " ProgramID Restriction" << std::endl;
|
std::cout << " ProgramID Restriction" << std::endl;
|
||||||
std::cout << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl;
|
std::cout << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl;
|
||||||
|
@ -341,23 +324,38 @@ void MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac)
|
||||||
std::cout << "[FS Access Control]" << std::endl;
|
std::cout << "[FS Access Control]" << std::endl;
|
||||||
std::cout << " Format Version: " << std::dec << (uint32_t)fac.getFormatVersion() << std::endl;
|
std::cout << " Format Version: " << std::dec << (uint32_t)fac.getFormatVersion() << std::endl;
|
||||||
|
|
||||||
if (fac.getFsaRightsList().size())
|
auto fs_access = fac.getFsAccess();
|
||||||
|
if (fs_access.any())
|
||||||
{
|
{
|
||||||
std::cout << " FS Rights:" << std::endl;
|
std::cout << " FsAccess:" << std::endl;
|
||||||
for (size_t i = 0; i < fac.getFsaRightsList().size(); i++)
|
// TODO this formatting loop could be a utils function
|
||||||
|
for (size_t flag = 0, printed = 0; flag < fs_access.size(); flag++)
|
||||||
{
|
{
|
||||||
if (i % 10 == 0)
|
// skip unset flags
|
||||||
|
if (fs_access.test(flag) == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// format the strings
|
||||||
|
// for each 10 printed we do a new line
|
||||||
|
if (printed % 10 == 0)
|
||||||
{
|
{
|
||||||
if (i != 0)
|
// skip new line when we haven't printed anything
|
||||||
|
if (printed != 0)
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << " ";
|
std::cout << " ";
|
||||||
}
|
}
|
||||||
std::cout << nn::hac::FileSystemAccessUtil::getFsaRightAsString(fac.getFsaRightsList()[i]);
|
// within a line we want to separate the next string from the last one with a comma and a space
|
||||||
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
else
|
||||||
std::cout << " (bit " << std::dec << (uint32_t)fac.getFsaRightsList()[i] << ")";
|
{
|
||||||
if (fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack())
|
|
||||||
std::cout << ", ";
|
std::cout << ", ";
|
||||||
}
|
}
|
||||||
|
printed++;
|
||||||
|
|
||||||
|
// output string info
|
||||||
|
std::cout << nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(flag));
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
std::cout << " (bit " << std::dec << (uint32_t)flag << ")";
|
||||||
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,21 +383,12 @@ void MetaProcess::displaySac(const nn::hac::ServiceAccessControl& sac)
|
||||||
{
|
{
|
||||||
std::cout << "[Service Access Control]" << std::endl;
|
std::cout << "[Service Access Control]" << std::endl;
|
||||||
std::cout << " Service List:" << std::endl;
|
std::cout << " Service List:" << std::endl;
|
||||||
|
std::vector<std::string> service_name_list;
|
||||||
for (size_t i = 0; i < sac.getServiceList().size(); i++)
|
for (size_t i = 0; i < sac.getServiceList().size(); i++)
|
||||||
{
|
{
|
||||||
if (i % 10 == 0)
|
service_name_list.push_back(sac.getServiceList()[i].getName() + (sac.getServiceList()[i].isServer() ? "(isSrv)" : ""));
|
||||||
{
|
|
||||||
if (i != 0)
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " ";
|
|
||||||
}
|
}
|
||||||
std::cout << sac.getServiceList()[i].getName();
|
fnd::SimpleTextOutput::dumpStringList(service_name_list, 60, 4);
|
||||||
if (sac.getServiceList()[i].isServer())
|
|
||||||
std::cout << "(isSrv)";
|
|
||||||
if (sac.getServiceList()[i] != sac.getServiceList().atBack())
|
|
||||||
std::cout << ", ";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
|
@ -418,40 +407,30 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
|
|
||||||
if (kern.getSystemCalls().isSet())
|
if (kern.getSystemCalls().isSet())
|
||||||
{
|
{
|
||||||
fnd::List<nn::hac::kc::SystemCall> syscalls = kern.getSystemCalls().getSystemCalls();
|
auto syscall_ids = kern.getSystemCalls().getSystemCallIds();
|
||||||
std::cout << " SystemCalls:" << std::endl;
|
std::cout << " SystemCalls:" << std::endl;
|
||||||
std::cout << " ";
|
std::vector<std::string> syscall_names;
|
||||||
size_t lineLen = 0;
|
for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++)
|
||||||
for (size_t i = 0; i < syscalls.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (lineLen > 60)
|
if (syscall_ids.test(syscall_id))
|
||||||
{
|
syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id)));
|
||||||
lineLen = 0;
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " ";
|
|
||||||
}
|
}
|
||||||
std::string syscall_name = nn::hac::KernelCapabilityUtil::getSystemCallAsString(syscalls[i]);
|
fnd::SimpleTextOutput::dumpStringList(syscall_names, 60, 4);
|
||||||
std::cout << syscall_name;
|
|
||||||
if (syscalls[i] != syscalls.atBack())
|
|
||||||
std::cout << ", ";
|
|
||||||
lineLen += syscall_name.length();
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
if (kern.getMemoryMaps().isSet())
|
if (kern.getMemoryMaps().isSet())
|
||||||
{
|
{
|
||||||
fnd::List<nn::hac::MemoryMappingHandler::sMemoryMapping> maps = kern.getMemoryMaps().getMemoryMaps();
|
auto maps = kern.getMemoryMaps().getMemoryMaps();
|
||||||
fnd::List<nn::hac::MemoryMappingHandler::sMemoryMapping> ioMaps = kern.getMemoryMaps().getIoMemoryMaps();
|
auto ioMaps = kern.getMemoryMaps().getIoMemoryMaps();
|
||||||
|
|
||||||
std::cout << " MemoryMaps:" << std::endl;
|
std::cout << " MemoryMaps:" << std::endl;
|
||||||
for (size_t i = 0; i < maps.size(); i++)
|
for (size_t i = 0; i < maps.size(); i++)
|
||||||
{
|
{
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(maps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(maps[i].type) << ")" << std::endl;
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)maps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(maps[i].addr + maps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(maps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(maps[i].type) << ")" << std::endl;
|
||||||
}
|
}
|
||||||
//std::cout << " IoMaps:" << std::endl;
|
//std::cout << " IoMaps:" << std::endl;
|
||||||
for (size_t i = 0; i < ioMaps.size(); i++)
|
for (size_t i = 0; i < ioMaps.size(); i++)
|
||||||
{
|
{
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemMapPermAsString(ioMaps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMemMapTypeAsString(ioMaps[i].type) << ")" << std::endl;
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << ((uint64_t)ioMaps[i].addr << 12) << " - 0x" << std::hex << std::setw(16) << std::setfill('0') << (((uint64_t)(ioMaps[i].addr + ioMaps[i].size) << 12) - 1) << " (perm=" << nn::hac::KernelCapabilityUtil::getMemoryPermissionAsString(ioMaps[i].perm) << ") (type=" << nn::hac::KernelCapabilityUtil::getMappingTypeAsString(ioMaps[i].type) << ")" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kern.getInterupts().isSet())
|
if (kern.getInterupts().isSet())
|
||||||
|
@ -474,7 +453,7 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
}
|
}
|
||||||
if (kern.getMiscParams().isSet())
|
if (kern.getMiscParams().isSet())
|
||||||
{
|
{
|
||||||
std::cout << " ProgramType: " << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << std::endl;
|
std::cout << " ProgramType: " << nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()) << " (" << std::dec << (uint32_t)kern.getMiscParams().getProgramType() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
if (kern.getKernelVersion().isSet())
|
if (kern.getKernelVersion().isSet())
|
||||||
{
|
{
|
||||||
|
@ -486,21 +465,14 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern)
|
||||||
}
|
}
|
||||||
if (kern.getMiscFlags().isSet())
|
if (kern.getMiscFlags().isSet())
|
||||||
{
|
{
|
||||||
fnd::List<nn::hac::kc::MiscFlags> flagList = kern.getMiscFlags().getFlagList();
|
auto misc_flags = kern.getMiscFlags().getMiscFlags();
|
||||||
|
|
||||||
std::cout << " Misc Flags:" << std::endl;
|
std::cout << " Misc Flags:" << std::endl;
|
||||||
for (uint32_t i = 0; i < flagList.size(); i++)
|
std::vector<std::string> misc_flags_names;
|
||||||
|
for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++)
|
||||||
{
|
{
|
||||||
if (i % 10 == 0)
|
if (misc_flags.test(misc_flags_bit))
|
||||||
{
|
misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit)));
|
||||||
if (i != 0)
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << " ";
|
|
||||||
}
|
|
||||||
std::cout << nn::hac::KernelCapabilityUtil::getMiscFlagAsString(flagList[i]);
|
|
||||||
if (flagList[i] != flagList.atBack())
|
|
||||||
std::cout << ", ";
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
|
fnd::SimpleTextOutput::dumpStringList(misc_flags_names, 60, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ private:
|
||||||
|
|
||||||
void importMeta();
|
void importMeta();
|
||||||
|
|
||||||
void validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid);
|
void validateAcidSignature(const nn::hac::AccessControlInfoDesc& acid, byte_t key_generation);
|
||||||
void validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid);
|
void validateAciFromAcid(const nn::hac::AccessControlInfo& aci, const nn::hac::AccessControlInfoDesc& acid);
|
||||||
|
|
||||||
void displayMetaHeader(const nn::hac::Meta& hdr);
|
void displayMetaHeader(const nn::hac::Meta& hdr);
|
||||||
|
|
|
@ -62,118 +62,431 @@ void NacpProcess::importNacp()
|
||||||
void NacpProcess::displayNacp()
|
void NacpProcess::displayNacp()
|
||||||
{
|
{
|
||||||
std::cout << "[ApplicationControlProperty]" << std::endl;
|
std::cout << "[ApplicationControlProperty]" << std::endl;
|
||||||
std::cout << " Menu Description:" << std::endl;
|
|
||||||
std::cout << " DisplayVersion: " << mNacp.getDisplayVersion() << std::endl;
|
// Title
|
||||||
if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
if (mNacp.getTitle().size() > 0)
|
||||||
std::cout << " ISBN: " << mNacp.getIsbn() << std::endl;
|
|
||||||
for (size_t i = 0; i < mNacp.getTitle().size(); i++)
|
|
||||||
{
|
{
|
||||||
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(mNacp.getTitle()[i].language) << " Title:" << std::endl;
|
std::cout << " Title:" << std::endl;
|
||||||
std::cout << " Name: " << mNacp.getTitle()[i].name << std::endl;
|
for (auto itr = mNacp.getTitle().begin(); itr != mNacp.getTitle().end(); itr++)
|
||||||
std::cout << " Publisher: " << mNacp.getTitle()[i].publisher << std::endl;
|
|
||||||
}
|
|
||||||
std::cout << " Logo:" << std::endl;
|
|
||||||
std::cout << " Type: " << nn::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType()) << std::endl;
|
|
||||||
std::cout << " Handling: " << nn::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling()) << std::endl;
|
|
||||||
std::cout << " AddOnContent:" << std::endl;
|
|
||||||
std::cout << " BaseId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getAocBaseId() << std::endl;
|
|
||||||
std::cout << " RegistrationType: " << nn::hac::ApplicationControlPropertyUtil::getAocRegistrationTypeAsString(mNacp.getAocRegistrationType()) << std::endl;
|
|
||||||
std::cout << " RuntimeInstallMode: " << nn::hac::ApplicationControlPropertyUtil::getRuntimeAocInstallModeAsString(mNacp.getRuntimeAocInstallMode()) << std::endl;
|
|
||||||
std::cout << " Play Log:" << std::endl;
|
|
||||||
std::cout << " PlayLogPolicy: " << nn::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy()) << std::endl;
|
|
||||||
std::cout << " PlayLogQueryCapability: " << nn::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability()) << std::endl;
|
|
||||||
if (mNacp.getPlayLogQueryableApplicationId().size() > 0)
|
|
||||||
{
|
{
|
||||||
std::cout << " PlayLogQueryableApplicationId:" << std::endl;
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language) << ":" << std::endl;
|
||||||
for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().size(); i++)
|
std::cout << " Name: " << itr->name << std::endl;
|
||||||
{
|
std::cout << " Publisher: " << itr->publisher << std::endl;
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPlayLogQueryableApplicationId()[i] << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << " Parental Controls:" << std::endl;
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
std::cout << " ParentalControlFlag: " << nn::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(mNacp.getParentalControlFlag()) << std::endl;
|
|
||||||
for (size_t i = 0; i < mNacp.getRatingAge().size(); i++)
|
|
||||||
{
|
{
|
||||||
std::cout << " Age Restriction:" << std::endl;
|
std::cout << " Title: None" << std::endl;
|
||||||
std::cout << " Agency: " << nn::hac::ApplicationControlPropertyUtil::getOrganisationAsString(mNacp.getRatingAge()[i].organisation) << std::endl;
|
|
||||||
std::cout << " Age: " << std::dec << (uint32_t)mNacp.getRatingAge()[i].age << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNacp.getBcatPassphase().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
// Isbn
|
||||||
|
if (mNacp.getIsbn().empty() == false)
|
||||||
{
|
{
|
||||||
std::cout << " BCAT:" << std::endl;
|
std::cout << " ISBN: " << mNacp.getIsbn() << std::endl;
|
||||||
std::cout << " BcatPassphase: " << mNacp.getBcatPassphase() << std::endl;
|
|
||||||
std::cout << " DeliveryCacheStorageSize: 0x" << std::hex << mNacp.getBcatDeliveryCacheStorageSize() << std::endl;
|
|
||||||
}
|
}
|
||||||
if (mNacp.getLocalCommunicationId().size() > 0)
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
{
|
{
|
||||||
std::cout << " Local Area Communication:" << std::endl;
|
std::cout << " ISBN: (NotSet)" << std::endl;
|
||||||
std::cout << " LocalCommunicationId:" << std::endl;
|
}
|
||||||
for (size_t i = 0; i < mNacp.getLocalCommunicationId().size(); i++)
|
|
||||||
|
// StartupUserAccount
|
||||||
|
if (mNacp.getStartupUserAccount() != nn::hac::nacp::StartupUserAccount::None || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
{
|
{
|
||||||
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getLocalCommunicationId()[i] << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << " SaveData:" << std::endl;
|
|
||||||
std::cout << " SaveDatawOwnerId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSaveDatawOwnerId() << std::endl;
|
|
||||||
if (mNacp.getUserAccountSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " UserAccountSaveData:" << std::endl;
|
|
||||||
std::cout << " Size: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size) << std::endl;
|
|
||||||
std::cout << " JournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size) << std::endl;
|
|
||||||
}
|
|
||||||
if (mNacp.getDeviceSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " DeviceSaveData:" << std::endl;
|
|
||||||
std::cout << " Size: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size) << std::endl;
|
|
||||||
std::cout << " JournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size) << std::endl;
|
|
||||||
}
|
|
||||||
if (mNacp.getUserAccountSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " UserAccountSaveDataMax:" << std::endl;
|
|
||||||
std::cout << " Size: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size) << std::endl;
|
|
||||||
std::cout << " JournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size) << std::endl;
|
|
||||||
}
|
|
||||||
if (mNacp.getDeviceSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " DeviceSaveDataMax:" << std::endl;
|
|
||||||
std::cout << " Size: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size) << std::endl;
|
|
||||||
std::cout << " JournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size) << std::endl;
|
|
||||||
}
|
|
||||||
if (mNacp.getTemporaryStorageSize() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " TemporaryStorageSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()) << std::endl;
|
|
||||||
}
|
|
||||||
if (mNacp.getCacheStorageSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
{
|
|
||||||
std::cout << " CacheStorage:" << std::endl;
|
|
||||||
std::cout << " Size: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size) << std::endl;
|
|
||||||
std::cout << " JournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size) << std::endl;
|
|
||||||
std::cout << " MaxDataAndJournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax()) << std::endl;
|
|
||||||
std::cout << " StorageIndexMax: 0x" << std::hex << mNacp.getCacheStorageIndexMax() << std::endl;
|
|
||||||
}
|
|
||||||
std::cout << " Other Flags:" << std::endl;
|
|
||||||
std::cout << " StartupUserAccount: " << nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()) << std::endl;
|
std::cout << " StartupUserAccount: " << nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()) << std::endl;
|
||||||
std::cout << " UserAccountSwitchLock: " << nn::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockValueAsString(mNacp.getUserAccountSwitchLockValue()) << std::endl;
|
}
|
||||||
std::cout << " AttributeFlag: " << nn::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(mNacp.getAttributeFlag()) << std::endl;
|
|
||||||
std::cout << " CrashReportMode: " << nn::hac::ApplicationControlPropertyUtil::getCrashReportModeAsString(mNacp.getCrashReportMode()) << std::endl;
|
// UserAccountSwitchLock
|
||||||
std::cout << " HDCP: " << nn::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()) << std::endl;
|
if (mNacp.getUserAccountSwitchLock() != nn::hac::nacp::UserAccountSwitchLock::Disable || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
std::cout << " ScreenshotMode: " << nn::hac::ApplicationControlPropertyUtil::getScreenshotModeAsString(mNacp.getScreenshotMode()) << std::endl;
|
{
|
||||||
std::cout << " VideoCaptureMode: " << nn::hac::ApplicationControlPropertyUtil::getVideoCaptureModeAsString(mNacp.getVideoCaptureMode()) << std::endl;
|
std::cout << " UserAccountSwitchLock: " << nn::hac::ApplicationControlPropertyUtil::getUserAccountSwitchLockAsString(mNacp.getUserAccountSwitchLock()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddOnContentRegistrationType
|
||||||
|
if (mNacp.getAddOnContentRegistrationType() != nn::hac::nacp::AddOnContentRegistrationType::AllOnLaunch || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " AddOnContentRegistrationType: " << nn::hac::ApplicationControlPropertyUtil::getAddOnContentRegistrationTypeAsString(mNacp.getAddOnContentRegistrationType()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attribute
|
||||||
|
if (mNacp.getAttribute().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " Attribute:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getAttribute().begin(); itr != mNacp.getAttribute().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " Attribute: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportedLanguage
|
||||||
|
if (mNacp.getSupportedLanguage().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " SupportedLanguage:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getSupportedLanguage().begin(); itr != mNacp.getSupportedLanguage().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " SupportedLanguage: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentalControl
|
||||||
|
if (mNacp.getParentalControl().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " ParentalControl:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getParentalControl().begin(); itr != mNacp.getParentalControl().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " ParentalControl: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Screenshot
|
||||||
|
if (mNacp.getScreenshot() != nn::hac::nacp::Screenshot::Allow || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " Screenshot: " << nn::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VideoCapture
|
||||||
|
if (mNacp.getVideoCapture() != nn::hac::nacp::VideoCapture::Disable || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " VideoCapture: " << nn::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataLossConfirmation
|
||||||
|
if (mNacp.getDataLossConfirmation() != nn::hac::nacp::DataLossConfirmation::None || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
std::cout << " DataLossConfirmation: " << nn::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()) << std::endl;
|
std::cout << " DataLossConfirmation: " << nn::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()) << std::endl;
|
||||||
std::cout << " RepairFlag: " << nn::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(mNacp.getRepairFlag()) << std::endl;
|
}
|
||||||
std::cout << " ProgramIndex: 0x" << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)mNacp.getProgramIndex() << std::endl;
|
|
||||||
std::cout << " Req NetworkLicenseOnLaunch: " << nn::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchValueAsString(mNacp.getRequiredNetworkServiceLicenseOnLaunchValue()) << std::endl;
|
// PlayLogPolicy
|
||||||
if (mNacp.getApplicationErrorCodeCategory().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
if (mNacp.getPlayLogPolicy() != nn::hac::nacp::PlayLogPolicy::All || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " PlayLogPolicy: " << nn::hac::ApplicationControlPropertyUtil::getPlayLogPolicyAsString(mNacp.getPlayLogPolicy()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PresenceGroupId
|
||||||
|
if (mNacp.getPresenceGroupId() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " PresenceGroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPresenceGroupId() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RatingAge
|
||||||
|
if (mNacp.getRatingAge().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " RatingAge:" << std::endl;
|
||||||
|
|
||||||
|
for (auto itr = mNacp.getRatingAge().begin(); itr != mNacp.getRatingAge().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getOrganisationAsString(itr->organisation) << ":" << std::endl;
|
||||||
|
std::cout << " Age: " << std::dec << (uint32_t)itr->age << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " RatingAge: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisplayVersion
|
||||||
|
if (mNacp.getDisplayVersion().empty() == false)
|
||||||
|
{
|
||||||
|
std::cout << " DisplayVersion: " << mNacp.getDisplayVersion() << std::endl;
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " DisplayVersion: (NotSet)" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddOnContentBaseId
|
||||||
|
if (mNacp.getAddOnContentBaseId() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " AddOnContentBaseId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getAddOnContentBaseId() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveDataOwnerId
|
||||||
|
if (mNacp.getSaveDataOwnerId() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " SaveDataOwnerId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSaveDataOwnerId() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAccountSaveDataSize
|
||||||
|
if (mNacp.getUserAccountSaveDataSize().size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " UserAccountSaveDataSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAccountSaveDataJournalSize
|
||||||
|
if (mNacp.getUserAccountSaveDataSize().journal_size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " UserAccountSaveDataJournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataSize().journal_size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceSaveDataSize
|
||||||
|
if (mNacp.getDeviceSaveDataSize().size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " DeviceSaveDataSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceSaveDataJournalSize
|
||||||
|
if (mNacp.getDeviceSaveDataSize().journal_size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " DeviceSaveDataJournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataSize().journal_size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BcatDeliveryCacheStorageSize
|
||||||
|
if (mNacp.getBcatDeliveryCacheStorageSize() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " BcatDeliveryCacheStorageSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getBcatDeliveryCacheStorageSize()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplicationErrorCodeCategory
|
||||||
|
if (mNacp.getApplicationErrorCodeCategory().empty() == false)
|
||||||
{
|
{
|
||||||
std::cout << " ApplicationErrorCodeCategory: " << mNacp.getApplicationErrorCodeCategory() << std::endl;
|
std::cout << " ApplicationErrorCodeCategory: " << mNacp.getApplicationErrorCodeCategory() << std::endl;
|
||||||
}
|
}
|
||||||
if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " ApplicationErrorCodeCategory: (NotSet)" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalCommunicationId
|
||||||
|
if (mNacp.getLocalCommunicationId().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " LocalCommunicationId:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getLocalCommunicationId().begin(); itr != mNacp.getLocalCommunicationId().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << *itr << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " LocalCommunicationId: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogoType
|
||||||
|
//if (mNacp.getLogoType() != nn::hac::nacp::LogoType::Nintendo || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
//{
|
||||||
|
std::cout << " LogoType: " << nn::hac::ApplicationControlPropertyUtil::getLogoTypeAsString(mNacp.getLogoType()) << std::endl;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// LogoHandling
|
||||||
|
if (mNacp.getLogoHandling() != nn::hac::nacp::LogoHandling::Auto || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " LogoHandling: " << nn::hac::ApplicationControlPropertyUtil::getLogoHandlingAsString(mNacp.getLogoHandling()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuntimeAddOnContentInstall
|
||||||
|
if (mNacp.getRuntimeAddOnContentInstall() != nn::hac::nacp::RuntimeAddOnContentInstall::Deny || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " RuntimeAddOnContentInstall: " << nn::hac::ApplicationControlPropertyUtil::getRuntimeAddOnContentInstallAsString(mNacp.getRuntimeAddOnContentInstall()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RuntimeParameterDelivery
|
||||||
|
if (mNacp.getRuntimeParameterDelivery() != nn::hac::nacp::RuntimeParameterDelivery::Always || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " RuntimeParameterDelivery: " << nn::hac::ApplicationControlPropertyUtil::getRuntimeParameterDeliveryAsString(mNacp.getRuntimeParameterDelivery()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CrashReport
|
||||||
|
if (mNacp.getCrashReport() != nn::hac::nacp::CrashReport::Deny || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " CrashReport: " << nn::hac::ApplicationControlPropertyUtil::getCrashReportAsString(mNacp.getCrashReport()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hdcp
|
||||||
|
if (mNacp.getHdcp() != nn::hac::nacp::Hdcp::None || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " Hdcp: " << nn::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeedForPsuedoDeviceId
|
||||||
|
if (mNacp.getSeedForPsuedoDeviceId() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
{
|
{
|
||||||
std::cout << " Other Ids:" << std::endl;
|
|
||||||
if (mNacp.getSeedForPsuedoDeviceId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
|
||||||
std::cout << " SeedForPsuedoDeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSeedForPsuedoDeviceId() << std::endl;
|
std::cout << " SeedForPsuedoDeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSeedForPsuedoDeviceId() << std::endl;
|
||||||
if (mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
}
|
||||||
std::cout << " PresenceGroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPresenceGroupId() << std::endl;
|
|
||||||
|
// BcatPassphase
|
||||||
|
if (mNacp.getBcatPassphase().empty() == false)
|
||||||
|
{
|
||||||
|
std::cout << " BcatPassphase: " << mNacp.getBcatPassphase() << std::endl;
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " BcatPassphase: (NotSet)" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartupUserAccountOption
|
||||||
|
if (mNacp.getStartupUserAccountOption().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " StartupUserAccountOption:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getStartupUserAccountOption().begin(); itr != mNacp.getStartupUserAccountOption().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountOptionFlagAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " StartupUserAccountOption: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAccountSaveDataSizeMax
|
||||||
|
if (mNacp.getUserAccountSaveDataMax().size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " UserAccountSaveDataSizeMax: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserAccountSaveDataJournalSizeMax
|
||||||
|
if (mNacp.getUserAccountSaveDataMax().journal_size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " UserAccountSaveDataJournalSizeMax: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getUserAccountSaveDataMax().journal_size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceSaveDataSizeMax
|
||||||
|
if (mNacp.getDeviceSaveDataMax().size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " DeviceSaveDataSizeMax: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceSaveDataJournalSizeMax
|
||||||
|
if (mNacp.getDeviceSaveDataMax().journal_size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " DeviceSaveDataJournalSizeMax: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getDeviceSaveDataMax().journal_size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemporaryStorageSize
|
||||||
|
if (mNacp.getTemporaryStorageSize() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " TemporaryStorageSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheStorageSize
|
||||||
|
if (mNacp.getCacheStorageSize().size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " CacheStorageSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheStorageJournalSize
|
||||||
|
if (mNacp.getCacheStorageSize().journal_size != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " CacheStorageJournalSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageSize().journal_size) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheStorageDataAndJournalSizeMax
|
||||||
|
if (mNacp.getCacheStorageDataAndJournalSizeMax() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " CacheStorageDataAndJournalSizeMax: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getCacheStorageDataAndJournalSizeMax()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheStorageIndexMax
|
||||||
|
if (mNacp.getCacheStorageIndexMax() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " CacheStorageIndexMax: 0x" << std::hex << std::setw(4) << std::setfill('0') << mNacp.getCacheStorageIndexMax() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlayLogQueryableApplicationId
|
||||||
|
if (mNacp.getPlayLogQueryableApplicationId().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " PlayLogQueryableApplicationId:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getPlayLogQueryableApplicationId().begin(); itr != mNacp.getPlayLogQueryableApplicationId().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << *itr << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " PlayLogQueryableApplicationId: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlayLogQueryCapability
|
||||||
|
if (mNacp.getPlayLogQueryCapability() != nn::hac::nacp::PlayLogQueryCapability::None || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " PlayLogQueryCapability: " << nn::hac::ApplicationControlPropertyUtil::getPlayLogQueryCapabilityAsString(mNacp.getPlayLogQueryCapability()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repair
|
||||||
|
if (mNacp.getRepair().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " Repair:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getRepair().begin(); itr != mNacp.getRepair().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getRepairFlagAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " Repair: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProgramIndex
|
||||||
|
if (mNacp.getProgramIndex() != 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " ProgramIndex: 0x" << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)mNacp.getProgramIndex() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequiredNetworkServiceLicenseOnLaunch
|
||||||
|
if (mNacp.getRequiredNetworkServiceLicenseOnLaunch().size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " RequiredNetworkServiceLicenseOnLaunch:" << std::endl;
|
||||||
|
for (auto itr = mNacp.getRequiredNetworkServiceLicenseOnLaunch().begin(); itr != mNacp.getRequiredNetworkServiceLicenseOnLaunch().end(); itr++)
|
||||||
|
{
|
||||||
|
std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getRequiredNetworkServiceLicenseOnLaunchFlagAsString(*itr) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " RequiredNetworkServiceLicenseOnLaunch: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NeighborDetectionClientConfiguration
|
||||||
|
auto detect_config = mNacp.getNeighborDetectionClientConfiguration();
|
||||||
|
if (detect_config.countSendGroupConfig() > 0 || detect_config.countReceivableGroupConfig() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " NeighborDetectionClientConfiguration:" << std::endl;
|
||||||
|
if (detect_config.countSendGroupConfig() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " SendGroupConfig:" << std::endl;
|
||||||
|
std::cout << " GroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << detect_config.send_data_configuration.group_id << std::endl;
|
||||||
|
std::cout << " Key: " << fnd::SimpleTextOutput::arrayToString(detect_config.send_data_configuration.key, nn::hac::nacp::kNeighborDetectionGroupConfigurationKeyLength, false, "") << std::endl;
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " SendGroupConfig: None" << std::endl;
|
||||||
|
}
|
||||||
|
if (detect_config.countReceivableGroupConfig() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " ReceivableGroupConfig:" << std::endl;
|
||||||
|
for (size_t i = 0; i < nn::hac::nacp::kReceivableGroupConfigurationCount; i++)
|
||||||
|
{
|
||||||
|
if (detect_config.receivable_data_configuration[i].isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::cout << " GroupId: 0x" << std::hex << std::setw(16) << std::setfill('0') << detect_config.receivable_data_configuration[i].group_id << std::endl;
|
||||||
|
std::cout << " Key: " << fnd::SimpleTextOutput::arrayToString(detect_config.receivable_data_configuration[i].key, nn::hac::nacp::kNeighborDetectionGroupConfigurationKeyLength, false, "") << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " ReceivableGroupConfig: None" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " NeighborDetectionClientConfiguration: None" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JitConfiguration
|
||||||
|
if (mNacp.getJitConfiguration().is_enabled || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << " JitConfiguration:" << std::endl;
|
||||||
|
std::cout << " IsEnabled: " << std::boolalpha << mNacp.getJitConfiguration().is_enabled << std::endl;
|
||||||
|
std::cout << " MemorySize: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getJitConfiguration().memory_size << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -232,14 +232,14 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
{
|
{
|
||||||
// get reference to relevant structures
|
// get reference to relevant structures
|
||||||
const nn::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i];
|
const nn::hac::ContentArchiveHeader::sPartitionEntry& partition = mHdr.getPartitionEntryList()[i];
|
||||||
nn::hac::sNcaFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index];
|
nn::hac::sContentArchiveFsHeader& fs_header = mHdrBlock.fs_header[partition.header_index];
|
||||||
|
|
||||||
// output structure
|
// output structure
|
||||||
sPartitionInfo& info = mPartitions[partition.header_index];
|
sPartitionInfo& info = mPartitions[partition.header_index];
|
||||||
|
|
||||||
// validate header hash
|
// validate header hash
|
||||||
fnd::sha::sSha256Hash fs_header_hash;
|
fnd::sha::sSha256Hash fs_header_hash;
|
||||||
fnd::sha::Sha256((const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(nn::hac::sNcaFsHeader), fs_header_hash.bytes);
|
fnd::sha::Sha256((const byte_t*)&mHdrBlock.fs_header[partition.header_index], sizeof(nn::hac::sContentArchiveFsHeader), fs_header_hash.bytes);
|
||||||
if (fs_header_hash.compare(partition.fs_header_hash) == false)
|
if (fs_header_hash.compare(partition.fs_header_hash) == false)
|
||||||
{
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
|
@ -265,16 +265,16 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
info.format_type = (nn::hac::nca::FormatType)fs_header.format_type;
|
info.format_type = (nn::hac::nca::FormatType)fs_header.format_type;
|
||||||
info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type;
|
info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type;
|
||||||
info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type;
|
info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type;
|
||||||
if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256)
|
if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
|
||||||
{
|
{
|
||||||
// info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_SHA256);
|
// info.hash_tree_meta.importData(fs_header.hash_info, nn::hac::nca::kHashInfoLen, LayeredIntegrityMetadata::HASH_TYPE_SHA256);
|
||||||
nn::hac::HierarchicalSha256Header hdr;
|
nn::hac::HierarchicalSha256Header hdr;
|
||||||
fnd::List<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
|
fnd::List<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
|
||||||
fnd::LayeredIntegrityMetadata::sLayer data_layer;
|
fnd::LayeredIntegrityMetadata::sLayer data_layer;
|
||||||
fnd::List<fnd::sha::sSha256Hash> master_hash_list;
|
fnd::List<fnd::sha::sSha256Hash> master_hash_list;
|
||||||
|
|
||||||
// import raw data
|
// import raw data
|
||||||
hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen);
|
hdr.fromBytes(fs_header.hash_info, nn::hac::nca::kHashInfoLen);
|
||||||
for (size_t i = 0; i < hdr.getLayerInfo().size(); i++)
|
for (size_t i = 0; i < hdr.getLayerInfo().size(); i++)
|
||||||
{
|
{
|
||||||
fnd::LayeredIntegrityMetadata::sLayer layer;
|
fnd::LayeredIntegrityMetadata::sLayer layer;
|
||||||
|
@ -298,15 +298,15 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
info.layered_intergrity_metadata.setDataLayerInfo(data_layer);
|
info.layered_intergrity_metadata.setDataLayerInfo(data_layer);
|
||||||
info.layered_intergrity_metadata.setMasterHashList(master_hash_list);
|
info.layered_intergrity_metadata.setMasterHashList(master_hash_list);
|
||||||
}
|
}
|
||||||
else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY)
|
else if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
|
||||||
{
|
{
|
||||||
// info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_INTEGRITY);
|
// info.hash_tree_meta.importData(fs_header.hash_info, nn::hac::nca::kHashInfoLen, LayeredIntegrityMetadata::HASH_TYPE_INTEGRITY);
|
||||||
nn::hac::HierarchicalIntegrityHeader hdr;
|
nn::hac::HierarchicalIntegrityHeader hdr;
|
||||||
fnd::List<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
|
fnd::List<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
|
||||||
fnd::LayeredIntegrityMetadata::sLayer data_layer;
|
fnd::LayeredIntegrityMetadata::sLayer data_layer;
|
||||||
fnd::List<fnd::sha::sSha256Hash> master_hash_list;
|
fnd::List<fnd::sha::sSha256Hash> master_hash_list;
|
||||||
|
|
||||||
hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen);
|
hdr.fromBytes(fs_header.hash_info, nn::hac::nca::kHashInfoLen);
|
||||||
for (size_t i = 0; i < hdr.getLayerInfo().size(); i++)
|
for (size_t i = 0; i < hdr.getLayerInfo().size(); i++)
|
||||||
{
|
{
|
||||||
fnd::LayeredIntegrityMetadata::sLayer layer;
|
fnd::LayeredIntegrityMetadata::sLayer layer;
|
||||||
|
@ -336,27 +336,27 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
// filter out unrecognised format types
|
// filter out unrecognised format types
|
||||||
switch (info.format_type)
|
switch (info.format_type)
|
||||||
{
|
{
|
||||||
case (nn::hac::nca::FORMAT_PFS0):
|
case (nn::hac::nca::FormatType::PartitionFs):
|
||||||
case (nn::hac::nca::FORMAT_ROMFS):
|
case (nn::hac::nca::FormatType::RomFs):
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "FormatType(" << info.format_type << "): UNKNOWN";
|
error << "FormatType(" << nn::hac::ContentArchiveUtil::getFormatTypeAsString(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
|
||||||
if (info.enc_type == nn::hac::nca::CRYPT_NONE)
|
if (info.enc_type == nn::hac::nca::EncryptionType::None)
|
||||||
{
|
{
|
||||||
info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size);
|
info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size);
|
||||||
}
|
}
|
||||||
else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR)
|
else if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
|
||||||
{
|
{
|
||||||
if (mContentKey.aes_ctr.isSet == false)
|
if (mContentKey.aes_ctr.isSet == false)
|
||||||
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
|
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
|
||||||
info.reader = new fnd::OffsetAdjustedIFile(new fnd::AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), info.offset, info.size);
|
info.reader = new fnd::OffsetAdjustedIFile(new fnd::AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), info.offset, info.size);
|
||||||
}
|
}
|
||||||
else if (info.enc_type == nn::hac::nca::CRYPT_AESXTS || info.enc_type == nn::hac::nca::CRYPT_AESCTREX)
|
else if (info.enc_type == nn::hac::nca::EncryptionType::AesXts || info.enc_type == nn::hac::nca::EncryptionType::AesCtrEx)
|
||||||
{
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "EncryptionType(" << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << "): UNSUPPORTED";
|
error << "EncryptionType(" << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << "): UNSUPPORTED";
|
||||||
|
@ -365,19 +365,19 @@ void NcaProcess::generatePartitionConfiguration()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "EncryptionType(" << info.enc_type << "): UNKNOWN";
|
error << "EncryptionType(" << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << "): UNKNOWN";
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter out unrecognised hash types, and hash based readers
|
// filter out unrecognised hash types, and hash based readers
|
||||||
if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256 || info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY)
|
if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256 || info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
|
||||||
{
|
{
|
||||||
info.reader = new fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata);
|
info.reader = new fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata);
|
||||||
}
|
}
|
||||||
else if (info.hash_type != nn::hac::nca::HASH_NONE)
|
else if (info.hash_type != nn::hac::nca::HashType::None)
|
||||||
{
|
{
|
||||||
error.clear();
|
error.clear();
|
||||||
error << "HashType(" << info.hash_type << "): UNKNOWN";
|
error << "HashType(" << nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type) << "): UNKNOWN";
|
||||||
throw fnd::Exception(kModuleName, error.str());
|
throw fnd::Exception(kModuleName, error.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,16 +392,16 @@ void NcaProcess::validateNcaSignatures()
|
||||||
{
|
{
|
||||||
// validate signature[0]
|
// validate signature[0]
|
||||||
fnd::rsa::sRsa2048Key sign0_key;
|
fnd::rsa::sRsa2048Key sign0_key;
|
||||||
mKeyCfg.getContentArchiveHeader0SignKey(sign0_key);
|
mKeyCfg.getContentArchiveHeader0SignKey(sign0_key, mHdr.getSignatureKeyGeneration());
|
||||||
if (fnd::rsa::pss::rsaVerify(sign0_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0)
|
if (fnd::rsa::pss::rsaVerify(sign0_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0)
|
||||||
{
|
{
|
||||||
std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl;
|
std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate signature[1]
|
// validate signature[1]
|
||||||
if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM)
|
if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
|
||||||
{
|
{
|
||||||
if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FORMAT_PFS0)
|
if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FormatType::PartitionFs)
|
||||||
{
|
{
|
||||||
if (*mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr)
|
if (*mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -417,10 +417,12 @@ void NcaProcess::validateNcaSignatures()
|
||||||
|
|
||||||
MetaProcess npdm;
|
MetaProcess npdm;
|
||||||
npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size));
|
npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size));
|
||||||
|
npdm.setKeyCfg(mKeyCfg);
|
||||||
|
npdm.setVerifyMode(true);
|
||||||
npdm.setCliOutputMode(0);
|
npdm.setCliOutputMode(0);
|
||||||
npdm.process();
|
npdm.process();
|
||||||
|
|
||||||
if (fnd::rsa::pss::rsaVerify(npdm.getMeta().getAcid().getContentArchiveHeaderSignature2Key(), fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0)
|
if (fnd::rsa::pss::rsaVerify(npdm.getMeta().getAccessControlInfoDesc().getContentArchiveHeaderSignature2Key(), fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_acid) != 0)
|
||||||
{
|
{
|
||||||
std::cout << "[WARNING] NCA Header ACID Signature: FAIL" << std::endl;
|
std::cout << "[WARNING] NCA Header ACID Signature: FAIL" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -446,17 +448,16 @@ void NcaProcess::validateNcaSignatures()
|
||||||
void NcaProcess::displayHeader()
|
void NcaProcess::displayHeader()
|
||||||
{
|
{
|
||||||
std::cout << "[NCA Header]" << std::endl;
|
std::cout << "[NCA Header]" << std::endl;
|
||||||
std::cout << " Format Type: " << nn::hac::ContentArchiveUtil::getFormatVersionAsString((nn::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion()) << std::endl;
|
std::cout << " Format Type: " << nn::hac::ContentArchiveUtil::getFormatHeaderVersionAsString((nn::hac::nca::HeaderFormatVersion)mHdr.getFormatVersion()) << std::endl;
|
||||||
std::cout << " Dist. Type: " << nn::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType()) << std::endl;
|
std::cout << " Dist. Type: " << nn::hac::ContentArchiveUtil::getDistributionTypeAsString(mHdr.getDistributionType()) << std::endl;
|
||||||
std::cout << " Content Type: " << nn::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()) << std::endl;
|
std::cout << " Content Type: " << nn::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()) << std::endl;
|
||||||
std::cout << " Key Generation: " << std::dec << (uint32_t)mHdr.getKeyGeneration() << std::endl;
|
std::cout << " Key Generation: " << std::dec << (uint32_t)mHdr.getKeyGeneration() << std::endl;
|
||||||
|
std::cout << " Sig. Generation: " << std::dec << (uint32_t)mHdr.getSignatureKeyGeneration() << std::endl;
|
||||||
std::cout << " Kaek Index: " << nn::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()) << " (" << std::dec << (uint32_t)mHdr.getKeyAreaEncryptionKeyIndex() << ")" << std::endl;
|
std::cout << " Kaek Index: " << nn::hac::ContentArchiveUtil::getKeyAreaEncryptionKeyIndexAsString((nn::hac::nca::KeyAreaEncryptionKeyIndex)mHdr.getKeyAreaEncryptionKeyIndex()) << " (" << std::dec << (uint32_t)mHdr.getKeyAreaEncryptionKeyIndex() << ")" << std::endl;
|
||||||
std::cout << " Size: 0x" << std::hex << mHdr.getContentSize() << std::endl;
|
std::cout << " Size: 0x" << std::hex << mHdr.getContentSize() << std::endl;
|
||||||
std::cout << " ProgID: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getProgramId() << std::endl;
|
std::cout << " ProgID: 0x" << std::hex << std::setw(16) << std::setfill('0') << mHdr.getProgramId() << std::endl;
|
||||||
std::cout << " Content Index: " << std::dec << mHdr.getContentIndex() << std::endl;
|
std::cout << " Content Index: " << std::dec << mHdr.getContentIndex() << std::endl;
|
||||||
#define _SPLIT_VER(ver) std::dec << (uint32_t)((ver>>24) & 0xff) << "." << (uint32_t)((ver>>16) & 0xff) << "." << (uint32_t)((ver>>8) & 0xff)
|
std::cout << " SdkAddon Ver.: " << nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()) << " (v" << std::dec << mHdr.getSdkAddonVersion() << ")" << std::endl;
|
||||||
std::cout << " SdkAddon Ver.: v" << std::dec << mHdr.getSdkAddonVersion() << " (" << _SPLIT_VER(mHdr.getSdkAddonVersion()) << ")" << std::endl;
|
|
||||||
#undef _SPLIT_VER
|
|
||||||
if (mHdr.hasRightsId())
|
if (mHdr.hasRightsId())
|
||||||
{
|
{
|
||||||
std::cout << " RightsId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRightsId(), nn::hac::nca::kRightsIdLen, true, "") << std::endl;
|
std::cout << " RightsId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRightsId(), nn::hac::nca::kRightsIdLen, true, "") << std::endl;
|
||||||
|
@ -500,14 +501,14 @@ void NcaProcess::displayHeader()
|
||||||
std::cout << " Format Type: " << nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type) << std::endl;
|
std::cout << " Format Type: " << nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type) << std::endl;
|
||||||
std::cout << " Hash Type: " << nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type) << std::endl;
|
std::cout << " Hash Type: " << nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type) << std::endl;
|
||||||
std::cout << " Enc. Type: " << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << std::endl;
|
std::cout << " Enc. Type: " << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << std::endl;
|
||||||
if (info.enc_type == nn::hac::nca::CRYPT_AESCTR)
|
if (info.enc_type == nn::hac::nca::EncryptionType::AesCtr)
|
||||||
{
|
{
|
||||||
fnd::aes::sAesIvCtr ctr;
|
fnd::aes::sAesIvCtr ctr;
|
||||||
fnd::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv);
|
fnd::aes::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv);
|
||||||
std::cout << " AesCtr Counter:" << std::endl;
|
std::cout << " AesCtr Counter:" << std::endl;
|
||||||
std::cout << " " << fnd::SimpleTextOutput::arrayToString(ctr.iv, sizeof(fnd::aes::sAesIvCtr), true, ":") << std::endl;
|
std::cout << " " << fnd::SimpleTextOutput::arrayToString(ctr.iv, sizeof(fnd::aes::sAesIvCtr), true, ":") << std::endl;
|
||||||
}
|
}
|
||||||
if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY)
|
if (info.hash_type == nn::hac::nca::HashType::HierarchicalIntegrity)
|
||||||
{
|
{
|
||||||
fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata;
|
fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata;
|
||||||
std::cout << " HierarchicalIntegrity Header:" << std::endl;
|
std::cout << " HierarchicalIntegrity Header:" << std::endl;
|
||||||
|
@ -530,7 +531,7 @@ void NcaProcess::displayHeader()
|
||||||
std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes+0x10, 0x10, true, ":") << std::endl;
|
std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[j].bytes+0x10, 0x10, true, ":") << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256)
|
else if (info.hash_type == nn::hac::nca::HashType::HierarchicalSha256)
|
||||||
{
|
{
|
||||||
fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata;
|
fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata;
|
||||||
std::cout << " HierarchicalSha256 Header:" << std::endl;
|
std::cout << " HierarchicalSha256 Header:" << std::endl;
|
||||||
|
@ -569,13 +570,13 @@ void NcaProcess::processPartitions()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partition.format_type == nn::hac::nca::FORMAT_PFS0)
|
if (partition.format_type == nn::hac::nca::FormatType::PartitionFs)
|
||||||
{
|
{
|
||||||
PfsProcess pfs;
|
PfsProcess pfs;
|
||||||
pfs.setInputFile(partition.reader);
|
pfs.setInputFile(partition.reader);
|
||||||
pfs.setCliOutputMode(mCliOutputMode);
|
pfs.setCliOutputMode(mCliOutputMode);
|
||||||
pfs.setListFs(mListFs);
|
pfs.setListFs(mListFs);
|
||||||
if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM)
|
if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
|
||||||
{
|
{
|
||||||
pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index));
|
pfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index));
|
||||||
}
|
}
|
||||||
|
@ -588,13 +589,13 @@ void NcaProcess::processPartitions()
|
||||||
pfs.setExtractPath(mPartitionPath[index].path);
|
pfs.setExtractPath(mPartitionPath[index].path);
|
||||||
pfs.process();
|
pfs.process();
|
||||||
}
|
}
|
||||||
else if (partition.format_type == nn::hac::nca::FORMAT_ROMFS)
|
else if (partition.format_type == nn::hac::nca::FormatType::RomFs)
|
||||||
{
|
{
|
||||||
RomfsProcess romfs;
|
RomfsProcess romfs;
|
||||||
romfs.setInputFile(partition.reader);
|
romfs.setInputFile(partition.reader);
|
||||||
romfs.setCliOutputMode(mCliOutputMode);
|
romfs.setCliOutputMode(mCliOutputMode);
|
||||||
romfs.setListFs(mListFs);
|
romfs.setListFs(mListFs);
|
||||||
if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM)
|
if (mHdr.getContentType() == nn::hac::nca::ContentType::Program)
|
||||||
{
|
{
|
||||||
romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index));
|
romfs.setMountPointName(std::string(getContentTypeForMountStr(mHdr.getContentType())) + ":/" + nn::hac::ContentArchiveUtil::getProgramContentParititionIndexAsString((nn::hac::nca::ProgramContentPartitionIndex)index));
|
||||||
}
|
}
|
||||||
|
@ -616,22 +617,22 @@ const char* NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont
|
||||||
|
|
||||||
switch (cont_type)
|
switch (cont_type)
|
||||||
{
|
{
|
||||||
case (nn::hac::nca::TYPE_PROGRAM):
|
case (nn::hac::nca::ContentType::Program):
|
||||||
str = "program";
|
str = "program";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::nca::TYPE_META):
|
case (nn::hac::nca::ContentType::Meta):
|
||||||
str = "meta";
|
str = "meta";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::nca::TYPE_CONTROL):
|
case (nn::hac::nca::ContentType::Control):
|
||||||
str = "control";
|
str = "control";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::nca::TYPE_MANUAL):
|
case (nn::hac::nca::ContentType::Manual):
|
||||||
str = "manual";
|
str = "manual";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::nca::TYPE_DATA):
|
case (nn::hac::nca::ContentType::Data):
|
||||||
str = "data";
|
str = "data";
|
||||||
break;
|
break;
|
||||||
case (nn::hac::nca::TYPE_PUBLIC_DATA):
|
case (nn::hac::nca::ContentType::PublicData):
|
||||||
str = "publicdata";
|
str = "publicdata";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -43,9 +43,9 @@ void NroProcess::setVerifyMode(bool verify)
|
||||||
mVerify = verify;
|
mVerify = verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NroProcess::setInstructionType(nn::hac::meta::InstructionType type)
|
void NroProcess::setIs64BitInstruction(bool flag)
|
||||||
{
|
{
|
||||||
mRoMeta.setInstructionType(type);
|
mRoMeta.setIs64BitInstruction(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NroProcess::setListApi(bool listApi)
|
void NroProcess::setListApi(bool listApi)
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
void setCliOutputMode(CliOutputMode type);
|
void setCliOutputMode(CliOutputMode type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
void setInstructionType(nn::hac::meta::InstructionType type);
|
void setIs64BitInstruction(bool flag);
|
||||||
void setListApi(bool listApi);
|
void setListApi(bool listApi);
|
||||||
void setListSymbols(bool listSymbols);
|
void setListSymbols(bool listSymbols);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
NsoProcess::NsoProcess():
|
NsoProcess::NsoProcess():
|
||||||
mFile(),
|
mFile(),
|
||||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
mVerify(false)
|
mVerify(false),
|
||||||
|
mIs64BitInstruction(true),
|
||||||
|
mListApi(false),
|
||||||
|
mListSymbols(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +41,9 @@ void NsoProcess::setVerifyMode(bool verify)
|
||||||
mVerify = verify;
|
mVerify = verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsoProcess::setInstructionType(nn::hac::meta::InstructionType type)
|
void NsoProcess::setIs64BitInstruction(bool flag)
|
||||||
{
|
{
|
||||||
mRoMeta.setInstructionType(type);
|
mRoMeta.setIs64BitInstruction(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsoProcess::setListApi(bool listApi)
|
void NsoProcess::setListApi(bool listApi)
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
void setCliOutputMode(CliOutputMode type);
|
void setCliOutputMode(CliOutputMode type);
|
||||||
void setVerifyMode(bool verify);
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
void setInstructionType(nn::hac::meta::InstructionType type);
|
void setIs64BitInstruction(bool flag);
|
||||||
void setListApi(bool listApi);
|
void setListApi(bool listApi);
|
||||||
void setListSymbols(bool listSymbols);
|
void setListSymbols(bool listSymbols);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ private:
|
||||||
fnd::SharedPtr<fnd::IFile> mFile;
|
fnd::SharedPtr<fnd::IFile> mFile;
|
||||||
CliOutputMode mCliOutputMode;
|
CliOutputMode mCliOutputMode;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
nn::hac::meta::InstructionType mInstructionType;
|
bool mIs64BitInstruction;
|
||||||
bool mListApi;
|
bool mListApi;
|
||||||
bool mListSymbols;
|
bool mListSymbols;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
RoMetadataProcess::RoMetadataProcess() :
|
RoMetadataProcess::RoMetadataProcess() :
|
||||||
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
mInstructionType(nn::hac::meta::INSTR_64BIT),
|
mIs64BitInstruction(true),
|
||||||
mListApi(false),
|
mListApi(false),
|
||||||
mListSymbols(false),
|
mListSymbols(false),
|
||||||
mApiInfo(),
|
mApiInfo(),
|
||||||
|
@ -57,9 +57,9 @@ void RoMetadataProcess::setCliOutputMode(CliOutputMode type)
|
||||||
mCliOutputMode = type;
|
mCliOutputMode = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoMetadataProcess::setInstructionType(nn::hac::meta::InstructionType type)
|
void RoMetadataProcess::setIs64BitInstruction(bool flag)
|
||||||
{
|
{
|
||||||
mInstructionType = type;
|
mIs64BitInstruction = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoMetadataProcess::setListApi(bool listApi)
|
void RoMetadataProcess::setListApi(bool listApi)
|
||||||
|
@ -92,6 +92,11 @@ const std::vector<SdkApiString>& RoMetadataProcess::getPrivateApiList() const
|
||||||
return mPrivateApiList;
|
return mPrivateApiList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<SdkApiString>& RoMetadataProcess::getGuidelineApiList() const
|
||||||
|
{
|
||||||
|
return mGuidelineApiList;
|
||||||
|
}
|
||||||
|
|
||||||
const fnd::List<ElfSymbolParser::sElfSymbol>& RoMetadataProcess::getSymbolList() const
|
const fnd::List<ElfSymbolParser::sElfSymbol>& RoMetadataProcess::getSymbolList() const
|
||||||
{
|
{
|
||||||
return mSymbolList.getSymbolList();
|
return mSymbolList.getSymbolList();
|
||||||
|
@ -113,20 +118,32 @@ void RoMetadataProcess::importApiList()
|
||||||
{
|
{
|
||||||
SdkApiString api(api_str);
|
SdkApiString api(api_str);
|
||||||
|
|
||||||
if (api.getApiType() == SdkApiString::API_SDK_VERSION)
|
switch (api.getApiType())
|
||||||
|
{
|
||||||
|
case SdkApiString::API_SDK_VERSION:
|
||||||
mSdkVerApiList.push_back(api);
|
mSdkVerApiList.push_back(api);
|
||||||
else if (api.getApiType() == SdkApiString::API_MIDDLEWARE)
|
break;
|
||||||
|
case SdkApiString::API_MIDDLEWARE:
|
||||||
mPublicApiList.push_back(api);
|
mPublicApiList.push_back(api);
|
||||||
else if (api.getApiType() == SdkApiString::API_DEBUG)
|
break;
|
||||||
|
case SdkApiString::API_DEBUG:
|
||||||
mDebugApiList.push_back(api);
|
mDebugApiList.push_back(api);
|
||||||
else if (api.getApiType() == SdkApiString::API_PRIVATE)
|
break;
|
||||||
|
case SdkApiString::API_PRIVATE:
|
||||||
mPrivateApiList.push_back(api);
|
mPrivateApiList.push_back(api);
|
||||||
|
break;
|
||||||
|
case SdkApiString::API_GUIDELINE:
|
||||||
|
mGuidelineApiList.push_back(api);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDynSym.size > 0)
|
if (mDynSym.size > 0)
|
||||||
{
|
{
|
||||||
mSymbolList.parseData(mRoBlob.data() + mDynSym.offset, mDynSym.size, mRoBlob.data() + mDynStr.offset, mDynStr.size, mInstructionType == nn::hac::meta::INSTR_64BIT);
|
mSymbolList.parseData(mRoBlob.data() + mDynSym.offset, mDynSym.size, mRoBlob.data() + mDynStr.offset, mDynStr.size, mIs64BitInstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +182,14 @@ void RoMetadataProcess::displayRoMetaData()
|
||||||
std::cout << " " << mPrivateApiList[i].getModuleName() << " (vender: " << mPrivateApiList[i].getVenderName() << ")" << std::endl;
|
std::cout << " " << mPrivateApiList[i].getModuleName() << " (vender: " << mPrivateApiList[i].getVenderName() << ")" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mGuidelineApiList.size() > 0)
|
||||||
|
{
|
||||||
|
std::cout << " Guideline APIs:" << std::endl;
|
||||||
|
for (size_t i = 0; i < mGuidelineApiList.size(); i++)
|
||||||
|
{
|
||||||
|
std::cout << " " << mGuidelineApiList[i].getModuleName() << " (vender: " << mGuidelineApiList[i].getVenderName() << ")" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mSymbolList.getSymbolList().size() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
if (mSymbolList.getSymbolList().size() > 0 && (mListSymbols || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)))
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
void setCliOutputMode(CliOutputMode type);
|
void setCliOutputMode(CliOutputMode type);
|
||||||
|
|
||||||
void setInstructionType(nn::hac::meta::InstructionType type);
|
void setIs64BitInstruction(bool flag);
|
||||||
void setListApi(bool listApi);
|
void setListApi(bool listApi);
|
||||||
void setListSymbols(bool listSymbols);
|
void setListSymbols(bool listSymbols);
|
||||||
|
|
||||||
|
@ -32,12 +32,13 @@ public:
|
||||||
const std::vector<SdkApiString>& getPublicApiList() const;
|
const std::vector<SdkApiString>& getPublicApiList() const;
|
||||||
const std::vector<SdkApiString>& getDebugApiList() const;
|
const std::vector<SdkApiString>& getDebugApiList() const;
|
||||||
const std::vector<SdkApiString>& getPrivateApiList() const;
|
const std::vector<SdkApiString>& getPrivateApiList() const;
|
||||||
|
const std::vector<SdkApiString>& getGuidelineApiList() const;
|
||||||
const fnd::List<ElfSymbolParser::sElfSymbol>& getSymbolList() const;
|
const fnd::List<ElfSymbolParser::sElfSymbol>& getSymbolList() const;
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "RoMetadataProcess";
|
const std::string kModuleName = "RoMetadataProcess";
|
||||||
|
|
||||||
CliOutputMode mCliOutputMode;
|
CliOutputMode mCliOutputMode;
|
||||||
nn::hac::meta::InstructionType mInstructionType;
|
bool mIs64BitInstruction;
|
||||||
bool mListApi;
|
bool mListApi;
|
||||||
bool mListSymbols;
|
bool mListSymbols;
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ private:
|
||||||
std::vector<SdkApiString> mPublicApiList;
|
std::vector<SdkApiString> mPublicApiList;
|
||||||
std::vector<SdkApiString> mDebugApiList;
|
std::vector<SdkApiString> mDebugApiList;
|
||||||
std::vector<SdkApiString> mPrivateApiList;
|
std::vector<SdkApiString> mPrivateApiList;
|
||||||
|
std::vector<SdkApiString> mGuidelineApiList;
|
||||||
|
|
||||||
ElfSymbolParser mSymbolList;
|
ElfSymbolParser mSymbolList;
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,14 @@ void SdkApiString::resolveApiString(const std::string& full_str)
|
||||||
{
|
{
|
||||||
mApiType = API_PRIVATE;
|
mApiType = API_PRIVATE;
|
||||||
}
|
}
|
||||||
|
else if (api_type == kSdkGuidelineApiString)
|
||||||
|
{
|
||||||
|
mApiType = API_GUIDELINE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO?
|
||||||
|
}
|
||||||
|
|
||||||
mVenderName = vender;
|
mVenderName = vender;
|
||||||
mModuleName = module;
|
mModuleName = module;
|
||||||
|
|
|
@ -9,7 +9,8 @@ public:
|
||||||
API_MIDDLEWARE,
|
API_MIDDLEWARE,
|
||||||
API_DEBUG,
|
API_DEBUG,
|
||||||
API_PRIVATE,
|
API_PRIVATE,
|
||||||
API_SDK_VERSION
|
API_SDK_VERSION,
|
||||||
|
API_GUIDELINE,
|
||||||
};
|
};
|
||||||
|
|
||||||
SdkApiString(const std::string& full_str);
|
SdkApiString(const std::string& full_str);
|
||||||
|
@ -32,6 +33,7 @@ private:
|
||||||
const std::string kSdkMiddleWareApiString = "SDK MW";
|
const std::string kSdkMiddleWareApiString = "SDK MW";
|
||||||
const std::string kSdkDebugApiString = "SDK Debug";
|
const std::string kSdkDebugApiString = "SDK Debug";
|
||||||
const std::string kSdkPrivateApiString = "SDK Private";
|
const std::string kSdkPrivateApiString = "SDK Private";
|
||||||
|
const std::string kSdkGuidelineApiString = "SDK Guideline";
|
||||||
const std::string kVenderNintendo = "Nintendo";
|
const std::string kVenderNintendo = "Nintendo";
|
||||||
const std::string kSdkVersionString = "NintendoSdk_nnSdk-";
|
const std::string kSdkVersionString = "NintendoSdk_nnSdk-";
|
||||||
|
|
||||||
|
|
|
@ -138,9 +138,9 @@ bool UserSettings::isListSymbols() const
|
||||||
return mListSymbols;
|
return mListSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
nn::hac::meta::InstructionType UserSettings::getInstType() const
|
bool UserSettings::getIs64BitInstruction() const
|
||||||
{
|
{
|
||||||
return mInstructionType;
|
return mIs64BitInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sOptional<std::string>& UserSettings::getXciUpdatePath() const
|
const sOptional<std::string>& UserSettings::getXciUpdatePath() const
|
||||||
|
@ -564,9 +564,9 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
||||||
|
|
||||||
// determine the architecture type for NSO/NRO
|
// determine the architecture type for NSO/NRO
|
||||||
if (args.inst_type.isSet)
|
if (args.inst_type.isSet)
|
||||||
mInstructionType = getInstructionTypeFromString(*args.inst_type);
|
mIs64BitInstruction = getIs64BitInstructionFromString(*args.inst_type);
|
||||||
else
|
else
|
||||||
mInstructionType = nn::hac::meta::INSTR_64BIT; // default 64bit
|
mIs64BitInstruction = true; // default 64bit
|
||||||
|
|
||||||
mListApi = args.list_api.isSet;
|
mListApi = args.list_api.isSet;
|
||||||
mListSymbols = args.list_sym.isSet;
|
mListSymbols = args.list_sym.isSet;
|
||||||
|
@ -758,13 +758,16 @@ bool UserSettings::determineValidCnmtFromSample(const fnd::Vec<byte_t>& sample)
|
||||||
if (sample.size() < minimum_size)
|
if (sample.size() < minimum_size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (data->type == nn::hac::cnmt::METATYPE_APPLICATION)
|
// include exthdr/data check if applicable
|
||||||
|
if (data->exhdr_size.get() > 0)
|
||||||
|
{
|
||||||
|
if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Application)
|
||||||
{
|
{
|
||||||
const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
const nn::hac::sApplicationMetaExtendedHeader* meta = (const nn::hac::sApplicationMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||||
if ((meta->patch_id.get() & data->id.get()) != data->id.get())
|
if ((meta->patch_id.get() & data->id.get()) != data->id.get())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (data->type == nn::hac::cnmt::METATYPE_PATCH)
|
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Patch)
|
||||||
{
|
{
|
||||||
const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
const nn::hac::sPatchMetaExtendedHeader* meta = (const nn::hac::sPatchMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||||
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
||||||
|
@ -772,13 +775,13 @@ bool UserSettings::determineValidCnmtFromSample(const fnd::Vec<byte_t>& sample)
|
||||||
|
|
||||||
minimum_size += meta->extended_data_size.get();
|
minimum_size += meta->extended_data_size.get();
|
||||||
}
|
}
|
||||||
else if (data->type == nn::hac::cnmt::METATYPE_ADD_ON_CONTENT)
|
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::AddOnContent)
|
||||||
{
|
{
|
||||||
const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
const nn::hac::sAddOnContentMetaExtendedHeader* meta = (const nn::hac::sAddOnContentMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||||
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (data->type == nn::hac::cnmt::METATYPE_DELTA)
|
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::Delta)
|
||||||
{
|
{
|
||||||
const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
const nn::hac::sDeltaMetaExtendedHeader* meta = (const nn::hac::sDeltaMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||||
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
if ((meta->application_id.get() & data->id.get()) != meta->application_id.get())
|
||||||
|
@ -786,6 +789,13 @@ bool UserSettings::determineValidCnmtFromSample(const fnd::Vec<byte_t>& sample)
|
||||||
|
|
||||||
minimum_size += meta->extended_data_size.get();
|
minimum_size += meta->extended_data_size.get();
|
||||||
}
|
}
|
||||||
|
else if (data->type == (byte_t)nn::hac::cnmt::ContentMetaType::SystemUpdate)
|
||||||
|
{
|
||||||
|
const nn::hac::sSystemUpdateMetaExtendedHeader* meta = (const nn::hac::sSystemUpdateMetaExtendedHeader*)(sample.data() + sizeof(nn::hac::sContentMetaHeader));
|
||||||
|
|
||||||
|
minimum_size += meta->extended_data_size.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sample.size() != minimum_size)
|
if (sample.size() != minimum_size)
|
||||||
return false;
|
return false;
|
||||||
|
@ -800,7 +810,7 @@ bool UserSettings::determineValidNacpFromSample(const fnd::Vec<byte_t>& sample)
|
||||||
|
|
||||||
const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data();
|
const nn::hac::sApplicationControlProperty* data = (const nn::hac::sApplicationControlProperty*)sample.data();
|
||||||
|
|
||||||
if (data->logo_type > nn::hac::nacp::LOGO_Nintendo)
|
if (data->logo_type > (byte_t)nn::hac::nacp::LogoType::Nintendo)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (data->display_version[0] == 0)
|
if (data->display_version[0] == 0)
|
||||||
|
@ -862,20 +872,20 @@ bool UserSettings::determineValidEsTikFromSample(const fnd::Vec<byte_t>& sample)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nn::hac::meta::InstructionType UserSettings::getInstructionTypeFromString(const std::string & type_str)
|
bool UserSettings::getIs64BitInstructionFromString(const std::string & type_str)
|
||||||
{
|
{
|
||||||
std::string str = type_str;
|
std::string str = type_str;
|
||||||
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
|
||||||
nn::hac::meta::InstructionType type;
|
bool flag;
|
||||||
if (str == "32bit")
|
if (str == "32bit")
|
||||||
type = nn::hac::meta::INSTR_32BIT;
|
flag = false;
|
||||||
else if (str == "64bit")
|
else if (str == "64bit")
|
||||||
type = nn::hac::meta::INSTR_64BIT;
|
flag = true;
|
||||||
else
|
else
|
||||||
throw fnd::Exception(kModuleName, "Unsupported instruction type: " + str);
|
throw fnd::Exception(kModuleName, "Unsupported instruction type: " + str);
|
||||||
|
|
||||||
return type;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserSettings::getHomePath(std::string& path) const
|
void UserSettings::getHomePath(std::string& path) const
|
||||||
|
@ -912,10 +922,19 @@ void UserSettings::dumpKeyConfig() const
|
||||||
|
|
||||||
std::cout << "[KeyConfiguration]" << std::endl;
|
std::cout << "[KeyConfiguration]" << std::endl;
|
||||||
std::cout << " NCA Keys:" << std::endl;
|
std::cout << " NCA Keys:" << std::endl;
|
||||||
if (mKeyCfg.getContentArchiveHeader0SignKey(rsa2048_key) == true)
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
dumpRsa2048Key(rsa2048_key, "Header Signature[0] Key", 2);
|
{
|
||||||
|
if (mKeyCfg.getContentArchiveHeader0SignKey(rsa2048_key, i) == true)
|
||||||
|
dumpRsa2048Key(rsa2048_key, "Header0-SignatureKey-" + kKeyIndex[i], 2);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
|
{
|
||||||
|
if (mKeyCfg.getAcidSignKey(rsa2048_key, i) == true)
|
||||||
|
dumpRsa2048Key(rsa2048_key, "Acid-SignatureKey-" + kKeyIndex[i], 2);
|
||||||
|
}
|
||||||
|
|
||||||
if (mKeyCfg.getContentArchiveHeaderKey(aesxts_key) == true)
|
if (mKeyCfg.getContentArchiveHeaderKey(aesxts_key) == true)
|
||||||
dumpAesXtsKey(aesxts_key, "Header Encryption Key", 2);
|
dumpAesXtsKey(aesxts_key, "Header-EncryptionKey", 2);
|
||||||
|
|
||||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
{
|
{
|
||||||
|
@ -937,15 +956,20 @@ void UserSettings::dumpKeyConfig() const
|
||||||
dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-System-" + kKeyIndex[i], 2);
|
dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-System-" + kKeyIndex[i], 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << " NRR Keys:" << std::endl;
|
||||||
|
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||||
|
{
|
||||||
|
if (mKeyCfg.getNrrCertificateSignKey(rsa2048_key, i) == true)
|
||||||
|
dumpRsa2048Key(rsa2048_key, "Certificate-SignatureKey-" + kKeyIndex[i], 2);
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << " XCI Keys:" << std::endl;
|
std::cout << " XCI Keys:" << std::endl;
|
||||||
if (mKeyCfg.getXciHeaderSignKey(rsa2048_key) == true)
|
if (mKeyCfg.getXciHeaderSignKey(rsa2048_key) == true)
|
||||||
dumpRsa2048Key(rsa2048_key, "Header Signature Key", 2);
|
dumpRsa2048Key(rsa2048_key, "Header-SignatureKey", 2);
|
||||||
if (mKeyCfg.getXciHeaderKey(aes_key) == true)
|
if (mKeyCfg.getXciHeaderKey(aes_key) == true)
|
||||||
dumpAesKey(aes_key, "Extended Header Encryption Key", 2);
|
dumpAesKey(aes_key, "ExtendedHeader-EncryptionKey", 2);
|
||||||
|
|
||||||
|
|
||||||
if (mKeyCfg.getAcidSignKey(rsa2048_key) == true)
|
|
||||||
dumpRsa2048Key(rsa2048_key, "ACID Signer Key", 1);
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << " Package1 Keys:" << std::endl;
|
std::cout << " Package1 Keys:" << std::endl;
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
bool isListFs() const;
|
bool isListFs() const;
|
||||||
bool isListApi() const;
|
bool isListApi() const;
|
||||||
bool isListSymbols() const;
|
bool isListSymbols() const;
|
||||||
nn::hac::meta::InstructionType getInstType() const;
|
bool getIs64BitInstruction() const;
|
||||||
|
|
||||||
// specialised paths
|
// specialised paths
|
||||||
const sOptional<std::string>& getXciUpdatePath() const;
|
const sOptional<std::string>& getXciUpdatePath() const;
|
||||||
|
@ -114,7 +114,7 @@ private:
|
||||||
|
|
||||||
bool mListApi;
|
bool mListApi;
|
||||||
bool mListSymbols;
|
bool mListSymbols;
|
||||||
nn::hac::meta::InstructionType mInstructionType;
|
bool mIs64BitInstruction;
|
||||||
|
|
||||||
void populateCmdArgs(const std::vector<std::string>& arg_list, sCmdArgs& cmd_args);
|
void populateCmdArgs(const std::vector<std::string>& arg_list, sCmdArgs& cmd_args);
|
||||||
void populateKeyset(sCmdArgs& args);
|
void populateKeyset(sCmdArgs& args);
|
||||||
|
@ -126,7 +126,7 @@ private:
|
||||||
bool determineValidNacpFromSample(const fnd::Vec<byte_t>& sample) const;
|
bool determineValidNacpFromSample(const fnd::Vec<byte_t>& sample) const;
|
||||||
bool determineValidEsCertFromSample(const fnd::Vec<byte_t>& sample) const;
|
bool determineValidEsCertFromSample(const fnd::Vec<byte_t>& sample) const;
|
||||||
bool determineValidEsTikFromSample(const fnd::Vec<byte_t>& sample) const;
|
bool determineValidEsTikFromSample(const fnd::Vec<byte_t>& sample) const;
|
||||||
nn::hac::meta::InstructionType getInstructionTypeFromString(const std::string& type_str);
|
bool getIs64BitInstructionFromString(const std::string& type_str);
|
||||||
void getHomePath(std::string& path) const;
|
void getHomePath(std::string& path) const;
|
||||||
void getSwitchPath(std::string& path) const;
|
void getSwitchPath(std::string& path) const;
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ int main(int argc, char** argv)
|
||||||
obj.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
obj.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
obj.setInstructionType(user_set.getInstType());
|
obj.setIs64BitInstruction(user_set.getIs64BitInstruction());
|
||||||
obj.setListApi(user_set.isListApi());
|
obj.setListApi(user_set.isListApi());
|
||||||
obj.setListSymbols(user_set.isListSymbols());
|
obj.setListSymbols(user_set.isListSymbols());
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ int main(int argc, char** argv)
|
||||||
obj.setCliOutputMode(user_set.getCliOutputMode());
|
obj.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
obj.setVerifyMode(user_set.isVerifyFile());
|
obj.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
obj.setInstructionType(user_set.getInstType());
|
obj.setIs64BitInstruction(user_set.getIs64BitInstruction());
|
||||||
obj.setListApi(user_set.isListApi());
|
obj.setListApi(user_set.isListApi());
|
||||||
obj.setListSymbols(user_set.isListSymbols());
|
obj.setListSymbols(user_set.isListSymbols());
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
#define APP_NAME "NSTool"
|
#define APP_NAME "NSTool"
|
||||||
#define BIN_NAME "nstool"
|
#define BIN_NAME "nstool"
|
||||||
#define VER_MAJOR 1
|
#define VER_MAJOR 1
|
||||||
#define VER_MINOR 2
|
#define VER_MINOR 3
|
||||||
#define VER_PATCH 0
|
#define VER_PATCH 0
|
||||||
#define AUTHORS "jakcron"
|
#define AUTHORS "jakcron"
|
Loading…
Reference in a new issue