From cbc20b2a15ee06db6d935d5cbb4072d47d28ba0b Mon Sep 17 00:00:00 2001 From: Jakcron Date: Tue, 29 Mar 2022 17:26:12 +0800 Subject: [PATCH 01/13] Honour opt.info when running CiaProcess --- ctrtool/src/CiaProcess.cpp | 4 +--- ctrtool/src/CiaProcess.h | 3 +-- ctrtool/src/main.cpp | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 9ebbb82f..974b661e 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -13,7 +13,6 @@ ctrtool::CiaProcess::CiaProcess() : mInputStream(), mKeyBag(), mShowHeaderInfo(false), - mShowFs(false), mVerbose(false), mVerify(false), mCertExtractPath(), @@ -49,10 +48,9 @@ void ctrtool::CiaProcess::setKeyBag(const ctrtool::KeyBag& key_bag) mNcchProcess.setKeyBag(key_bag); } -void ctrtool::CiaProcess::setCliOutputMode(bool show_header_info, bool show_fs) +void ctrtool::CiaProcess::setCliOutputMode(bool show_header_info) { mShowHeaderInfo = show_header_info; - mShowFs = show_fs; } void ctrtool::CiaProcess::setVerboseMode(bool verbose) diff --git a/ctrtool/src/CiaProcess.h b/ctrtool/src/CiaProcess.h index 4c37be69..245184eb 100644 --- a/ctrtool/src/CiaProcess.h +++ b/ctrtool/src/CiaProcess.h @@ -20,7 +20,7 @@ class CiaProcess void setInputStream(const std::shared_ptr& input_stream); void setKeyBag(const ctrtool::KeyBag& key_bag); - void setCliOutputMode(bool show_header_info, bool show_fs); + void setCliOutputMode(bool show_header_info); void setVerboseMode(bool verbose); void setVerifyMode(bool verify); void setCertExtractPath(const tc::io::Path& extract_path); @@ -44,7 +44,6 @@ class CiaProcess std::shared_ptr mInputStream; ctrtool::KeyBag mKeyBag; bool mShowHeaderInfo; - bool mShowFs; bool mVerbose; bool mVerify; tc::Optional mCertExtractPath; diff --git a/ctrtool/src/main.cpp b/ctrtool/src/main.cpp index a5a8bf17..7d1fa861 100644 --- a/ctrtool/src/main.cpp +++ b/ctrtool/src/main.cpp @@ -126,7 +126,7 @@ int umain(const std::vector& args, const std::vector& ctrtool::CiaProcess proc; proc.setInputStream(infile_stream); proc.setKeyBag(set.opt.keybag); - proc.setCliOutputMode(true, false); + proc.setCliOutputMode(set.opt.info); proc.setVerboseMode(set.opt.verbose); proc.setVerifyMode(set.opt.verify); if (set.rom.content_extract_path.isSet()) From b1629a4aa6bdce7b2667c516ad546d1fde049474 Mon Sep 17 00:00:00 2001 From: Jakcron Date: Tue, 29 Mar 2022 17:34:45 +0800 Subject: [PATCH 02/13] Fix bug when processing NCCH files directly, -p/--plain flag was not honoured. --- ctrtool/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctrtool/src/main.cpp b/ctrtool/src/main.cpp index 7d1fa861..5a9f94a6 100644 --- a/ctrtool/src/main.cpp +++ b/ctrtool/src/main.cpp @@ -77,7 +77,7 @@ int umain(const std::vector& args, const std::vector& proc.setVerboseMode(set.opt.verbose); proc.setVerifyMode(set.opt.verify); proc.setRawMode(set.opt.raw); - proc.setPlainMode(set.opt.raw); + proc.setPlainMode(set.opt.plain); proc.setShowSyscallName(set.exheader.show_syscalls_as_names); proc.setRegionProcessOutputMode(proc.NcchRegion_Header, set.opt.info, false, tc::Optional(), tc::Optional()); proc.setRegionProcessOutputMode(proc.NcchRegion_ExHeader, set.opt.info, false, set.ncch.exheader_path, tc::Optional()); From 0715b3d5b9fdc90da91d46184a148a3f00c0fb14 Mon Sep 17 00:00:00 2001 From: Jakcron Date: Tue, 29 Mar 2022 17:37:26 +0800 Subject: [PATCH 03/13] Add flag -q/--quiet to suppress non-errors. --- ctrtool/src/Settings.cpp | 22 ++++++++++++++++++---- ctrtool/src/Settings.h | 6 ++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ctrtool/src/Settings.cpp b/ctrtool/src/Settings.cpp index 1cfafbe4..a41cacfe 100644 --- a/ctrtool/src/Settings.cpp +++ b/ctrtool/src/Settings.cpp @@ -356,6 +356,8 @@ class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler ctrtool::SettingsInitializer::SettingsInitializer(const std::vector& args) : Settings(), mModuleLabel("ctrtool::SettingsInitializer"), + mSuppressOutput(false), + mShowKeys(false), mFallBackTitleKey(), mFallBackSeed(), mSeedDbPath() @@ -365,6 +367,15 @@ ctrtool::SettingsInitializer::SettingsInitializer(const std::vector if (infile.path.isNull()) throw tc::ArgumentException(mModuleLabel, "No input file was specified."); + // suppress output if requested + if (mSuppressOutput) + { + opt.info = false; + opt.verbose = false; + exefs.list_fs = false; + romfs.list_fs = false; + } + opt.keybag = KeyBagInitializer(opt.is_dev, mFallBackTitleKey, mSeedDbPath, mFallBackSeed); // determine filetype if not manually specified @@ -417,9 +428,10 @@ void ctrtool::SettingsInitializer::parse_args(const std::vector& ar // get option flags opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.info, {"-i", "--info"}))); + opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.verbose, {"-v", "--verbose"}))); + opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(mSuppressOutput, {"-q", "--quiet"}))); opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.plain, {"-p", "--plain"}))); opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.raw, {"-r", "--raw"}))); - opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.verbose, {"-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"}))); opts.registerOptionHandler(std::shared_ptr(new FlagOptionHandler(opt.show_keys, {"--showkeys"}))); @@ -593,14 +605,16 @@ void ctrtool::SettingsInitializer::usage_text() fmt::print(stderr, "Options:\n" - " -i, --info Show file info.\n" - " This is the default action.\n" + //" -i, --info Show file info.\n" + //" This is the default action.\n" //" -x, --extract Extract data from file.\n" //" This is also the default action.\n" + " -v, --verbose Give verbose output.\n" + " -q, --quiet Only output errors (regular output is silenced).\n" " -p, --plain Extract data without decrypting.\n" " -r, --raw Keep raw data, don't unpack.\n" //" -k, --keyset=file Specify keyset file.\n" - " -v, --verbose Give verbose output.\n" + " -y, --verify Verify hashes and signatures.\n" " -d, --dev Decrypt with development keys instead of retail.\n" //" --unitsize=size Set media unit size (default 0x200).\n" diff --git a/ctrtool/src/Settings.h b/ctrtool/src/Settings.h index be4ef4bc..e3301fb5 100644 --- a/ctrtool/src/Settings.h +++ b/ctrtool/src/Settings.h @@ -40,9 +40,9 @@ struct Settings struct Options { bool info; + bool verbose; bool plain; bool raw; - bool verbose; bool verify; bool show_keys; bool is_dev; @@ -123,9 +123,9 @@ struct Settings infile.path = tc::Optional(); opt.info = true; + opt.verbose = false; opt.plain = false; opt.raw = false; - opt.verbose = false; opt.verify = false; opt.show_keys = false; opt.is_dev = false; @@ -168,6 +168,8 @@ class SettingsInitializer : public Settings std::string mModuleLabel; + bool mSuppressOutput; + bool mShowKeys; tc::Optional mFallBackTitleKey; tc::Optional mFallBackSeed; From e7d872934a62b8b10040622092c4a577517d3f08 Mon Sep 17 00:00:00 2001 From: jakcron Date: Wed, 30 Mar 2022 20:09:04 +0800 Subject: [PATCH 04/13] (ctrtool::CciProcess) Emit errors/warns/logs in a consistent manner. --- ctrtool/src/CciProcess.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/ctrtool/src/CciProcess.cpp b/ctrtool/src/CciProcess.cpp index fccad6fa..b0fc98c8 100644 --- a/ctrtool/src/CciProcess.cpp +++ b/ctrtool/src/CciProcess.cpp @@ -192,7 +192,7 @@ void ctrtool::CciProcess::importHeader() } else { - fmt::print("[WARNING] Unsupported CardInfo::CryptoType ({})\n", (uint32_t)mHeader.card_info.flag.crypto_type); + fmt::print(stderr, "[{} LOG] Unsupported CardInfo::CryptoType ({})\n", mModuleLabel, (uint32_t)mHeader.card_info.flag.crypto_type); } if (initial_data_key_available) @@ -210,6 +210,16 @@ void ctrtool::CciProcess::importHeader() { mDecryptedTitleKey = decrypted_title_key; } + // Since CCM mode decrypts AND verifies, we should process the result here if required + if (mVerify) + { + mValidInitialDataMac = dec_result == 0 ? ValidState::Good : ValidState::Fail; + + if (mValidInitialDataMac != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] InitialData MAC was invalid.\n", mModuleLabel); + } + } /* // test encrypt @@ -222,6 +232,11 @@ void ctrtool::CciProcess::importHeader() mbedtls_ccm_free(&ccm_ctx); } + else + { + // no initial data key + fmt::print(stderr, "[{} LOG] Failed to determine key to decrypt InitialData.\n", mModuleLabel); + } // open fs reader mFsReader = std::shared_ptr(new tc::io::VirtualFileSystem(ntd::n3ds::CciFsShapshotGenerator(mInputStream))); @@ -241,11 +256,14 @@ void ctrtool::CciProcess::verifyHeader() } else { - fmt::print(stderr, "Could not read static CFA_CCI public key.\n"); + fmt::print(stderr, "[{} LOG] Could not read static CFA/CCI RSA2048 public key.\n", mModuleLabel); mValidSignature = ValidState::Fail; } - mValidInitialDataMac = mDecryptedTitleKey.isSet() ? ValidState::Good : ValidState::Fail; + if (mValidSignature != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for NcsdCommonHeader was invalid.\n", mModuleLabel); + } } void ctrtool::CciProcess::printHeader() @@ -347,7 +365,7 @@ void ctrtool::CciProcess::extractFs() // build out path out_path = mExtractPath.get() + *itr; - fmt::print("Saving {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); // begin export mFsReader->openFile(*itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream); @@ -360,7 +378,7 @@ void ctrtool::CciProcess::extractFs() 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(mModuleLabel, fmt::format("Failed to read from \"{}\".", (std::string)(dir.abs_path + *itr))); } out_stream->write(cache.data(), cache_read_len); @@ -374,7 +392,7 @@ void ctrtool::CciProcess::processContent() { if (mContentIndex >= ntd::n3ds::NcsdCommonHeader::kPartitionNum) { - fmt::print(stderr, "Content index {:d} isn't valid for CCI, use index 0-7, defaulting to 0 now.\n", mContentIndex); + fmt::print(stderr, "[{} LOG] Content index {:d} isn't valid for CCI, use index 0-7, defaulting to 0 now.\n", mModuleLabel, mContentIndex); mContentIndex = 0; } if (mHeader.ncsd_header.partition_offsetsize[mContentIndex].blk_size.unwrap() != 0) From 6509b431d8d6d1abcf1c2ece3970f3d95603811c Mon Sep 17 00:00:00 2001 From: jakcron Date: Wed, 30 Mar 2022 20:09:25 +0800 Subject: [PATCH 05/13] (ctrtool::CiaProcess) Emit errors/warns/logs in a consistent manner. --- ctrtool/src/CiaProcess.cpp | 52 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 974b661e..7ca595fc 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -286,10 +286,9 @@ void ctrtool::CiaProcess::importHeader() } } - // TODO load certificates from KeyBag else { - fmt::print("[LOG] CIA has no Certificate, cannot verify Ticket or TitleMetaData.\n"); + fmt::print(stderr, "[{} LOG] CIA has no Certificate, cannot verify Ticket or TitleMetaData.\n", mModuleLabel); } if (mTikSizeInfo.size > 0) @@ -299,12 +298,12 @@ void ctrtool::CiaProcess::importHeader() // determine title key if (mKeyBag.fallback_title_key.isSet()) { - fmt::print("[LOG] Using fallback titlekey.\n"); + fmt::print(stderr, "[{} LOG] Using fallback titlekey.\n", mModuleLabel); mDecryptedTitleKey = mKeyBag.fallback_title_key.get(); } else if (mKeyBag.common_key.find(mTicket.key_id) != mKeyBag.common_key.end()) { - fmt::print("[LOG] Decrypting titlekey from ticket.\n"); + fmt::print(stderr, "[{} LOG] Decrypting titlekey from ticket.\n", mModuleLabel); // get common key auto common_key = mKeyBag.common_key[mTicket.key_id]; @@ -322,7 +321,7 @@ void ctrtool::CiaProcess::importHeader() } else { - fmt::print("[LOG] Cannot determine titlekey.\n"); + fmt::print(stderr, "[{} LOG] Cannot determine titlekey.\n", mModuleLabel); } } else @@ -419,9 +418,15 @@ void ctrtool::CiaProcess::verifyMetadata() else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (certificate).\n", mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } + + // log certificate signature validation error + if (mCertSigValid[i] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); + } } } if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTikSizeInfo.size > 0) @@ -443,9 +448,15 @@ void ctrtool::CiaProcess::verifyMetadata() else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (ticket).\n", mTicket.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (ticket).\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = ValidState::Fail; } + + // log ticket signature validation error + if (mTicketSigValid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for Ticket \"{}\" was invalid.\n", mModuleLabel, mTicket.signature.issuer); + } } if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTmdSizeInfo.size > 0) { @@ -466,9 +477,15 @@ void ctrtool::CiaProcess::verifyMetadata() else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (tmd).\n", mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = ValidState::Fail; } + + // log tmd signature validation error + if (mTitleMetaDataSigValid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for TitleMetaData \"{}\" was invalid.\n", mModuleLabel, mTitleMetaData.signature.issuer); + } } } @@ -517,6 +534,11 @@ void ctrtool::CiaProcess::verifyContent() sha256_calc.getHash(sha256_hash.data()); itr->second.valid_state = memcmp(sha256_hash.data(), itr->second.hash.data(), sha256_hash.size()) == 0 ? ValidState::Good : ValidState::Fail; + + if (itr->second.valid_state != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Hash for content (index=0x{:04x}, id=0x{:08x}) was invalid.\n", mModuleLabel, itr->second.cindex, itr->second.cid); + } } } } @@ -671,7 +693,7 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mCertSizeInfo.offset, mCertSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print("Saving certs to {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving certs to {}...\n", mModuleLabel, out_path.to_string()); copyStream(in_stream, out_stream); } @@ -682,7 +704,7 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTikSizeInfo.offset, mTikSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print("Saving tik to {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving tik to {}...\n", mModuleLabel, out_path.to_string()); copyStream(in_stream, out_stream); } @@ -693,7 +715,7 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTmdSizeInfo.offset, mTmdSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print("Saving tmd to {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving tmd to {}...\n", mModuleLabel, out_path.to_string()); copyStream(in_stream, out_stream); } @@ -704,7 +726,7 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mFooterSizeInfo.offset, mFooterSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print("Saving meta to {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving meta to {}...\n", mModuleLabel, out_path.to_string()); copyStream(in_stream, out_stream); } @@ -727,7 +749,7 @@ void ctrtool::CiaProcess::extractCia() out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print("Saving content {:04x} to {}...\n", itr->second.cindex, out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving content {:04x} to {}...\n", mModuleLabel, itr->second.cindex, out_path.to_string()); copyStream(in_stream, out_stream); } } @@ -758,7 +780,7 @@ void ctrtool::CiaProcess::processContent() { if (mContentIndex >= ntd::n3ds::CiaHeader::kCiaMaxContentNum) { - fmt::print(stderr, "Content index {:d} isn't valid for CIA, use index 0-{:d}, defaulting to 0 now.\n", mContentIndex, ((size_t)ntd::n3ds::CiaHeader::kCiaMaxContentNum)-1); + fmt::print(stderr, "[{} LOG] Content index {:d} isn't valid for CIA, use index 0-{:d}, defaulting to 0 now.\n", mModuleLabel, mContentIndex, ((size_t)ntd::n3ds::CiaHeader::kCiaMaxContentNum)-1); mContentIndex = 0; } if (mContentInfo.find(mContentIndex) != mContentInfo.end() && mContentInfo[mContentIndex].size != 0) @@ -780,7 +802,7 @@ void ctrtool::CiaProcess::processContent() } else { - fmt::print("[LOG] TWL title processing not supported\n"); + fmt::print(stderr, "[{} LOG] TWL title processing not supported\n", mModuleLabel); } } } From 4652a08d1029c1fc0d448bed5f1b105efa72fadc Mon Sep 17 00:00:00 2001 From: jakcron Date: Thu, 31 Mar 2022 14:59:55 +0800 Subject: [PATCH 06/13] (ctrtool::CrrProcess) Emit errors/warns/logs in a consistent manner. --- ctrtool/src/CrrProcess.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ctrtool/src/CrrProcess.cpp b/ctrtool/src/CrrProcess.cpp index a0f35376..bffd1b5c 100644 --- a/ctrtool/src/CrrProcess.cpp +++ b/ctrtool/src/CrrProcess.cpp @@ -124,7 +124,7 @@ void ctrtool::CrrProcess::verifyData() } else { - fmt::print(stderr, "Could not read static CRR public key.\n"); + fmt::print(stderr, "[{} LOG] Could not read static CRR public key.\n", mModuleLabel); mValidCertificateSignature = ValidState::Fail; } @@ -145,6 +145,20 @@ void ctrtool::CrrProcess::verifyData() { mValidUniqueId = ((mBodyHeader.unique_id.unwrap() & mHeader.body_certificate.unique_id_mask.unwrap()) == 0) ? ValidState::Good : ValidState::Fail; } + + // log validation errors + if (mValidCertificateSignature != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for CRR Certificate was invalid.\n", mModuleLabel); + } + if (mValidBodySignature != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for CRR Body was invalid.\n", mModuleLabel); + } + if (mValidUniqueId != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] CRR UniqueId was invalid.\n", mModuleLabel); + } } void ctrtool::CrrProcess::printData() From f79a5666a5aa7954eb6dd57cd7aa2a0df68613ed Mon Sep 17 00:00:00 2001 From: jakcron Date: Thu, 31 Mar 2022 16:01:36 +0800 Subject: [PATCH 07/13] When verifying CIA cert/tik/tmd, preference certchain over keybag. --- ctrtool/src/CiaProcess.cpp | 65 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 7ca595fc..8c5868bc 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -288,7 +288,11 @@ void ctrtool::CiaProcess::importHeader() } else { - fmt::print(stderr, "[{} LOG] CIA has no Certificate, cannot verify Ticket or TitleMetaData.\n", mModuleLabel); + if (mVerify) + { + fmt::print(stderr, "[{} LOG] CIA has no Certificates, verifying Ticket or TitleMetaData will use the bundled public keys.\n", mModuleLabel); + } + } if (mTikSizeInfo.size > 0) @@ -402,23 +406,28 @@ void ctrtool::CiaProcess::verifyMetadata() // verify cert for (size_t i = 0; i < mCertChain.size(); i++) { - auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); auto local_issuer_itr = mCertImportedIssuerSigner.find(mCertChain[i].signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + // only show this warning for non-root signed certificates + if (mCertChain[i].signature.issuer != "Root") + { + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + } + mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } @@ -432,59 +441,61 @@ void ctrtool::CiaProcess::verifyMetadata() if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTikSizeInfo.size > 0) { // verify ticket - auto keybag_issuer_itr = mIssuerSigner.find(mTicket.signature.issuer); auto local_issuer_itr = mCertImportedIssuerSigner.find(mTicket.signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mTicket.signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mTicketSigValid = local_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTicket.signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - mTicketSigValid = local_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mTicket.signature.issuer); + mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (ticket).\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = ValidState::Fail; } // log ticket signature validation error if (mTicketSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for Ticket \"{}\" was invalid.\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} LOG] Signature for Ticket was invalid.\n", mModuleLabel); } } if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTmdSizeInfo.size > 0) { // verify tmd - auto keybag_issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer); auto local_issuer_itr = mCertImportedIssuerSigner.find(mTitleMetaData.signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mTitleMetaDataSigValid = local_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - mTitleMetaDataSigValid = local_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); + mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not read public key for \"{}\" (tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = ValidState::Fail; } // log tmd signature validation error if (mTitleMetaDataSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for TitleMetaData \"{}\" was invalid.\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} LOG] Signature for TitleMetaData was invalid.\n", mModuleLabel); } } } From 7798ddda90bcb3cb0577cc2b33deafb9b6bf2077 Mon Sep 17 00:00:00 2001 From: jakcron Date: Thu, 31 Mar 2022 16:15:49 +0800 Subject: [PATCH 08/13] (ctrtool::ExeFsProcess) Emit errors/warns/logs in a consistent manner. --- ctrtool/src/ExeFsProcess.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ctrtool/src/ExeFsProcess.cpp b/ctrtool/src/ExeFsProcess.cpp index 6acada89..3f2adba5 100644 --- a/ctrtool/src/ExeFsProcess.cpp +++ b/ctrtool/src/ExeFsProcess.cpp @@ -130,11 +130,11 @@ void ctrtool::ExeFsProcess::verifyFs() } hash_calc.getHash(hash.data()); - mSectionValidation[i] = memcmp(hash.data(), hdr_hash.data(), hash.size()) == 0? Good : Fail; + mSectionValidation[i] = memcmp(hash.data(), hdr_hash.data(), hash.size()) == 0? ValidState::Good : ValidState::Fail; - if (mVerbose) + if (mSectionValidation[i] != ValidState::Good) { - fmt::print("[LOG/ExeFs] File: \"{}\" {} hash validation\n", mHeader.file_table[i].name.decode(), (mSectionValidation[i] == ValidState::Good ? "passed" : "failed")); + fmt::print(stderr, "[{} LOG] ExeFs file \"{}\" had an invalid SHA2-256 hash.\n", mModuleLabel, mHeader.file_table[i].name.decode()); } } } @@ -223,7 +223,7 @@ void ctrtool::ExeFsProcess::extractFs() } if (test_hash != nullptr && memcmp(test_hash, hash.data(), hash.size()) == 0) { - fmt::print("Decompressing section {} to {}...\n", *itr, f_path.to_string()); + fmt::print(stderr, "[{} LOG] Decompressing file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); tc::ByteData decompdata = tc::ByteData(lzss_get_decompressed_size(compdata.data(), compdata.size())); lzss_decompress(compdata.data(), compdata.size(), decompdata.data(), decompdata.size()); @@ -233,7 +233,7 @@ void ctrtool::ExeFsProcess::extractFs() } else { - fmt::print("Saving section {} to {}...\n", *itr, f_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); out_stream->seek(0, tc::io::SeekOrigin::Begin); out_stream->write(compdata.data(), compdata.size()); @@ -241,7 +241,7 @@ void ctrtool::ExeFsProcess::extractFs() } else { - fmt::print("Saving section {} to {}...\n", *itr, f_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); tc::ByteData filedata = tc::ByteData(in_stream->length()); in_stream->seek(0, tc::io::SeekOrigin::Begin); From 60334cd7ddd2bc76815d7f25b15b73de7797bb62 Mon Sep 17 00:00:00 2001 From: jakcron Date: Tue, 12 Apr 2022 19:43:24 +0800 Subject: [PATCH 09/13] Don't silence verbosity with -q/--quiet --- ctrtool/src/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctrtool/src/Settings.cpp b/ctrtool/src/Settings.cpp index a41cacfe..52f5dff7 100644 --- a/ctrtool/src/Settings.cpp +++ b/ctrtool/src/Settings.cpp @@ -371,7 +371,7 @@ ctrtool::SettingsInitializer::SettingsInitializer(const std::vector if (mSuppressOutput) { opt.info = false; - opt.verbose = false; + //opt.verbose = false; exefs.list_fs = false; romfs.list_fs = false; } From c0ce043b306f1613f9420db8da661317f1989658 Mon Sep 17 00:00:00 2001 From: jakcron Date: Tue, 12 Apr 2022 20:05:02 +0800 Subject: [PATCH 10/13] Emit errors/warns/logs in a consistent manner. --- ctrtool/src/CciProcess.cpp | 22 ++++------ ctrtool/src/CiaProcess.cpp | 24 +++++------ ctrtool/src/ExHeaderProcess.cpp | 74 +++++++++++++++++++++++++++++---- ctrtool/src/ExHeaderProcess.h | 4 +- ctrtool/src/FirmProcess.cpp | 11 ++++- ctrtool/src/IvfcProcess.cpp | 7 ++-- ctrtool/src/NcchProcess.cpp | 57 ++++++++++++++++++------- ctrtool/src/RomFsProcess.cpp | 2 +- ctrtool/src/TikProcess.cpp | 62 +++++++++++++++++++-------- ctrtool/src/TmdProcess.cpp | 57 +++++++++++++++++-------- 10 files changed, 227 insertions(+), 93 deletions(-) diff --git a/ctrtool/src/CciProcess.cpp b/ctrtool/src/CciProcess.cpp index 888c8071..53201297 100644 --- a/ctrtool/src/CciProcess.cpp +++ b/ctrtool/src/CciProcess.cpp @@ -171,10 +171,14 @@ void ctrtool::CciProcess::importHeader() ctrtool::KeyBag::Aes128Key initial_data_key; bool initial_data_key_available = false; + // crypto_type 3 zeros initial_data key (used in developer ROMs only) + if (mHeader.card_info.flag.crypto_type == ntd::n3ds::CciHeader::CryptoType_FixedKey) + { + memset(initial_data_key.data(), 0, initial_data_key.size()); + initial_data_key_available = true; + } // crypto_type 0-2 is the normal "secure" initial data key - if (mHeader.card_info.flag.crypto_type == ntd::n3ds::CciHeader::CryptoType_Secure0 || - mHeader.card_info.flag.crypto_type == ntd::n3ds::CciHeader::CryptoType_Secure1 || - mHeader.card_info.flag.crypto_type == ntd::n3ds::CciHeader::CryptoType_Secure2) + else { if (mKeyBag.brom_static_key_x.find(mKeyBag.KEYSLOT_INITIAL_DATA) != mKeyBag.brom_static_key_x.end()) { @@ -186,16 +190,6 @@ void ctrtool::CciProcess::importHeader() initial_data_key_available = false; } } - // crypto_type 3 zeros initial_data key (used in developer roms mostly) - else if (mHeader.card_info.flag.crypto_type == ntd::n3ds::CciHeader::CryptoType_FixedKey) - { - memset(initial_data_key.data(), 0, initial_data_key.size()); - initial_data_key_available = true; - } - else - { - fmt::print(stderr, "[{} LOG] Unsupported CardInfo::CryptoType ({})\n", mModuleLabel, (uint32_t)mHeader.card_info.flag.crypto_type); - } if (initial_data_key_available) { @@ -258,7 +252,7 @@ void ctrtool::CciProcess::verifyHeader() } else { - fmt::print(stderr, "[{} LOG] Could not read static CFA/CCI RSA2048 public key.\n", mModuleLabel); + fmt::print(stderr, "[{} LOG] Could not load CCI RSA2048 public key.\n", mModuleLabel); mValidSignature = ValidState::Fail; } diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 8c5868bc..5e037f27 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -285,14 +285,6 @@ void ctrtool::CiaProcess::importHeader() } } - } - else - { - if (mVerify) - { - fmt::print(stderr, "[{} LOG] CIA has no Certificates, verifying Ticket or TitleMetaData will use the bundled public keys.\n", mModuleLabel); - } - } if (mTikSizeInfo.size > 0) @@ -302,12 +294,18 @@ void ctrtool::CiaProcess::importHeader() // determine title key if (mKeyBag.fallback_title_key.isSet()) { - fmt::print(stderr, "[{} LOG] Using fallback titlekey.\n", mModuleLabel); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Using fallback titlekey.\n", mModuleLabel); + } mDecryptedTitleKey = mKeyBag.fallback_title_key.get(); } else if (mKeyBag.common_key.find(mTicket.key_id) != mKeyBag.common_key.end()) { - fmt::print(stderr, "[{} LOG] Decrypting titlekey from ticket.\n", mModuleLabel); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Decrypting titlekey from ticket.\n", mModuleLabel); + } // get common key auto common_key = mKeyBag.common_key[mTicket.key_id]; @@ -420,7 +418,7 @@ void ctrtool::CiaProcess::verifyMetadata() // only show this warning for non-root signed certificates if (mCertChain[i].signature.issuer != "Root") { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); } mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } @@ -452,7 +450,7 @@ void ctrtool::CiaProcess::verifyMetadata() // fallback try with the keybag imported issuer else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else @@ -482,7 +480,7 @@ void ctrtool::CiaProcess::verifyMetadata() // fallback try with the keybag imported issuer else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the CIA certificate chain. The bundled public key was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else diff --git a/ctrtool/src/ExHeaderProcess.cpp b/ctrtool/src/ExHeaderProcess.cpp index fc5976c8..ebaf9c84 100644 --- a/ctrtool/src/ExHeaderProcess.cpp +++ b/ctrtool/src/ExHeaderProcess.cpp @@ -96,13 +96,18 @@ void ctrtool::ExHeaderProcess::verifyExHeader() } else { - fmt::print(stderr, "Could not read AccessDescriptor public key.\n"); + fmt::print(stderr, "[{} LOG] Could not load AccessDescriptor RSA2048 public key.\n", mModuleLabel); mValidSignature = ValidState::Fail; } - + + if (mValidSignature != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for AccessDescriptor was invalid.\n", mModuleLabel); + } + mValidLocalCaps.system_save_id[0] = ValidState::Good; mValidLocalCaps.system_save_id[1] = ValidState::Good; - mValidLocalCaps.access_info = ValidState::Good; + mValidLocalCaps.fs_access = ValidState::Good; mValidLocalCaps.core_version = ValidState::Good; mValidLocalCaps.program_id = ValidState::Good; mValidLocalCaps.priority = ValidState::Good; @@ -183,10 +188,10 @@ void ctrtool::ExHeaderProcess::verifyExHeader() { if (exhdr_fs_access.test(fs_bit) == true && desc_fs_access.test(fs_bit) == false) { - mValidLocalCaps.access_info = ValidState::Fail; + mValidLocalCaps.fs_access = ValidState::Fail; if (mVerbose) { - fmt::print("[LOG/ExHeader] FsAccess Bit {:d} was not permitted\n", fs_bit); + fmt::print(stderr, "[{} LOG] FsAccess Bit {:d} was not permitted\n", mModuleLabel, fs_bit); } } } @@ -213,10 +218,65 @@ void ctrtool::ExHeaderProcess::verifyExHeader() mValidLocalCaps.service_control = Fail; if (mVerbose) { - fmt::print("[LOG/ExHeader] Service \"{}\" was not permitted\n", exhdr_service_access_control[i].decode()); + fmt::print(stderr, "[{} LOG] Service \"{}\" was not permitted\n", mModuleLabel, exhdr_service_access_control[i].decode()); } } } + + if (mValidLocalCaps.system_save_id[0] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId1"); + } + if (mValidLocalCaps.system_save_id[1] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId2"); + } + if (mValidLocalCaps.fs_access != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "FsAccess"); + } + /* + if (mValidLocalCaps.core_version != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CoreVersion"); + } + */ + if (mValidLocalCaps.program_id != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ProgramId"); + } + if (mValidLocalCaps.priority != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ThreadPriority"); + } + if (mValidLocalCaps.affinity_mask != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "AffinityMask"); + } + if (mValidLocalCaps.ideal_processor != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "IdealProcessor"); + } + if (mValidLocalCaps.old3ds_system_mode != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (Old3DS)"); + } + if (mValidLocalCaps.new3ds_system_mode != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (New3DS)"); + } + if (mValidLocalCaps.enable_l2_cache != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "EnableL2Cache"); + } + if (mValidLocalCaps.new3ds_cpu_speed != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CpuSpeed"); + } + if (mValidLocalCaps.service_control != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ServiceAccess"); + } } void ctrtool::ExHeaderProcess::printExHeader() @@ -355,7 +415,7 @@ void ctrtool::ExHeaderProcess::printARM11SystemLocalCapabilities(const ntd::n3ds } fmt::print("Other Variation Saves: {}\n", (use_other_variation_savedata ? "Accessible" : "Inaccessible")); uint64_t fs_access_raw = ((((tc::bn::le64*)&info.fs_access)->unwrap() << 8) >> 8); // clearing the upper 8 bits since fs_access is 56 bits - fmt::print("Access info: {:6} 0x{:014x}\n", getValidString(valid.access_info), fs_access_raw); + fmt::print("FS access: {:6} 0x{:014x}\n", getValidString(valid.fs_access), fs_access_raw); for (size_t i = 0; i < info.fs_access.bit_size(); i++) { if (info.fs_access.test(i)) diff --git a/ctrtool/src/ExHeaderProcess.h b/ctrtool/src/ExHeaderProcess.h index 38219850..dace5d67 100644 --- a/ctrtool/src/ExHeaderProcess.h +++ b/ctrtool/src/ExHeaderProcess.h @@ -39,7 +39,7 @@ class ExHeaderProcess { system_save_id[0] = ValidState::Unchecked; system_save_id[1] = ValidState::Unchecked; - access_info = ValidState::Unchecked; + fs_access = ValidState::Unchecked; core_version = ValidState::Unchecked; program_id = ValidState::Unchecked; priority = ValidState::Unchecked; @@ -53,7 +53,7 @@ class ExHeaderProcess } std::array system_save_id; - byte_t access_info; + byte_t fs_access; byte_t core_version; byte_t program_id; byte_t priority; diff --git a/ctrtool/src/FirmProcess.cpp b/ctrtool/src/FirmProcess.cpp index aefa57ab..c98f9e05 100644 --- a/ctrtool/src/FirmProcess.cpp +++ b/ctrtool/src/FirmProcess.cpp @@ -188,6 +188,11 @@ void ctrtool::FirmProcess::verifyHashes() hash_calc.getHash(hash.data()); mValidFirmSectionHash[i] = memcmp(hash.data(), hdr_hash.data(), hash.size()) == 0? ValidState::Good : ValidState::Fail; + + if (mValidFirmSectionHash[i] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] FIRM section {:d} SHA2-256 hash was invalid.\n", mModuleLabel, i); + } } } } @@ -226,7 +231,7 @@ void ctrtool::FirmProcess::verifySignature() } else { - fmt::print(stderr, "Could not read static rsa_key {}.\n", key_id == mKeyBag.RSAKEY_FIRM_NAND ? "RSAKEY_FIRM_NAND" : "RSAKEY_FIRM_RECOVERY"); + fmt::print(stderr, "[{} LOG] Could not load {} RSA2048 public key.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); valid_signature = ValidState::Fail; } @@ -239,7 +244,7 @@ void ctrtool::FirmProcess::verifySignature() } else { - fmt::print(stderr, "Could not read rsa_sighax_signature for {}.\n", key_id == mKeyBag.RSAKEY_FIRM_NAND ? "RSAKEY_FIRM_NAND" : "RSAKEY_FIRM_RECOVERY"); + fmt::print(stderr, "[{} LOG] Could not load {} SigHax RSA2048 signature.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); is_sighax = false; } @@ -251,10 +256,12 @@ void ctrtool::FirmProcess::verifySignature() // check if sighax else if (valid_signature == ValidState::Fail && is_sighax == true) { + fmt::print(stderr, "[{} LOG] Signature for FIRM was invalid (SigHax).\n", mModuleLabel); mSignatureState = SignatureState_SigHax; } else { + fmt::print(stderr, "[{} LOG] Signature for FIRM was invalid.\n", mModuleLabel); mSignatureState = SignatureState_Fail; } } diff --git a/ctrtool/src/IvfcProcess.cpp b/ctrtool/src/IvfcProcess.cpp index 80343426..56c8579c 100644 --- a/ctrtool/src/IvfcProcess.cpp +++ b/ctrtool/src/IvfcProcess.cpp @@ -127,7 +127,7 @@ void ctrtool::IvfcProcess::verifyLevels() { if (mVerbose) { - fmt::print("[LOG/IVFC] IVFC Layer {:d}, Block {:d} failed validation\n", i, j); + fmt::print(stderr, "[{} LOG] IVFC Layer {:d}, Block {:d} failed validation.\n", mModuleLabel, i, j); } } @@ -138,9 +138,10 @@ void ctrtool::IvfcProcess::verifyLevels() } mLevelValidation[i] = bad_blocks == 0? ValidState::Good : ValidState::Fail; - if (mVerbose) + + if (mLevelValidation[i] != ValidState::Good) { - fmt::print("[LOG/IVFC] IVFC Layer {:d} {} validation\n", i, (mLevelValidation[i] == ValidState::Good ? "passed" : "failed")); + fmt::print(stderr, "[{} LOG] IVFC Layer {:d} failed validation.\n", mModuleLabel, i); } } } diff --git a/ctrtool/src/NcchProcess.cpp b/ctrtool/src/NcchProcess.cpp index d3ab0073..642b9dec 100644 --- a/ctrtool/src/NcchProcess.cpp +++ b/ctrtool/src/NcchProcess.cpp @@ -241,7 +241,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() } if (crypto_is_stripped) { - fmt::print("[LOG/NCCH] NCCH appears to be decrypted, contrary to header flags.\n"); + fmt::print(stderr, "[{} LOG] NCCH appears to be decrypted, contrary to header flags.\n", mModuleLabel); } // determine encryption mode @@ -287,7 +287,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() keyslot[0].valid_key = ValidState::Fail; keyslot[1].valid_key = ValidState::Fail; - fmt::print(stderr, "Could not read {} fixed key.\n", (isSystemTitle()? "system" : "application")); + fmt::print(stderr, "[{} LOG] Could not load {} fixed key.\n", mModuleLabel, (isSystemTitle()? "system" : "application")); } // save keys @@ -307,7 +307,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[0].valid_x = ValidState::Fail; - fmt::print(stderr, "Could not read secure key_x[0x{:02x}].\n", 0); + fmt::print(stderr, "[{} LOG] Could not load secure key_x[0x{:02x}].\n", mModuleLabel, 0); } else { @@ -328,7 +328,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_x = ValidState::Fail; - fmt::print(stderr, "Could not read secure key_x[0x{:02x}].\n", security_version); + fmt::print(stderr, "[{} LOG] Could not read secure key_x[0x{:02x}].\n", mModuleLabel, security_version); } else { @@ -360,8 +360,8 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_y = ValidState::Fail; - fmt::print(stderr, "This title uses seed crypto, but no seed is set, unable to decrypt.\n"); - fmt::print(stderr, "Use -p to avoid decryption or use --seeddb=dbfile or --seed=SEEDHERE.\n"); + fmt::print(stderr, "[{} LOG] This title uses seed crypto, but no seed is set, unable to decrypt.\n", mModuleLabel); + fmt::print(stderr, " Use -p to avoid decryption or use --seeddb=dbfile or --seed=SEEDHERE.\n"); } if (keyslot[1].valid_y != ValidState::Fail) @@ -375,7 +375,8 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_y = ValidState::Fail; - fmt::print(stderr, "Seed check mismatch. (Got {:08x}, expected: {:08x})\n", + fmt::print(stderr, "[{} LOG] Seed check mismatch. (Got {:08x}, expected: {:08x})\n", + mModuleLabel, ((tc::bn::be32*)hash.data())->unwrap(), ((tc::bn::be32*)mHeader.header.seed_checksum.data())->unwrap()); } @@ -424,8 +425,8 @@ void ctrtool::NcchProcess::determineRegionEncryption() // output keys if required if (mVerbose) { - fmt::print("[LOG/NCCH] NCCH AES Key0 {}\n", (keyslot[0].valid_key ? tc::cli::FormatUtil::formatBytesAsString(keyslot[0].key.data(), keyslot[0].key.size(), true, "") : "could not be determined")); - fmt::print("[LOG/NCCH] NCCH AES Key1 {}\n", (keyslot[1].valid_key ? tc::cli::FormatUtil::formatBytesAsString(keyslot[1].key.data(), keyslot[1].key.size(), true, "") : "could not be determined")); + fmt::print(stderr, "[{} LOG] NCCH AES Key0 {}\n", mModuleLabel, (keyslot[0].valid_key ? tc::cli::FormatUtil::formatBytesAsString(keyslot[0].key.data(), keyslot[0].key.size(), true, "") : "could not be determined")); + fmt::print(stderr, "[{} LOG] NCCH AES Key1 {}\n", mModuleLabel, (keyslot[1].valid_key ? tc::cli::FormatUtil::formatBytesAsString(keyslot[1].key.data(), keyslot[1].key.size(), true, "") : "could not be determined")); } // generate aes counter @@ -436,7 +437,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() if (mVerbose) { - fmt::print("[LOG/NCCH] NCCH ExHeader AES Counter {}\n", tc::cli::FormatUtil::formatBytesAsString(exheader_aesctr.data(), exheader_aesctr.size(), true, "")); + fmt::print(stderr, "[{} LOG] NCCH ExHeader AES Counter {}\n", mModuleLabel, tc::cli::FormatUtil::formatBytesAsString(exheader_aesctr.data(), exheader_aesctr.size(), true, "")); } } if (mRegionInfo[NcchRegion_ExeFs].size) @@ -445,7 +446,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() if (mVerbose) { - fmt::print("[LOG/NCCH] NCCH ExeFS AES Counter {}\n", tc::cli::FormatUtil::formatBytesAsString(exefs_aesctr.data(), exefs_aesctr.size(), true, "")); + fmt::print(stderr, "[{} LOG] NCCH ExeFS AES Counter {}\n", mModuleLabel, tc::cli::FormatUtil::formatBytesAsString(exefs_aesctr.data(), exefs_aesctr.size(), true, "")); } } if (mRegionInfo[NcchRegion_RomFs].size) @@ -454,7 +455,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() if (mVerbose) { - fmt::print("[LOG/NCCH] NCCH RomFS AES Counter {}\n", tc::cli::FormatUtil::formatBytesAsString(romfs_aesctr.data(), romfs_aesctr.size(), true, "")); + fmt::print(stderr, "[{} LOG] NCCH RomFS AES Counter {}\n", mModuleLabel, tc::cli::FormatUtil::formatBytesAsString(romfs_aesctr.data(), romfs_aesctr.size(), true, "")); } } @@ -531,7 +532,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() // otherwise use the "best-effort" single key stream (only icon and banner will be decrypt properly) else { - fmt::print(stderr, "Only NCCH key0 was determined, so ExeFS will be partially decrypted\n"); + fmt::print(stderr, "[{} LOG] Only NCCH key0 was determined, ExeFS may be partially decrypted\n", mModuleLabel); mRegionInfo[NcchRegion_ExeFs].ready_stream = std::shared_ptr(new tc::crypto::Aes128CtrEncryptedStream(mRegionInfo[NcchRegion_ExeFs].raw_stream, keyslot[0].key, exefs_aesctr)); } } @@ -596,7 +597,7 @@ void ctrtool::NcchProcess::verifyRegions() else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read CFA public key.\n"); + fmt::print(stderr, "[{} LOG] Could not load CFA RSA2048 public key.\n", mModuleLabel); mRegionInfo[NcchRegion_Header].valid = ValidState::Fail; } @@ -621,36 +622,60 @@ void ctrtool::NcchProcess::verifyRegions() else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read CXI public key from AccessDescriptor.\n"); + fmt::print(stderr, "[{} LOG] Could not load CXI RSA2048 public key from AccessDescriptor.\n", mModuleLabel); mRegionInfo[NcchRegion_Header].valid = ValidState::Fail; } } + + if (mRegionInfo[NcchRegion_Header].valid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for NcchHeader was invalid.\n", mModuleLabel); + } } // exheader hash if (mRegionInfo[NcchRegion_ExHeader].hashed_size > 0) { mRegionInfo[NcchRegion_ExHeader].valid = memcmp(region_hashes[NcchRegion_ExHeader].data(), mHeader.header.exhdr_hash.data(), region_hashes[NcchRegion_ExHeader].size()) == 0 ? ValidState::Good : ValidState::Fail; + + if (mRegionInfo[NcchRegion_ExHeader].valid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] ExtendedHeader SHA2-256 hash was invalid.\n", mModuleLabel); + } } // logo hash if (mRegionInfo[NcchRegion_Logo].hashed_size > 0) { mRegionInfo[NcchRegion_Logo].valid = memcmp(region_hashes[NcchRegion_Logo].data(), mHeader.header.logo_hash.data(), region_hashes[NcchRegion_Logo].size()) == 0 ? ValidState::Good : ValidState::Fail; + + if (mRegionInfo[NcchRegion_Logo].valid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Logo SHA2-256 hash was invalid.\n", mModuleLabel); + } } // exefs hash if (mRegionInfo[NcchRegion_ExeFs].hashed_size > 0) { mRegionInfo[NcchRegion_ExeFs].valid = memcmp(region_hashes[NcchRegion_ExeFs].data(), mHeader.header.exefs_prot_hash.data(), region_hashes[NcchRegion_ExeFs].size()) == 0 ? ValidState::Good : ValidState::Fail; + + if (mRegionInfo[NcchRegion_ExeFs].valid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] ExeFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); + } } // romfs hash if (mRegionInfo[NcchRegion_RomFs].hashed_size > 0) { mRegionInfo[NcchRegion_RomFs].valid = memcmp(region_hashes[NcchRegion_RomFs].data(), mHeader.header.romfs_prot_hash.data(), region_hashes[NcchRegion_RomFs].size()) == 0 ? ValidState::Good : ValidState::Fail; + + if (mRegionInfo[NcchRegion_RomFs].valid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] RomFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); + } } - } void ctrtool::NcchProcess::printHeader() diff --git a/ctrtool/src/RomFsProcess.cpp b/ctrtool/src/RomFsProcess.cpp index dfbb2c08..cb362f57 100644 --- a/ctrtool/src/RomFsProcess.cpp +++ b/ctrtool/src/RomFsProcess.cpp @@ -200,7 +200,7 @@ void ctrtool::RomFsProcess::visitDir(const tc::io::Path& v_path, const tc::io::P // build out path out_path = l_path + *itr; - fmt::print("Saving {}...\n", out_path.to_string()); + fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); // begin export mFsReader->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream); diff --git a/ctrtool/src/TikProcess.cpp b/ctrtool/src/TikProcess.cpp index 598fca84..0fc7989b 100644 --- a/ctrtool/src/TikProcess.cpp +++ b/ctrtool/src/TikProcess.cpp @@ -93,7 +93,10 @@ void ctrtool::TikProcess::importData() // determine title key if (mKeyBag.common_key.find(mTicket.key_id) != mKeyBag.common_key.end()) { - fmt::print("[LOG] Decrypting titlekey from ticket.\n"); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Decrypting titlekey from ticket.\n", mModuleLabel); + } // get common key auto common_key = mKeyBag.common_key[mTicket.key_id]; @@ -111,7 +114,7 @@ void ctrtool::TikProcess::importData() } else { - fmt::print("[LOG] Cannot determine titlekey.\n"); + fmt::print(stderr, "[{} LOG] Cannot determine titlekey.\n", mModuleLabel); } } @@ -150,48 +153,71 @@ void ctrtool::TikProcess::verifyData() // verify cert for (size_t i = 0; i < mCertChain.size(); i++) { - auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); auto local_issuer_itr = mCertImportedIssuerSigner.find(mCertChain[i].signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + // only show this warning for non-root signed certificates + if (mCertChain[i].signature.issuer != "Root") + { + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + } + mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (certificate).\n", mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } + + // log certificate signature validation error + if (mCertSigValid[i] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); + } } // verify ticket { - auto keybag_issuer_itr = mIssuerSigner.find(mTicket.signature.issuer); + // verify ticket auto local_issuer_itr = mCertImportedIssuerSigner.find(mTicket.signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mTicket.signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mTicketSigValid = local_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTicket.signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - mTicketSigValid = local_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + // only show this warning when there are certificates appended to the ticket (only tickets downloaded from CDN will have an appended certificate chain) + if (mCertChain.size() != 0) + { + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); + } + mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (ticket).\n", mTicket.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = ValidState::Fail; } + + // log ticket signature validation error + if (mTicketSigValid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for Ticket was invalid.\n", mModuleLabel); + } } } diff --git a/ctrtool/src/TmdProcess.cpp b/ctrtool/src/TmdProcess.cpp index ba45c2c1..0fe136aa 100644 --- a/ctrtool/src/TmdProcess.cpp +++ b/ctrtool/src/TmdProcess.cpp @@ -125,48 +125,71 @@ void ctrtool::TmdProcess::verifyData() // verify cert for (size_t i = 0; i < mCertChain.size(); i++) { - auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); auto local_issuer_itr = mCertImportedIssuerSigner.find(mCertChain[i].signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type) { - mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; + // only show this warning for non-root signed certificates + if (mCertChain[i].signature.issuer != "Root") + { + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + } + mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (certificate).\n", mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } + + // log certificate signature validation error + if (mCertSigValid[i] != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); + } } - // verify tmd + // verify ticket { - auto keybag_issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer); + // verify ticket auto local_issuer_itr = mCertImportedIssuerSigner.find(mTitleMetaData.signature.issuer); + auto keybag_issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer); - // try first with the keybag imported issuer - if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) + // first try with the issuer profiles imported from the local certificates + if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + mTitleMetaDataSigValid = local_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } - // fallback try with the issuer profiles imported from the local certificates - else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) + // fallback try with the keybag imported issuer + else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - mTitleMetaDataSigValid = local_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; + // only show this warning when there are certificates appended to the tmd (only tmd downloaded from CDN will have an appended certificate chain) + if (mCertChain.size() != 0) + { + fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); + } + mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "Could not read public key for \"{}\" (tmd).\n", mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = ValidState::Fail; } + + // log tmd signature validation error + if (mTitleMetaDataSigValid != ValidState::Good) + { + fmt::print(stderr, "[{} LOG] Signature for TitleMetaData was invalid.\n", mModuleLabel); + } } } From 247045ba8f69d3fc7c678a30d9cab6025a770f07 Mon Sep 17 00:00:00 2001 From: Jakcron Date: Fri, 15 Apr 2022 00:21:35 +0800 Subject: [PATCH 11/13] Extraction progress logs are now only shown in verbose mode. --- ctrtool/src/CciProcess.cpp | 7 +++++-- ctrtool/src/CiaProcess.cpp | 27 ++++++++++++++++++++++----- ctrtool/src/ExeFsProcess.cpp | 19 ++++++++++++++----- ctrtool/src/FirmProcess.cpp | 5 ++++- ctrtool/src/NcchProcess.cpp | 18 +++++++++++------- ctrtool/src/RomFsProcess.cpp | 5 ++++- 6 files changed, 60 insertions(+), 21 deletions(-) diff --git a/ctrtool/src/CciProcess.cpp b/ctrtool/src/CciProcess.cpp index 53201297..39c08c7d 100644 --- a/ctrtool/src/CciProcess.cpp +++ b/ctrtool/src/CciProcess.cpp @@ -209,7 +209,7 @@ void ctrtool::CciProcess::importHeader() // Since CCM mode decrypts AND verifies, we should process the result here if required if (mVerify) { - mValidInitialDataMac = dec_result == 0 ? ValidState::Good : ValidState::Fail; + mValidInitialDataMac = dec_result == 0 ? ValidState::Good : ValidState::Fail; if (mValidInitialDataMac != ValidState::Good) { @@ -361,7 +361,10 @@ void ctrtool::CciProcess::extractFs() // build out path out_path = mExtractPath.get() + *itr; - fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); + } // begin export mFsReader->openFile(*itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream); diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 5e037f27..dd8f9a85 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -702,7 +702,11 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mCertSizeInfo.offset, mCertSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print(stderr, "[{} LOG] Saving certs to {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving certs to {}...\n", mModuleLabel, out_path.to_string()); + } + copyStream(in_stream, out_stream); } @@ -713,7 +717,10 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTikSizeInfo.offset, mTikSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print(stderr, "[{} LOG] Saving tik to {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving tik to {}...\n", mModuleLabel, out_path.to_string()); + } copyStream(in_stream, out_stream); } @@ -724,7 +731,10 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mTmdSizeInfo.offset, mTmdSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print(stderr, "[{} LOG] Saving tmd to {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving tmd to {}...\n", mModuleLabel, out_path.to_string()); + } copyStream(in_stream, out_stream); } @@ -735,7 +745,10 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mFooterSizeInfo.offset, mFooterSizeInfo.size)); out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print(stderr, "[{} LOG] Saving meta to {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving meta to {}...\n", mModuleLabel, out_path.to_string()); + } copyStream(in_stream, out_stream); } @@ -758,7 +771,11 @@ void ctrtool::CiaProcess::extractCia() out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - fmt::print(stderr, "[{} LOG] Saving content {:04x} to {}...\n", mModuleLabel, itr->second.cindex, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving content {:04x} to {}...\n", mModuleLabel, itr->second.cindex, out_path.to_string()); + } + copyStream(in_stream, out_stream); } } diff --git a/ctrtool/src/ExeFsProcess.cpp b/ctrtool/src/ExeFsProcess.cpp index 3f2adba5..d2a068eb 100644 --- a/ctrtool/src/ExeFsProcess.cpp +++ b/ctrtool/src/ExeFsProcess.cpp @@ -223,8 +223,11 @@ void ctrtool::ExeFsProcess::extractFs() } if (test_hash != nullptr && memcmp(test_hash, hash.data(), hash.size()) == 0) { - fmt::print(stderr, "[{} LOG] Decompressing file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); - + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Decompressing {} to {}...\n", mModuleLabel, *itr, f_path.to_string()); + } + tc::ByteData decompdata = tc::ByteData(lzss_get_decompressed_size(compdata.data(), compdata.size())); lzss_decompress(compdata.data(), compdata.size(), decompdata.data(), decompdata.size()); @@ -233,7 +236,10 @@ void ctrtool::ExeFsProcess::extractFs() } else { - fmt::print(stderr, "[{} LOG] Saving file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving {} to {}...\n", mModuleLabel, *itr, f_path.to_string()); + } out_stream->seek(0, tc::io::SeekOrigin::Begin); out_stream->write(compdata.data(), compdata.size()); @@ -241,8 +247,11 @@ void ctrtool::ExeFsProcess::extractFs() } else { - fmt::print(stderr, "[{} LOG] Saving file /{} to {}...\n", mModuleLabel, *itr, f_path.to_string()); - + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving {} to {}...\n", mModuleLabel, *itr, f_path.to_string()); + } + tc::ByteData filedata = tc::ByteData(in_stream->length()); in_stream->seek(0, tc::io::SeekOrigin::Begin); in_stream->read(filedata.data(), filedata.size()); diff --git a/ctrtool/src/FirmProcess.cpp b/ctrtool/src/FirmProcess.cpp index c98f9e05..671d27fd 100644 --- a/ctrtool/src/FirmProcess.cpp +++ b/ctrtool/src/FirmProcess.cpp @@ -311,7 +311,10 @@ void ctrtool::FirmProcess::extractSections() local_fs.createDirectory(mExtractPath.get()); local_fs.openFile(f_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write, out_stream); - fmt::print("Saving section {} to {}...\n", i, f_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving section {} to {}...\n", mModuleLabel, i, f_path.to_string()); + } tc::ByteData filedata = tc::ByteData(in_stream->length()); in_stream->seek(0, tc::io::SeekOrigin::Begin); diff --git a/ctrtool/src/NcchProcess.cpp b/ctrtool/src/NcchProcess.cpp index 642b9dec..21ac722b 100644 --- a/ctrtool/src/NcchProcess.cpp +++ b/ctrtool/src/NcchProcess.cpp @@ -768,15 +768,19 @@ void ctrtool::NcchProcess::extractRegionBinaries() { if (mRegionOpt[i].bin_extract_path.isSet() && mRegionInfo[i].ready_stream != nullptr) { - switch(i) + if (mVerbose) { - case NcchRegion_Header: fmt::print("Saving Header...\n"); break; - case NcchRegion_ExHeader: fmt::print("Saving Extended Header...\n"); break; - case NcchRegion_PlainRegion: fmt::print("Saving Plain Region...\n"); break; - case NcchRegion_Logo: fmt::print("Saving Logo...\n"); break; - case NcchRegion_ExeFs: fmt::print("Saving ExeFS...\n"); break; - case NcchRegion_RomFs: fmt::print("Saving RomFS...\n"); break; + switch(i) + { + case NcchRegion_Header: fmt::print(stderr, "[{} LOG] Saving Header...\n", mModuleLabel); break; + case NcchRegion_ExHeader: fmt::print(stderr, "[{} LOG] Saving Extended Header...\n", mModuleLabel); break; + case NcchRegion_PlainRegion: fmt::print(stderr, "[{} LOG] Saving Plain Region...\n", mModuleLabel); break; + case NcchRegion_Logo: fmt::print(stderr, "[{} LOG] Saving Logo...\n", mModuleLabel); break; + case NcchRegion_ExeFs: fmt::print(stderr, "[{} LOG] Saving ExeFS...\n", mModuleLabel); break; + case NcchRegion_RomFs: fmt::print(stderr, "[{} LOG] Saving RomFS...\n", mModuleLabel); break; + } } + in_stream = mRegionInfo[i].ready_stream; local_fs.openFile(mRegionOpt[i].bin_extract_path.get(), tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write, out_stream); diff --git a/ctrtool/src/RomFsProcess.cpp b/ctrtool/src/RomFsProcess.cpp index cb362f57..cc1bc739 100644 --- a/ctrtool/src/RomFsProcess.cpp +++ b/ctrtool/src/RomFsProcess.cpp @@ -200,7 +200,10 @@ void ctrtool::RomFsProcess::visitDir(const tc::io::Path& v_path, const tc::io::P // build out path out_path = l_path + *itr; - fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); + if (mVerbose) + { + fmt::print(stderr, "[{} LOG] Saving {}...\n", mModuleLabel, out_path.to_string()); + } // begin export mFsReader->openFile(v_path + *itr, tc::io::FileMode::Open, tc::io::FileAccess::Read, in_stream); From be1394234a4c65c006cb34a11964d96737077acf Mon Sep 17 00:00:00 2001 From: jakcron Date: Fri, 15 Apr 2022 11:26:20 +0800 Subject: [PATCH 12/13] Tag error output as [ctrtool::ClassName ERROR], leaving warnings/progress indicators as [ctrtool::ClassName LOG] --- ctrtool/src/CciProcess.cpp | 10 +++++----- ctrtool/src/CiaProcess.cpp | 26 ++++++++++++------------- ctrtool/src/CrrProcess.cpp | 8 ++++---- ctrtool/src/ExHeaderProcess.cpp | 34 ++++++++++++++++----------------- ctrtool/src/ExeFsProcess.cpp | 2 +- ctrtool/src/FirmProcess.cpp | 10 +++++----- ctrtool/src/IvfcProcess.cpp | 4 ++-- ctrtool/src/NcchProcess.cpp | 32 +++++++++++++++---------------- ctrtool/src/TikProcess.cpp | 6 +++--- ctrtool/src/TmdProcess.cpp | 12 ++++++------ 10 files changed, 72 insertions(+), 72 deletions(-) diff --git a/ctrtool/src/CciProcess.cpp b/ctrtool/src/CciProcess.cpp index 39c08c7d..f1bc54d1 100644 --- a/ctrtool/src/CciProcess.cpp +++ b/ctrtool/src/CciProcess.cpp @@ -213,7 +213,7 @@ void ctrtool::CciProcess::importHeader() if (mValidInitialDataMac != ValidState::Good) { - fmt::print(stderr, "[{} LOG] InitialData MAC was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] InitialData MAC was invalid.\n", mModuleLabel); } } @@ -231,7 +231,7 @@ void ctrtool::CciProcess::importHeader() else { // no initial data key - fmt::print(stderr, "[{} LOG] Failed to determine key to decrypt InitialData.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Failed to determine key to decrypt InitialData.\n", mModuleLabel); } // open fs reader @@ -252,13 +252,13 @@ void ctrtool::CciProcess::verifyHeader() } else { - fmt::print(stderr, "[{} LOG] Could not load CCI RSA2048 public key.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Could not load CCI RSA2048 public key.\n", mModuleLabel); mValidSignature = ValidState::Fail; } if (mValidSignature != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for NcsdCommonHeader was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for NcsdCommonHeader was invalid.\n", mModuleLabel); } } @@ -391,7 +391,7 @@ void ctrtool::CciProcess::processContent() { if (mContentIndex >= ntd::n3ds::NcsdCommonHeader::kPartitionNum) { - fmt::print(stderr, "[{} LOG] Content index {:d} isn't valid for CCI, use index 0-7, defaulting to 0 now.\n", mModuleLabel, mContentIndex); + fmt::print(stderr, "[{} ERROR] Content index {:d} isn't valid for CCI, use index 0-7, defaulting to 0 now.\n", mModuleLabel, mContentIndex); mContentIndex = 0; } if (mHeader.ncsd_header.partition_offsetsize[mContentIndex].blk_size.unwrap() != 0) diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index dd8f9a85..6b89d7ab 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -323,7 +323,7 @@ void ctrtool::CiaProcess::importHeader() } else { - fmt::print(stderr, "[{} LOG] Cannot determine titlekey.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Cannot determine titlekey.\n", mModuleLabel); } } else @@ -418,21 +418,21 @@ void ctrtool::CiaProcess::verifyMetadata() // only show this warning for non-root signed certificates if (mCertChain[i].signature.issuer != "Root") { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for certificate \"{}\") was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); } mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } // log certificate signature validation error if (mCertSigValid[i] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} ERROR] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); } } } @@ -450,20 +450,20 @@ void ctrtool::CiaProcess::verifyMetadata() // fallback try with the keybag imported issuer else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for ticket) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = ValidState::Fail; } // log ticket signature validation error if (mTicketSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for Ticket was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for Ticket was invalid.\n", mModuleLabel); } } if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTmdSizeInfo.size > 0) @@ -480,20 +480,20 @@ void ctrtool::CiaProcess::verifyMetadata() // fallback try with the keybag imported issuer else if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for tmd) was not present in the CIA certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = ValidState::Fail; } // log tmd signature validation error if (mTitleMetaDataSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for TitleMetaData was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for TitleMetaData was invalid.\n", mModuleLabel); } } } @@ -546,7 +546,7 @@ void ctrtool::CiaProcess::verifyContent() if (itr->second.valid_state != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Hash for content (index=0x{:04x}, id=0x{:08x}) was invalid.\n", mModuleLabel, itr->second.cindex, itr->second.cid); + fmt::print(stderr, "[{} ERROR] Hash for content (index=0x{:04x}, id=0x{:08x}) was invalid.\n", mModuleLabel, itr->second.cindex, itr->second.cid); } } } @@ -806,7 +806,7 @@ void ctrtool::CiaProcess::processContent() { if (mContentIndex >= ntd::n3ds::CiaHeader::kCiaMaxContentNum) { - fmt::print(stderr, "[{} LOG] Content index {:d} isn't valid for CIA, use index 0-{:d}, defaulting to 0 now.\n", mModuleLabel, mContentIndex, ((size_t)ntd::n3ds::CiaHeader::kCiaMaxContentNum)-1); + fmt::print(stderr, "[{} ERROR] Content index {:d} isn't valid for CIA, use index 0-{:d}, defaulting to 0 now.\n", mModuleLabel, mContentIndex, ((size_t)ntd::n3ds::CiaHeader::kCiaMaxContentNum)-1); mContentIndex = 0; } if (mContentInfo.find(mContentIndex) != mContentInfo.end() && mContentInfo[mContentIndex].size != 0) @@ -828,7 +828,7 @@ void ctrtool::CiaProcess::processContent() } else { - fmt::print(stderr, "[{} LOG] TWL title processing not supported\n", mModuleLabel); + throw tc::NotImplementedException(mModuleLabel, "TWL title processing not supported."); } } } diff --git a/ctrtool/src/CrrProcess.cpp b/ctrtool/src/CrrProcess.cpp index bffd1b5c..90aba6e6 100644 --- a/ctrtool/src/CrrProcess.cpp +++ b/ctrtool/src/CrrProcess.cpp @@ -124,7 +124,7 @@ void ctrtool::CrrProcess::verifyData() } else { - fmt::print(stderr, "[{} LOG] Could not read static CRR public key.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Could not read static CRR public key.\n", mModuleLabel); mValidCertificateSignature = ValidState::Fail; } @@ -149,15 +149,15 @@ void ctrtool::CrrProcess::verifyData() // log validation errors if (mValidCertificateSignature != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for CRR Certificate was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for CRR Certificate was invalid.\n", mModuleLabel); } if (mValidBodySignature != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for CRR Body was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for CRR Body was invalid.\n", mModuleLabel); } if (mValidUniqueId != ValidState::Good) { - fmt::print(stderr, "[{} LOG] CRR UniqueId was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] CRR UniqueId was invalid.\n", mModuleLabel); } } diff --git a/ctrtool/src/ExHeaderProcess.cpp b/ctrtool/src/ExHeaderProcess.cpp index ebaf9c84..be07f417 100644 --- a/ctrtool/src/ExHeaderProcess.cpp +++ b/ctrtool/src/ExHeaderProcess.cpp @@ -96,13 +96,13 @@ void ctrtool::ExHeaderProcess::verifyExHeader() } else { - fmt::print(stderr, "[{} LOG] Could not load AccessDescriptor RSA2048 public key.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Could not load AccessDescriptor RSA2048 public key.\n", mModuleLabel); mValidSignature = ValidState::Fail; } if (mValidSignature != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for AccessDescriptor was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for AccessDescriptor was invalid.\n", mModuleLabel); } mValidLocalCaps.system_save_id[0] = ValidState::Good; @@ -191,7 +191,7 @@ void ctrtool::ExHeaderProcess::verifyExHeader() mValidLocalCaps.fs_access = ValidState::Fail; if (mVerbose) { - fmt::print(stderr, "[{} LOG] FsAccess Bit {:d} was not permitted\n", mModuleLabel, fs_bit); + fmt::print(stderr, "[{} ERROR] FsAccess Bit {:d} was not permitted\n", mModuleLabel, fs_bit); } } } @@ -218,64 +218,64 @@ void ctrtool::ExHeaderProcess::verifyExHeader() mValidLocalCaps.service_control = Fail; if (mVerbose) { - fmt::print(stderr, "[{} LOG] Service \"{}\" was not permitted\n", mModuleLabel, exhdr_service_access_control[i].decode()); + fmt::print(stderr, "[{} ERROR] Service \"{}\" was not permitted\n", mModuleLabel, exhdr_service_access_control[i].decode()); } } } if (mValidLocalCaps.system_save_id[0] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId1"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId1"); } if (mValidLocalCaps.system_save_id[1] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId2"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemSaveId2"); } if (mValidLocalCaps.fs_access != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "FsAccess"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "FsAccess"); } /* if (mValidLocalCaps.core_version != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CoreVersion"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CoreVersion"); } */ if (mValidLocalCaps.program_id != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ProgramId"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ProgramId"); } if (mValidLocalCaps.priority != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ThreadPriority"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ThreadPriority"); } if (mValidLocalCaps.affinity_mask != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "AffinityMask"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "AffinityMask"); } if (mValidLocalCaps.ideal_processor != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "IdealProcessor"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "IdealProcessor"); } if (mValidLocalCaps.old3ds_system_mode != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (Old3DS)"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (Old3DS)"); } if (mValidLocalCaps.new3ds_system_mode != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (New3DS)"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "SystemMode (New3DS)"); } if (mValidLocalCaps.enable_l2_cache != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "EnableL2Cache"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "EnableL2Cache"); } if (mValidLocalCaps.new3ds_cpu_speed != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CpuSpeed"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "CpuSpeed"); } if (mValidLocalCaps.service_control != ValidState::Good) { - fmt::print(stderr, "[{} LOG] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ServiceAccess"); + fmt::print(stderr, "[{} ERROR] {} was not permmited by AccessDescriptor.\n", mModuleLabel, "ServiceAccess"); } } diff --git a/ctrtool/src/ExeFsProcess.cpp b/ctrtool/src/ExeFsProcess.cpp index d2a068eb..3d6c62f7 100644 --- a/ctrtool/src/ExeFsProcess.cpp +++ b/ctrtool/src/ExeFsProcess.cpp @@ -134,7 +134,7 @@ void ctrtool::ExeFsProcess::verifyFs() if (mSectionValidation[i] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] ExeFs file \"{}\" had an invalid SHA2-256 hash.\n", mModuleLabel, mHeader.file_table[i].name.decode()); + fmt::print(stderr, "[{} ERROR] ExeFs file \"{}\" had an invalid SHA2-256 hash.\n", mModuleLabel, mHeader.file_table[i].name.decode()); } } } diff --git a/ctrtool/src/FirmProcess.cpp b/ctrtool/src/FirmProcess.cpp index 671d27fd..d979d95a 100644 --- a/ctrtool/src/FirmProcess.cpp +++ b/ctrtool/src/FirmProcess.cpp @@ -191,7 +191,7 @@ void ctrtool::FirmProcess::verifyHashes() if (mValidFirmSectionHash[i] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] FIRM section {:d} SHA2-256 hash was invalid.\n", mModuleLabel, i); + fmt::print(stderr, "[{} ERROR] FIRM section {:d} SHA2-256 hash was invalid.\n", mModuleLabel, i); } } } @@ -231,7 +231,7 @@ void ctrtool::FirmProcess::verifySignature() } else { - fmt::print(stderr, "[{} LOG] Could not load {} RSA2048 public key.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); + fmt::print(stderr, "[{} ERROR] Could not load {} RSA2048 public key.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); valid_signature = ValidState::Fail; } @@ -244,7 +244,7 @@ void ctrtool::FirmProcess::verifySignature() } else { - fmt::print(stderr, "[{} LOG] Could not load {} SigHax RSA2048 signature.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); + fmt::print(stderr, "[{} ERROR] Could not load {} SigHax RSA2048 signature.\n", mModuleLabel, key_id == mKeyBag.RSAKEY_FIRM_NAND ? "FIRM_NAND" : "FIRM_RECOVERY"); is_sighax = false; } @@ -256,12 +256,12 @@ void ctrtool::FirmProcess::verifySignature() // check if sighax else if (valid_signature == ValidState::Fail && is_sighax == true) { - fmt::print(stderr, "[{} LOG] Signature for FIRM was invalid (SigHax).\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for FIRM was invalid (SigHax).\n", mModuleLabel); mSignatureState = SignatureState_SigHax; } else { - fmt::print(stderr, "[{} LOG] Signature for FIRM was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for FIRM was invalid.\n", mModuleLabel); mSignatureState = SignatureState_Fail; } } diff --git a/ctrtool/src/IvfcProcess.cpp b/ctrtool/src/IvfcProcess.cpp index 56c8579c..2550c5e2 100644 --- a/ctrtool/src/IvfcProcess.cpp +++ b/ctrtool/src/IvfcProcess.cpp @@ -127,7 +127,7 @@ void ctrtool::IvfcProcess::verifyLevels() { if (mVerbose) { - fmt::print(stderr, "[{} LOG] IVFC Layer {:d}, Block {:d} failed validation.\n", mModuleLabel, i, j); + fmt::print(stderr, "[{} ERROR] IVFC Layer {:d}, Block {:d} failed validation.\n", mModuleLabel, i, j); } } @@ -141,7 +141,7 @@ void ctrtool::IvfcProcess::verifyLevels() if (mLevelValidation[i] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] IVFC Layer {:d} failed validation.\n", mModuleLabel, i); + fmt::print(stderr, "[{} ERROR] IVFC Layer {:d} failed validation.\n", mModuleLabel, i); } } } diff --git a/ctrtool/src/NcchProcess.cpp b/ctrtool/src/NcchProcess.cpp index 21ac722b..30417229 100644 --- a/ctrtool/src/NcchProcess.cpp +++ b/ctrtool/src/NcchProcess.cpp @@ -241,7 +241,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() } if (crypto_is_stripped) { - fmt::print(stderr, "[{} LOG] NCCH appears to be decrypted, contrary to header flags.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] NCCH appears to be decrypted, contrary to header flags.\n", mModuleLabel); } // determine encryption mode @@ -287,7 +287,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() keyslot[0].valid_key = ValidState::Fail; keyslot[1].valid_key = ValidState::Fail; - fmt::print(stderr, "[{} LOG] Could not load {} fixed key.\n", mModuleLabel, (isSystemTitle()? "system" : "application")); + fmt::print(stderr, "[{} ERROR] Could not load {} fixed key.\n", mModuleLabel, (isSystemTitle()? "system" : "application")); } // save keys @@ -307,7 +307,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[0].valid_x = ValidState::Fail; - fmt::print(stderr, "[{} LOG] Could not load secure key_x[0x{:02x}].\n", mModuleLabel, 0); + fmt::print(stderr, "[{} ERROR] Could not load secure key_x[0x{:02x}].\n", mModuleLabel, 0); } else { @@ -328,7 +328,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_x = ValidState::Fail; - fmt::print(stderr, "[{} LOG] Could not read secure key_x[0x{:02x}].\n", mModuleLabel, security_version); + fmt::print(stderr, "[{} ERROR] Could not load secure key_x[0x{:02x}].\n", mModuleLabel, security_version); } else { @@ -360,7 +360,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_y = ValidState::Fail; - fmt::print(stderr, "[{} LOG] This title uses seed crypto, but no seed is set, unable to decrypt.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] This title uses seed crypto, but no seed is set, unable to decrypt.\n", mModuleLabel); fmt::print(stderr, " Use -p to avoid decryption or use --seeddb=dbfile or --seed=SEEDHERE.\n"); } @@ -375,7 +375,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() { keyslot[1].valid_y = ValidState::Fail; - fmt::print(stderr, "[{} LOG] Seed check mismatch. (Got {:08x}, expected: {:08x})\n", + fmt::print(stderr, "[{} ERROR] Seed check mismatch. (Got {:08x}, expected: {:08x})\n", mModuleLabel, ((tc::bn::be32*)hash.data())->unwrap(), ((tc::bn::be32*)mHeader.header.seed_checksum.data())->unwrap()); @@ -532,7 +532,7 @@ void ctrtool::NcchProcess::determineRegionEncryption() // otherwise use the "best-effort" single key stream (only icon and banner will be decrypt properly) else { - fmt::print(stderr, "[{} LOG] Only NCCH key0 was determined, ExeFS may be partially decrypted\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Only NCCH key0 was determined, ExeFS may be partially decrypted\n", mModuleLabel); mRegionInfo[NcchRegion_ExeFs].ready_stream = std::shared_ptr(new tc::crypto::Aes128CtrEncryptedStream(mRegionInfo[NcchRegion_ExeFs].raw_stream, keyslot[0].key, exefs_aesctr)); } } @@ -597,7 +597,7 @@ void ctrtool::NcchProcess::verifyRegions() else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not load CFA RSA2048 public key.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Could not load CFA RSA2048 public key.\n", mModuleLabel); mRegionInfo[NcchRegion_Header].valid = ValidState::Fail; } @@ -622,14 +622,14 @@ void ctrtool::NcchProcess::verifyRegions() else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not load CXI RSA2048 public key from AccessDescriptor.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Could not load CXI RSA2048 public key from AccessDescriptor.\n", mModuleLabel); mRegionInfo[NcchRegion_Header].valid = ValidState::Fail; } } if (mRegionInfo[NcchRegion_Header].valid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for NcchHeader was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for NcchHeader was invalid.\n", mModuleLabel); } } @@ -640,7 +640,7 @@ void ctrtool::NcchProcess::verifyRegions() if (mRegionInfo[NcchRegion_ExHeader].valid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] ExtendedHeader SHA2-256 hash was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] ExtendedHeader SHA2-256 hash was invalid.\n", mModuleLabel); } } @@ -651,7 +651,7 @@ void ctrtool::NcchProcess::verifyRegions() if (mRegionInfo[NcchRegion_Logo].valid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Logo SHA2-256 hash was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Logo SHA2-256 hash was invalid.\n", mModuleLabel); } } @@ -662,7 +662,7 @@ void ctrtool::NcchProcess::verifyRegions() if (mRegionInfo[NcchRegion_ExeFs].valid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] ExeFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] ExeFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); } } @@ -673,7 +673,7 @@ void ctrtool::NcchProcess::verifyRegions() if (mRegionInfo[NcchRegion_RomFs].valid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] RomFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] RomFs SuperBlock SHA2-256 hash was invalid.\n", mModuleLabel); } } } @@ -776,8 +776,8 @@ void ctrtool::NcchProcess::extractRegionBinaries() case NcchRegion_ExHeader: fmt::print(stderr, "[{} LOG] Saving Extended Header...\n", mModuleLabel); break; case NcchRegion_PlainRegion: fmt::print(stderr, "[{} LOG] Saving Plain Region...\n", mModuleLabel); break; case NcchRegion_Logo: fmt::print(stderr, "[{} LOG] Saving Logo...\n", mModuleLabel); break; - case NcchRegion_ExeFs: fmt::print(stderr, "[{} LOG] Saving ExeFS...\n", mModuleLabel); break; - case NcchRegion_RomFs: fmt::print(stderr, "[{} LOG] Saving RomFS...\n", mModuleLabel); break; + case NcchRegion_ExeFs: fmt::print(stderr, "[{} LOG] Saving ExeFs...\n", mModuleLabel); break; + case NcchRegion_RomFs: fmt::print(stderr, "[{} LOG] Saving RomFs...\n", mModuleLabel); break; } } diff --git a/ctrtool/src/TikProcess.cpp b/ctrtool/src/TikProcess.cpp index 0fc7989b..71042fdb 100644 --- a/ctrtool/src/TikProcess.cpp +++ b/ctrtool/src/TikProcess.cpp @@ -202,21 +202,21 @@ void ctrtool::TikProcess::verifyData() // only show this warning when there are certificates appended to the ticket (only tickets downloaded from CDN will have an appended certificate chain) if (mCertChain.size() != 0) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for ticket) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for ticket) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTicket.signature.issuer); } mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key \"{}\" (for ticket).\n", mModuleLabel, mTicket.signature.issuer); mTicketSigValid = ValidState::Fail; } // log ticket signature validation error if (mTicketSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for Ticket was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for Ticket was invalid.\n", mModuleLabel); } } } diff --git a/ctrtool/src/TmdProcess.cpp b/ctrtool/src/TmdProcess.cpp index 0fe136aa..3d469b59 100644 --- a/ctrtool/src/TmdProcess.cpp +++ b/ctrtool/src/TmdProcess.cpp @@ -139,21 +139,21 @@ void ctrtool::TmdProcess::verifyData() // only show this warning for non-root signed certificates if (mCertChain[i].signature.issuer != "Root") { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for certificate \"{}\") was not present in the certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for certificate \"{}\") was not present in the certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mCertChain[i].signature.issuer, mCertChain[i].subject); } mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key for \"{}\" (certificate).\n", mModuleLabel, mCertChain[i].signature.issuer); mCertSigValid[i] = ValidState::Fail; } // log certificate signature validation error if (mCertSigValid[i] != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); + fmt::print(stderr, "[{} ERROR] Signature for Certificate \"{}\" was invalid.\n", mModuleLabel, mCertChain[i].signature.issuer); } } @@ -174,21 +174,21 @@ void ctrtool::TmdProcess::verifyData() // only show this warning when there are certificates appended to the tmd (only tmd downloaded from CDN will have an appended certificate chain) if (mCertChain.size() != 0) { - fmt::print(stderr, "[{} LOG] Public key \"{}\" (for tmd) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} ERROR] Public key \"{}\" (for tmd) was not present in the appended certificate chain. The public key included with CTRTool was used instead.\n", mModuleLabel, mTitleMetaData.signature.issuer); } mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail; } else { // cannot locate rsa key to verify - fmt::print(stderr, "[{} LOG] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); + fmt::print(stderr, "[{} ERROR] Could not locate public key \"{}\" (for tmd).\n", mModuleLabel, mTitleMetaData.signature.issuer); mTitleMetaDataSigValid = ValidState::Fail; } // log tmd signature validation error if (mTitleMetaDataSigValid != ValidState::Good) { - fmt::print(stderr, "[{} LOG] Signature for TitleMetaData was invalid.\n", mModuleLabel); + fmt::print(stderr, "[{} ERROR] Signature for TitleMetaData was invalid.\n", mModuleLabel); } } } From e1a6f9101d024c2283312143f3a31a0419fb0693 Mon Sep 17 00:00:00 2001 From: jakcron Date: Fri, 15 Apr 2022 11:27:33 +0800 Subject: [PATCH 13/13] Bump version to v1.1.0 --- ctrtool/src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ctrtool/src/version.h b/ctrtool/src/version.h index 27dba3b5..c59c9ed7 100644 --- a/ctrtool/src/version.h +++ b/ctrtool/src/version.h @@ -2,6 +2,6 @@ #define APP_NAME "CTRTool" #define BIN_NAME "ctrtool" #define VER_MAJOR 1 -#define VER_MINOR 0 -#define VER_PATCH 4 +#define VER_MINOR 1 +#define VER_PATCH 0 #define AUTHORS "jakcron" \ No newline at end of file