From 334f6f04683e788c1bc9e614a554d078005adc1f Mon Sep 17 00:00:00 2001 From: Jack Date: Sun, 19 Jun 2022 13:53:25 +0800 Subject: [PATCH] [CTRTool] Honour plain flag when processing CIA files. (#126) * Add util functions to CTRTool * [ctrtool] Honour -p flag when processing CIA files. * Bump CTRTool version to v1.1.1 --- .../visualstudio/CTRTool/CTRTool.vcxproj | 2 + .../CTRTool/CTRTool.vcxproj.filters | 6 +++ ctrtool/src/CiaProcess.cpp | 51 ++++++------------ ctrtool/src/CiaProcess.h | 2 +- ctrtool/src/util.cpp | 52 +++++++++++++++++++ ctrtool/src/util.h | 15 ++++++ ctrtool/src/version.h | 2 +- 7 files changed, 92 insertions(+), 38 deletions(-) create mode 100644 ctrtool/src/util.cpp create mode 100644 ctrtool/src/util.h diff --git a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj index c8f7dc3..3648b45 100644 --- a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj +++ b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj @@ -153,6 +153,7 @@ + @@ -172,6 +173,7 @@ + diff --git a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters index 91b9ca0..1955240 100644 --- a/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters +++ b/ctrtool/build/visualstudio/CTRTool/CTRTool.vcxproj.filters @@ -66,6 +66,9 @@ Header Files + + Header Files + Header Files @@ -119,5 +122,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/ctrtool/src/CiaProcess.cpp b/ctrtool/src/CiaProcess.cpp index 6b89d7a..237f3e3 100644 --- a/ctrtool/src/CiaProcess.cpp +++ b/ctrtool/src/CiaProcess.cpp @@ -1,4 +1,5 @@ #include "CiaProcess.h" +#include "util.h" #include #include #include @@ -15,6 +16,7 @@ ctrtool::CiaProcess::CiaProcess() : mShowHeaderInfo(false), mVerbose(false), mVerify(false), + mPlain(false), mCertExtractPath(), mTikExtractPath(), mTmdExtractPath(), @@ -103,6 +105,7 @@ void ctrtool::CiaProcess::setRawMode(bool raw) void ctrtool::CiaProcess::setPlainMode(bool plain) { + mPlain = plain; mNcchProcess.setPlainMode(plain); } @@ -515,7 +518,7 @@ void ctrtool::CiaProcess::verifyContent() content_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, itr->second.offset, itr->second.size)); - if (itr->second.is_encrypted && mDecryptedTitleKey.isSet()) + if (!mPlain && itr->second.is_encrypted && mDecryptedTitleKey.isSet()) { tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv; createContentIv(content_iv, itr->second.cindex); @@ -691,23 +694,22 @@ void ctrtool::CiaProcess::printHeader() void ctrtool::CiaProcess::extractCia() { + tc::ByteData cache = tc::ByteData(0x10000); tc::io::Path out_path; std::shared_ptr in_stream; - std::shared_ptr out_stream; if (mCertExtractPath.isSet() && mCertSizeInfo.size > 0) { out_path = mCertExtractPath.get(); 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)); if (mVerbose) { fmt::print(stderr, "[{} LOG] Saving certs to {}...\n", mModuleLabel, out_path.to_string()); } - copyStream(in_stream, out_stream); + writeStreamToFile(in_stream, out_path, cache); } if (mTikExtractPath.isSet() && mTikSizeInfo.size > 0) @@ -715,13 +717,13 @@ void ctrtool::CiaProcess::extractCia() out_path = mTikExtractPath.get(); 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)); if (mVerbose) { fmt::print(stderr, "[{} LOG] Saving tik to {}...\n", mModuleLabel, out_path.to_string()); } - copyStream(in_stream, out_stream); + + writeStreamToFile(in_stream, out_path, cache); } if (mTmdExtractPath.isSet() && mTmdSizeInfo.size > 0) @@ -729,13 +731,13 @@ void ctrtool::CiaProcess::extractCia() out_path = mTmdExtractPath.get(); 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)); if (mVerbose) { fmt::print(stderr, "[{} LOG] Saving tmd to {}...\n", mModuleLabel, out_path.to_string()); } - copyStream(in_stream, out_stream); + + writeStreamToFile(in_stream, out_path, cache); } if (mFooterExtractPath.isSet() && mFooterSizeInfo.size > 0) @@ -743,13 +745,13 @@ void ctrtool::CiaProcess::extractCia() out_path = mFooterExtractPath.get(); 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)); if (mVerbose) { fmt::print(stderr, "[{} LOG] Saving meta to {}...\n", mModuleLabel, out_path.to_string()); } - copyStream(in_stream, out_stream); + + writeStreamToFile(in_stream, out_path, cache); } if (mContentExtractPath.isSet() && mContentInfo.size() > 0) @@ -761,7 +763,7 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, itr->second.offset, itr->second.size)); - if (itr->second.is_encrypted && mDecryptedTitleKey.isSet()) + if (!mPlain && itr->second.is_encrypted && mDecryptedTitleKey.isSet()) { tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv; createContentIv(content_iv, itr->second.cindex); @@ -769,39 +771,16 @@ void ctrtool::CiaProcess::extractCia() in_stream = std::shared_ptr(new tc::crypto::Aes128CbcEncryptedStream(in_stream, mDecryptedTitleKey.get(), content_iv)); } - out_stream = std::shared_ptr(new tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)); - if (mVerbose) { fmt::print(stderr, "[{} LOG] Saving content {:04x} to {}...\n", mModuleLabel, itr->second.cindex, out_path.to_string()); } - copyStream(in_stream, out_stream); + writeStreamToFile(in_stream, out_path, cache); } } } -void ctrtool::CiaProcess::copyStream(const std::shared_ptr& in, const std::shared_ptr& out) -{ - tc::ByteData cache = tc::ByteData(0x10000); - size_t cache_read_len; - - in->seek(0, tc::io::SeekOrigin::Begin); - out->seek(0, tc::io::SeekOrigin::Begin); - for (int64_t remaining_data = in->length(); remaining_data > 0;) - { - cache_read_len = in->read(cache.data(), cache.size()); - if (cache_read_len == 0) - { - throw tc::io::IOException(mModuleLabel, "Failed to read from source file."); - } - - out->write(cache.data(), cache_read_len); - - remaining_data -= int64_t(cache_read_len); - } -} - void ctrtool::CiaProcess::processContent() { if (mContentIndex >= ntd::n3ds::CiaHeader::kCiaMaxContentNum) @@ -813,7 +792,7 @@ void ctrtool::CiaProcess::processContent() { std::shared_ptr content_stream = std::shared_ptr(new tc::io::SubStream(mInputStream, mContentInfo[mContentIndex].offset, mContentInfo[mContentIndex].size)); - if (mContentInfo[mContentIndex].is_encrypted && mDecryptedTitleKey.isSet()) + if (!mPlain && mContentInfo[mContentIndex].is_encrypted && mDecryptedTitleKey.isSet()) { tc::crypto::Aes128CbcEncryptedStream::iv_t content_iv; createContentIv(content_iv, mContentInfo[mContentIndex].cindex); diff --git a/ctrtool/src/CiaProcess.h b/ctrtool/src/CiaProcess.h index 245184e..c708936 100644 --- a/ctrtool/src/CiaProcess.h +++ b/ctrtool/src/CiaProcess.h @@ -46,6 +46,7 @@ private: bool mShowHeaderInfo; bool mVerbose; bool mVerify; + bool mPlain; tc::Optional mCertExtractPath; tc::Optional mTikExtractPath; tc::Optional mTmdExtractPath; @@ -108,7 +109,6 @@ private: void verifyContent(); void printHeader(); void extractCia(); - void copyStream(const std::shared_ptr& in, const std::shared_ptr& out); void processContent(); void createContentIv(std::array& content_iv, uint16_t index); diff --git a/ctrtool/src/util.cpp b/ctrtool/src/util.cpp new file mode 100644 index 0000000..c729587 --- /dev/null +++ b/ctrtool/src/util.cpp @@ -0,0 +1,52 @@ +#include "util.h" + +#include +#include +#include + +void ctrtool::writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, tc::ByteData& cache) +{ + writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache); +} + +void ctrtool::writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size) +{ + writeStreamToStream(std::make_shared(tc::io::SubStream(in_stream, offset, length)), std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache_size); +} + +void ctrtool::writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, tc::ByteData& cache) +{ + writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache); +} + +void ctrtool::writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, size_t cache_size) +{ + writeStreamToStream(in_stream, std::make_shared(tc::io::FileStream(out_path, tc::io::FileMode::Create, tc::io::FileAccess::Write)), cache_size); +} + +void ctrtool::writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, tc::ByteData& cache) +{ + // iterate thru child files + size_t cache_read_len; + + in_stream->seek(0, tc::io::SeekOrigin::Begin); + out_stream->seek(0, tc::io::SeekOrigin::Begin); + for (int64_t remaining_data = in_stream->length(); remaining_data > 0;) + { + cache_read_len = in_stream->read(cache.data(), cache.size()); + if (cache_read_len == 0) + { + throw tc::io::IOException("ctrtool::writeStreamToStream()", "Failed to read from source streeam."); + } + + out_stream->write(cache.data(), cache_read_len); + + remaining_data -= int64_t(cache_read_len); + } +} + +void ctrtool::writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, size_t cache_size) +{ + tc::ByteData cache = tc::ByteData(cache_size); + writeStreamToStream(in_stream, out_stream, cache); +} \ No newline at end of file diff --git a/ctrtool/src/util.h b/ctrtool/src/util.h new file mode 100644 index 0000000..de4071e --- /dev/null +++ b/ctrtool/src/util.h @@ -0,0 +1,15 @@ +#pragma once +#include "types.h" +#include + +namespace ctrtool +{ + +void writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, tc::ByteData& cache); +void writeSubStreamToFile(const std::shared_ptr& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size = 0x10000); +void writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, tc::ByteData& cache); +void writeStreamToFile(const std::shared_ptr& in_stream, const tc::io::Path& out_path, size_t cache_size = 0x10000); +void writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, tc::ByteData& cache); +void writeStreamToStream(const std::shared_ptr& in_stream, const std::shared_ptr& out_stream, size_t cache_size = 0x10000); + +} \ No newline at end of file diff --git a/ctrtool/src/version.h b/ctrtool/src/version.h index c59c9ed..0ae3d8b 100644 --- a/ctrtool/src/version.h +++ b/ctrtool/src/version.h @@ -3,5 +3,5 @@ #define BIN_NAME "ctrtool" #define VER_MAJOR 1 #define VER_MINOR 1 -#define VER_PATCH 0 +#define VER_PATCH 1 #define AUTHORS "jakcron" \ No newline at end of file