diff --git a/programs/nstool/source/AesCtrWrappedIFile.cpp b/programs/nstool/source/AesCtrWrappedIFile.cpp index 81fd145..4a1cc71 100644 --- a/programs/nstool/source/AesCtrWrappedIFile.cpp +++ b/programs/nstool/source/AesCtrWrappedIFile.cpp @@ -1,10 +1,5 @@ #include "AesCtrWrappedIFile.h" -AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr) : - AesCtrWrappedIFile(file, false, key, ctr) -{ -} - AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr) : mOwnIFile(ownIfile), mFile(file), diff --git a/programs/nstool/source/AesCtrWrappedIFile.h b/programs/nstool/source/AesCtrWrappedIFile.h index 2f83e1a..e76dc81 100644 --- a/programs/nstool/source/AesCtrWrappedIFile.h +++ b/programs/nstool/source/AesCtrWrappedIFile.h @@ -5,7 +5,6 @@ class AesCtrWrappedIFile : public fnd::IFile { public: - AesCtrWrappedIFile(fnd::IFile* file, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr); AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const crypto::aes::sAes128Key& key, const crypto::aes::sAesIvCtr& ctr); ~AesCtrWrappedIFile(); diff --git a/programs/nstool/source/CnmtProcess.cpp b/programs/nstool/source/CnmtProcess.cpp index bba920a..69b4869 100644 --- a/programs/nstool/source/CnmtProcess.cpp +++ b/programs/nstool/source/CnmtProcess.cpp @@ -143,7 +143,8 @@ void CnmtProcess::displayCmnt() } CnmtProcess::CnmtProcess() : - mReader(nullptr), + mFile(nullptr), + mOwnIFile(false), mCliOutputType(OUTPUT_NORMAL), mVerify(false) { @@ -151,9 +152,9 @@ CnmtProcess::CnmtProcess() : CnmtProcess::~CnmtProcess() { - if (mReader != nullptr) + if (mOwnIFile) { - delete mReader; + delete mFile; } } @@ -161,13 +162,13 @@ void CnmtProcess::process() { fnd::MemoryBlob scratch; - if (mReader == nullptr) + if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mReader->size()); - mReader->read(scratch.getBytes(), 0, scratch.getSize()); + scratch.alloc(mFile->size()); + mFile->read(scratch.getBytes(), 0, scratch.getSize()); mCnmt.importBinary(scratch.getBytes(), scratch.getSize()); @@ -177,9 +178,10 @@ void CnmtProcess::process() } } -void CnmtProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +void CnmtProcess::setInputFile(fnd::IFile* file, bool ownIFile) { - mReader = new OffsetAdjustedIFile(file, offset, size); + mFile = file; + mOwnIFile = ownIFile; } void CnmtProcess::setCliOutputMode(CliOutputType type) diff --git a/programs/nstool/source/CnmtProcess.h b/programs/nstool/source/CnmtProcess.h index 4e57947..f3b0367 100644 --- a/programs/nstool/source/CnmtProcess.h +++ b/programs/nstool/source/CnmtProcess.h @@ -14,7 +14,7 @@ public: void process(); - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -23,7 +23,8 @@ public: private: const std::string kModuleName = "CnmtProcess"; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/CopiedIFile.h b/programs/nstool/source/CopiedIFile.h deleted file mode 100644 index 918b28e..0000000 --- a/programs/nstool/source/CopiedIFile.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include - -class CopiedIFile : public fnd::IFile -{ -public: - inline CopiedIFile(fnd::IFile* file) : mFile(file) {} - - inline size_t size() { return mFile->size(); } - inline void seek(size_t offset) { mFile->seek(offset); } - inline void read(byte_t* out, size_t len) { mFile->read(out, len); } - inline void read(byte_t* out, size_t offset, size_t len) { mFile->read(out, offset, len); } - inline void write(const byte_t* out, size_t len) { mFile->write(out, len); } - inline void write(const byte_t* out, size_t offset, size_t len) { mFile->write(out, offset, len); } -private: - fnd::IFile* mFile; -}; \ No newline at end of file diff --git a/programs/nstool/source/HashTreeWrappedIFile.cpp b/programs/nstool/source/HashTreeWrappedIFile.cpp index dd995f6..39783dd 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.cpp +++ b/programs/nstool/source/HashTreeWrappedIFile.cpp @@ -1,18 +1,7 @@ +#include "nstool.h" #include "HashTreeWrappedIFile.h" -#include "CopiedIFile.h" #include "OffsetAdjustedIFile.h" - -HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, const HashTreeMeta& hdr) : - mOwnIFile(true), - mFile(file), - mData(nullptr), - mDataHashLayer(), - mAlignHashCalcToBlock(false) -{ - initialiseDataLayer(hdr); -} - HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr) : mOwnIFile(ownIFile), mFile(file), @@ -156,7 +145,7 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) } // generate reader for data layer - mData = new OffsetAdjustedIFile(mFile, false, hdr.getDataLayer().offset, hdr.getDataLayer().size); + mData = new OffsetAdjustedIFile(mFile, SHARED_IFILE, hdr.getDataLayer().offset, hdr.getDataLayer().size); mDataOffset = 0; mDataBlockSize = hdr.getDataLayer().block_size; diff --git a/programs/nstool/source/HashTreeWrappedIFile.h b/programs/nstool/source/HashTreeWrappedIFile.h index cb64f6e..cb89ae8 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.h +++ b/programs/nstool/source/HashTreeWrappedIFile.h @@ -9,7 +9,6 @@ class HashTreeWrappedIFile : public fnd::IFile { public: - HashTreeWrappedIFile(fnd::IFile* file, const HashTreeMeta& hdr); HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr); ~HashTreeWrappedIFile(); diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index 5310017..7b11e13 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -9,7 +9,6 @@ #include "NpdmProcess.h" #include "OffsetAdjustedIFile.h" #include "AesCtrWrappedIFile.h" -#include "CopiedIFile.h" #include "HashTreeWrappedIFile.h" const char* getFormatVersionStr(nx::NcaHeader::FormatVersion format_ver) @@ -222,7 +221,8 @@ const char* getProgramPartitionNameStr(size_t i) NcaProcess::NcaProcess() : - mReader(nullptr), + mFile(nullptr), + mOwnIFile(false), mKeyset(nullptr), mCliOutputType(OUTPUT_NORMAL), mVerify(false), @@ -237,9 +237,9 @@ NcaProcess::NcaProcess() : NcaProcess::~NcaProcess() { - if (mReader != nullptr) + if (mOwnIFile) { - delete mReader; + delete mFile; } for (size_t i = 0; i < nx::nca::kPartitionNum; i++) @@ -255,13 +255,13 @@ void NcaProcess::process() { fnd::MemoryBlob scratch; - if (mReader == nullptr) + if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // read header block - mReader->read((byte_t*)&mHdrBlock, 0, sizeof(nx::sNcaHeaderBlock)); + mFile->read((byte_t*)&mHdrBlock, 0, sizeof(nx::sNcaHeaderBlock)); // decrypt header block nx::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyset->nca.header_key); @@ -311,9 +311,10 @@ void NcaProcess::process() */ } -void NcaProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +void NcaProcess::setInputFile(fnd::IFile* file, bool ownIFile) { - mReader = new OffsetAdjustedIFile(file, offset, size); + mFile = file; + mOwnIFile = ownIFile; } void NcaProcess::setKeyset(const sKeyset* keyset) @@ -539,13 +540,13 @@ void NcaProcess::generatePartitionConfiguration() // create reader based on encryption type0 if (info.enc_type == nx::nca::CRYPT_NONE) { - info.reader = new OffsetAdjustedIFile(mReader, info.offset, info.size); + info.reader = new OffsetAdjustedIFile(mFile, SHARED_IFILE, info.offset, info.size); } else if (info.enc_type == nx::nca::CRYPT_AESCTR) { if (mBodyKeys.aes_ctr.isSet == false) throw fnd::Exception(kModuleName, "AES-CTR Key was not determined"); - info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mReader, mBodyKeys.aes_ctr.var, info.aes_ctr), true, info.offset, info.size); + info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mFile, SHARED_IFILE, mBodyKeys.aes_ctr.var, info.aes_ctr), OWN_IFILE, info.offset, info.size); } else if (info.enc_type == nx::nca::CRYPT_AESXTS || info.enc_type == nx::nca::CRYPT_AESCTREX) { @@ -565,7 +566,7 @@ void NcaProcess::generatePartitionConfiguration() { fnd::IFile* tmp = info.reader; info.reader = nullptr; - info.reader = new HashTreeWrappedIFile(tmp, true, info.hash_tree_meta); + info.reader = new HashTreeWrappedIFile(tmp, OWN_IFILE, info.hash_tree_meta); } else if (info.hash_type != nx::nca::HASH_NONE) { @@ -602,7 +603,7 @@ void NcaProcess::validateNcaSignatures() if (mPartitions[nx::nca::PARTITION_CODE].reader != nullptr) { PfsProcess exefs; - exefs.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, 0, mPartitions[nx::nca::PARTITION_CODE].reader->size()); + exefs.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE); exefs.setCliOutputMode(OUTPUT_MINIMAL); exefs.process(); @@ -612,7 +613,7 @@ void NcaProcess::validateNcaSignatures() const nx::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList()[exefs.getPfsHeader().getFileList().getIndexOf(kNpdmExefsPath)]; NpdmProcess npdm; - npdm.setInputFile(mPartitions[nx::nca::PARTITION_CODE].reader, file.offset, file.size); + npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nx::nca::PARTITION_CODE].reader, SHARED_IFILE, file.offset, file.size), OWN_IFILE); npdm.setCliOutputMode(OUTPUT_MINIMAL); npdm.process(); @@ -789,7 +790,7 @@ void NcaProcess::processPartitions() if (partition.format_type == nx::nca::FORMAT_PFS0) { PfsProcess pfs; - pfs.setInputFile(partition.reader, 0, partition.reader->size()); + pfs.setInputFile(partition.reader, SHARED_IFILE); pfs.setCliOutputMode(mCliOutputType); pfs.setListFs(mListFs); if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM) @@ -810,7 +811,7 @@ void NcaProcess::processPartitions() else if (partition.format_type == nx::nca::FORMAT_ROMFS) { RomfsProcess romfs; - romfs.setInputFile(partition.reader, 0, partition.reader->size()); + romfs.setInputFile(partition.reader, SHARED_IFILE); romfs.setCliOutputMode(mCliOutputType); romfs.setListFs(mListFs); if (mHdr.getContentType() == nx::nca::TYPE_PROGRAM) diff --git a/programs/nstool/source/NcaProcess.h b/programs/nstool/source/NcaProcess.h index 666c9a4..38029db 100644 --- a/programs/nstool/source/NcaProcess.h +++ b/programs/nstool/source/NcaProcess.h @@ -17,7 +17,7 @@ public: void process(); // generic - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setKeyset(const sKeyset* keyset); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -34,7 +34,8 @@ private: const std::string kNpdmExefsPath = "main.npdm"; // user options - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; const sKeyset* mKeyset; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/NpdmProcess.cpp b/programs/nstool/source/NpdmProcess.cpp index 27b1abe..36d36c0 100644 --- a/programs/nstool/source/NpdmProcess.cpp +++ b/programs/nstool/source/NpdmProcess.cpp @@ -1,6 +1,87 @@ -#include "OffsetAdjustedIFile.h" #include "NpdmProcess.h" +NpdmProcess::NpdmProcess() : + mFile(nullptr), + mOwnIFile(false), + mKeyset(nullptr), + mCliOutputType(OUTPUT_NORMAL), + mVerify(false) +{ +} + +NpdmProcess::~NpdmProcess() +{ + if (mOwnIFile) + { + delete mFile; + } +} + +void NpdmProcess::process() +{ + fnd::MemoryBlob scratch; + + if (mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + scratch.alloc(mFile->size()); + mFile->read(scratch.getBytes(), 0, scratch.getSize()); + + mNpdm.importBinary(scratch.getBytes(), scratch.getSize()); + + if (mVerify) + { + validateAcidSignature(mNpdm.getAcid()); + validateAciFromAcid(mNpdm.getAci(), mNpdm.getAcid()); + } + + if (mCliOutputType >= OUTPUT_NORMAL) + { + // npdm binary + displayNpdmHeader(mNpdm); + + // aci binary + displayAciHdr(mNpdm.getAci()); + displayFac(mNpdm.getAci().getFac()); + displaySac(mNpdm.getAci().getSac()); + displayKernelCap(mNpdm.getAci().getKc()); + + // acid binary + displayAciHdr(mNpdm.getAcid()); + displayFac(mNpdm.getAcid().getFac()); + displaySac(mNpdm.getAcid().getSac()); + displayKernelCap(mNpdm.getAcid().getKc()); + } +} + +void NpdmProcess::setInputFile(fnd::IFile* file, bool ownIFile) +{ + mFile = file; + mOwnIFile = ownIFile; +} + +void NpdmProcess::setKeyset(const sKeyset* keyset) +{ + mKeyset = keyset; +} + +void NpdmProcess::setCliOutputMode(CliOutputType type) +{ + mCliOutputType = type; +} + +void NpdmProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const +{ + return mNpdm; +} + const std::string kInstructionType[2] = { "32Bit", "64Bit" }; const std::string kProcAddrSpace[4] = { "Unknown", "64Bit", "32Bit", "32Bit no reserved" }; const std::string kAciType[2] = { "ACI0", "ACID" }; @@ -615,83 +696,3 @@ void NpdmProcess::displayKernelCap(const nx::KcBinary& kern) } } } - -NpdmProcess::NpdmProcess() : - mReader(nullptr), - mKeyset(nullptr), - mCliOutputType(OUTPUT_NORMAL), - mVerify(false) -{ -} - -NpdmProcess::~NpdmProcess() -{ - if (mReader != nullptr) - { - delete mReader; - } -} - -void NpdmProcess::process() -{ - fnd::MemoryBlob scratch; - - if (mReader == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - scratch.alloc(mReader->size()); - mReader->read(scratch.getBytes(), 0, scratch.getSize()); - - mNpdm.importBinary(scratch.getBytes(), scratch.getSize()); - - if (mVerify) - { - validateAcidSignature(mNpdm.getAcid()); - validateAciFromAcid(mNpdm.getAci(), mNpdm.getAcid()); - } - - if (mCliOutputType >= OUTPUT_NORMAL) - { - // npdm binary - displayNpdmHeader(mNpdm); - - // aci binary - displayAciHdr(mNpdm.getAci()); - displayFac(mNpdm.getAci().getFac()); - displaySac(mNpdm.getAci().getSac()); - displayKernelCap(mNpdm.getAci().getKc()); - - // acid binary - displayAciHdr(mNpdm.getAcid()); - displayFac(mNpdm.getAcid().getFac()); - displaySac(mNpdm.getAcid().getSac()); - displayKernelCap(mNpdm.getAcid().getKc()); - } -} - -void NpdmProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) -{ - mReader = new OffsetAdjustedIFile(file, offset, size); -} - -void NpdmProcess::setKeyset(const sKeyset* keyset) -{ - mKeyset = keyset; -} - -void NpdmProcess::setCliOutputMode(CliOutputType type) -{ - mCliOutputType = type; -} - -void NpdmProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -const nx::NpdmBinary& NpdmProcess::getNpdmBinary() const -{ - return mNpdm; -} \ No newline at end of file diff --git a/programs/nstool/source/NpdmProcess.h b/programs/nstool/source/NpdmProcess.h index e14cbd0..f9d4e95 100644 --- a/programs/nstool/source/NpdmProcess.h +++ b/programs/nstool/source/NpdmProcess.h @@ -14,7 +14,7 @@ public: void process(); - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setKeyset(const sKeyset* keyset); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -24,7 +24,8 @@ public: private: const std::string kModuleName = "NpdmProcess"; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; const sKeyset* mKeyset; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index 8b080c0..3d9708a 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -6,7 +6,8 @@ #include "NsoProcess.h" NsoProcess::NsoProcess(): - mReader(nullptr), + mFile(nullptr), + mOwnIFile(false), mCliOutputType(OUTPUT_NORMAL), mVerify(false) { @@ -15,15 +16,15 @@ NsoProcess::NsoProcess(): NsoProcess::~NsoProcess() { - if (mReader != nullptr) + if (mOwnIFile) { - delete mReader; + delete mFile; } } void NsoProcess::process() { - if (mReader == nullptr) + if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } @@ -39,9 +40,10 @@ void NsoProcess::process() } } -void NsoProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +void NsoProcess::setInputFile(fnd::IFile* file, bool ownIFile) { - mReader = new OffsetAdjustedIFile(file, offset, size); + mFile = file; + mOwnIFile = ownIFile; } void NsoProcess::setCliOutputMode(CliOutputType type) @@ -84,17 +86,16 @@ const std::vector& NsoProcess::getApiList() const return mApiList; } - void NsoProcess::importHeader() { fnd::MemoryBlob scratch; - if (mReader->size() < sizeof(nx::sNsoHeader)) + if (mFile->size() < sizeof(nx::sNsoHeader)) { throw fnd::Exception(kModuleName, "Corrupt NSO file too small"); } scratch.alloc(sizeof(nx::sNsoHeader)); - mReader->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.getBytes(), 0, scratch.getSize()); mHdr.importBinary(scratch.getBytes(), scratch.getSize()); } @@ -109,7 +110,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getTextSegmentInfo().is_compressed) { scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mReader->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize()); mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mTextBlob.getBytes(), mTextBlob.getSize(), decompressed_len); if (decompressed_len != mTextBlob.getSize()) @@ -120,7 +121,7 @@ void NsoProcess::importCodeSegments() else { mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mReader->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize()); + mFile->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize()); } if (mHdr.getTextSegmentInfo().is_hashed) { @@ -135,7 +136,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getRoSegmentInfo().is_compressed) { scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mReader->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize()); mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mRoBlob.getBytes(), mRoBlob.getSize(), decompressed_len); if (decompressed_len != mRoBlob.getSize()) @@ -146,7 +147,7 @@ void NsoProcess::importCodeSegments() else { mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mReader->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize()); + mFile->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize()); } if (mHdr.getRoSegmentInfo().is_hashed) { @@ -161,7 +162,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getDataSegmentInfo().is_compressed) { scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mReader->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize()); + mFile->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize()); mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mDataBlob.getBytes(), mDataBlob.getSize(), decompressed_len); if (decompressed_len != mDataBlob.getSize()) @@ -172,7 +173,7 @@ void NsoProcess::importCodeSegments() else { mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mReader->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize()); + mFile->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize()); } if (mHdr.getDataSegmentInfo().is_hashed) { diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index 0a34c75..fe0271e 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -17,7 +17,7 @@ public: void process(); - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -33,7 +33,9 @@ public: private: const std::string kModuleName = "NsoProcess"; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; + CliOutputType mCliOutputType; bool mVerify; sOptional mArchType; diff --git a/programs/nstool/source/OffsetAdjustedIFile.cpp b/programs/nstool/source/OffsetAdjustedIFile.cpp index e4dcd49..9938883 100644 --- a/programs/nstool/source/OffsetAdjustedIFile.cpp +++ b/programs/nstool/source/OffsetAdjustedIFile.cpp @@ -1,15 +1,5 @@ #include "OffsetAdjustedIFile.h" -OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, size_t offset, size_t size) : - mOwnIFile(false), - mFile(file), - mBaseOffset(offset), - mCurrentOffset(0), - mSize(size) -{ - -} - OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size) : mOwnIFile(ownIFile), mFile(file), diff --git a/programs/nstool/source/OffsetAdjustedIFile.h b/programs/nstool/source/OffsetAdjustedIFile.h index b1c1e09..4c68558 100644 --- a/programs/nstool/source/OffsetAdjustedIFile.h +++ b/programs/nstool/source/OffsetAdjustedIFile.h @@ -3,7 +3,6 @@ class OffsetAdjustedIFile : public fnd::IFile { public: - OffsetAdjustedIFile(fnd::IFile* file, size_t offset, size_t size); OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size); ~OffsetAdjustedIFile(); diff --git a/programs/nstool/source/PfsProcess.cpp b/programs/nstool/source/PfsProcess.cpp index 1f63f2c..2fd27db 100644 --- a/programs/nstool/source/PfsProcess.cpp +++ b/programs/nstool/source/PfsProcess.cpp @@ -1,10 +1,10 @@ #include #include -#include "OffsetAdjustedIFile.h" #include "PfsProcess.h" PfsProcess::PfsProcess() : - mReader(nullptr), + mFile(nullptr), + mOwnIFile(false), mCliOutputType(OUTPUT_NORMAL), mVerify(false), mExtractPath(), @@ -17,9 +17,9 @@ PfsProcess::PfsProcess() : PfsProcess::~PfsProcess() { - if (mReader != nullptr) + if (mOwnIFile) { - delete mReader; + delete mFile; } } @@ -27,14 +27,14 @@ void PfsProcess::process() { fnd::MemoryBlob scratch; - if (mReader == nullptr) + if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // open minimum header to get full header size scratch.alloc(sizeof(nx::sPfsHeader)); - mReader->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.getBytes(), 0, scratch.getSize()); if (validateHeaderMagic(((nx::sPfsHeader*)scratch.getBytes())) == false) { throw fnd::Exception(kModuleName, "Corrupt Header"); @@ -43,7 +43,7 @@ void PfsProcess::process() // open minimum header to get full header size scratch.alloc(pfsHeaderSize); - mReader->read(scratch.getBytes(), 0, scratch.getSize()); + mFile->read(scratch.getBytes(), 0, scratch.getSize()); mPfs.importBinary(scratch.getBytes(), scratch.getSize()); if (mCliOutputType >= OUTPUT_NORMAL) @@ -56,9 +56,10 @@ void PfsProcess::process() extractFs(); } -void PfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +void PfsProcess::setInputFile(fnd::IFile* file, bool ownIFile) { - mReader = new OffsetAdjustedIFile(file, offset, size); + mFile = file; + mOwnIFile = ownIFile; } void PfsProcess::setCliOutputMode(CliOutputType type) @@ -144,7 +145,7 @@ void PfsProcess::validateHfs() for (size_t i = 0; i < file.getSize(); i++) { mCache.alloc(file[i].hash_protected_size); - mReader->read(mCache.getBytes(), file[i].offset, file[i].hash_protected_size); + mFile->read(mCache.getBytes(), file[i].offset, file[i].hash_protected_size); crypto::sha::Sha256(mCache.getBytes(), mCache.getSize(), hash.bytes); if (hash != file[i].hash) { @@ -177,10 +178,10 @@ void PfsProcess::extractFs() printf("extract=[%s]\n", file_path.c_str()); outFile.open(file_path, outFile.Create); - mReader->seek(file[i].offset); + mFile->seek(file[i].offset); for (size_t j = 0; j < ((file[i].size / kCacheSize) + ((file[i].size % kCacheSize) != 0)); j++) { - mReader->read(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize)); + mFile->read(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize)); outFile.write(mCache.getBytes(), MIN(file[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); diff --git a/programs/nstool/source/PfsProcess.h b/programs/nstool/source/PfsProcess.h index 5a61f1b..24b4c63 100644 --- a/programs/nstool/source/PfsProcess.h +++ b/programs/nstool/source/PfsProcess.h @@ -15,7 +15,7 @@ public: void process(); // generic - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -30,7 +30,8 @@ private: const std::string kModuleName = "PfsProcess"; static const size_t kCacheSize = 0x10000; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/RomfsProcess.cpp b/programs/nstool/source/RomfsProcess.cpp index a0642c9..1c30b5e 100644 --- a/programs/nstool/source/RomfsProcess.cpp +++ b/programs/nstool/source/RomfsProcess.cpp @@ -1,11 +1,11 @@ #include #include #include -#include "OffsetAdjustedIFile.h" #include "RomfsProcess.h" RomfsProcess::RomfsProcess() : - mReader(nullptr), + mFile(nullptr), + mOwnIFile(false), mCliOutputType(OUTPUT_NORMAL), mVerify(false), mExtractPath(), @@ -22,15 +22,15 @@ RomfsProcess::RomfsProcess() : RomfsProcess::~RomfsProcess() { - if (mReader != nullptr) + if (mOwnIFile) { - delete mReader; + delete mFile; } } void RomfsProcess::process() { - if (mReader == nullptr) + if (mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } @@ -45,9 +45,10 @@ void RomfsProcess::process() extractFs(); } -void RomfsProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +void RomfsProcess::setInputFile(fnd::IFile* file, bool ownIFile) { - mReader = new OffsetAdjustedIFile(file, offset, size); + mFile = file; + mOwnIFile = ownIFile; } void RomfsProcess::setCliOutputMode(CliOutputType type) @@ -158,10 +159,10 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir) outFile.open(file_path, outFile.Create); - mReader->seek(dir.file_list[i].offset); + mFile->seek(dir.file_list[i].offset); for (size_t j = 0; j < ((dir.file_list[i].size / kCacheSize) + ((dir.file_list[i].size % kCacheSize) != 0)); j++) { - mReader->read(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); + mFile->read(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); outFile.write(mCache.getBytes(), MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); @@ -254,7 +255,7 @@ void RomfsProcess::importDirectory(uint32_t dir_offset, sDirectory& dir) void RomfsProcess::resolveRomfs() { // read header - mReader->read((byte_t*)&mHdr, 0, sizeof(nx::sRomfsHeader)); + mFile->read((byte_t*)&mHdr, 0, sizeof(nx::sRomfsHeader)); // logic check on the header layout if (validateHeaderLayout(&mHdr) == false) @@ -264,13 +265,13 @@ void RomfsProcess::resolveRomfs() // read directory nodes mDirNodes.alloc(mHdr.sections[nx::romfs::DIR_NODE_TABLE].size.get()); - mReader->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize()); + mFile->read(mDirNodes.getBytes(), mHdr.sections[nx::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.getSize()); //printf("[RAW DIR NODES]\n"); //fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.getBytes(), mDirNodes.getSize()); // read file nodes mFileNodes.alloc(mHdr.sections[nx::romfs::FILE_NODE_TABLE].size.get()); - mReader->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize()); + mFile->read(mFileNodes.getBytes(), mHdr.sections[nx::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.getSize()); //printf("[RAW FILE NODES]\n"); //fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.getBytes(), mFileNodes.getSize()); diff --git a/programs/nstool/source/RomfsProcess.h b/programs/nstool/source/RomfsProcess.h index d90220d..a183517 100644 --- a/programs/nstool/source/RomfsProcess.h +++ b/programs/nstool/source/RomfsProcess.h @@ -94,7 +94,7 @@ public: void process(); // generic - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -108,7 +108,8 @@ private: const std::string kModuleName = "RomfsProcess"; static const size_t kCacheSize = 0x10000; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/XciProcess.cpp index 0082be9..6e4281b 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/XciProcess.cpp @@ -3,6 +3,95 @@ #include "OffsetAdjustedIFile.h" #include "XciProcess.h" +XciProcess::XciProcess() : + mFile(nullptr), + mOwnIFile(false), + mKeyset(nullptr), + mCliOutputType(OUTPUT_NORMAL), + mVerify(false), + mListFs(false), + mRootPfs(), + mExtractInfo() +{ +} + +XciProcess::~XciProcess() +{ + if (mOwnIFile) + { + delete mFile; + } +} + +void XciProcess::process() +{ + fnd::MemoryBlob scratch; + + if (mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + // read header page + mFile->read((byte_t*)&mHdrPage, 0, sizeof(nx::sXciHeaderPage)); + + // allocate memory for and decrypt sXciHeader + scratch.alloc(sizeof(nx::sXciHeader)); + nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.getBytes(), mKeyset->xci.header_key.key); + + // validate header signature + if (mVerify) + { + validateXciSignature(); + } + + // deserialise header + mHdr.importBinary(scratch.getBytes(), scratch.getSize()); + + // display header + if (mCliOutputType >= OUTPUT_NORMAL) + { + displayHeader(); + } + + // process root partition + processRootPfs(); + + // process partitions + processPartitionPfs(); +} + +void XciProcess::setInputFile(fnd::IFile* file, bool ownIFile) +{ + mFile = file; + mOwnIFile = ownIFile; +} + +void XciProcess::setKeyset(const sKeyset* keyset) +{ + mKeyset = keyset; +} + +void XciProcess::setCliOutputMode(CliOutputType type) +{ + mCliOutputType = type; +} + +void XciProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) +{ + mExtractInfo.push_back({partition_name, extract_path}); +} + +void XciProcess::setListFs(bool list_fs) +{ + mListFs = list_fs; +} + inline const char* getBoolStr(bool isTrue) { return isTrue? "TRUE" : "FALSE"; @@ -51,17 +140,16 @@ inline const char* getCardClockRate(uint32_t acc_ctrl_1) return str; } - void XciProcess::displayHeader() { printf("[XCI HEADER]\n"); printf(" Magic: HEAD\n"); printf(" RomAreaStartPage: 0x%0x", mHdr.getRomAreaStartPage()); - if (mHdr.getRomAreaStartPage() != -1) + if (mHdr.getRomAreaStartPage() != (uint32_t)(-1)) printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getRomAreaStartPage())); printf("\n"); printf(" BackupAreaStartPage: 0x%0x", mHdr.getBackupAreaStartPage()); - if (mHdr.getBackupAreaStartPage() != -1) + if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1)) printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage())); printf("\n"); printf(" KekIndex: %d\n", mHdr.getKekIndex()); @@ -74,7 +162,7 @@ void XciProcess::displayHeader() printf(" RepairTool: %s\n", getBoolStr(_HAS_BIT(mHdr.getFlags(), nx::xci::FLAG_REPAIR_TOOL))); printf(" PackageId: 0x%" PRIx64 "\n", mHdr.getPackageId()); printf(" ValidDataEndPage: 0x%x", mHdr.getValidDataEndPage()); - if (mHdr.getValidDataEndPage() != -1) + if (mHdr.getValidDataEndPage() != (uint32_t)(-1)) printf(" (0x%" PRIx64 ")", nx::XciUtils::blockToAddr(mHdr.getValidDataEndPage())); printf("\n"); printf(" AesIv: "); @@ -118,7 +206,7 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t fnd::MemoryBlob scratch; crypto::sha::sSha256Hash calc_hash; scratch.alloc(len); - mReader->read(scratch.getBytes(), offset, len); + mFile->read(scratch.getBytes(), offset, len); crypto::sha::Sha256(scratch.getBytes(), scratch.getSize(), calc_hash.bytes); return calc_hash.compare(test_hash); } @@ -144,7 +232,7 @@ void XciProcess::processRootPfs() printf("[WARNING] XCI Root HFS0: FAIL (bad hash)\n"); } } - mRootPfs.setInputFile(mReader, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()); + mRootPfs.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()), OWN_IFILE); mRootPfs.setListFs(mListFs); mRootPfs.setVerifyMode(mVerify); mRootPfs.setCliOutputMode(mCliOutputType); @@ -158,7 +246,7 @@ void XciProcess::processPartitionPfs() for (size_t i = 0; i < rootPartitions.getSize(); i++) { PfsProcess tmp; - tmp.setInputFile(mReader, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size); + tmp.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size), OWN_IFILE); tmp.setListFs(mListFs); tmp.setVerifyMode(mVerify); tmp.setCliOutputMode(mCliOutputType); @@ -172,91 +260,4 @@ void XciProcess::processPartitionPfs() } tmp.process(); } -} - -XciProcess::XciProcess() : - mReader(nullptr), - mKeyset(nullptr), - mCliOutputType(OUTPUT_NORMAL), - mVerify(false), - mListFs(false), - mRootPfs(), - mExtractInfo() -{ -} - -XciProcess::~XciProcess() -{ - if (mReader != nullptr) - { - delete mReader; - } -} - -void XciProcess::process() -{ - fnd::MemoryBlob scratch; - - if (mReader == nullptr) - { - throw fnd::Exception(kModuleName, "No file reader set."); - } - - // read header page - mReader->read((byte_t*)&mHdrPage, 0, sizeof(nx::sXciHeaderPage)); - - // allocate memory for and decrypt sXciHeader - scratch.alloc(sizeof(nx::sXciHeader)); - nx::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.getBytes(), mKeyset->xci.header_key.key); - - // validate header signature - if (mVerify) - { - validateXciSignature(); - } - - // deserialise header - mHdr.importBinary(scratch.getBytes(), scratch.getSize()); - - // display header - if (mCliOutputType >= OUTPUT_NORMAL) - { - displayHeader(); - } - - // process root partition - processRootPfs(); - - // process partitions - processPartitionPfs(); -} - -void XciProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) -{ - mReader = new OffsetAdjustedIFile(file, offset, size); -} - -void XciProcess::setKeyset(const sKeyset* keyset) -{ - mKeyset = keyset; -} - -void XciProcess::setCliOutputMode(CliOutputType type) -{ - mCliOutputType = type; -} - -void XciProcess::setVerifyMode(bool verify) -{ - mVerify = verify; -} - -void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) -{ - mExtractInfo.push_back({partition_name, extract_path}); -} - -void XciProcess::setListFs(bool list_fs) -{ - mListFs = list_fs; -} +} \ No newline at end of file diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/XciProcess.h index c66fc76..0579941 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/XciProcess.h @@ -18,7 +18,7 @@ public: void process(); // generic - void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setInputFile(fnd::IFile* file, bool ownIFile); void setKeyset(const sKeyset* keyset); void setCliOutputMode(CliOutputType type); void setVerifyMode(bool verify); @@ -32,7 +32,8 @@ private: const std::string kXciMountPointName = "gamecard:/"; static const size_t kFileExportBlockSize = 0x1000000; - fnd::IFile* mReader; + fnd::IFile* mFile; + bool mOwnIFile; const sKeyset* mKeyset; CliOutputType mCliOutputType; bool mVerify; diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 8e85a7f..4a3a448 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -15,14 +15,11 @@ int main(int argc, char** argv) try { user_set.parseCmdArgs(argc, argv); - fnd::SimpleFile inputFile; - inputFile.open(user_set.getInputPath(), inputFile.Read); - if (user_set.getFileType() == FILE_XCI) { XciProcess xci; - xci.setInputFile(&inputFile, 0, inputFile.size()); + xci.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); xci.setKeyset(&user_set.getKeyset()); xci.setCliOutputMode(user_set.getCliOutputType()); @@ -44,7 +41,7 @@ int main(int argc, char** argv) { PfsProcess pfs; - pfs.setInputFile(&inputFile, 0, inputFile.size()); + pfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); pfs.setCliOutputMode(user_set.getCliOutputType()); pfs.setVerifyMode(user_set.isVerifyFile()); @@ -58,7 +55,7 @@ int main(int argc, char** argv) { RomfsProcess romfs; - romfs.setInputFile(&inputFile, 0, inputFile.size()); + romfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); romfs.setCliOutputMode(user_set.getCliOutputType()); romfs.setVerifyMode(user_set.isVerifyFile()); @@ -72,7 +69,7 @@ int main(int argc, char** argv) { NcaProcess nca; - nca.setInputFile(&inputFile, 0, inputFile.size()); + nca.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); nca.setKeyset(&user_set.getKeyset()); nca.setCliOutputMode(user_set.getCliOutputType()); nca.setVerifyMode(user_set.isVerifyFile()); @@ -94,7 +91,7 @@ int main(int argc, char** argv) { NpdmProcess npdm; - npdm.setInputFile(&inputFile, 0, inputFile.size()); + npdm.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); npdm.setKeyset(&user_set.getKeyset()); npdm.setCliOutputMode(user_set.getCliOutputType()); npdm.setVerifyMode(user_set.isVerifyFile()); @@ -105,7 +102,7 @@ int main(int argc, char** argv) { CnmtProcess cnmt; - cnmt.setInputFile(&inputFile, 0, inputFile.size()); + cnmt.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); cnmt.setCliOutputMode(user_set.getCliOutputType()); cnmt.setVerifyMode(user_set.isVerifyFile()); @@ -115,7 +112,7 @@ int main(int argc, char** argv) { NsoProcess nso; - nso.setInputFile(&inputFile, 0, inputFile.size()); + nso.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); nso.setCliOutputMode(user_set.getCliOutputType()); nso.setVerifyMode(user_set.isVerifyFile()); diff --git a/programs/nstool/source/nstool.h b/programs/nstool/source/nstool.h index c8d1d5d..0a07356 100644 --- a/programs/nstool/source/nstool.h +++ b/programs/nstool/source/nstool.h @@ -9,6 +9,11 @@ static const size_t kMasterKeyNum = 0x20; static const size_t kNcaKeakNum = nx::nca::kKeyAreaEncryptionKeyNum; +enum IFileOwnershipMode +{ + SHARED_IFILE = false, + OWN_IFILE = true +}; enum FileType {