From 09e6b8a85755d15222d1a36b7b4537713a15cae3 Mon Sep 17 00:00:00 2001 From: jakcron Date: Fri, 1 Oct 2021 17:39:34 +0800 Subject: [PATCH] Move some files around to test each process as it's ported. --- src/AssetProcess.cpp | 20 +-- src/AssetProcess.h | 4 +- src/CnmtProcess.cpp | 3 +- src/EsTikProcess.cpp | 143 +++++++++-------- src/EsTikProcess.h | 11 +- src/GameCardProcess.h | 8 +- src/IniProcess.h | 5 +- src/KeyBag.h | 1 + src/NcaProcess.h | 28 ++-- src/NroProcess.h | 6 +- src/PfsProcess.h | 5 +- src/PkiValidator.cpp | 53 ++----- src/RomfsProcess.h | 9 +- src/Settings.cpp | 26 ++- src/Settings.h | 1 + src/main.cpp | 176 +++++++++++---------- src/{ => not_ported}/GameCardProcess.cpp | 0 src/{ => not_ported}/IniProcess.cpp | 0 src/{ => not_ported}/KipProcess.cpp | 0 src/{ => not_ported}/MetaProcess.cpp | 0 src/{ => not_ported}/NacpProcess.cpp | 0 src/{ => not_ported}/NcaProcess.cpp | 0 src/{ => not_ported}/NroProcess.cpp | 0 src/{ => not_ported}/NsoProcess.cpp | 0 src/{ => not_ported}/PfsProcess.cpp | 0 src/{ => not_ported}/PkiCertProcess.cpp | 0 src/{ => not_ported}/RoMetadataProcess.cpp | 0 src/{ => not_ported}/RomfsProcess.cpp | 0 src/types.h | 1 + src/util.cpp | 6 +- 30 files changed, 258 insertions(+), 248 deletions(-) rename src/{ => not_ported}/GameCardProcess.cpp (100%) rename src/{ => not_ported}/IniProcess.cpp (100%) rename src/{ => not_ported}/KipProcess.cpp (100%) rename src/{ => not_ported}/MetaProcess.cpp (100%) rename src/{ => not_ported}/NacpProcess.cpp (100%) rename src/{ => not_ported}/NcaProcess.cpp (100%) rename src/{ => not_ported}/NroProcess.cpp (100%) rename src/{ => not_ported}/NsoProcess.cpp (100%) rename src/{ => not_ported}/PfsProcess.cpp (100%) rename src/{ => not_ported}/PkiCertProcess.cpp (100%) rename src/{ => not_ported}/RoMetadataProcess.cpp (100%) rename src/{ => not_ported}/RomfsProcess.cpp (100%) diff --git a/src/AssetProcess.cpp b/src/AssetProcess.cpp index ffc0d1e..06873d6 100644 --- a/src/AssetProcess.cpp +++ b/src/AssetProcess.cpp @@ -35,7 +35,7 @@ void nstool::AssetProcess::setVerifyMode(bool verify) void nstool::AssetProcess::setListFs(bool list) { - mRomfs.setListFs(list); + //mRomfs.setListFs(list); } void nstool::AssetProcess::setIconExtractPath(const tc::io::Path& path) @@ -50,7 +50,7 @@ void nstool::AssetProcess::setNacpExtractPath(const tc::io::Path& path) void nstool::AssetProcess::setRomfsExtractPath(const tc::io::Path& path) { - mRomfs.setExtractPath(path); + //mRomfs.setExtractPath(path); } @@ -95,11 +95,11 @@ void nstool::AssetProcess::processSections() writeSubStreamToFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size, mNacpExtractPath.get()); } - mNacp.setInputFile(std::make_shared(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size)); - mNacp.setCliOutputMode(mCliOutputMode); - mNacp.setVerifyMode(mVerify); + //mNacp.setInputFile(std::make_shared(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size)); + //mNacp.setCliOutputMode(mCliOutputMode); + //mNacp.setVerifyMode(mVerify); - mNacp.process(); + //mNacp.process(); } if (mHdr.getRomfsInfo().size > 0) @@ -107,11 +107,11 @@ void nstool::AssetProcess::processSections() if ((mHdr.getRomfsInfo().size + mHdr.getRomfsInfo().offset) > file_size) throw tc::Exception(mModuleName, "ASET geometry for romfs beyond file size"); - mRomfs.setInputFile(std::make_shared(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); - mRomfs.setCliOutputMode(mCliOutputMode); - mRomfs.setVerifyMode(mVerify); + //mRomfs.setInputFile(std::make_shared(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); + //mRomfs.setCliOutputMode(mCliOutputMode); + //mRomfs.setVerifyMode(mVerify); - mRomfs.process(); + //mRomfs.process(); } } diff --git a/src/AssetProcess.h b/src/AssetProcess.h index 5d1ea5b..a2ce24b 100644 --- a/src/AssetProcess.h +++ b/src/AssetProcess.h @@ -36,8 +36,8 @@ private: tc::Optional mNacpExtractPath; nn::hac::AssetHeader mHdr; - NacpProcess mNacp; - RomfsProcess mRomfs; + //NacpProcess mNacp; + //RomfsProcess mRomfs; void importHeader(); void processSections(); diff --git a/src/CnmtProcess.cpp b/src/CnmtProcess.cpp index 75a46c4..785c453 100644 --- a/src/CnmtProcess.cpp +++ b/src/CnmtProcess.cpp @@ -44,7 +44,6 @@ void nstool::CnmtProcess::importCnmt() { throw tc::Exception(mModuleName, "No file reader set."); } - // check if file_size is greater than 20MB, don't import. size_t cnmt_file_size = tc::io::IOUtil::castInt64ToSize(mFile->length()); @@ -68,7 +67,7 @@ void nstool::CnmtProcess::displayCnmt() fmt::print("[ContentMeta]\n"); fmt::print(" TitleId: 0x{:016x}\n", mCnmt.getTitleId()); fmt::print(" Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()), mCnmt.getTitleVersion()); - fmt::print(" Type: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType()); + fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType()); fmt::print(" Attributes: 0x{:x}", *((byte_t*)&cnmt_hdr->attributes)); if (mCnmt.getAttribute().size()) { diff --git a/src/EsTikProcess.cpp b/src/EsTikProcess.cpp index 561b6fb..78ee18a 100644 --- a/src/EsTikProcess.cpp +++ b/src/EsTikProcess.cpp @@ -1,14 +1,10 @@ -#include -#include -#include -#include -#include #include "EsTikProcess.h" #include "PkiValidator.h" - +#include nstool::EsTikProcess::EsTikProcess() : + mModuleName("nstool::EsTikProcess"), mFile(), mCliOutputMode(true, false, false, false), mVerify(false) @@ -53,16 +49,23 @@ void nstool::EsTikProcess::setVerifyMode(bool verify) void nstool::EsTikProcess::importTicket() { - tc::ByteData scratch; - - - if (*mFile == nullptr) + if (mFile == nullptr) { - throw tc::Exception(kModuleName, "No file reader set."); + throw tc::Exception(mModuleName, "No file reader set."); } - scratch.alloc((*mFile)->size()); - (*mFile)->read(scratch.data(), 0, scratch.size()); + // check if file_size is greater than 20MB, don't import. + size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length()); + if (file_size > (0x100000 * 20)) + { + throw tc::Exception(mModuleName, "File too large."); + } + + // read cnmt + tc::ByteData scratch = tc::ByteData(file_size); + mFile->seek(0, tc::io::SeekOrigin::Begin); + mFile->read(scratch.data(), scratch.size()); + mTik.fromBytes(scratch.data(), scratch.size()); } @@ -74,12 +77,12 @@ void nstool::EsTikProcess::verifyTicket() switch (nn::pki::sign::getHashAlgo(mTik.getSignature().getSignType())) { case (nn::pki::sign::HASH_ALGO_SHA1): - tik_hash.alloc(fnd::sha::kSha1HashLen); - fnd::sha::Sha1(mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size(), tik_hash.data()); + tik_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize); + tc::crypto::GenerateSha1Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size()); break; case (nn::pki::sign::HASH_ALGO_SHA256): - tik_hash.alloc(fnd::sha::kSha256HashLen); - fnd::sha::Sha256(mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size(), tik_hash.data()); + tik_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize); + tc::crypto::GenerateSha256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size()); break; } @@ -91,85 +94,73 @@ void nstool::EsTikProcess::verifyTicket() } catch (const tc::Exception& e) { - std::cout << "[WARNING] Ticket signature could not be validated (" << e.error() << ")" << std::endl; + fmt::print("[WARNING] Ticket signature could not be validated ({:s})\n", e.error()); } } void nstool::EsTikProcess::displayTicket() { -#define _SPLIT_VER(ver) (uint32_t)((ver>>10) & 0x3f) << "." << (uint32_t)((ver>>4) & 0x3f) << "." << (uint32_t)((ver>>0) & 0xf) - const nn::es::TicketBody_V2& body = mTik.getBody(); - std::cout << "[ES Ticket]" << std::endl; - - std::cout << " SignType: " << getSignTypeStr(mTik.getSignature().getSignType()); + fmt::print("[ES Ticket]\n"); + fmt::print(" SignType: {:s}", getSignTypeStr(mTik.getSignature().getSignType())); if (mCliOutputMode.show_extended_info) - std::cout << " (0x" << std::hex << mTik.getSignature().getSignType() << ")"; - std::cout << std::endl; + fmt::print(" (0x{:x})", mTik.getSignature().getSignType()); + fmt::print("\n"); - std::cout << " Issuer: " << body.getIssuer() << std::endl; - std::cout << " Title Key:" << std::endl; - std::cout << " EncMode: " << getTitleKeyPersonalisationStr(body.getTitleKeyEncType()) << std::endl; - std::cout << " KeyGeneration: " << std::dec << (uint32_t)body.getCommonKeyId() << std::endl; + fmt::print(" Issuer: {:s}\n", body.getIssuer()); + fmt::print(" Title Key:\n"); + fmt::print(" EncMode: {:s}\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType())); + fmt::print(" KeyGeneration: {:d}\n", (uint32_t)body.getCommonKeyId()); if (body.getTitleKeyEncType() == nn::es::ticket::RSA2048) { - std::cout << " Data:" << std::endl; - for (size_t i = 0; i < 0x10; i++) - std::cout << " " << fnd::SimpleTextOutput::arrayToString(body.getEncTitleKey() + 0x10*i, 0x10, true, ":") << std::endl; + fmt::print(" Data:\n"); + fmt::print(" {:s}", tc::cli::FormatUtil::formatBytesAsStringWithLineLimit(body.getEncTitleKey(), 0x100, true, ":", 0x10, 6, false)); } else if (body.getTitleKeyEncType() == nn::es::ticket::AES128_CBC) { - std::cout << " Data:" << std::endl; - std::cout << " " << fnd::SimpleTextOutput::arrayToString(body.getEncTitleKey(), 0x10, true, ":") << std::endl; + fmt::print(" Data:\n"); + fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getEncTitleKey(), 0x10, true, ":")); } else { - std::cout << " Data: " << std::endl; + fmt::print(" Data: \n"); } - - std::cout << " Version: v" << _SPLIT_VER(body.getTicketVersion()); - if (mCliOutputMode.show_extended_info) - std::cout << " (" << (uint32_t)body.getTicketVersion() << ")"; - std::cout << std::endl; - - std::cout << " License Type: " << getLicenseTypeStr(body.getLicenseType()) << std::endl; - + fmt::print(" Version: {:s} (v{:d})\n", getTitleVersionStr(body.getTicketVersion()), body.getTicketVersion()); + fmt::print(" License Type: {:s}\n", getLicenseTypeStr(body.getLicenseType())); if (body.getPropertyFlags().size() > 0) { - std::cout << " Flags:" << std::endl; + nn::es::sTicketBody_v2* raw_body = (nn::es::sTicketBody_v2*)body.getBytes().data(); + fmt::print(" PropertyMask: 0x{:04x}\n", ((tc::bn::le16*)&raw_body->property_mask)->unwrap()); for (size_t i = 0; i < body.getPropertyFlags().size(); i++) { - std::cout << " " << getPropertyFlagStr(body.getPropertyFlags()[i]) << std::endl; + fmt::print(" {:s}\n", getPropertyFlagStr(body.getPropertyFlags()[i])); } } - if (mCliOutputMode.show_extended_info) { - std::cout << " Reserved Region:" << std::endl; - fnd::SimpleTextOutput::hexDump(body.getReservedRegion(), 8, 0x10, 4); + fmt::print(" Reserved Region:\n"); + fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getReservedRegion(), 8, true, "")); } if (body.getTicketId() != 0 || mCliOutputMode.show_extended_info) - std::cout << " TicketId: 0x" << std::hex << std::setw(16) << std::setfill('0') << body.getTicketId() << std::endl; + fmt::print(" TicketId: 0x{:016x}\n", body.getTicketId()); if (body.getDeviceId() != 0 || mCliOutputMode.show_extended_info) - std::cout << " DeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << body.getDeviceId() << std::endl; + fmt::print(" DeviceId: 0x{:016x}\n", body.getDeviceId()); - std::cout << " RightsId: " << std::endl << " "; - fnd::SimpleTextOutput::hexDump(body.getRightsId(), 16); + fmt::print(" RightsId: \n"); + fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getRightsId(), 16, true, "")); - std::cout << " SectionTotalSize: 0x" << std::hex << body.getSectionTotalSize() << std::endl; - std::cout << " SectionHeaderOffset: 0x" << std::hex << body.getSectionHeaderOffset() << std::endl; - std::cout << " SectionNum: 0x" << std::hex << body.getSectionNum() << std::endl; - std::cout << " SectionEntrySize: 0x" << std::hex << body.getSectionEntrySize() << std::endl; - -#undef _SPLIT_VER + fmt::print(" SectionTotalSize: 0x{:x}\n", body.getSectionTotalSize()); + fmt::print(" SectionHeaderOffset: 0x{:x}\n", body.getSectionHeaderOffset()); + fmt::print(" SectionNum: 0x{:x}\n", body.getSectionNum()); + fmt::print(" SectionEntrySize: 0x{:x}\n", body.getSectionEntrySize()); } -const char* nstool::EsTikProcess::getSignTypeStr(uint32_t type) const +std::string nstool::EsTikProcess::getSignTypeStr(uint32_t type) const { - const char* str = nullptr; + std::string str; switch(type) { case (nn::pki::sign::SIGN_ID_RSA4096_SHA1): @@ -197,9 +188,9 @@ const char* nstool::EsTikProcess::getSignTypeStr(uint32_t type) const return str; } -const char* nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) const +std::string nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) const { - const char* str = nullptr; + std::string str; switch(flag) { case (nn::es::ticket::AES128_CBC): @@ -209,15 +200,15 @@ const char* nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) con str = "Personalised (RSA2048)"; break; default: - str = "Unknown"; + str = fmt::format("Unknown ({:d})", flag); break; } return str; } -const char* nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const +std::string nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const { - const char* str = nullptr; + std::string str; switch(flag) { case (nn::es::ticket::LICENSE_PERMANENT): @@ -239,15 +230,15 @@ const char* nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const str = "Service"; break; default: - str = "Unknown"; + str = fmt::format("Unknown ({:d})", flag); break; } return str; } -const char* nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const +std::string nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const { - const char* str = nullptr; + std::string str; switch(flag) { case (nn::es::ticket::FLAG_PRE_INSTALL): @@ -259,9 +250,23 @@ const char* nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const case (nn::es::ticket::FLAG_ALLOW_ALL_CONTENT): str = "AllContent"; break; + case (nn::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT): + str = "DeviceLinkIndependent"; + break; + case (nn::es::ticket::FLAG_VOLATILE): + str = "Volatile"; + break; + case (nn::es::ticket::FLAG_ELICENSE_REQUIRED): + str = "ELicenseRequired"; + break; default: - str = "Unknown"; + str = fmt::format("Unknown ({:d})", flag); break; } return str; +} + +std::string nstool::EsTikProcess::getTitleVersionStr(uint16_t version) const +{ + return fmt::format("{:d}.{:d}.{:d}", ((version>>10) & 0x3f), ((version>>4) & 0x3f), ((version>>0) & 0xf)); } \ No newline at end of file diff --git a/src/EsTikProcess.h b/src/EsTikProcess.h index 075759c..d146b65 100644 --- a/src/EsTikProcess.h +++ b/src/EsTikProcess.h @@ -22,7 +22,7 @@ public: void setVerifyMode(bool verify); private: - const std::string kModuleName = "EsTikProcess"; + std::string mModuleName; std::shared_ptr mFile; KeyBag mKeyCfg; @@ -36,10 +36,11 @@ private: void importTicket(); void verifyTicket(); void displayTicket(); - const char* getSignTypeStr(uint32_t type) const; - const char* getTitleKeyPersonalisationStr(byte_t flag) const; - const char* getLicenseTypeStr(byte_t flag) const; - const char* getPropertyFlagStr(byte_t flag) const; + std::string getSignTypeStr(uint32_t type) const; + std::string getTitleKeyPersonalisationStr(byte_t flag) const; + std::string getLicenseTypeStr(byte_t flag) const; + std::string getPropertyFlagStr(byte_t flag) const; + std::string getTitleVersionStr(uint16_t version) const; }; } \ No newline at end of file diff --git a/src/GameCardProcess.h b/src/GameCardProcess.h index 61243b7..3f294a8 100644 --- a/src/GameCardProcess.h +++ b/src/GameCardProcess.h @@ -21,7 +21,7 @@ public: void setVerifyMode(bool verify); // xci specific - void setPartitionForExtract(const std::string& partition_name, const std::string& extract_path); + void setPartitionForExtract(const std::string& partition_name, const tc::io::Path& extract_path); void setListFs(bool list_fs); private: @@ -37,7 +37,7 @@ private: struct sExtractInfo { std::string partition_name; - std::string extract_path; + tc::io::Path extract_path; void operator=(const sExtractInfo& other) { @@ -45,7 +45,7 @@ private: extract_path = other.extract_path; } - bool operator==(const std::string& name) const + bool operator==(const tc::io::Path& name) const { return name == partition_name; } @@ -57,7 +57,7 @@ private: bool mIsSdkXciEncrypted; size_t mGcHeaderOffset; bool mProccessExtendedHeader; - byte_t mHdrSignature[fnd::rsa::kRsa2048Size]; + nn::hac::detail::rsa2048_signature_t mHdrSignature; fnd::sha::sSha256Hash mHdrHash; nn::hac::GameCardHeader mHdr; diff --git a/src/IniProcess.h b/src/IniProcess.h index 365f715..59499ae 100644 --- a/src/IniProcess.h +++ b/src/IniProcess.h @@ -17,7 +17,7 @@ public: void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); - void setKipExtractPath(const std::string& path); + void setKipExtractPath(const tc::io::Path& path); private: const std::string kModuleName = "IniProcess"; const std::string kKipExtention = ".kip"; @@ -27,8 +27,7 @@ private: CliOutputMode mCliOutputMode; bool mVerify; - bool mDoExtractKip; - std::string mKipExtractPath; + tc::Optional mKipExtractPath; nn::hac::IniHeader mHdr; std::vector> mKipList; diff --git a/src/KeyBag.h b/src/KeyBag.h index b83445d..0e3ab9b 100644 --- a/src/KeyBag.h +++ b/src/KeyBag.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/src/NcaProcess.h b/src/NcaProcess.h index 0f7538b..4a11c91 100644 --- a/src/NcaProcess.h +++ b/src/NcaProcess.h @@ -20,10 +20,10 @@ public: void setVerifyMode(bool verify); // nca specfic - void setPartition0ExtractPath(const std::string& path); - void setPartition1ExtractPath(const std::string& path); - void setPartition2ExtractPath(const std::string& path); - void setPartition3ExtractPath(const std::string& path); + void setPartition0ExtractPath(const tc::io::Path& path); + void setPartition1ExtractPath(const tc::io::Path& path); + void setPartition2ExtractPath(const tc::io::Path& path); + void setPartition3ExtractPath(const tc::io::Path& path); void setListFs(bool list_fs); private: @@ -36,11 +36,7 @@ private: CliOutputMode mCliOutputMode; bool mVerify; - struct sExtract - { - std::string path; - bool doExtract; - } mPartitionPath[nn::hac::nca::kPartitionNum]; + std::array, nn::hac::nca::kPartitionNum> mPartitionPath; bool mListFs; @@ -82,23 +78,25 @@ private: }; std::vector kak_list; - tc::Optional aes_ctr; + tc::Optional aes_ctr; } mContentKey; struct sPartitionInfo { std::shared_ptr reader; std::string fail_reason; - size_t offset; - size_t size; + int64_t offset; + int64_t size; // meta data nn::hac::nca::FormatType format_type; nn::hac::nca::HashType hash_type; nn::hac::nca::EncryptionType enc_type; - fnd::LayeredIntegrityMetadata layered_intergrity_metadata; - fnd::aes::sAesIvCtr aes_ctr; - } mPartitions[nn::hac::nca::kPartitionNum]; + //fnd::LayeredIntegrityMetadata layered_intergrity_metadata; + nn::hac::detail::aes_iv_t aes_ctr; + } + + std::array mPartitions; void importHeader(); void generateNcaBodyEncryptionKeys(); diff --git a/src/NroProcess.h b/src/NroProcess.h index 420b58d..efc8610 100644 --- a/src/NroProcess.h +++ b/src/NroProcess.h @@ -25,9 +25,9 @@ public: // for homebrew NROs with Asset blobs appended void setAssetListFs(bool list); - void setAssetIconExtractPath(const std::string& path); - void setAssetNacpExtractPath(const std::string& path); - void setAssetRomfsExtractPath(const std::string& path); + void setAssetIconExtractPath(const tc::io::Path& path); + void setAssetNacpExtractPath(const tc::io::Path& path); + void setAssetRomfsExtractPath(const tc::io::Path& path); const RoMetadataProcess& getRoMetadataProcess() const; private: diff --git a/src/PfsProcess.h b/src/PfsProcess.h index 2736809..50a482b 100644 --- a/src/PfsProcess.h +++ b/src/PfsProcess.h @@ -19,7 +19,7 @@ public: // pfs specific void setMountPointName(const std::string& mount_name); - void setExtractPath(const std::string& path); + void setExtractPath(const tc::io::Path& path); void setListFs(bool list_fs); const nn::hac::PartitionFsHeader& getPfsHeader() const; @@ -32,8 +32,7 @@ private: CliOutputMode mCliOutputMode; bool mVerify; - std::string mExtractPath; - bool mExtract; + tc::Optional mExtractPath; std::string mMountName; bool mListFs; diff --git a/src/PkiValidator.cpp b/src/PkiValidator.cpp index e25902a..861b15d 100644 --- a/src/PkiValidator.cpp +++ b/src/PkiValidator.cpp @@ -77,7 +77,7 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedDatasecond.key_type) { - throw tc::Exception(mModuleName, fmt::print("Public key for issuer \"{:s}\" cannot verify this signature.", issuer); + throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" cannot verify this signature.", issuer)); } if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240) @@ -129,7 +127,7 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki: if (issuer_pubk_type == nn::pki::cert::RSA4096 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096) { - rsa_key = issuer_cert.getRsa4098PublicKey(); + rsa_key = issuer_cert.getRsa4096PublicKey(); } else if (issuer_pubk_type == nn::pki::cert::RSA2048 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048) { @@ -148,42 +146,25 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki: // verify signature switch (signature_id) { - case (SIGN_ID_RSA4096_SHA1): - sig_validate_res = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key); + case (nn::pki::sign::SIGN_ID_RSA4096_SHA1): + sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key); break; - case (SIGN_ID_RSA2048_SHA1): - sig_validate_res = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key); + case (nn::pki::sign::SIGN_ID_RSA2048_SHA1): + sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key); break; - case (SIGN_ID_ECDSA240_SHA1): - sig_validate_res = false; + case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1): + sig_valid = false; break; - case (SIGN_ID_RSA4096_SHA256): - sig_validate_res = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key); + case (nn::pki::sign::SIGN_ID_RSA4096_SHA256): + sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key); break; - case (SIGN_ID_RSA2048_SHA256): - sig_validate_res = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key); + case (nn::pki::sign::SIGN_ID_RSA2048_SHA256): + sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key); break; - case (SIGN_ID_ECDSA240_SHA256): - sig_validate_res = false; + case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256): + sig_valid = false; break; } - if (sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096) - { - sig_validate_res = fnd::rsa::pkcs::rsaVerify(issuer_cert.getRsa4098PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); - } - else if (sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048) - { - sig_validate_res = fnd::rsa::pkcs::rsaVerify(issuer_cert.getRsa2048PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); - } - else if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240) - { - throw tc::Exception(mModuleName, "ECDSA signatures are not supported"); - } - else - { - throw tc::Exception(mModuleName, "Mismatch between issuer public key and signature type"); - } - if (sig_valid == false) { diff --git a/src/RomfsProcess.h b/src/RomfsProcess.h index dc39ff4..35575c4 100644 --- a/src/RomfsProcess.h +++ b/src/RomfsProcess.h @@ -45,8 +45,8 @@ public: struct sFile { std::string name; - uint64_t offset; - uint64_t size; + int64_t offset; + int64_t size; void operator=(const sFile& other) { @@ -84,7 +84,7 @@ public: // romfs specific void setMountPointName(const std::string& mount_name); - void setExtractPath(const std::string& path); + void setExtractPath(const tc::io::Path& path); void setListFs(bool list_fs); const sDirectory& getRootDir() const; @@ -101,8 +101,7 @@ private: bool mVerbose; bool mVerify; - std::string mExtractPath; - bool mExtract; + tc::Optional mExtractPath; std::string mMountName; bool mListFs; diff --git a/src/Settings.cpp b/src/Settings.cpp index a9a6bce..4e15cbb 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -349,6 +349,9 @@ private: nstool::SettingsInitializer::SettingsInitializer(const std::vector& args) : Settings(), mModuleLabel("nstool::SettingsInitializer"), + mShowLayout(false), + mShowKeydata(false), + mVerbose(false), mTitleKey(), mBodyKey(), mTikPath(), @@ -359,6 +362,23 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector& if (infile.path.isNull()) throw tc::ArgumentException(mModuleLabel, "No input file was specified."); + // determine CLI output mode + opt.cli_output_mode.show_basic_info = true; + if (mVerbose) + { + opt.cli_output_mode.show_extended_info = true; + opt.cli_output_mode.show_layout = true; + opt.cli_output_mode.show_keydata = true; + } + if (mShowKeydata) + { + opt.cli_output_mode.show_keydata = true; + } + if (mShowLayout) + { + opt.cli_output_mode.show_layout = true; + } + // locate key file, if not specfied if (mKeysetPath.isNull()) { @@ -431,9 +451,9 @@ void nstool::SettingsInitializer::parse_args(const std::vector& arg // none just yet // get option flags - opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.show_layout, {"--showlayout"}))); - opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.show_keydata, { "--showkeys" }))); - opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.verbose, {"-v", "--verbose"}))); + opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(mShowLayout, {"--showlayout"}))); + opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(mShowKeydata, { "--showkeys" }))); + opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(mVerbose, {"-v", "--verbose"}))); opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.verify, {"-y", "--verify"}))); opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.is_dev, {"-d", "--dev"}))); diff --git a/src/Settings.h b/src/Settings.h index 75564c1..6ba3f5c 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -138,6 +138,7 @@ private: bool mShowLayout; bool mShowKeydata; + bool mVerbose; tc::Optional mKeysetPath; tc::Optional mTitleKey; diff --git a/src/main.cpp b/src/main.cpp index 4c6ba2f..4a86c61 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,22 +2,22 @@ #include #include "Settings.h" -/* -#include "GameCardProcess.h" -#include "PfsProcess.h" -#include "RomfsProcess.h" -#include "NcaProcess.h" -#include "MetaProcess.h" + +//#include "GameCardProcess.h" +//#include "PfsProcess.h" +//#include "RomfsProcess.h" +//#include "NcaProcess.h" +//#include "MetaProcess.h" #include "CnmtProcess.h" -#include "NsoProcess.h" -#include "NroProcess.h" -#include "NacpProcess.h" -#include "IniProcess.h" -#include "KipProcess.h" -#include "PkiCertProcess.h" +//#include "NsoProcess.h" +//#include "NroProcess.h" +//#include "NacpProcess.h" +//#include "IniProcess.h" +//#include "KipProcess.h" +//#include "PkiCertProcess.h" #include "EsTikProcess.h" #include "AssetProcess.h" -*/ + int umain(const std::vector& args, const std::vector& env) { @@ -27,208 +27,214 @@ int umain(const std::vector& args, const std::vector& std::shared_ptr infile_stream = std::make_shared(tc::io::FileStream(set.infile.path.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read)); + /* if (set.infile.filetype == nstool::Settings::FILE_TYPE_GAMECARD) { - GameCardProcess obj; + nstool::GameCardProcess obj; obj.setInputFile(infile_stream); obj.setKeyCfg(set.opt.keybag); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); if (set.xci.update_extract_path.isSet()) obj.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, set.xci.update_extract_path.get()); if (set.xci.logo_extract_path.isSet()) obj.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, set.xci.logo_extract_path.get()); - if (user_set.getXciNormalPath().isSet()) - obj.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().get()); - if (user_set.getXciSecurePath().isSet()) - obj.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().get()); - obj.setListFs(user_set.isListFs()); + if (set.xci.normal_extract_path.isSet()) + obj.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, set.xci.normal_extract_path.get()); + if (set.xci.secure_extract_path.isSet()) + obj.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, set.xci.secure_extract_path.get()); + obj.setListFs(set.fs.show_fs_tree); obj.process(); } + */ + /* else if (set.infile.filetype == nstool::Settings::FILE_TYPE_PARTITIONFS || set.infile.filetype == nstool::Settings::FILE_TYPE_NSP) { - PfsProcess obj; + nstool::PfsProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - if (user_set.getFsPath().isSet()) - obj.setExtractPath(user_set.getFsPath().get()); - obj.setListFs(user_set.isListFs()); + if (set.fs.extract_path.isSet()) + obj.setExtractPath(set.fs.extract_path.get()); + obj.setListFs(set.fs.show_fs_tree); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_ROMFS) { - RomfsProcess obj; + nstool::RomfsProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - if (user_set.getFsPath().isSet()) - obj.setExtractPath(user_set.getFsPath().get()); - obj.setListFs(user_set.isListFs()); + if (set.fs.extract_path.isSet()) + obj.setExtractPath(set.fs.extract_path.get()); + obj.setListFs(set.fs.show_fs_tree); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NCA) { - NcaProcess obj; + nstool::NcaProcess obj; obj.setInputFile(infile_stream); obj.setKeyCfg(set.opt.keybag); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - if (user_set.getNcaPart0Path().isSet()) - obj.setPartition0ExtractPath(user_set.getNcaPart0Path().get()); - if (user_set.getNcaPart1Path().isSet()) - obj.setPartition1ExtractPath(user_set.getNcaPart1Path().get()); - if (user_set.getNcaPart2Path().isSet()) - obj.setPartition2ExtractPath(user_set.getNcaPart2Path().get()); - if (user_set.getNcaPart3Path().isSet()) - obj.setPartition3ExtractPath(user_set.getNcaPart3Path().get()); - obj.setListFs(user_set.isListFs()); + if (set.nca.part0_extract_path.isSet()) + obj.setPartition0ExtractPath(set.nca.part0_extract_path.get()); + if (set.nca.part1_extract_path.isSet()) + obj.setPartition1ExtractPath(set.nca.part1_extract_path.get()); + if (set.nca.part2_extract_path.isSet()) + obj.setPartition2ExtractPath(set.nca.part2_extract_path.get()); + if (set.nca.part3_extract_path.isSet()) + obj.setPartition3ExtractPath(set.nca.part3_extract_path.get()); + obj.setListFs(set.fs.show_fs_tree); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_META) { - MetaProcess obj; + nstool::MetaProcess obj; obj.setInputFile(infile_stream); obj.setKeyCfg(set.opt.keybag); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } - else if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT) + + else*/ if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT) { - CnmtProcess obj; + nstool::CnmtProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } + /* else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NSO) { - NsoProcess obj; + nstool::NsoProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - obj.setIs64BitInstruction(user_set.getIs64BitInstruction()); - obj.setListApi(user_set.isListApi()); - obj.setListSymbols(user_set.isListSymbols()); + obj.setIs64BitInstruction(set.code.is_64bit_instruction); + obj.setListApi(set.code.list_api); + obj.setListSymbols(set.code.list_symbols); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NRO) { - NroProcess obj; + nstool::NroProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - obj.setIs64BitInstruction(user_set.getIs64BitInstruction()); - obj.setListApi(user_set.isListApi()); - obj.setListSymbols(user_set.isListSymbols()); + obj.setIs64BitInstruction(set.code.is_64bit_instruction); + obj.setListApi(set.code.list_api); + obj.setListSymbols(set.code.list_symbols); - if (user_set.getAssetIconPath().isSet()) - obj.setAssetIconExtractPath(user_set.getAssetIconPath().get()); - if (user_set.getAssetNacpPath().isSet()) - obj.setAssetNacpExtractPath(user_set.getAssetNacpPath().get()); + if (set.aset.icon_extract_path.isSet()) + obj.setAssetIconExtractPath(set.aset.icon_extract_path.get()); + if (set.aset.nacp_extract_path.isSet()) + obj.setAssetNacpExtractPath(set.aset.nacp_extract_path.get()); - if (user_set.getFsPath().isSet()) - obj.setAssetRomfsExtractPath(user_set.getFsPath().get()); - obj.setAssetListFs(user_set.isListFs()); + if (set.fs.extract_path.isSet()) + obj.setAssetRomfsExtractPath(set.fs.extract_path.get()); + obj.setAssetListFs(set.fs.show_fs_tree); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NACP) { - NacpProcess obj; + nstool::NacpProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_INI) { - IniProcess obj; + nstool::IniProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - if (user_set.getKipExtractPath().isSet()) - obj.setKipExtractPath(user_set.getKipExtractPath().get()); + if (set.kip.extract_path.isSet()) + obj.setKipExtractPath(set.kip.extract_path.get()); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_KIP) { - KipProcess obj; + nstool::KipProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_PKI_CERT) { - PkiCertProcess obj; + nstool::PkiCertProcess obj; obj.setInputFile(infile_stream); obj.setKeyCfg(set.opt.keybag); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } + */ else if (set.infile.filetype == nstool::Settings::FILE_TYPE_ES_TIK) { - EsTikProcess obj; + nstool::EsTikProcess obj; obj.setInputFile(infile_stream); obj.setKeyCfg(set.opt.keybag); - obj.setCertificateChain(user_set.getCertificateChain()); - obj.setCliOutputMode(user_set.getCliOutputMode()); + //obj.setCertificateChain(user_set.getCertificateChain()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); obj.process(); } else if (set.infile.filetype == nstool::Settings::FILE_TYPE_HB_ASSET) { - AssetProcess obj; + nstool::AssetProcess obj; obj.setInputFile(infile_stream); - obj.setCliOutputMode(user_set.getCliOutputMode()); + obj.setCliOutputMode(set.opt.cli_output_mode); obj.setVerifyMode(set.opt.verify); - if (user_set.getAssetIconPath().isSet()) - obj.setIconExtractPath(user_set.getAssetIconPath().get()); - if (user_set.getAssetNacpPath().isSet()) - obj.setNacpExtractPath(user_set.getAssetNacpPath().get()); + if (set.aset.icon_extract_path.isSet()) + obj.setIconExtractPath(set.aset.icon_extract_path.get()); + if (set.aset.nacp_extract_path.isSet()) + obj.setNacpExtractPath(set.aset.nacp_extract_path.get()); - if (user_set.getFsPath().isSet()) - obj.setRomfsExtractPath(user_set.getFsPath().get()); - obj.setListFs(user_set.isListFs()); + if (set.fs.extract_path.isSet()) + obj.setRomfsExtractPath(set.fs.extract_path.get()); + obj.setListFs(set.fs.show_fs_tree); obj.process(); } diff --git a/src/GameCardProcess.cpp b/src/not_ported/GameCardProcess.cpp similarity index 100% rename from src/GameCardProcess.cpp rename to src/not_ported/GameCardProcess.cpp diff --git a/src/IniProcess.cpp b/src/not_ported/IniProcess.cpp similarity index 100% rename from src/IniProcess.cpp rename to src/not_ported/IniProcess.cpp diff --git a/src/KipProcess.cpp b/src/not_ported/KipProcess.cpp similarity index 100% rename from src/KipProcess.cpp rename to src/not_ported/KipProcess.cpp diff --git a/src/MetaProcess.cpp b/src/not_ported/MetaProcess.cpp similarity index 100% rename from src/MetaProcess.cpp rename to src/not_ported/MetaProcess.cpp diff --git a/src/NacpProcess.cpp b/src/not_ported/NacpProcess.cpp similarity index 100% rename from src/NacpProcess.cpp rename to src/not_ported/NacpProcess.cpp diff --git a/src/NcaProcess.cpp b/src/not_ported/NcaProcess.cpp similarity index 100% rename from src/NcaProcess.cpp rename to src/not_ported/NcaProcess.cpp diff --git a/src/NroProcess.cpp b/src/not_ported/NroProcess.cpp similarity index 100% rename from src/NroProcess.cpp rename to src/not_ported/NroProcess.cpp diff --git a/src/NsoProcess.cpp b/src/not_ported/NsoProcess.cpp similarity index 100% rename from src/NsoProcess.cpp rename to src/not_ported/NsoProcess.cpp diff --git a/src/PfsProcess.cpp b/src/not_ported/PfsProcess.cpp similarity index 100% rename from src/PfsProcess.cpp rename to src/not_ported/PfsProcess.cpp diff --git a/src/PkiCertProcess.cpp b/src/not_ported/PkiCertProcess.cpp similarity index 100% rename from src/PkiCertProcess.cpp rename to src/not_ported/PkiCertProcess.cpp diff --git a/src/RoMetadataProcess.cpp b/src/not_ported/RoMetadataProcess.cpp similarity index 100% rename from src/RoMetadataProcess.cpp rename to src/not_ported/RoMetadataProcess.cpp diff --git a/src/RomfsProcess.cpp b/src/not_ported/RomfsProcess.cpp similarity index 100% rename from src/RomfsProcess.cpp rename to src/not_ported/RomfsProcess.cpp diff --git a/src/types.h b/src/types.h index 5721307..2d22f1c 100644 --- a/src/types.h +++ b/src/types.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include diff --git a/src/util.cpp b/src/util.cpp index 8db21e2..b8fb0cc 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -68,13 +68,13 @@ void nstool::processResFile(const std::shared_ptr& file, std::m void nstool::writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size) { - writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileAccess::OpenOrCreate, tc::io::FileMode::Write)), cache_size); + writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)), cache_size); } void nstool::writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, size_t cache_size) { - writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileAccess::OpenOrCreate, tc::io::FileMode::Write)), cache_size); + writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)), cache_size); } void nstool::writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, size_t cache_size) @@ -90,7 +90,7 @@ void nstool::writeStreamToStream(const std::shared_ptr& in_stre cache_read_len = in_stream->read(cache.data(), cache.size()); if (cache_read_len == 0) { - throw tc::io::IOException(mModuleLabel, "Failed to read from RomFs file."); + throw tc::io::IOException("nstool::writeStreamToStream()", "Failed to read from source streeam."); } out_stream->write(cache.data(), cache_read_len);