diff --git a/.gitignore b/.gitignore index 2498fdd..8e47c60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bin/* +data/* *.o *.a *.so.* diff --git a/SWITCH_KEYS.md b/SWITCH_KEYS.md index 038dd1e..2bb3efd 100644 --- a/SWITCH_KEYS.md +++ b/SWITCH_KEYS.md @@ -29,36 +29,49 @@ nca_body_keak_ocean_source : Used with master_key_##, aes_kek_generation_s nca_body_keak_system_source : Used with master_key_##, aes_kek_generation_source and aes_key_generation_source to generate nca_body_keak_system_##. (0x10 bytes) ; Package1 keys -package1_key_## : AES128 Key (0x10 bytes) +package1_key_## : AES128 Key (0x10 bytes) ; Package2 Keys -package2_key_## : AES128 Key (0x10 bytes) -package2_sign_key_modulus : RSA2048 Modulus (0x100 bytes) -package2_sign_key_private : RSA2048 Private Exponent (0x100 bytes) +package2_key_## : AES128 Key (0x10 bytes) +package2_sign_key_modulus : RSA2048 Modulus (0x100 bytes) +package2_sign_key_private : RSA2048 Private Exponent (0x100 bytes) ; Ticket Keys -ticket_commonkey_## : AES128 Key (0x10 bytes) +ticket_commonkey_## : AES128 Key (0x10 bytes) ; PKI Root Signing Key -pki_root_sign_key_modulus : RSA4096 Modulus (0x200 bytes) -pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes) +pki_root_sign_key_modulus : RSA4096 Modulus (0x200 bytes) +pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes) ; NCA Keys -nca_header_key : AES128-XTS Key (0x20 bytes) -nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes) -nca_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes) -nca_body_keak_application_## : AES128 Key (0x10 bytes) -nca_body_keak_ocean_## : AES128 Key (0x10 bytes) -nca_body_keak_system_## : AES128 Key (0x10 bytes) +nca_header_key : AES128-XTS Key (0x20 bytes) +nca_header_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes) +nca_header_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes) +nca_body_keak_application_## : AES128 Key (0x10 bytes) +nca_body_keak_ocean_## : 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_header_key : AES128 Key (0x10 bytes) -xci_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes) -xci_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes) +xci_header_key : AES128 Key (0x10 bytes) +xci_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes) +xci_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes) ; ACID Keys -acid_sign_key_modulus : RSA2048 Modulus (0x100 bytes) -acid_sign_key_private : RSA2048 Private Exponent (0x100 bytes) +acid_sign_key_##_modulus : RSA2048 Modulus (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 diff --git a/deps/libfnd b/deps/libfnd index 98a6f62..234c81d 160000 --- a/deps/libfnd +++ b/deps/libfnd @@ -1 +1 @@ -Subproject commit 98a6f623361781e5bf4efbec0477efa9729de2cd +Subproject commit 234c81d864e53cd208bb93bce69a1f5ff7e44161 diff --git a/deps/libnintendo-hac b/deps/libnintendo-hac index 112f9b5..9372cb3 160000 --- a/deps/libnintendo-hac +++ b/deps/libnintendo-hac @@ -1 +1 @@ -Subproject commit 112f9b59a3914dcc06a2713de8c7cd67112c57bb +Subproject commit 9372cb34d8ffdf4c84cc7a25ec9e675fdaff32c6 diff --git a/src/CnmtProcess.cpp b/src/CnmtProcess.cpp index 6faef8c..8e8c4ed 100644 --- a/src/CnmtProcess.cpp +++ b/src/CnmtProcess.cpp @@ -60,42 +60,59 @@ void CnmtProcess::importCnmt() 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 << " 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 << " Type: " << nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()) << " (" << std::dec << mCnmt.getContentMetaType() << ")" << std::endl; - std::cout << " Attributes: 0x" << std::hex << (uint32_t)mCnmt.getAttributes() << std::endl; - if (mCnmt.getAttributes() != 0) + 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 << (uint32_t)mCnmt.getContentMetaType() << ")" << std::endl; + std::cout << " Attributes: 0x" << std::hex << mCnmt.getAttribute().to_ullong(); + if (mCnmt.getAttribute().any()) { - for (size_t bit = 0; bit < (sizeof(byte_t)*8); bit++) + std::vector 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 << "]"; } - std::cout << " RequiredDownloadSystemVersion: v" << mCnmt.getRequiredDownloadSystemVersion() << " (" << _SPLIT_VER(mCnmt.getRequiredDownloadSystemVersion()) << ")"<< std::endl; + 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()) { - case (nn::hac::cnmt::METATYPE_APPLICATION): + case (nn::hac::cnmt::ContentMetaType::Application): std::cout << " ApplicationExtendedHeader:" << std::endl; - std::cout << " RequiredSystemVersion: v" << std::dec << mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion() << " (" << _SPLIT_VER(mCnmt.getApplicationMetaExtendedHeader().getRequiredSystemVersion()) << ")"<< std::endl; - std::cout << " PatchId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getApplicationMetaExtendedHeader().getPatchId() << 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; break; - case (nn::hac::cnmt::METATYPE_PATCH): + case (nn::hac::cnmt::ContentMetaType::Patch): 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; break; - case (nn::hac::cnmt::METATYPE_ADD_ON_CONTENT): + case (nn::hac::cnmt::ContentMetaType::AddOnContent): 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; break; - case (nn::hac::cnmt::METATYPE_DELTA): + case (nn::hac::cnmt::ContentMetaType::Delta): std::cout << " DeltaMetaExtendedHeader:" << std::endl; std::cout << " ApplicationId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mCnmt.getDeltaMetaExtendedHeader().getApplicationId() << std::endl; break; @@ -109,8 +126,8 @@ void CnmtProcess::displayCnmt() { const nn::hac::ContentInfo& info = mCnmt.getContentInfo()[i]; std::cout << " " << std::dec << i << std::endl; - std::cout << " Type: " << nn::hac::ContentMetaUtil::getContentTypeAsString(info.getContentType()) << " (" << std::dec << info.getContentType() << ")" << std::endl; - std::cout << " Id: " << fnd::SimpleTextOutput::arrayToString(info.getContentId().data, nn::hac::cnmt::kContentIdLen, false, "") << 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(), info.getContentId().size(), false, "") << 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; } @@ -118,33 +135,88 @@ void CnmtProcess::displayCnmt() if (mCnmt.getContentMetaInfo().size() > 0) { 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++) { - const nn::hac::ContentMetaInfo& info = mCnmt.getContentMetaInfo()[i]; - std::cout << " " << std::dec << i << std::endl; - std::cout << " Id: 0x" << std::hex << std::setw(16) << std::setfill('0') << info.getTitleId() << std::endl; - std::cout << " Version: v" << std::dec << info.getTitleVersion() << " (" << _SPLIT_VER(info.getTitleVersion()) << ")"<< 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) + 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) { - for (size_t bit = 0; bit < (sizeof(byte_t)*8); bit++) + std::cout << " ReferToBase: " << std::boolalpha << variation_info[i].meta.empty() << std::endl; + if (variation_info[i].meta.empty() == false) { - if (_HAS_BIT(info.getAttributes(), bit)) - { - std::cout << " > " << nn::hac::ContentMetaUtil::getContentMetaAttributeAsString((nn::hac::cnmt::ContentMetaAttribute)bit) << std::endl; - } + std::cout << " ContentMeta:" << std::endl; + displayContentMetaInfoList(variation_info[i].meta, " "); } } } - } + } - std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data, nn::hac::cnmt::kDigestLen, false, "") << std::endl; + -#undef _SPLIT_VER + std::cout << " Digest: " << fnd::SimpleTextOutput::arrayToString(mCnmt.getDigest().data(), mCnmt.getDigest().size(), false, "") << std::endl; } -const char* CnmtProcess::getBoolStr(bool state) const +void CnmtProcess::displayContentMetaInfo(const nn::hac::ContentMetaInfo& content_meta_info, const std::string& prefix) { - return state? "TRUE" : "FALSE"; + 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 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& 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]; + std::cout << prefix << std::dec << i << std::endl; + displayContentMetaInfo(info, prefix + " "); + std::cout << std::endl; + } } \ No newline at end of file diff --git a/src/CnmtProcess.h b/src/CnmtProcess.h index aa75790..2353f68 100644 --- a/src/CnmtProcess.h +++ b/src/CnmtProcess.h @@ -32,5 +32,6 @@ private: void importCnmt(); 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& content_meta_info_list, const std::string& prefix); }; \ No newline at end of file diff --git a/src/GameCardProcess.cpp b/src/GameCardProcess.cpp index 7271023..b0cfb4a 100644 --- a/src/GameCardProcess.cpp +++ b/src/GameCardProcess.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "GameCardProcess.h" GameCardProcess::GameCardProcess() : @@ -138,9 +140,9 @@ void GameCardProcess::displayHeader() } if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { + 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 << " 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 << " TitleKeyDecIndex: " << std::dec << (uint32_t)mHdr.getTitleKeyDecIndex() << 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, 0x10, true, ":") << std::endl; @@ -190,32 +192,45 @@ void GameCardProcess::displayHeader() if (mProccessExtendedHeader) { std::cout << "[GameCard Extended Header]" << std::endl; - std::cout << " FwVersion: v" << std::dec << mHdr.getFwVersion() << "(" << nn::hac::GameCardUtil::getCardFwVersionDescriptionAsString((nn::hac::gc::FwVersion)mHdr.getFwVersion()) << ")" << std::endl; + std::cout << " FwVersion: v" << std::dec << mHdr.getFwVersion() << " (" << nn::hac::GameCardUtil::getCardFwVersionDescriptionAsString((nn::hac::gc::FwVersion)mHdr.getFwVersion()) << ")" << std::endl; std::cout << " AccCtrl1: 0x" << std::hex << mHdr.getAccCtrl1() << std::endl; std::cout << " CardClockRate: " << nn::hac::GameCardUtil::getCardClockRateAsString((nn::hac::gc::CardClockRate)mHdr.getAccCtrl1()) << std::endl; std::cout << " Wait1TimeRead: 0x" << std::hex << mHdr.getWait1TimeRead() << std::endl; std::cout << " Wait2TimeRead: 0x" << std::hex << mHdr.getWait2TimeRead() << std::endl; std::cout << " Wait1TimeWrite: 0x" << std::hex << mHdr.getWait1TimeWrite() << std::endl; std::cout << " Wait2TimeWrite: 0x" << std::hex << mHdr.getWait2TimeWrite() << std::endl; - std::cout << " FwMode: 0x" << std::hex << 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 << " 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 << (uint32_t) mHdr.getCompatibilityType() << ")" << 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: v" << std::dec << mHdr.getUppVersion() << " (" << _SPLIT_VER(mHdr.getUppVersion()) << ")" << std::endl; -#undef _SPLIT_VER + std::cout << " CUP Version: " << nn::hac::ContentMetaUtil::getVersionAsString(mHdr.getUppVersion()) << " (v" << std::dec << mHdr.getUppVersion() << ")" << 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 use_salt, byte_t salt) +{ + fnd::Vec scratch; + fnd::sha::sSha256Hash calc_hash; + if (use_salt) + { + scratch.alloc(len + 1); + scratch.data()[len] = salt; + } + else + { + scratch.alloc(len); + } + + (*mFile)->read(scratch.data(), offset, len); + fnd::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes); + + return calc_hash.compare(test_hash); +} + bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) { - fnd::Vec scratch; - fnd::sha::sSha256Hash calc_hash; - scratch.alloc(len); - (*mFile)->read(scratch.data(), offset, scratch.size()); - fnd::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes); - return calc_hash.compare(test_hash); + return validateRegionOfFile(offset, len, test_hash, false, 0); } void GameCardProcess::validateXciSignature() @@ -231,7 +246,7 @@ void GameCardProcess::validateXciSignature() 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; } diff --git a/src/GameCardProcess.h b/src/GameCardProcess.h index 4f4b43c..b32ec0f 100644 --- a/src/GameCardProcess.h +++ b/src/GameCardProcess.h @@ -69,6 +69,7 @@ private: void importHeader(); 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); void validateXciSignature(); void processRootPfs(); diff --git a/src/KeyConfiguration.cpp b/src/KeyConfiguration.cpp index 1698eab..8164091 100644 --- a/src/KeyConfiguration.cpp +++ b/src/KeyConfiguration.cpp @@ -16,9 +16,7 @@ KeyConfiguration::KeyConfiguration(const KeyConfiguration& other) void KeyConfiguration::operator=(const KeyConfiguration& other) { - mAcidSignKey = other.mAcidSignKey; mPkg2SignKey = other.mPkg2SignKey; - mContentArchiveHeader0SignKey = other.mContentArchiveHeader0SignKey; mXciHeaderSignKey = other.mXciHeaderSignKey; mContentArchiveHeaderKey = other.mContentArchiveHeaderKey; @@ -26,6 +24,9 @@ void KeyConfiguration::operator=(const KeyConfiguration& other) 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]; mPkg1Key[i] = other.mPkg1Key[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_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; fnd::Vec 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_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_3_STRINGS(kXciHeaderBase[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], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20); // Store Key Variants/Derivatives 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[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_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 @@ -119,20 +128,23 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path) _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10); // 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); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyModulus), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size); + // legacy header nca key name + _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_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kPrivateStr), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kModulusStr), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.modulus, fnd::rsa::kRsa2048Size); + // legacy acid header key name + _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(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kPrivateStr), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size); + _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kModulusStr), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyPrivate), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyModulus), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size); + _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 @@ -193,9 +205,9 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path) void KeyConfiguration::clearGeneralKeyConfiguration() { - mAcidSignKey = kNullRsa2048Key; + mPkg2SignKey = kNullRsa2048Key; - mContentArchiveHeader0SignKey = kNullRsa2048Key; + mXciHeaderSignKey = kNullRsa2048Key; mPkiRootKeyList.clear(); @@ -204,6 +216,9 @@ void KeyConfiguration::clearGeneralKeyConfiguration() for (size_t i = 0; i < kMasterKeyNum; i++) { + mAcidSignKey[i] = kNullRsa2048Key; + mContentArchiveHeader0SignKey[i] = kNullRsa2048Key; + mNrrCertificateSignKey[i] = kNullRsa2048Key; mPkg1Key[i] = kNullAesKey; mPkg2Key[i] = kNullAesKey; mETicketCommonKey[i] = kNullAesKey; @@ -225,14 +240,26 @@ bool KeyConfiguration::getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) 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; + } + + return copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey[key_generation], key, kNullRsa2048Key); } -bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key) const +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 @@ -284,6 +311,17 @@ bool KeyConfiguration::getNcaExternalContentKey(const byte_t rights_id[nn::hac:: 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 { if (masterkey_index >= kMasterKeyNum) diff --git a/src/KeyConfiguration.h b/src/KeyConfiguration.h index cbf2060..4a112c6 100644 --- a/src/KeyConfiguration.h +++ b/src/KeyConfiguration.h @@ -25,8 +25,8 @@ public: // nca keys bool getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key) const; - bool getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key) const; - bool getAcidSignKey(fnd::rsa::sRsa2048Key& key) const; + bool getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) 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 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); 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 bool getPkg1Key(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 kContentArchiveHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" }; 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 kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" }; 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 kKekStr = "kek"; const std::string kSourceStr = "source"; - const std::string kRsaKeyModulus = "sign_key_modulus"; - const std::string kRsaKeyPrivate = "sign_key_private"; + const std::string kSignKey = "sign_key"; + const std::string kModulusStr = "modulus"; + const std::string kPrivateStr = "private"; 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"}; @@ -167,7 +172,7 @@ private: /* general key config */ // acid - fnd::rsa::sRsa2048Key mAcidSignKey; + fnd::rsa::sRsa2048Key mAcidSignKey[kMasterKeyNum]; // pkg1 and pkg2 fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum]; @@ -175,11 +180,14 @@ private: fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum]; // nca - fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey; + fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey[kMasterKeyNum]; fnd::aes::sAesXts128Key mContentArchiveHeaderKey; fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum]; fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum]; + // nrr + fnd::rsa::sRsa2048Key mNrrCertificateSignKey[kMasterKeyNum]; + // xci fnd::rsa::sRsa2048Key mXciHeaderSignKey; fnd::aes::sAes128Key mXciHeaderKey; diff --git a/src/KipProcess.cpp b/src/KipProcess.cpp index b980efb..2c787e2 100644 --- a/src/KipProcess.cpp +++ b/src/KipProcess.cpp @@ -8,8 +8,6 @@ #include #include -#include - KipProcess::KipProcess(): mFile(), @@ -145,12 +143,12 @@ void KipProcess::displayHeader() { std::cout << "[KIP Header]" << std::endl; std::cout << " Meta:" << 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 << " ProcessCategory: " << nn::hac::KernelInitialProcessUtil::getProcessCategoryAsString(mHdr.getProcessCategory()) << std::endl; - std::cout << " InstructionType: " << getInstructionTypeStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_INSTRUCTION_64BIT)) << std::endl; - std::cout << " AddrSpaceWidth: " << getAddressSpaceStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_ADDR_SPACE_64BIT)) << std::endl; - std::cout << " MemoryPool: " << getMemoryPoolStr(mHdr.getFlagList().hasElement(nn::hac::kip::FLAG_USE_SYSTEM_POOL_PARTITION)) << 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 << " Version: v" << std::dec << mHdr.getVersion() << std::endl; + std::cout << " Is64BitInstruction: " << std::boolalpha << mHdr.getIs64BitInstructionFlag() << std::endl; + std::cout << " Is64BitAddressSpace: " << std::boolalpha << mHdr.getIs64BitAddressSpaceFlag() << std::endl; + std::cout << " UseSecureMemory: " << std::boolalpha << mHdr.getUseSecureMemoryFlag() << std::endl; std::cout << " Program Sections:" << std::endl; std::cout << " .text:" << std::endl; if (_HAS_BIT(mCliOutputMode, OUTPUT_LAYOUT)) @@ -197,25 +195,15 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) if (kern.getSystemCalls().isSet()) { - fnd::List syscalls = kern.getSystemCalls().getSystemCalls(); + auto syscall_ids = kern.getSystemCalls().getSystemCallIds(); std::cout << " SystemCalls:" << std::endl; - std::cout << " "; - size_t lineLen = 0; - for (size_t i = 0; i < syscalls.size(); i++) + std::vector syscall_names; + for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) { - if (lineLen > 60) - { - lineLen = 0; - std::cout << std::endl; - std::cout << " "; - } - std::string syscall_string = nn::hac::KernelCapabilityUtil::getSystemCallAsString(syscalls[i]); - std::cout << syscall_string; - if (syscalls[i] != syscalls.atBack()) - std::cout << ", "; - lineLen += syscall_string.length(); + if (syscall_ids.test(syscall_id)) + syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id))); } - std::cout << std::endl; + fnd::SimpleTextOutput::dumpStringList(syscall_names, 60, 4); } if (kern.getMemoryMaps().isSet()) { @@ -225,12 +213,12 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) std::cout << " MemoryMaps:" << std::endl; 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; 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()) @@ -253,7 +241,7 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) } 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()) { @@ -265,36 +253,14 @@ void KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) } if (kern.getMiscFlags().isSet()) { - fnd::List flagList = kern.getMiscFlags().getFlagList(); - + auto misc_flags = kern.getMiscFlags().getMiscFlags(); std::cout << " Misc Flags:" << std::endl; - for (uint32_t i = 0; i < flagList.size(); i++) + std::vector misc_flags_names; + for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++) { - if (i % 10 == 0) - { - 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; + if (misc_flags.test(misc_flags_bit)) + misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit))); } + fnd::SimpleTextOutput::dumpStringList(misc_flags_names, 60, 4); } -} - -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"; } \ No newline at end of file diff --git a/src/KipProcess.h b/src/KipProcess.h index 47a88f2..09580e1 100644 --- a/src/KipProcess.h +++ b/src/KipProcess.h @@ -32,8 +32,4 @@ private: void importCodeSegments(); void displayHeader(); 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; }; \ No newline at end of file diff --git a/src/MetaProcess.cpp b/src/MetaProcess.cpp index 5e9b0ae..c299704 100644 --- a/src/MetaProcess.cpp +++ b/src/MetaProcess.cpp @@ -8,6 +8,8 @@ #include #include +#include + MetaProcess::MetaProcess() : mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), @@ -21,8 +23,8 @@ void MetaProcess::process() if (mVerify) { - validateAcidSignature(mMeta.getAcid()); - validateAciFromAcid(mMeta.getAci(), mMeta.getAcid()); + validateAcidSignature(mMeta.getAccessControlInfoDesc(), mMeta.getAccessControlInfoDescKeyGeneration()); + validateAciFromAcid(mMeta.getAccessControlInfo(), mMeta.getAccessControlInfoDesc()); } if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC)) @@ -31,18 +33,18 @@ void MetaProcess::process() displayMetaHeader(mMeta); // aci binary - displayAciHdr(mMeta.getAci()); - displayFac(mMeta.getAci().getFileSystemAccessControl()); - displaySac(mMeta.getAci().getServiceAccessControl()); - displayKernelCap(mMeta.getAci().getKernelCapabilities()); + displayAciHdr(mMeta.getAccessControlInfo()); + displayFac(mMeta.getAccessControlInfo().getFileSystemAccessControl()); + displaySac(mMeta.getAccessControlInfo().getServiceAccessControl()); + displayKernelCap(mMeta.getAccessControlInfo().getKernelCapabilities()); // acid binary if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - displayAciDescHdr(mMeta.getAcid()); - displayFac(mMeta.getAcid().getFileSystemAccessControl()); - displaySac(mMeta.getAcid().getServiceAccessControl()); - displayKernelCap(mMeta.getAcid().getKernelCapabilities()); + displayAciDescHdr(mMeta.getAccessControlInfoDesc()); + displayFac(mMeta.getAccessControlInfoDesc().getFileSystemAccessControl()); + displaySac(mMeta.getAccessControlInfoDesc().getServiceAccessControl()); + displayKernelCap(mMeta.getAccessControlInfoDesc().getKernelCapabilities()); } } } @@ -87,11 +89,11 @@ void MetaProcess::importMeta() 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 { 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(); 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; } - 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; - for (size_t j = 0; j < acid.getFileSystemAccessControl().getFsaRightsList().size() && fsaRightFound == false; j++) + if (fs_access.test(i) && desc_fs_access.test(i) == false) { - if (aci.getFileSystemAccessControl().getFsaRightsList()[i] == acid.getFileSystemAccessControl().getFsaRightsList()[j]) - fsaRightFound = true; - } - - if (fsaRightFound == false) - { - - std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << nn::hac::FileSystemAccessUtil::getFsaRightAsString(aci.getFileSystemAccessControl().getFsaRightsList()[i]) << " not permitted)" << std::endl; + std::cout << "[WARNING] ACI/FAC FsaRights: FAIL (" << nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(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; } // 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; - for (size_t j = 0; j < acid.getKernelCapabilities().getSystemCalls().getSystemCalls().size() && rightFound == false; j++) + if (syscall_ids.test(i) && desc_syscall_ids.test(i) == false) { - if (aci.getKernelCapabilities().getSystemCalls().getSystemCalls()[i] == acid.getKernelCapabilities().getSystemCalls().getSystemCalls()[j]) - 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; + std::cout << "[WARNING] ACI/KC SystemCallList: FAIL (" << nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(i)) << " not permitted)" << std::endl; } } // check memory maps @@ -223,9 +214,9 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con 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++) @@ -239,9 +230,9 @@ void MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo& aci, con 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 @@ -277,29 +268,26 @@ 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; } // 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; - for (size_t j = 0; j < acid.getKernelCapabilities().getMiscFlags().getFlagList().size() && rightFound == false; j++) + if (misc_flags.test(i) && desc_misc_flags.test(i) == false) { - if (aci.getKernelCapabilities().getMiscFlags().getFlagList()[i] == acid.getKernelCapabilities().getMiscFlags().getFlagList()[j]) - 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; - } + std::cout << "[WARNING] ACI/KC MiscFlag: FAIL (" << nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(i)) << " not permitted)" << std::endl; + } } } void MetaProcess::displayMetaHeader(const nn::hac::Meta& hdr) { std::cout << "[Meta Header]" << std::endl; - std::cout << " ACID KeyGeneration: " << std::dec << hdr.getAcidKeyGeneration() << std::endl; - std::cout << " Process Architecture Params:" << std::endl; - std::cout << " Ins. Type: " << nn::hac::MetaUtil::getInstructionTypeAsString(hdr.getInstructionType()) << std::endl; - std::cout << " Addr Space: " << nn::hac::MetaUtil::getProcAddressSpaceTypeAsString(hdr.getProcAddressSpaceType()) << std::endl; + std::cout << " ACID KeyGeneration: " << std::dec << (uint32_t)hdr.getAccessControlInfoDescKeyGeneration() << std::endl; + std::cout << " Flags:" << std::endl; + std::cout << " Is64BitInstruction: " << std::boolalpha << hdr.getIs64BitInstructionFlag() << 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 << " Priority: " << std::dec << (uint32_t)hdr.getMainThreadPriority() << std::endl; std::cout << " CpuId: " << std::dec << (uint32_t)hdr.getMainThreadCpuId() << std::endl; @@ -322,15 +310,10 @@ void MetaProcess::displayAciHdr(const nn::hac::AccessControlInfo& aci) void MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc& acid) { std::cout << "[Access Control Info Desc]" << std::endl; - if (acid.getFlagList().size() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - { - std::cout << " Flags: " << std::endl; - for (size_t i = 0; i < acid.getFlagList().size(); i++) - { - 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 << " Flags: " << std::endl; + std::cout << " Production: " << std::boolalpha << acid.getProductionFlag() << std::endl; + std::cout << " Unqualified Approval: " << std::boolalpha << acid.getUnqualifiedApprovalFlag() << 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 << " Min: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().min << std::endl; std::cout << " Max: 0x" << std::hex << std::setw(16) << std::setfill('0') << acid.getProgramIdRestrict().max << std::endl; @@ -341,22 +324,37 @@ void MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac) std::cout << "[FS Access Control]" << 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; - for (size_t i = 0; i < fac.getFsaRightsList().size(); i++) + std::cout << " FsAccess:" << std::endl; + // 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::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 + else + { + 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)fac.getFsaRightsList()[i] << ")"; - if (fac.getFsaRightsList()[i] != fac.getFsaRightsList().atBack()) - std::cout << ", "; + std::cout << " (bit " << std::dec << (uint32_t)flag << ")"; } 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 List:" << std::endl; + std::vector service_name_list; for (size_t i = 0; i < sac.getServiceList().size(); i++) { - if (i % 10 == 0) - { - if (i != 0) - std::cout << std::endl; - std::cout << " "; - } - std::cout << sac.getServiceList()[i].getName(); - if (sac.getServiceList()[i].isServer()) - std::cout << "(isSrv)"; - if (sac.getServiceList()[i] != sac.getServiceList().atBack()) - std::cout << ", "; + service_name_list.push_back(sac.getServiceList()[i].getName() + (sac.getServiceList()[i].isServer() ? "(isSrv)" : "")); } - std::cout << std::endl; + fnd::SimpleTextOutput::dumpStringList(service_name_list, 60, 4); } void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) @@ -418,40 +407,30 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) if (kern.getSystemCalls().isSet()) { - fnd::List syscalls = kern.getSystemCalls().getSystemCalls(); + auto syscall_ids = kern.getSystemCalls().getSystemCallIds(); std::cout << " SystemCalls:" << std::endl; - std::cout << " "; - size_t lineLen = 0; - for (size_t i = 0; i < syscalls.size(); i++) + std::vector syscall_names; + for (size_t syscall_id = 0; syscall_id < syscall_ids.size(); syscall_id++) { - if (lineLen > 60) - { - lineLen = 0; - std::cout << std::endl; - std::cout << " "; - } - std::string syscall_name = nn::hac::KernelCapabilityUtil::getSystemCallAsString(syscalls[i]); - std::cout << syscall_name; - if (syscalls[i] != syscalls.atBack()) - std::cout << ", "; - lineLen += syscall_name.length(); + if (syscall_ids.test(syscall_id)) + syscall_names.push_back(nn::hac::KernelCapabilityUtil::getSystemCallIdAsString(nn::hac::kc::SystemCallId(syscall_id))); } - std::cout << std::endl; + fnd::SimpleTextOutput::dumpStringList(syscall_names, 60, 4); } if (kern.getMemoryMaps().isSet()) { - fnd::List maps = kern.getMemoryMaps().getMemoryMaps(); - fnd::List ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); + auto maps = kern.getMemoryMaps().getMemoryMaps(); + auto ioMaps = kern.getMemoryMaps().getIoMemoryMaps(); std::cout << " MemoryMaps:" << std::endl; 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; 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()) @@ -474,7 +453,7 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) } 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()) { @@ -486,21 +465,14 @@ void MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityControl& kern) } if (kern.getMiscFlags().isSet()) { - fnd::List flagList = kern.getMiscFlags().getFlagList(); - + auto misc_flags = kern.getMiscFlags().getMiscFlags(); std::cout << " Misc Flags:" << std::endl; - for (uint32_t i = 0; i < flagList.size(); i++) + std::vector misc_flags_names; + for (size_t misc_flags_bit = 0; misc_flags_bit < misc_flags.size(); misc_flags_bit++) { - if (i % 10 == 0) - { - 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; + if (misc_flags.test(misc_flags_bit)) + misc_flags_names.push_back(nn::hac::KernelCapabilityUtil::getMiscFlagsBitAsString(nn::hac::kc::MiscFlagsBit(misc_flags_bit))); } + fnd::SimpleTextOutput::dumpStringList(misc_flags_names, 60, 4); } } \ No newline at end of file diff --git a/src/MetaProcess.h b/src/MetaProcess.h index 2c838bb..85618a5 100644 --- a/src/MetaProcess.h +++ b/src/MetaProcess.h @@ -34,7 +34,7 @@ private: 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 displayMetaHeader(const nn::hac::Meta& hdr); diff --git a/src/NacpProcess.cpp b/src/NacpProcess.cpp index 9ae16e9..78bfd4b 100644 --- a/src/NacpProcess.cpp +++ b/src/NacpProcess.cpp @@ -62,118 +62,431 @@ void NacpProcess::importNacp() void NacpProcess::displayNacp() { std::cout << "[ApplicationControlProperty]" << std::endl; - std::cout << " Menu Description:" << std::endl; - std::cout << " DisplayVersion: " << mNacp.getDisplayVersion() << std::endl; - if (mNacp.getIsbn().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) - std::cout << " ISBN: " << mNacp.getIsbn() << std::endl; - for (size_t i = 0; i < mNacp.getTitle().size(); i++) + + // Title + if (mNacp.getTitle().size() > 0) { - std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(mNacp.getTitle()[i].language) << " Title:" << std::endl; - std::cout << " Name: " << mNacp.getTitle()[i].name << std::endl; - 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; - for (size_t i = 0; i < mNacp.getPlayLogQueryableApplicationId().size(); i++) + std::cout << " Title:" << std::endl; + for (auto itr = mNacp.getTitle().begin(); itr != mNacp.getTitle().end(); itr++) { - std::cout << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getPlayLogQueryableApplicationId()[i] << std::endl; + std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getLanguageAsString(itr->language) << ":" << std::endl; + std::cout << " Name: " << itr->name << std::endl; + std::cout << " Publisher: " << itr->publisher << std::endl; } } - std::cout << " Parental Controls:" << std::endl; - std::cout << " ParentalControlFlag: " << nn::hac::ApplicationControlPropertyUtil::getParentalControlFlagAsString(mNacp.getParentalControlFlag()) << std::endl; - for (size_t i = 0; i < mNacp.getRatingAge().size(); i++) + else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - std::cout << " Age Restriction:" << 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; + std::cout << " Title: None" << std::endl; + } + + // Isbn + if (mNacp.getIsbn().empty() == false) + { + std::cout << " ISBN: " << mNacp.getIsbn() << std::endl; + } + else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + { + std::cout << " ISBN: (NotSet)" << std::endl; } - if (mNacp.getBcatPassphase().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + // StartupUserAccount + if (mNacp.getStartupUserAccount() != nn::hac::nacp::StartupUserAccount::None || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - std::cout << " BCAT:" << std::endl; - std::cout << " BcatPassphase: " << mNacp.getBcatPassphase() << std::endl; - std::cout << " DeliveryCacheStorageSize: 0x" << std::hex << mNacp.getBcatDeliveryCacheStorageSize() << std::endl; + std::cout << " StartupUserAccount: " << nn::hac::ApplicationControlPropertyUtil::getStartupUserAccountAsString(mNacp.getStartupUserAccount()) << std::endl; } - if (mNacp.getLocalCommunicationId().size() > 0) + + // UserAccountSwitchLock + if (mNacp.getUserAccountSwitchLock() != nn::hac::nacp::UserAccountSwitchLock::Disable || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - std::cout << " Local Area Communication:" << std::endl; - std::cout << " LocalCommunicationId:" << std::endl; - for (size_t i = 0; i < mNacp.getLocalCommunicationId().size(); i++) + 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 << " 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getLocalCommunicationId()[i] << std::endl; + std::cout << " " << nn::hac::ApplicationControlPropertyUtil::getAttributeFlagAsString(*itr) << 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)) + else if (_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; + std::cout << " Attribute: None" << std::endl; } - if (mNacp.getDeviceSaveDataSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + + // SupportedLanguage + if (mNacp.getSupportedLanguage().size() > 0) { - 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; + 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; + } } - if (mNacp.getUserAccountSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + else if (_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; + std::cout << " SupportedLanguage: None" << std::endl; } - if (mNacp.getDeviceSaveDataMax().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + + // ParentalControl + if (mNacp.getParentalControl().size() > 0) { - 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; + 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; + } } - if (mNacp.getTemporaryStorageSize() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + else if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - std::cout << " TemporaryStorageSize: " << nn::hac::ApplicationControlPropertyUtil::getSaveDataSizeAsString(mNacp.getTemporaryStorageSize()) << std::endl; + std::cout << " ParentalControl: None" << std::endl; } - if (mNacp.getCacheStorageSize().journal_size > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + + // Screenshot + if (mNacp.getScreenshot() != nn::hac::nacp::Screenshot::Allow || _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 << " Screenshot: " << nn::hac::ApplicationControlPropertyUtil::getScreenshotAsString(mNacp.getScreenshot()) << std::endl; } - std::cout << " Other Flags:" << 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; - std::cout << " HDCP: " << nn::hac::ApplicationControlPropertyUtil::getHdcpAsString(mNacp.getHdcp()) << std::endl; - std::cout << " ScreenshotMode: " << nn::hac::ApplicationControlPropertyUtil::getScreenshotModeAsString(mNacp.getScreenshotMode()) << std::endl; - std::cout << " VideoCaptureMode: " << nn::hac::ApplicationControlPropertyUtil::getVideoCaptureModeAsString(mNacp.getVideoCaptureMode()) << 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; - if (mNacp.getApplicationErrorCodeCategory().empty() == false || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + + // VideoCapture + if (mNacp.getVideoCapture() != nn::hac::nacp::VideoCapture::Disable || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) { - std::cout << " ApplicationErrorCodeCategory: " << mNacp.getApplicationErrorCodeCategory() << std::endl; + std::cout << " VideoCapture: " << nn::hac::ApplicationControlPropertyUtil::getVideoCaptureAsString(mNacp.getVideoCapture()) << std::endl; } - if (mNacp.getSeedForPsuedoDeviceId() > 0 || mNacp.getPresenceGroupId() > 0 || _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) + + // DataLossConfirmation + if (mNacp.getDataLossConfirmation() != nn::hac::nacp::DataLossConfirmation::None || _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; - 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; + std::cout << " DataLossConfirmation: " << nn::hac::ApplicationControlPropertyUtil::getDataLossConfirmationAsString(mNacp.getDataLossConfirmation()) << std::endl; + } + + // PlayLogPolicy + 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; + } + 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 << " SeedForPsuedoDeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << mNacp.getSeedForPsuedoDeviceId() << 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; } } \ No newline at end of file diff --git a/src/NcaProcess.cpp b/src/NcaProcess.cpp index 334af7b..51cad14 100644 --- a/src/NcaProcess.cpp +++ b/src/NcaProcess.cpp @@ -232,14 +232,14 @@ void NcaProcess::generatePartitionConfiguration() { // get reference to relevant structures 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 sPartitionInfo& info = mPartitions[partition.header_index]; // validate 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) { error.clear(); @@ -265,16 +265,16 @@ void NcaProcess::generatePartitionConfiguration() info.format_type = (nn::hac::nca::FormatType)fs_header.format_type; info.hash_type = (nn::hac::nca::HashType)fs_header.hash_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; fnd::List hash_layers; fnd::LayeredIntegrityMetadata::sLayer data_layer; fnd::List master_hash_list; // 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++) { fnd::LayeredIntegrityMetadata::sLayer layer; @@ -298,15 +298,15 @@ void NcaProcess::generatePartitionConfiguration() info.layered_intergrity_metadata.setDataLayerInfo(data_layer); 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; fnd::List hash_layers; fnd::LayeredIntegrityMetadata::sLayer data_layer; fnd::List 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++) { fnd::LayeredIntegrityMetadata::sLayer layer; @@ -336,27 +336,27 @@ void NcaProcess::generatePartitionConfiguration() // filter out unrecognised format types switch (info.format_type) { - case (nn::hac::nca::FORMAT_PFS0): - case (nn::hac::nca::FORMAT_ROMFS): + case (nn::hac::nca::FormatType::PartitionFs): + case (nn::hac::nca::FormatType::RomFs): break; default: error.clear(); - error << "FormatType(" << info.format_type << "): UNKNOWN"; + error << "FormatType(" << nn::hac::ContentArchiveUtil::getFormatTypeAsString(info.format_type) << "): UNKNOWN"; throw fnd::Exception(kModuleName, error.str()); } // 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); } - 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) 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); } - 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 << "EncryptionType(" << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << "): UNSUPPORTED"; @@ -365,19 +365,19 @@ void NcaProcess::generatePartitionConfiguration() else { error.clear(); - error << "EncryptionType(" << info.enc_type << "): UNKNOWN"; + error << "EncryptionType(" << nn::hac::ContentArchiveUtil::getEncryptionTypeAsString(info.enc_type) << "): UNKNOWN"; throw fnd::Exception(kModuleName, error.str()); } // 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); } - else if (info.hash_type != nn::hac::nca::HASH_NONE) + else if (info.hash_type != nn::hac::nca::HashType::None) { error.clear(); - error << "HashType(" << info.hash_type << "): UNKNOWN"; + error << "HashType(" << nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_type) << "): UNKNOWN"; throw fnd::Exception(kModuleName, error.str()); } } @@ -392,16 +392,16 @@ void NcaProcess::validateNcaSignatures() { // validate signature[0] 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) { std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl; } // 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) { @@ -417,10 +417,12 @@ void NcaProcess::validateNcaSignatures() MetaProcess npdm; 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.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; } @@ -446,17 +448,16 @@ void NcaProcess::validateNcaSignatures() void NcaProcess::displayHeader() { 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 << " Content Type: " << nn::hac::ContentArchiveUtil::getContentTypeAsString(mHdr.getContentType()) << 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 << " 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 << " 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.: v" << std::dec << mHdr.getSdkAddonVersion() << " (" << _SPLIT_VER(mHdr.getSdkAddonVersion()) << ")" << std::endl; -#undef _SPLIT_VER + std::cout << " SdkAddon Ver.: " << nn::hac::ContentArchiveUtil::getSdkAddonVersionAsString(mHdr.getSdkAddonVersion()) << " (v" << std::dec << mHdr.getSdkAddonVersion() << ")" << std::endl; if (mHdr.hasRightsId()) { 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 << " Hash Type: " << nn::hac::ContentArchiveUtil::getHashTypeAsString(info.hash_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::AesIncrementCounter(info.aes_ctr.iv, info.offset>>4, ctr.iv); std::cout << " AesCtr Counter:" << 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; 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; } } - 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; std::cout << " HierarchicalSha256 Header:" << std::endl; @@ -569,13 +570,13 @@ void NcaProcess::processPartitions() continue; } - if (partition.format_type == nn::hac::nca::FORMAT_PFS0) + if (partition.format_type == nn::hac::nca::FormatType::PartitionFs) { PfsProcess pfs; pfs.setInputFile(partition.reader); pfs.setCliOutputMode(mCliOutputMode); 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)); } @@ -588,13 +589,13 @@ void NcaProcess::processPartitions() pfs.setExtractPath(mPartitionPath[index].path); pfs.process(); } - else if (partition.format_type == nn::hac::nca::FORMAT_ROMFS) + else if (partition.format_type == nn::hac::nca::FormatType::RomFs) { RomfsProcess romfs; romfs.setInputFile(partition.reader); romfs.setCliOutputMode(mCliOutputMode); 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)); } @@ -616,22 +617,22 @@ const char* NcaProcess::getContentTypeForMountStr(nn::hac::nca::ContentType cont switch (cont_type) { - case (nn::hac::nca::TYPE_PROGRAM): + case (nn::hac::nca::ContentType::Program): str = "program"; break; - case (nn::hac::nca::TYPE_META): + case (nn::hac::nca::ContentType::Meta): str = "meta"; break; - case (nn::hac::nca::TYPE_CONTROL): + case (nn::hac::nca::ContentType::Control): str = "control"; break; - case (nn::hac::nca::TYPE_MANUAL): + case (nn::hac::nca::ContentType::Manual): str = "manual"; break; - case (nn::hac::nca::TYPE_DATA): + case (nn::hac::nca::ContentType::Data): str = "data"; break; - case (nn::hac::nca::TYPE_PUBLIC_DATA): + case (nn::hac::nca::ContentType::PublicData): str = "publicdata"; break; default: diff --git a/src/NroProcess.cpp b/src/NroProcess.cpp index ca7401b..465c1cc 100644 --- a/src/NroProcess.cpp +++ b/src/NroProcess.cpp @@ -43,9 +43,9 @@ void NroProcess::setVerifyMode(bool 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) diff --git a/src/NroProcess.h b/src/NroProcess.h index b019208..2ef222f 100644 --- a/src/NroProcess.h +++ b/src/NroProcess.h @@ -22,7 +22,7 @@ public: void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); - void setInstructionType(nn::hac::meta::InstructionType type); + void setIs64BitInstruction(bool flag); void setListApi(bool listApi); void setListSymbols(bool listSymbols); diff --git a/src/NsoProcess.cpp b/src/NsoProcess.cpp index 7db1e16..7b8db33 100644 --- a/src/NsoProcess.cpp +++ b/src/NsoProcess.cpp @@ -9,7 +9,10 @@ NsoProcess::NsoProcess(): mFile(), 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; } -void NsoProcess::setInstructionType(nn::hac::meta::InstructionType type) +void NsoProcess::setIs64BitInstruction(bool flag) { - mRoMeta.setInstructionType(type); + mRoMeta.setIs64BitInstruction(flag); } void NsoProcess::setListApi(bool listApi) diff --git a/src/NsoProcess.h b/src/NsoProcess.h index 70b2f31..2d29784 100644 --- a/src/NsoProcess.h +++ b/src/NsoProcess.h @@ -21,7 +21,7 @@ public: void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); - void setInstructionType(nn::hac::meta::InstructionType type); + void setIs64BitInstruction(bool flag); void setListApi(bool listApi); void setListSymbols(bool listSymbols); @@ -32,7 +32,7 @@ private: fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; - nn::hac::meta::InstructionType mInstructionType; + bool mIs64BitInstruction; bool mListApi; bool mListSymbols; diff --git a/src/RoMetadataProcess.cpp b/src/RoMetadataProcess.cpp index 3025fbf..81e9b47 100644 --- a/src/RoMetadataProcess.cpp +++ b/src/RoMetadataProcess.cpp @@ -7,7 +7,7 @@ RoMetadataProcess::RoMetadataProcess() : mCliOutputMode(_BIT(OUTPUT_BASIC)), - mInstructionType(nn::hac::meta::INSTR_64BIT), + mIs64BitInstruction(true), mListApi(false), mListSymbols(false), mApiInfo(), @@ -57,9 +57,9 @@ void RoMetadataProcess::setCliOutputMode(CliOutputMode 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) @@ -92,6 +92,11 @@ const std::vector& RoMetadataProcess::getPrivateApiList() const return mPrivateApiList; } +const std::vector& RoMetadataProcess::getGuidelineApiList() const +{ + return mGuidelineApiList; +} + const fnd::List& RoMetadataProcess::getSymbolList() const { return mSymbolList.getSymbolList(); @@ -113,20 +118,32 @@ void RoMetadataProcess::importApiList() { SdkApiString api(api_str); - if (api.getApiType() == SdkApiString::API_SDK_VERSION) + switch (api.getApiType()) + { + case SdkApiString::API_SDK_VERSION: mSdkVerApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_MIDDLEWARE) + break; + case SdkApiString::API_MIDDLEWARE: mPublicApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_DEBUG) + break; + case SdkApiString::API_DEBUG: mDebugApiList.push_back(api); - else if (api.getApiType() == SdkApiString::API_PRIVATE) + break; + case SdkApiString::API_PRIVATE: mPrivateApiList.push_back(api); + break; + case SdkApiString::API_GUIDELINE: + mGuidelineApiList.push_back(api); + break; + default: + break; + } } } 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; } } + 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))) { diff --git a/src/RoMetadataProcess.h b/src/RoMetadataProcess.h index bef72d9..df854c1 100644 --- a/src/RoMetadataProcess.h +++ b/src/RoMetadataProcess.h @@ -24,7 +24,7 @@ public: void setCliOutputMode(CliOutputMode type); - void setInstructionType(nn::hac::meta::InstructionType type); + void setIs64BitInstruction(bool flag); void setListApi(bool listApi); void setListSymbols(bool listSymbols); @@ -32,12 +32,13 @@ public: const std::vector& getPublicApiList() const; const std::vector& getDebugApiList() const; const std::vector& getPrivateApiList() const; + const std::vector& getGuidelineApiList() const; const fnd::List& getSymbolList() const; private: const std::string kModuleName = "RoMetadataProcess"; CliOutputMode mCliOutputMode; - nn::hac::meta::InstructionType mInstructionType; + bool mIs64BitInstruction; bool mListApi; bool mListSymbols; @@ -56,6 +57,7 @@ private: std::vector mPublicApiList; std::vector mDebugApiList; std::vector mPrivateApiList; + std::vector mGuidelineApiList; ElfSymbolParser mSymbolList; diff --git a/src/SdkApiString.cpp b/src/SdkApiString.cpp index 2268fd6..1f3c9e6 100644 --- a/src/SdkApiString.cpp +++ b/src/SdkApiString.cpp @@ -81,6 +81,14 @@ void SdkApiString::resolveApiString(const std::string& full_str) { mApiType = API_PRIVATE; } + else if (api_type == kSdkGuidelineApiString) + { + mApiType = API_GUIDELINE; + } + else + { + // TODO? + } mVenderName = vender; mModuleName = module; diff --git a/src/SdkApiString.h b/src/SdkApiString.h index 5c794df..c1a8ffa 100644 --- a/src/SdkApiString.h +++ b/src/SdkApiString.h @@ -9,7 +9,8 @@ public: API_MIDDLEWARE, API_DEBUG, API_PRIVATE, - API_SDK_VERSION + API_SDK_VERSION, + API_GUIDELINE, }; SdkApiString(const std::string& full_str); @@ -32,6 +33,7 @@ private: const std::string kSdkMiddleWareApiString = "SDK MW"; const std::string kSdkDebugApiString = "SDK Debug"; const std::string kSdkPrivateApiString = "SDK Private"; + const std::string kSdkGuidelineApiString = "SDK Guideline"; const std::string kVenderNintendo = "Nintendo"; const std::string kSdkVersionString = "NintendoSdk_nnSdk-"; diff --git a/src/UserSettings.cpp b/src/UserSettings.cpp index 97fae08..eb2b772 100644 --- a/src/UserSettings.cpp +++ b/src/UserSettings.cpp @@ -138,9 +138,9 @@ bool UserSettings::isListSymbols() const return mListSymbols; } -nn::hac::meta::InstructionType UserSettings::getInstType() const +bool UserSettings::getIs64BitInstruction() const { - return mInstructionType; + return mIs64BitInstruction; } const sOptional& UserSettings::getXciUpdatePath() const @@ -564,9 +564,9 @@ void UserSettings::populateUserSettings(sCmdArgs& args) // determine the architecture type for NSO/NRO if (args.inst_type.isSet) - mInstructionType = getInstructionTypeFromString(*args.inst_type); + mIs64BitInstruction = getIs64BitInstructionFromString(*args.inst_type); else - mInstructionType = nn::hac::meta::INSTR_64BIT; // default 64bit + mIs64BitInstruction = true; // default 64bit mListApi = args.list_api.isSet; mListSymbols = args.list_sym.isSet; @@ -758,33 +758,43 @@ bool UserSettings::determineValidCnmtFromSample(const fnd::Vec& sample) if (sample.size() < minimum_size) return false; - if (data->type == nn::hac::cnmt::METATYPE_APPLICATION) + // include exthdr/data check if applicable + if (data->exhdr_size.get() > 0) { - 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()) - return false; - } - else if (data->type == nn::hac::cnmt::METATYPE_PATCH) - { - 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()) - return false; + 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)); + if ((meta->patch_id.get() & data->id.get()) != data->id.get()) + return false; + } + 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)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; - minimum_size += meta->extended_data_size.get(); - } - else if (data->type == nn::hac::cnmt::METATYPE_ADD_ON_CONTENT) - { - 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()) - return false; - } - else if (data->type == nn::hac::cnmt::METATYPE_DELTA) - { - 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()) - return false; + minimum_size += meta->extended_data_size.get(); + } + 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)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; + } + 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)); + if ((meta->application_id.get() & data->id.get()) != meta->application_id.get()) + return false; - 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) @@ -800,7 +810,7 @@ bool UserSettings::determineValidNacpFromSample(const fnd::Vec& sample) 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; if (data->display_version[0] == 0) @@ -862,20 +872,20 @@ bool UserSettings::determineValidEsTikFromSample(const fnd::Vec& sample) 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::transform(str.begin(), str.end(), str.begin(), ::tolower); - nn::hac::meta::InstructionType type; + bool flag; if (str == "32bit") - type = nn::hac::meta::INSTR_32BIT; + flag = false; else if (str == "64bit") - type = nn::hac::meta::INSTR_64BIT; + flag = true; else throw fnd::Exception(kModuleName, "Unsupported instruction type: " + str); - return type; + return flag; } void UserSettings::getHomePath(std::string& path) const @@ -912,10 +922,19 @@ void UserSettings::dumpKeyConfig() const std::cout << "[KeyConfiguration]" << std::endl; std::cout << " NCA Keys:" << std::endl; - if (mKeyCfg.getContentArchiveHeader0SignKey(rsa2048_key) == true) - dumpRsa2048Key(rsa2048_key, "Header Signature[0] Key", 2); + for (size_t i = 0; i < kMasterKeyNum; i++) + { + 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) - dumpAesXtsKey(aesxts_key, "Header Encryption Key", 2); + dumpAesXtsKey(aesxts_key, "Header-EncryptionKey", 2); for (size_t i = 0; i < kMasterKeyNum; i++) { @@ -937,15 +956,20 @@ void UserSettings::dumpKeyConfig() const 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; 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) - 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; diff --git a/src/UserSettings.h b/src/UserSettings.h index dff6153..379fb9b 100644 --- a/src/UserSettings.h +++ b/src/UserSettings.h @@ -29,7 +29,7 @@ public: bool isListFs() const; bool isListApi() const; bool isListSymbols() const; - nn::hac::meta::InstructionType getInstType() const; + bool getIs64BitInstruction() const; // specialised paths const sOptional& getXciUpdatePath() const; @@ -114,7 +114,7 @@ private: bool mListApi; bool mListSymbols; - nn::hac::meta::InstructionType mInstructionType; + bool mIs64BitInstruction; void populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args); void populateKeyset(sCmdArgs& args); @@ -126,7 +126,7 @@ private: bool determineValidNacpFromSample(const fnd::Vec& sample) const; bool determineValidEsCertFromSample(const fnd::Vec& sample) const; bool determineValidEsTikFromSample(const fnd::Vec& 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 getSwitchPath(std::string& path) const; diff --git a/src/main.cpp b/src/main.cpp index 5e0e45b..bad4a3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -141,7 +141,7 @@ int main(int argc, char** argv) obj.setCliOutputMode(user_set.getCliOutputMode()); obj.setVerifyMode(user_set.isVerifyFile()); - obj.setInstructionType(user_set.getInstType()); + obj.setIs64BitInstruction(user_set.getIs64BitInstruction()); obj.setListApi(user_set.isListApi()); obj.setListSymbols(user_set.isListSymbols()); @@ -155,7 +155,7 @@ int main(int argc, char** argv) obj.setCliOutputMode(user_set.getCliOutputMode()); obj.setVerifyMode(user_set.isVerifyFile()); - obj.setInstructionType(user_set.getInstType()); + obj.setIs64BitInstruction(user_set.getIs64BitInstruction()); obj.setListApi(user_set.isListApi()); obj.setListSymbols(user_set.isListSymbols()); diff --git a/src/version.h b/src/version.h index 5089bc4..f518f46 100644 --- a/src/version.h +++ b/src/version.h @@ -2,6 +2,6 @@ #define APP_NAME "NSTool" #define BIN_NAME "nstool" #define VER_MAJOR 1 -#define VER_MINOR 2 +#define VER_MINOR 3 #define VER_PATCH 0 #define AUTHORS "jakcron" \ No newline at end of file