diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index f658b73..d7e3785 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -65,7 +65,14 @@ "name": "Win32", "includePath": [ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", - "${workspaceRoot}" + "${workspaceRoot}", + "${workspaceRoot}/lib/libfnd/include", + "${workspaceRoot}/lib/libpolarssl/include", + "${workspaceRoot}/lib/liblz4/include", + "${workspaceRoot}/lib/libes/include", + "${workspaceRoot}/lib/libpki/include", + "${workspaceRoot}/lib/libhac/include", + "${workspaceRoot}/lib/libhac-hb/include" ], "defines": [ "_DEBUG", diff --git a/lib/libes/makefile b/lib/libes/makefile index a6d2bf8..d8a204a 100644 --- a/lib/libes/makefile +++ b/lib/libes/makefile @@ -33,7 +33,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libfnd/include/fnd/AesCtrWrappedIFile.h b/lib/libfnd/include/fnd/AesCtrWrappedIFile.h new file mode 100644 index 0000000..88b2df6 --- /dev/null +++ b/lib/libfnd/include/fnd/AesCtrWrappedIFile.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include + +namespace fnd +{ + class AesCtrWrappedIFile : public fnd::IFile + { + public: + AesCtrWrappedIFile(const fnd::SharedPtr& file, const fnd::aes::sAes128Key& key, const fnd::aes::sAesIvCtr& ctr); + + size_t size(); + void seek(size_t offset); + void read(byte_t* out, size_t len); + void read(byte_t* out, size_t offset, size_t len); + void write(const byte_t* out, size_t len); + void write(const byte_t* out, size_t offset, size_t len); + private: + const std::string kModuleName = "AesCtrWrappedIFile"; + static const size_t kCacheSize = 0x10000; + static const size_t kCacheSizeAllocSize = kCacheSize + fnd::aes::kAesBlockSize; + + fnd::SharedPtr mFile; + fnd::aes::sAes128Key mKey; + fnd::aes::sAesIvCtr mBaseCtr, mCurrentCtr; + size_t mFileOffset; + + fnd::Vec mCache; + }; +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/IFile.h b/lib/libfnd/include/fnd/IFile.h index d992962..e93bbf0 100644 --- a/lib/libfnd/include/fnd/IFile.h +++ b/lib/libfnd/include/fnd/IFile.h @@ -6,7 +6,7 @@ namespace fnd class IFile { public: - inline virtual ~IFile() {} + virtual ~IFile() = default; virtual size_t size() = 0; virtual void seek(size_t offset) = 0; diff --git a/lib/libfnd/include/fnd/ISerialisable.h b/lib/libfnd/include/fnd/ISerialisable.h index a484ea0..b0d49c7 100644 --- a/lib/libfnd/include/fnd/ISerialisable.h +++ b/lib/libfnd/include/fnd/ISerialisable.h @@ -7,6 +7,8 @@ namespace fnd class ISerialisable { public: + virtual ~ISerialisable() = default; + // serialise virtual void toBytes() = 0; // deserialise diff --git a/lib/libfnd/include/fnd/LayeredIntegrityMetadata.h b/lib/libfnd/include/fnd/LayeredIntegrityMetadata.h new file mode 100644 index 0000000..7d1e3ac --- /dev/null +++ b/lib/libfnd/include/fnd/LayeredIntegrityMetadata.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include + +namespace fnd +{ + class LayeredIntegrityMetadata + { + public: + struct sLayer + { + size_t offset; + size_t size; + size_t block_size; + + void operator=(const sLayer& other) + { + offset = other.offset; + size = other.size; + block_size = other.block_size; + } + + bool operator==(const sLayer& other) const + { + return (offset == other.offset && size == other.size && block_size == other.block_size); + } + + bool operator!=(const sLayer& other) const + { + return !(*this == other); + } + }; + + LayeredIntegrityMetadata(); + + void operator=(const LayeredIntegrityMetadata& other); + bool operator==(const LayeredIntegrityMetadata& other) const; + bool operator!=(const LayeredIntegrityMetadata& other) const; + + const fnd::List& getHashLayerInfo() const; + void setHashLayerInfo(const fnd::List& layer_info); + + const sLayer& getDataLayer() const; + void setDataLayerInfo(const sLayer& data_info); + + const fnd::List& getMasterHashList() const; + void setMasterHashList(const fnd::List& master_hash_list); + + bool getAlignHashToBlock() const; + void setAlignHashToBlock(bool doAlign); + private: + // data + fnd::List mLayerInfo; + sLayer mDataLayer; + fnd::List mMasterHashList; + bool mDoAlignHashToBlock; + }; +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/LayeredIntegrityWrappedIFile.h b/lib/libfnd/include/fnd/LayeredIntegrityWrappedIFile.h new file mode 100644 index 0000000..2bc2a4d --- /dev/null +++ b/lib/libfnd/include/fnd/LayeredIntegrityWrappedIFile.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +namespace fnd +{ + class LayeredIntegrityWrappedIFile : public fnd::IFile + { + public: + LayeredIntegrityWrappedIFile(const fnd::SharedPtr& file, const LayeredIntegrityMetadata& hdr); + + size_t size(); + void seek(size_t offset); + void read(byte_t* out, size_t len); + void read(byte_t* out, size_t offset, size_t len); + void write(const byte_t* out, size_t len); + void write(const byte_t* out, size_t offset, size_t len); + private: + const std::string kModuleName = "LayeredIntegrityWrappedIFile"; + static const size_t kDefaultCacheSize = 0x10000; + std::stringstream mErrorSs; + + fnd::SharedPtr mFile; + + // data file + fnd::SharedPtr mData; + size_t mDataOffset; + size_t mDataBlockSize; + fnd::List mDataHashLayer; + bool mAlignHashCalcToBlock; + + fnd::Vec mCache; + size_t mCacheBlockNum; + + inline size_t getOffsetBlock(size_t offset) const { return offset / mDataBlockSize; } + inline size_t getOffsetInBlock(size_t offset) const { return offset % mDataBlockSize; } + inline size_t getRemanderBlockReadSize(size_t total_size) const { return total_size % mDataBlockSize; } + inline size_t getBlockNum(size_t total_size) const { return (total_size / mDataBlockSize) + (getRemanderBlockReadSize(total_size) > 0); } + + void initialiseDataLayer(const LayeredIntegrityMetadata& hdr); + void readData(size_t block_offset, size_t block_num); + }; +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/OffsetAdjustedIFile.h b/lib/libfnd/include/fnd/OffsetAdjustedIFile.h new file mode 100644 index 0000000..706e63c --- /dev/null +++ b/lib/libfnd/include/fnd/OffsetAdjustedIFile.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +namespace fnd +{ + class OffsetAdjustedIFile : public fnd::IFile + { + public: + OffsetAdjustedIFile(const fnd::SharedPtr& file, size_t offset, size_t size); + + size_t size(); + void seek(size_t offset); + void read(byte_t* out, size_t len); + void read(byte_t* out, size_t offset, size_t len); + void write(const byte_t* out, size_t len); + void write(const byte_t* out, size_t offset, size_t len); + private: + fnd::SharedPtr mFile; + size_t mBaseOffset, mCurrentOffset; + size_t mSize; + }; +} \ No newline at end of file diff --git a/lib/libfnd/include/fnd/SharedPtr.h b/lib/libfnd/include/fnd/SharedPtr.h new file mode 100644 index 0000000..e976d4e --- /dev/null +++ b/lib/libfnd/include/fnd/SharedPtr.h @@ -0,0 +1,141 @@ +#pragma once +#include +#include + +namespace fnd +{ + template + class SharedPtr + { + public: + SharedPtr(); + + // constructor for creating owner object + SharedPtr(T* ptr); + + // copy constructor + SharedPtr(const SharedPtr& other); + + // destructor + ~SharedPtr(); + + // own operator + void operator=(T* ptr); + + // copy operator + void operator=(const SharedPtr& other); + + // access ptr + const T* operator*() const; + T* operator*(); + + private: + T* mPtr; + size_t* mRefCnt; + + void deletePtr(); + }; + + template + inline SharedPtr::SharedPtr() : + mPtr(nullptr), + mRefCnt(new size_t) + { + *mRefCnt = 0; + } + + template + inline SharedPtr::SharedPtr(T* ptr) : + SharedPtr() + { + *this = ptr; + } + + template + inline SharedPtr::SharedPtr(const SharedPtr& other) : + SharedPtr() + { + *this = other; + } + + template + inline SharedPtr::~SharedPtr() + { + deletePtr(); + } + + template + inline void SharedPtr::operator=(T* ptr) + { + deletePtr(); + if (ptr != nullptr) + { + mPtr = ptr; + mRefCnt = new size_t; + *mRefCnt = 1; + } + else + { + mPtr = nullptr; + mRefCnt = new size_t; + *mRefCnt = 0; + } + + } + + template + inline void SharedPtr::operator=(const SharedPtr& other) + { + deletePtr(); + + mPtr = other.mPtr; + mRefCnt = other.mRefCnt; + *mRefCnt += 1; + } + + template + inline const T* SharedPtr::operator*() const + { + return mPtr; + } + + template + inline T* SharedPtr::operator*() + { + return mPtr; + } + + template + inline void SharedPtr::deletePtr() + { + // if this is not the last reference + if (*mRefCnt > 1) + { + // decrement reference count + *mRefCnt -= 1; + + // make ptrs null + mPtr = nullptr; + mRefCnt = nullptr; + } + // if this is the last refeference + else if (*mRefCnt == 1) + { + // delete memory + delete mPtr; + delete mRefCnt; + + // make ptrs null + mPtr = nullptr; + mRefCnt = nullptr; + } + // else if this is an empty refernce + else if (*mRefCnt == 0) + { + delete mRefCnt; + + mPtr = nullptr; + mRefCnt = nullptr; + } + } +} \ No newline at end of file diff --git a/lib/libfnd/libfnd.vcxproj b/lib/libfnd/libfnd.vcxproj index 82253b7..0603ace 100644 --- a/lib/libfnd/libfnd.vcxproj +++ b/lib/libfnd/libfnd.vcxproj @@ -122,6 +122,7 @@ + @@ -131,11 +132,15 @@ + + + + @@ -143,11 +148,15 @@ + + + + diff --git a/lib/libfnd/libfnd.vcxproj.filters b/lib/libfnd/libfnd.vcxproj.filters index d13edab..56f7ae5 100644 --- a/lib/libfnd/libfnd.vcxproj.filters +++ b/lib/libfnd/libfnd.vcxproj.filters @@ -21,6 +21,9 @@ Header Files + + Header Files + Header Files @@ -48,12 +51,21 @@ Header Files + + Header Files + + + Header Files + Header Files Header Files + + Header Files + Header Files @@ -63,6 +75,9 @@ Header Files + + Header Files + Header Files @@ -83,6 +98,9 @@ Source Files + + Source Files + Source Files @@ -92,9 +110,18 @@ Source Files + + Source Files + + + Source Files + Source Files + + Source Files + Source Files diff --git a/lib/libfnd/makefile b/lib/libfnd/makefile index 73af097..0ec7dcf 100644 --- a/lib/libfnd/makefile +++ b/lib/libfnd/makefile @@ -33,7 +33,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libfnd/source/AesCtrWrappedIFile.cpp b/lib/libfnd/source/AesCtrWrappedIFile.cpp new file mode 100644 index 0000000..ce8daf3 --- /dev/null +++ b/lib/libfnd/source/AesCtrWrappedIFile.cpp @@ -0,0 +1,80 @@ +#include + +fnd::AesCtrWrappedIFile::AesCtrWrappedIFile(const fnd::SharedPtr& file, const fnd::aes::sAes128Key& key, const fnd::aes::sAesIvCtr& ctr) : + mFile(file), + mKey(key), + mBaseCtr(ctr), + mFileOffset(0) +{ + mCache.alloc(kCacheSizeAllocSize); +} + +size_t fnd::AesCtrWrappedIFile::size() +{ + return (*mFile)->size(); +} + +void fnd::AesCtrWrappedIFile::seek(size_t offset) +{ + mFileOffset = offset; +} + +void fnd::AesCtrWrappedIFile::read(byte_t* out, size_t len) +{ + size_t read_len; + size_t read_pos; + + size_t cache_reads = (len / kCacheSize) + ((len % kCacheSize) != 0); + + for (size_t i = 0; i < cache_reads; i++) + { + read_len = _MIN(len - (i * kCacheSize), kCacheSize); + read_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); + + (*mFile)->seek(read_pos); + (*mFile)->read(mCache.data(), kCacheSizeAllocSize); + + fnd::aes::AesIncrementCounter(mBaseCtr.iv, read_pos>>4, mCurrentCtr.iv); + fnd::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); + + memcpy(out + (i * kCacheSize), mCache.data() + (mFileOffset & 0xf), read_len); + } + + seek(mFileOffset + len); +} + +void fnd::AesCtrWrappedIFile::read(byte_t* out, size_t offset, size_t len) +{ + seek(offset); + read(out, len); +} + +void fnd::AesCtrWrappedIFile::write(const byte_t* in, size_t len) +{ + size_t write_len; + size_t write_pos; + + size_t cache_writes = (len / kCacheSize) + ((len % kCacheSize) != 0); + + for (size_t i = 0; i < cache_writes; i++) + { + write_len = _MIN(len - (i * kCacheSize), kCacheSize); + write_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); + + memcpy(mCache.data() + (mFileOffset & 0xf), in + (i * kCacheSize), write_len); + + fnd::aes::AesIncrementCounter(mBaseCtr.iv, write_pos>>4, mCurrentCtr.iv); + fnd::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); + + (*mFile)->seek(write_pos); + (*mFile)->write(mCache.data(), kCacheSizeAllocSize); + } + + seek(mFileOffset + len); +} + +void fnd::AesCtrWrappedIFile::write(const byte_t* in, size_t offset, size_t len) +{ + seek(offset); + write(in, len); +} \ No newline at end of file diff --git a/lib/libfnd/source/LayeredIntegrityMetadata.cpp b/lib/libfnd/source/LayeredIntegrityMetadata.cpp new file mode 100644 index 0000000..95c06da --- /dev/null +++ b/lib/libfnd/source/LayeredIntegrityMetadata.cpp @@ -0,0 +1,71 @@ +#include + +fnd::LayeredIntegrityMetadata::LayeredIntegrityMetadata() : + mLayerInfo(), + mDataLayer(), + mMasterHashList(), + mDoAlignHashToBlock(false) +{ + +} + +void fnd::LayeredIntegrityMetadata::operator=(const LayeredIntegrityMetadata& other) +{ + mLayerInfo = other.mLayerInfo; + mDataLayer = other.mDataLayer; + mMasterHashList = other.mMasterHashList; + mDoAlignHashToBlock = other.mDoAlignHashToBlock; +} + +bool fnd::LayeredIntegrityMetadata::operator==(const LayeredIntegrityMetadata& other) const +{ + return (mLayerInfo == other.mLayerInfo) \ + && (mDataLayer == other.mDataLayer) \ + && (mMasterHashList == other.mMasterHashList) \ + && (mDoAlignHashToBlock == other.mDoAlignHashToBlock); +} + +bool fnd::LayeredIntegrityMetadata::operator!=(const LayeredIntegrityMetadata& other) const +{ + return !(*this == other); +} + +const fnd::List& fnd::LayeredIntegrityMetadata::getHashLayerInfo() const +{ + return mLayerInfo; +} + +void fnd::LayeredIntegrityMetadata::setHashLayerInfo(const fnd::List& layer_info) +{ + mLayerInfo = layer_info; +} + +const fnd::LayeredIntegrityMetadata::sLayer& fnd::LayeredIntegrityMetadata::getDataLayer() const +{ + return mDataLayer; +} + +void fnd::LayeredIntegrityMetadata::setDataLayerInfo(const sLayer& data_info) +{ + mDataLayer = data_info; +} + +const fnd::List& fnd::LayeredIntegrityMetadata::getMasterHashList() const +{ + return mMasterHashList; +} + +void fnd::LayeredIntegrityMetadata::setMasterHashList(const fnd::List& master_hash_list) +{ + mMasterHashList = master_hash_list; +} + +bool fnd::LayeredIntegrityMetadata::getAlignHashToBlock() const +{ + return mDoAlignHashToBlock; +} + +void fnd::LayeredIntegrityMetadata::setAlignHashToBlock(bool doAlign) +{ + mDoAlignHashToBlock = doAlign; +} \ No newline at end of file diff --git a/programs/nstool/source/HashTreeWrappedIFile.cpp b/lib/libfnd/source/LayeredIntegrityWrappedIFile.cpp similarity index 50% rename from programs/nstool/source/HashTreeWrappedIFile.cpp rename to lib/libfnd/source/LayeredIntegrityWrappedIFile.cpp index 7ff7e7c..38b5602 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.cpp +++ b/lib/libfnd/source/LayeredIntegrityWrappedIFile.cpp @@ -1,9 +1,7 @@ -#include "common.h" -#include "HashTreeWrappedIFile.h" -#include "OffsetAdjustedIFile.h" +#include +#include -HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr) : - mOwnIFile(ownIFile), +fnd::LayeredIntegrityWrappedIFile::LayeredIntegrityWrappedIFile(const fnd::SharedPtr& file, const fnd::LayeredIntegrityMetadata& hdr) : mFile(file), mData(nullptr), mDataHashLayer(), @@ -12,89 +10,84 @@ HashTreeWrappedIFile::HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, cons initialiseDataLayer(hdr); } -HashTreeWrappedIFile::~HashTreeWrappedIFile() +size_t fnd::LayeredIntegrityWrappedIFile::size() { - if (mOwnIFile) - { - delete mFile; - } - delete mData; + return (*mData)->size(); } -size_t HashTreeWrappedIFile::size() -{ - return mData->size(); -} - -void HashTreeWrappedIFile::seek(size_t offset) +void fnd::LayeredIntegrityWrappedIFile::seek(size_t offset) { mDataOffset = offset; } -void HashTreeWrappedIFile::read(byte_t* out, size_t len) +void fnd::LayeredIntegrityWrappedIFile::read(byte_t* out, size_t len) { - size_t offset_in_start_block = getOffsetInBlock(mDataOffset); - size_t offset_in_end_block = getOffsetInBlock(offset_in_start_block + len); - - size_t start_block = getOffsetBlock(mDataOffset); - size_t block_num = align(offset_in_start_block + len, mDataBlockSize) / mDataBlockSize; - - size_t partial_last_block_num = block_num % mCacheBlockNum; - bool has_partial_block_num = partial_last_block_num > 0; - size_t read_iterations = (block_num / mCacheBlockNum) + has_partial_block_num; - - size_t block_read_len; - size_t block_export_offset; - size_t block_export_size; - size_t block_export_pos = 0; - for (size_t i = 0; i < read_iterations; i++) + struct sBlockPosition { - // how many blocks to read from source file - block_read_len = (i+1 == read_iterations && has_partial_block_num) ? partial_last_block_num : mCacheBlockNum; + size_t index; + size_t pos; + } start_blk, end_blk; - // offset in this current read to copy from - block_export_offset = (i == 0) ? offset_in_start_block : 0; + start_blk.index = getOffsetBlock(mDataOffset); + start_blk.pos = getOffsetInBlock(mDataOffset); - // size of current read to copy - block_export_size = (block_read_len * mDataBlockSize) - block_export_offset; + end_blk.index = getOffsetBlock(mDataOffset + len); + end_blk.pos = getOffsetInBlock(mDataOffset + len); + if (end_blk.pos == 0 && len != 0) + { + end_blk.index -= 1; + end_blk.pos = mDataBlockSize; + } - // if last read, reduce the export size by one block less offset_in_end_block - if (i+1 == read_iterations) - { - block_export_size -= (mDataBlockSize - offset_in_end_block); - } + size_t total_blk_num = (end_blk.index - start_blk.index) + 1; - // read the blocks - readData(start_block + (i * mCacheBlockNum), block_read_len); + size_t read_blk_num = 0; + size_t cache_export_start_pos, cache_export_end_pos, cache_export_size; + size_t export_pos = 0; + for (size_t i = 0; i < total_blk_num; i += read_blk_num, export_pos += cache_export_size) + { + read_blk_num = _MIN(mCacheBlockNum, (total_blk_num - i)); + readData(start_blk.index + i, read_blk_num); - // export the section of data that is relevant - memcpy(out + block_export_pos, mCache.data() + block_export_offset, block_export_size); + // if this is the first read, adjust offset + if (i == 0) + cache_export_start_pos = start_blk.pos; + else + cache_export_start_pos = 0; + + // if this is the last block, adjust end offset + if ((i + read_blk_num) == total_blk_num) + cache_export_end_pos = ((read_blk_num - 1) * mDataBlockSize) + end_blk.pos; + else + cache_export_end_pos = read_blk_num * mDataBlockSize; - // update export position - block_export_pos += block_export_size; + // determine cache export size + cache_export_size = cache_export_end_pos - cache_export_start_pos; + + memcpy(out + export_pos, mCache.data() + cache_export_start_pos, cache_export_size); } // update offset seek(mDataOffset + len); } -void HashTreeWrappedIFile::read(byte_t* out, size_t offset, size_t len) +void fnd::LayeredIntegrityWrappedIFile::read(byte_t* out, size_t offset, size_t len) { seek(offset); read(out, len); } -void HashTreeWrappedIFile::write(const byte_t* out, size_t len) +void fnd::LayeredIntegrityWrappedIFile::write(const byte_t* out, size_t len) { throw fnd::Exception(kModuleName, "write() not supported"); } -void HashTreeWrappedIFile::write(const byte_t* out, size_t offset, size_t len) +void fnd::LayeredIntegrityWrappedIFile::write(const byte_t* out, size_t offset, size_t len) { throw fnd::Exception(kModuleName, "write() not supported"); } -void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) +void fnd::LayeredIntegrityWrappedIFile::initialiseDataLayer(const fnd::LayeredIntegrityMetadata& hdr) { fnd::sha::sSha256Hash hash; fnd::Vec cur, prev; @@ -112,13 +105,13 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) for (size_t i = 0; i < hdr.getHashLayerInfo().size(); i++) { // get block size - const HashTreeMeta::sLayer& layer = hdr.getHashLayerInfo()[i]; + const fnd::LayeredIntegrityMetadata::sLayer& layer = hdr.getHashLayerInfo()[i]; // allocate layer cur.alloc(align(layer.size, layer.block_size)); // read layer - mFile->read(cur.data(), layer.offset, layer.size); + (*mFile)->read(cur.data(), layer.offset, layer.size); // validate blocks size_t validate_size; @@ -145,32 +138,28 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) } // generate reader for data layer - mData = new OffsetAdjustedIFile(mFile, SHARED_IFILE, hdr.getDataLayer().offset, hdr.getDataLayer().size); + mData = new fnd::OffsetAdjustedIFile(mFile, hdr.getDataLayer().offset, hdr.getDataLayer().size); mDataOffset = 0; mDataBlockSize = hdr.getDataLayer().block_size; - // allocate scratchpad - //mScratch.alloc(mDataBlockSize * 0x10); + // allocate cache size_t cache_size = align(kDefaultCacheSize, mDataBlockSize); mCacheBlockNum = cache_size / mDataBlockSize; - //printf("Block Size: 0x%" PRIx64 "\n", mDataBlockSize); - //printf("Cache size: 0x%" PRIx64 ", (block_num: %" PRId64 ")\n", cache_size, mCacheBlockNum); mCache.alloc(cache_size); } -void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) +void fnd::LayeredIntegrityWrappedIFile::readData(size_t block_offset, size_t block_num) { - mData->seek(block_offset * mDataBlockSize); fnd::sha::sSha256Hash hash; // determine read size size_t read_len = 0; - if ((block_offset + block_num) == getBlockNum(mData->size())) + if ((block_offset + block_num) == getBlockNum((*mData)->size())) { - read_len = (block_num-1) * mDataBlockSize + getRemanderBlockReadSize(mData->size()); + read_len = (block_num-1) * mDataBlockSize + getRemanderBlockReadSize((*mData)->size()); memset(mCache.data(), 0, block_num * mDataBlockSize); } - else if ((block_offset + block_num) < getBlockNum(mData->size())) + else if ((block_offset + block_num) < getBlockNum((*mData)->size())) { read_len = block_num * mDataBlockSize; } @@ -180,15 +169,13 @@ void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) } // read - mData->read(mCache.data(), block_offset * mDataBlockSize, read_len); + (*mData)->read(mCache.data(), block_offset * mDataBlockSize, read_len); if (block_num > mCacheBlockNum) { throw fnd::Exception(kModuleName, "Read excessive of cache size"); } - //printf("readlen=0x%" PRIx64 "\n", read_len); - // validate blocks size_t validate_size; for (size_t i = 0; i < block_num; i++) diff --git a/lib/libfnd/source/OffsetAdjustedIFile.cpp b/lib/libfnd/source/OffsetAdjustedIFile.cpp new file mode 100644 index 0000000..4cebf16 --- /dev/null +++ b/lib/libfnd/source/OffsetAdjustedIFile.cpp @@ -0,0 +1,47 @@ +#include + +fnd::OffsetAdjustedIFile::OffsetAdjustedIFile(const fnd::SharedPtr& file, size_t offset, size_t size) : + mFile(file), + mBaseOffset(offset), + mCurrentOffset(0), + mSize(size) +{ +} + +size_t fnd::OffsetAdjustedIFile::size() +{ + return mSize; +} + +void fnd::OffsetAdjustedIFile::seek(size_t offset) +{ + mCurrentOffset = _MIN(offset, mSize); +} + +void fnd::OffsetAdjustedIFile::read(byte_t* out, size_t len) +{ + // assert proper position in file + (*mFile)->seek(mCurrentOffset + mBaseOffset); + (*mFile)->read(out, len); + seek(mCurrentOffset + len); +} + +void fnd::OffsetAdjustedIFile::read(byte_t* out, size_t offset, size_t len) +{ + seek(offset); + read(out, len); +} + +void fnd::OffsetAdjustedIFile::write(const byte_t* out, size_t len) +{ + // assert proper position in file + (*mFile)->seek(mCurrentOffset + mBaseOffset); + (*mFile)->write(out, len); + seek(mCurrentOffset + len); +} + +void fnd::OffsetAdjustedIFile::write(const byte_t* out, size_t offset, size_t len) +{ + seek(offset); + write(out, len); +} \ No newline at end of file diff --git a/lib/libhac-hb/makefile b/lib/libhac-hb/makefile index c91b3df..f84b880 100644 --- a/lib/libhac-hb/makefile +++ b/lib/libhac-hb/makefile @@ -33,7 +33,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libhac/makefile b/lib/libhac/makefile index a6d2bf8..d8a204a 100644 --- a/lib/libhac/makefile +++ b/lib/libhac/makefile @@ -33,7 +33,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libhac/source/NpdmBinary.cpp b/lib/libhac/source/NpdmBinary.cpp index 716cc08..fe26c3a 100644 --- a/lib/libhac/source/NpdmBinary.cpp +++ b/lib/libhac/source/NpdmBinary.cpp @@ -132,16 +132,8 @@ void nn::hac::NpdmBinary::fromBytes(const byte_t* data, size_t len) mMainThreadCpuId = hdr.main_thread_cpu_id; mVersion = hdr.version.get(); mMainThreadStackSize = hdr.main_thread_stack_size.get(); - mName = std::string(hdr.name, npdm::kNameMaxLen); - if (mName[0] == '\0') - { - mName.clear(); - } - mProductCode = std::string(hdr.product_code, npdm::kProductCodeMaxLen); - if (mProductCode[0] == '\0') - { - mProductCode.clear(); - } + mName = std::string(hdr.name, _MIN(strlen(hdr.name), npdm::kNameMaxLen)); + mProductCode = std::string(hdr.product_code, _MIN(strlen(hdr.product_code), npdm::kProductCodeMaxLen)); // total size size_t total_size = _MAX(_MAX(hdr.acid.offset.get() + hdr.acid.size.get(), hdr.aci.offset.get() + hdr.aci.size.get()), sizeof(sNpdmHeader)); diff --git a/lib/liblz4/makefile b/lib/liblz4/makefile index b6fc4ef..ff57976 100644 --- a/lib/liblz4/makefile +++ b/lib/liblz4/makefile @@ -32,7 +32,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libpki/makefile b/lib/libpki/makefile index da68d0b..045b0ab 100644 --- a/lib/libpki/makefile +++ b/lib/libpki/makefile @@ -32,7 +32,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/lib/libpolarssl/makefile b/lib/libpolarssl/makefile index 2c2becf..95b8e7c 100644 --- a/lib/libpolarssl/makefile +++ b/lib/libpolarssl/makefile @@ -32,7 +32,7 @@ else endif # Output -OUTPUT = $(shell basename $(CURDIR)).a +OUTPUT = $(shell basename "$(CURDIR)").a main: build diff --git a/makefile b/makefile index c99fe52..1fd6780 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -PROJECT_DIR = $(CURDIR) +PROJECT_DIR = "$(CURDIR)" LIB_DIR = $(PROJECT_DIR)/lib PROGRAM_DIR = $(PROJECT_DIR)/programs BIN_DIR = $(PROJECT_DIR)/bin diff --git a/programs/nstool/makefile b/programs/nstool/makefile index d73e3b4..91999dc 100644 --- a/programs/nstool/makefile +++ b/programs/nstool/makefile @@ -34,7 +34,7 @@ else endif BIN_DIR = bin -OUTPUT = $(BIN_DIR)/$(shell basename $(CURDIR)) +OUTPUT = $(BIN_DIR)/$(shell basename "$(CURDIR)") all: build diff --git a/programs/nstool/nstool.vcxproj b/programs/nstool/nstool.vcxproj index b72bf95..ea08f49 100644 --- a/programs/nstool/nstool.vcxproj +++ b/programs/nstool/nstool.vcxproj @@ -178,21 +178,17 @@ - + - - - - @@ -204,13 +200,10 @@ - - - @@ -218,7 +211,6 @@ - diff --git a/programs/nstool/nstool.vcxproj.filters b/programs/nstool/nstool.vcxproj.filters index e9e9105..7404275 100644 --- a/programs/nstool/nstool.vcxproj.filters +++ b/programs/nstool/nstool.vcxproj.filters @@ -19,27 +19,21 @@ - - Header Files - Header Files Header Files + + Header Files + Header Files Header Files - - Header Files - - - Header Files - Header Files @@ -58,12 +52,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -93,9 +81,6 @@ - - Source Files - Source Files @@ -108,12 +93,6 @@ Source Files - - Source Files - - - Source Files - Source Files @@ -135,9 +114,6 @@ Source Files - - Source Files - Source Files diff --git a/programs/nstool/source/AesCtrWrappedIFile.cpp b/programs/nstool/source/AesCtrWrappedIFile.cpp deleted file mode 100644 index 06ea584..0000000 --- a/programs/nstool/source/AesCtrWrappedIFile.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "AesCtrWrappedIFile.h" - -AesCtrWrappedIFile::AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const fnd::aes::sAes128Key& key, const fnd::aes::sAesIvCtr& ctr) : - mOwnIFile(ownIfile), - mFile(file), - mKey(key), - mBaseCtr(ctr), - mFileOffset(0) -{ - mCache.alloc(kCacheSizeAllocSize); -} - -AesCtrWrappedIFile::~AesCtrWrappedIFile() -{ - if (mOwnIFile) - { - delete mFile; - } -} - -size_t AesCtrWrappedIFile::size() -{ - return mFile->size(); -} - -void AesCtrWrappedIFile::seek(size_t offset) -{ - mFileOffset = offset; -} - -void AesCtrWrappedIFile::read(byte_t* out, size_t len) -{ - //printf("[%x] AesCtrWrappedIFile::read(offset=0x%" PRIx64 ", size=0x%" PRIx64 ")\n", this, mFileOffset, len); - - size_t read_len; - size_t read_pos; - - size_t cache_reads = (len / kCacheSize) + ((len % kCacheSize) != 0); - - for (size_t i = 0; i < cache_reads; i++) - { - read_len = _MIN(len - (i * kCacheSize), kCacheSize); - read_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); - - //printf("[%x] AesCtrWrappedIFile::read() CACHE READ: readlen=%" PRIx64 "\n", this, read_len); - - mFile->seek(read_pos); - mFile->read(mCache.data(), kCacheSizeAllocSize); - - fnd::aes::AesIncrementCounter(mBaseCtr.iv, read_pos>>4, mCurrentCtr.iv); - fnd::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); - - memcpy(out + (i * kCacheSize), mCache.data() + (mFileOffset & 0xf), read_len); - } - - seek(mFileOffset + len); -} - -void AesCtrWrappedIFile::read(byte_t* out, size_t offset, size_t len) -{ - seek(offset); - read(out, len); -} - -void AesCtrWrappedIFile::write(const byte_t* in, size_t len) -{ - size_t write_len; - size_t write_pos; - - size_t cache_writes = (len / kCacheSize) + ((len % kCacheSize) != 0); - - for (size_t i = 0; i < cache_writes; i++) - { - write_len = _MIN(len - (i * kCacheSize), kCacheSize); - write_pos = ((mFileOffset >> 4) << 4) + (i * kCacheSize); - - //printf("[%x] AesCtrWrappedIFile::read() CACHE READ: readlen=%" PRIx64 "\n", this, read_len); - - memcpy(mCache.data() + (mFileOffset & 0xf), in + (i * kCacheSize), write_len); - - fnd::aes::AesIncrementCounter(mBaseCtr.iv, write_pos>>4, mCurrentCtr.iv); - fnd::aes::AesCtr(mCache.data(), kCacheSizeAllocSize, mKey.key, mCurrentCtr.iv, mCache.data()); - - mFile->seek(write_pos); - mFile->write(mCache.data(), kCacheSizeAllocSize); - } - - seek(mFileOffset + len); - - /* - for (size_t i = 0; i < (len / kAesCtrScratchSize); i++) - { - memcpy(mScratch.data() + mBlockOffset, out + (i * kAesCtrScratchSize), kAesCtrScratchSize); - fnd::aes::AesCtr(mScratch.data(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.data()); - mFile->write(mScratch.data() + mBlockOffset, kAesCtrScratchSize); - } - - if (len % kAesCtrScratchSize) - { - size_t write_len = len % kAesCtrScratchSize; - size_t write_pos = ((len / kAesCtrScratchSize) * kAesCtrScratchSize); - memcpy(mScratch.data() + mBlockOffset, out + write_pos, write_len); - fnd::aes::AesCtr(mScratch.data(), kAesCtrScratchAllocSize, mKey.key, mCurrentCtr.iv, mScratch.data()); - mFile->write(mScratch.data() + mBlockOffset, write_len); - } - */ - seek(mFileOffset + len); -} - -void AesCtrWrappedIFile::write(const byte_t* in, size_t offset, size_t len) -{ - seek(offset); - write(in, len); -} \ No newline at end of file diff --git a/programs/nstool/source/AesCtrWrappedIFile.h b/programs/nstool/source/AesCtrWrappedIFile.h deleted file mode 100644 index 1703bc8..0000000 --- a/programs/nstool/source/AesCtrWrappedIFile.h +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include - -class AesCtrWrappedIFile : public fnd::IFile -{ -public: - AesCtrWrappedIFile(fnd::IFile* file, bool ownIfile, const fnd::aes::sAes128Key& key, const fnd::aes::sAesIvCtr& ctr); - ~AesCtrWrappedIFile(); - - size_t size(); - void seek(size_t offset); - void read(byte_t* out, size_t len); - void read(byte_t* out, size_t offset, size_t len); - void write(const byte_t* out, size_t len); - void write(const byte_t* out, size_t offset, size_t len); -private: - const std::string kModuleName = "AesCtrWrappedIFile"; - static const size_t kCacheSize = 0x10000; - static const size_t kCacheSizeAllocSize = kCacheSize + fnd::aes::kAesBlockSize; - - bool mOwnIFile; - fnd::IFile* mFile; - fnd::aes::sAes128Key mKey; - fnd::aes::sAesIvCtr mBaseCtr, mCurrentCtr; - size_t mFileOffset; - - fnd::Vec mCache; -}; \ No newline at end of file diff --git a/programs/nstool/source/AssetProcess.cpp b/programs/nstool/source/AssetProcess.cpp index 0128ee1..fcca0ce 100644 --- a/programs/nstool/source/AssetProcess.cpp +++ b/programs/nstool/source/AssetProcess.cpp @@ -1,26 +1,16 @@ #include #include #include +#include #include #include "AssetProcess.h" -#include "OffsetAdjustedIFile.h" AssetProcess::AssetProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { - -} - -AssetProcess::~AssetProcess() -{ - if (mOwnIFile) - { - delete mFile; - } } void AssetProcess::process() @@ -31,10 +21,9 @@ void AssetProcess::process() processSections(); } -void AssetProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void AssetProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void AssetProcess::setCliOutputMode(CliOutputMode type) @@ -72,18 +61,18 @@ void AssetProcess::importHeader() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - if (mFile->size() < sizeof(nn::hac::sAssetHeader)) + if ((*mFile)->size() < sizeof(nn::hac::sAssetHeader)) { throw fnd::Exception(kModuleName, "Corrupt ASET: file too small"); } scratch.alloc(sizeof(nn::hac::sAssetHeader)); - mFile->read(scratch.data(), 0, scratch.size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mHdr.fromBytes(scratch.data(), scratch.size()); } @@ -92,21 +81,21 @@ void AssetProcess::processSections() { if (mHdr.getIconInfo().size > 0 && mIconExtractPath.isSet) { - if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > mFile->size()) + if ((mHdr.getIconInfo().size + mHdr.getIconInfo().offset) > (*mFile)->size()) throw fnd::Exception(kModuleName, "ASET geometry for icon beyond file size"); fnd::SimpleFile outfile(mIconExtractPath.var, fnd::SimpleFile::Create); fnd::Vec cache; cache.alloc(mHdr.getIconInfo().size); - mFile->read(cache.data(), mHdr.getIconInfo().offset, cache.size()); + (*mFile)->read(cache.data(), mHdr.getIconInfo().offset, cache.size()); outfile.write(cache.data(), cache.size()); outfile.close(); } if (mHdr.getNacpInfo().size > 0) { - if ((mHdr.getNacpInfo().size + mHdr.getNacpInfo().offset) > mFile->size()) + if ((mHdr.getNacpInfo().size + mHdr.getNacpInfo().offset) > (*mFile)->size()) throw fnd::Exception(kModuleName, "ASET geometry for nacp beyond file size"); if (mNacpExtractPath.isSet) @@ -115,12 +104,12 @@ void AssetProcess::processSections() fnd::Vec cache; cache.alloc(mHdr.getNacpInfo().size); - mFile->read(cache.data(), mHdr.getNacpInfo().offset, cache.size()); + (*mFile)->read(cache.data(), mHdr.getNacpInfo().offset, cache.size()); outfile.write(cache.data(), cache.size()); outfile.close(); } - mNacp.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size), true); + mNacp.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size)); mNacp.setCliOutputMode(mCliOutputMode); mNacp.setVerifyMode(mVerify); @@ -129,10 +118,10 @@ void AssetProcess::processSections() if (mHdr.getRomfsInfo().size > 0) { - if ((mHdr.getRomfsInfo().size + mHdr.getRomfsInfo().offset) > mFile->size()) + if ((mHdr.getRomfsInfo().size + mHdr.getRomfsInfo().offset) > (*mFile)->size()) throw fnd::Exception(kModuleName, "ASET geometry for romfs beyond file size"); - mRomfs.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size), true); + mRomfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); mRomfs.setCliOutputMode(mCliOutputMode); mRomfs.setVerifyMode(mVerify); diff --git a/programs/nstool/source/AssetProcess.h b/programs/nstool/source/AssetProcess.h index 64efbc7..7364d15 100644 --- a/programs/nstool/source/AssetProcess.h +++ b/programs/nstool/source/AssetProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "NacpProcess.h" #include "RomfsProcess.h" @@ -12,11 +13,10 @@ class AssetProcess { public: AssetProcess(); - ~AssetProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -30,8 +30,7 @@ public: private: const std::string kModuleName = "AssetProcess"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/CnmtProcess.cpp b/programs/nstool/source/CnmtProcess.cpp index 29caeb4..e49093d 100644 --- a/programs/nstool/source/CnmtProcess.cpp +++ b/programs/nstool/source/CnmtProcess.cpp @@ -1,25 +1,16 @@ #include #include #include -#include "OffsetAdjustedIFile.h" +#include #include "CnmtProcess.h" CnmtProcess::CnmtProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -CnmtProcess::~CnmtProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void CnmtProcess::process() { importCnmt(); @@ -28,10 +19,9 @@ void CnmtProcess::process() displayCnmt(); } -void CnmtProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void CnmtProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void CnmtProcess::setCliOutputMode(CliOutputMode type) @@ -53,13 +43,13 @@ void CnmtProcess::importCnmt() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mFile->size()); - mFile->read(scratch.data(), 0, scratch.size()); + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mCnmt.fromBytes(scratch.data(), scratch.size()); } diff --git a/programs/nstool/source/CnmtProcess.h b/programs/nstool/source/CnmtProcess.h index 2fbcd15..4fa561c 100644 --- a/programs/nstool/source/CnmtProcess.h +++ b/programs/nstool/source/CnmtProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "common.h" @@ -10,11 +11,10 @@ class CnmtProcess { public: CnmtProcess(); - ~CnmtProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -23,8 +23,7 @@ public: private: const std::string kModuleName = "CnmtProcess"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/EsTikProcess.cpp b/programs/nstool/source/EsTikProcess.cpp index 4832276..41da96c 100644 --- a/programs/nstool/source/EsTikProcess.cpp +++ b/programs/nstool/source/EsTikProcess.cpp @@ -1,29 +1,20 @@ #include #include #include +#include #include -#include "OffsetAdjustedIFile.h" #include "EsTikProcess.h" #include "PkiValidator.h" EsTikProcess::EsTikProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -EsTikProcess::~EsTikProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void EsTikProcess::process() { importTicket(); @@ -35,10 +26,9 @@ void EsTikProcess::process() displayTicket(); } -void EsTikProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void EsTikProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void EsTikProcess::setKeyCfg(const KeyConfiguration& keycfg) @@ -66,13 +56,13 @@ void EsTikProcess::importTicket() fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mFile->size()); - mFile->read(scratch.data(), 0, scratch.size()); + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mTik.fromBytes(scratch.data(), scratch.size()); } diff --git a/programs/nstool/source/EsTikProcess.h b/programs/nstool/source/EsTikProcess.h index 94f5b05..cf3e36e 100644 --- a/programs/nstool/source/EsTikProcess.h +++ b/programs/nstool/source/EsTikProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -13,11 +14,10 @@ class EsTikProcess { public: EsTikProcess(); - ~EsTikProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setKeyCfg(const KeyConfiguration& keycfg); void setCertificateChain(const fnd::List>& certs); void setCliOutputMode(CliOutputMode mode); @@ -26,8 +26,7 @@ public: private: const std::string kModuleName = "EsTikProcess"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/HashTreeMeta.cpp b/programs/nstool/source/HashTreeMeta.cpp deleted file mode 100644 index 3276d41..0000000 --- a/programs/nstool/source/HashTreeMeta.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "HashTreeMeta.h" - -HashTreeMeta::HashTreeMeta() : - mLayerInfo(), - mDataLayer(), - mMasterHashList(), - mDoAlignHashToBlock(false) -{ - -} - -HashTreeMeta::HashTreeMeta(const byte_t* data, size_t len, HashTreeType type) : - HashTreeMeta() -{ - importData(data, len, type); -} - -void HashTreeMeta::operator=(const HashTreeMeta& other) -{ - mLayerInfo = other.mLayerInfo; - mDataLayer = other.mDataLayer; - mMasterHashList = other.mMasterHashList; - mDoAlignHashToBlock = other.mDoAlignHashToBlock; -} - -bool HashTreeMeta::operator==(const HashTreeMeta& other) const -{ - return (mLayerInfo == other.mLayerInfo) \ - && (mDataLayer == other.mDataLayer) \ - && (mMasterHashList == other.mMasterHashList) \ - && (mDoAlignHashToBlock == other.mDoAlignHashToBlock); -} - -bool HashTreeMeta::operator!=(const HashTreeMeta& other) const -{ - return !(*this == other); -} - -void HashTreeMeta::importData(const byte_t* data, size_t len, HashTreeType type) -{ - if (type == HASH_TYPE_INTEGRITY) - { - nn::hac::HierarchicalIntegrityHeader hdr; - hdr.fromBytes(data, len); - importHierarchicalIntergityHeader(hdr); - } - else if (type == HASH_TYPE_SHA256) - { - nn::hac::HierarchicalSha256Header hdr; - hdr.fromBytes(data, len); - importHierarchicalSha256Header(hdr); - } -} - -const fnd::List& HashTreeMeta::getHashLayerInfo() const -{ - return mLayerInfo; -} - -void HashTreeMeta::setHashLayerInfo(const fnd::List& layer_info) -{ - mLayerInfo = layer_info; -} - -const HashTreeMeta::sLayer& HashTreeMeta::getDataLayer() const -{ - return mDataLayer; -} - -void HashTreeMeta::setDataLayer(const sLayer& data_info) -{ - mDataLayer = data_info; -} - -const fnd::List& HashTreeMeta::getMasterHashList() const -{ - return mMasterHashList; -} - -void HashTreeMeta::setMasterHashList(const fnd::List& master_hash_list) -{ - mMasterHashList = master_hash_list; -} - -bool HashTreeMeta::getAlignHashToBlock() const -{ - return mDoAlignHashToBlock; -} - -void HashTreeMeta::setAlignHashToBlock(bool doAlign) -{ - mDoAlignHashToBlock = doAlign; -} - -void HashTreeMeta::importHierarchicalIntergityHeader(const nn::hac::HierarchicalIntegrityHeader& hdr) -{ - mDoAlignHashToBlock = true; - for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) - { - sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); - if (i+1 == hdr.getLayerInfo().size()) - { - mDataLayer = layer; - } - else - { - mLayerInfo.addElement(layer); - } - } - mMasterHashList = hdr.getMasterHashList(); -} - -void HashTreeMeta::importHierarchicalSha256Header(const nn::hac::HierarchicalSha256Header& hdr) -{ - mDoAlignHashToBlock = false; - for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) - { - sLayer layer; - layer.offset = hdr.getLayerInfo()[i].offset; - layer.size = hdr.getLayerInfo()[i].size; - layer.block_size = hdr.getHashBlockSize(); - if (i+1 == hdr.getLayerInfo().size()) - { - mDataLayer = layer; - } - else - { - mLayerInfo.addElement(layer); - } - } - mMasterHashList.addElement(hdr.getMasterHash()); -} \ No newline at end of file diff --git a/programs/nstool/source/HashTreeMeta.h b/programs/nstool/source/HashTreeMeta.h deleted file mode 100644 index 1568b5e..0000000 --- a/programs/nstool/source/HashTreeMeta.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include -#include - -class HashTreeMeta -{ -public: - enum HashTreeType - { - HASH_TYPE_INTEGRITY, - HASH_TYPE_SHA256 - }; - - struct sLayer - { - size_t offset; - size_t size; - size_t block_size; - - void operator=(const sLayer& other) - { - offset = other.offset; - size = other.size; - block_size = other.block_size; - } - - bool operator==(const sLayer& other) const - { - return (offset == other.offset && size == other.size && block_size == other.block_size); - } - - bool operator!=(const sLayer& other) const - { - return !(*this == other); - } - }; - - HashTreeMeta(); - HashTreeMeta(const byte_t* data, size_t len, HashTreeType type); - - void operator=(const HashTreeMeta& other); - bool operator==(const HashTreeMeta& other) const; - bool operator!=(const HashTreeMeta& other) const; - - void importData(const byte_t* data, size_t len, HashTreeType type); - - const fnd::List& getHashLayerInfo() const; - void setHashLayerInfo(const fnd::List& layer_info); - - const sLayer& getDataLayer() const; - void setDataLayer(const sLayer& data_info); - - const fnd::List& getMasterHashList() const; - void setMasterHashList(const fnd::List& master_hash_list); - - bool getAlignHashToBlock() const; - void setAlignHashToBlock(bool doAlign); -private: - - // data - fnd::List mLayerInfo; - sLayer mDataLayer; - fnd::List mMasterHashList; - bool mDoAlignHashToBlock; - - void importHierarchicalIntergityHeader(const nn::hac::HierarchicalIntegrityHeader& hdr); - void importHierarchicalSha256Header(const nn::hac::HierarchicalSha256Header& hdr); -}; \ No newline at end of file diff --git a/programs/nstool/source/HashTreeWrappedIFile.h b/programs/nstool/source/HashTreeWrappedIFile.h deleted file mode 100644 index 6e97181..0000000 --- a/programs/nstool/source/HashTreeWrappedIFile.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "HashTreeMeta.h" - - -class HashTreeWrappedIFile : public fnd::IFile -{ -public: - HashTreeWrappedIFile(fnd::IFile* file, bool ownIFile, const HashTreeMeta& hdr); - ~HashTreeWrappedIFile(); - - size_t size(); - void seek(size_t offset); - void read(byte_t* out, size_t len); - void read(byte_t* out, size_t offset, size_t len); - void write(const byte_t* out, size_t len); - void write(const byte_t* out, size_t offset, size_t len); -private: - const std::string kModuleName = "HashTreeWrappedIFile"; - static const size_t kDefaultCacheSize = 0x10000; - std::stringstream mErrorSs; - - bool mOwnIFile; - fnd::IFile* mFile; - - // data file - fnd::IFile* mData; - size_t mDataOffset; - size_t mDataBlockSize; - fnd::List mDataHashLayer; - bool mAlignHashCalcToBlock; - - fnd::Vec mCache; - size_t mCacheBlockNum; - - inline size_t getOffsetBlock(size_t offset) const { return offset / mDataBlockSize; } - inline size_t getOffsetInBlock(size_t offset) const { return offset % mDataBlockSize; } - inline size_t getRemanderBlockReadSize(size_t total_size) const { return total_size % mDataBlockSize; } - inline size_t getBlockNum(size_t total_size) const { return (total_size / mDataBlockSize) + (getRemanderBlockReadSize(total_size) > 0); } - - void initialiseDataLayer(const HashTreeMeta& hdr); - void readData(size_t block_offset, size_t block_num); -}; \ No newline at end of file diff --git a/programs/nstool/source/NacpProcess.cpp b/programs/nstool/source/NacpProcess.cpp index fb6d5bf..fb04870 100644 --- a/programs/nstool/source/NacpProcess.cpp +++ b/programs/nstool/source/NacpProcess.cpp @@ -2,25 +2,16 @@ #include #include #include -#include "OffsetAdjustedIFile.h" +#include #include "NacpProcess.h" NacpProcess::NacpProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -NacpProcess::~NacpProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void NacpProcess::process() { importNacp(); @@ -29,10 +20,9 @@ void NacpProcess::process() displayNacp(); } -void NacpProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void NacpProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void NacpProcess::setCliOutputMode(CliOutputMode type) @@ -54,13 +44,13 @@ void NacpProcess::importNacp() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mFile->size()); - mFile->read(scratch.data(), 0, scratch.size()); + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mNacp.fromBytes(scratch.data(), scratch.size()); } diff --git a/programs/nstool/source/NacpProcess.h b/programs/nstool/source/NacpProcess.h index 0e6aed3..8a5064c 100644 --- a/programs/nstool/source/NacpProcess.h +++ b/programs/nstool/source/NacpProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "common.h" @@ -10,11 +11,10 @@ class NacpProcess { public: NacpProcess(); - ~NacpProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -23,8 +23,7 @@ public: private: const std::string kModuleName = "NacpProcess"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index f637e17..870aa7d 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -2,19 +2,21 @@ #include #include #include +#include +#include +#include #include #include +#include +#include #include "NcaProcess.h" #include "PfsProcess.h" #include "RomfsProcess.h" #include "NpdmProcess.h" -#include "OffsetAdjustedIFile.h" -#include "AesCtrWrappedIFile.h" -#include "HashTreeWrappedIFile.h" + NcaProcess::NcaProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mListFs(false) @@ -22,23 +24,6 @@ NcaProcess::NcaProcess() : for (size_t i = 0; i < nn::hac::nca::kPartitionNum; i++) { mPartitionPath[i].doExtract = false; - mPartitions[i].reader = nullptr; - } -} - -NcaProcess::~NcaProcess() -{ - if (mOwnIFile) - { - delete mFile; - } - - for (size_t i = 0; i < nn::hac::nca::kPartitionNum; i++) - { - if (mPartitions[i].reader != nullptr) - { - delete mPartitions[i].reader; - } } } @@ -65,10 +50,9 @@ void NcaProcess::process() processPartitions(); } -void NcaProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void NcaProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void NcaProcess::setKeyCfg(const KeyConfiguration& keycfg) @@ -117,13 +101,13 @@ void NcaProcess::setListFs(bool list_fs) void NcaProcess::importHeader() { - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // read header block - mFile->read((byte_t*)&mHdrBlock, 0, sizeof(nn::hac::sNcaHeaderBlock)); + (*mFile)->read((byte_t*)&mHdrBlock, 0, sizeof(nn::hac::sNcaHeaderBlock)); // decrypt header block fnd::aes::sAesXts128Key header_key; @@ -277,9 +261,69 @@ void NcaProcess::generatePartitionConfiguration() info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type; info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type; if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) - info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, HashTreeMeta::HASH_TYPE_SHA256); + { + // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_SHA256); + nn::hac::HierarchicalSha256Header hdr; + fnd::List hash_layers; + fnd::LayeredIntegrityMetadata::sLayer data_layer; + fnd::List master_hash_list; + + // import raw data + hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + fnd::LayeredIntegrityMetadata::sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = hdr.getHashBlockSize(); + if (i + 1 == hdr.getLayerInfo().size()) + { + data_layer = layer; + } + else + { + hash_layers.addElement(layer); + } + } + master_hash_list.addElement(hdr.getMasterHash()); + + // write data into metadata + info.layered_intergrity_metadata.setAlignHashToBlock(false); + info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); + info.layered_intergrity_metadata.setDataLayerInfo(data_layer); + info.layered_intergrity_metadata.setMasterHashList(master_hash_list); + } else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) - info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, HashTreeMeta::HASH_TYPE_INTEGRITY); + { + // info.hash_tree_meta.importData(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen, LayeredIntegrityMetadata::HASH_TYPE_INTEGRITY); + nn::hac::HierarchicalIntegrityHeader hdr; + fnd::List hash_layers; + fnd::LayeredIntegrityMetadata::sLayer data_layer; + fnd::List master_hash_list; + + hdr.fromBytes(fs_header.hash_superblock, nn::hac::nca::kFsHeaderHashSuperblockLen); + for (size_t i = 0; i < hdr.getLayerInfo().size(); i++) + { + fnd::LayeredIntegrityMetadata::sLayer layer; + layer.offset = hdr.getLayerInfo()[i].offset; + layer.size = hdr.getLayerInfo()[i].size; + layer.block_size = _BIT(hdr.getLayerInfo()[i].block_size); + if (i + 1 == hdr.getLayerInfo().size()) + { + data_layer = layer; + } + else + { + hash_layers.addElement(layer); + } + } + + // write data into metadata + info.layered_intergrity_metadata.setAlignHashToBlock(true); + info.layered_intergrity_metadata.setHashLayerInfo(hash_layers); + info.layered_intergrity_metadata.setDataLayerInfo(data_layer); + info.layered_intergrity_metadata.setMasterHashList(hdr.getMasterHashList()); + } // create reader try @@ -299,13 +343,13 @@ void NcaProcess::generatePartitionConfiguration() // create reader based on encryption type0 if (info.enc_type == nn::hac::nca::CRYPT_NONE) { - info.reader = new OffsetAdjustedIFile(mFile, SHARED_IFILE, info.offset, info.size); + info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size); } else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) { if (mContentKey.aes_ctr.isSet == false) throw fnd::Exception(kModuleName, "AES-CTR Key was not determined"); - info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mFile, SHARED_IFILE, mContentKey.aes_ctr.var, info.aes_ctr), OWN_IFILE, info.offset, info.size); + info.reader = new fnd::OffsetAdjustedIFile(new fnd::AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), info.offset, info.size); } else if (info.enc_type == nn::hac::nca::CRYPT_AESXTS || info.enc_type == nn::hac::nca::CRYPT_AESCTREX) { @@ -323,9 +367,7 @@ void NcaProcess::generatePartitionConfiguration() // filter out unrecognised hash types, and hash based readers if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256 || info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) { - fnd::IFile* tmp = info.reader; - info.reader = nullptr; - info.reader = new HashTreeWrappedIFile(tmp, OWN_IFILE, info.hash_tree_meta); + info.reader = new fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata); } else if (info.hash_type != nn::hac::nca::HASH_NONE) { @@ -337,9 +379,6 @@ void NcaProcess::generatePartitionConfiguration() catch (const fnd::Exception& e) { info.fail_reason = std::string(e.error()); - if (info.reader != nullptr) - delete info.reader; - info.reader = nullptr; } } } @@ -359,10 +398,10 @@ void NcaProcess::validateNcaSignatures() { if (mPartitions[nn::hac::nca::PARTITION_CODE].format_type == nn::hac::nca::FORMAT_PFS0) { - if (mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr) + if (*mPartitions[nn::hac::nca::PARTITION_CODE].reader != nullptr) { PfsProcess exefs; - exefs.setInputFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, SHARED_IFILE); + exefs.setInputFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader); exefs.setCliOutputMode(0); exefs.process(); @@ -372,7 +411,7 @@ void NcaProcess::validateNcaSignatures() const nn::hac::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath); NpdmProcess npdm; - npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, SHARED_IFILE, file.offset, file.size), OWN_IFILE); + npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size)); npdm.setCliOutputMode(0); npdm.process(); @@ -464,7 +503,7 @@ void NcaProcess::displayHeader() } if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) { - HashTreeMeta& hash_hdr = info.hash_tree_meta; + fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; std::cout << " HierarchicalIntegrity Header:" << std::endl; for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) { @@ -487,7 +526,7 @@ void NcaProcess::displayHeader() } else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) { - HashTreeMeta& hash_hdr = info.hash_tree_meta; + fnd::LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; std::cout << " HierarchicalSha256 Header:" << std::endl; std::cout << " Master Hash:" << std::endl; std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes, 0x10, true, ":") << std::endl; @@ -513,7 +552,7 @@ void NcaProcess::processPartitions() struct sPartitionInfo& partition = mPartitions[index]; // if the reader is null, skip - if (partition.reader == nullptr) + if (*partition.reader == nullptr) { std::cout << "[WARNING] NCA Partition " << std::dec << index << " not readable."; if (partition.fail_reason.empty() == false) @@ -527,7 +566,7 @@ void NcaProcess::processPartitions() if (partition.format_type == nn::hac::nca::FORMAT_PFS0) { PfsProcess pfs; - pfs.setInputFile(partition.reader, SHARED_IFILE); + pfs.setInputFile(partition.reader); pfs.setCliOutputMode(mCliOutputMode); pfs.setListFs(mListFs); if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) @@ -546,7 +585,7 @@ void NcaProcess::processPartitions() else if (partition.format_type == nn::hac::nca::FORMAT_ROMFS) { RomfsProcess romfs; - romfs.setInputFile(partition.reader, SHARED_IFILE); + romfs.setInputFile(partition.reader); romfs.setCliOutputMode(mCliOutputMode); romfs.setListFs(mListFs); if (mHdr.getContentType() == nn::hac::nca::TYPE_PROGRAM) diff --git a/programs/nstool/source/NcaProcess.h b/programs/nstool/source/NcaProcess.h index f467945..e87a408 100644 --- a/programs/nstool/source/NcaProcess.h +++ b/programs/nstool/source/NcaProcess.h @@ -1,9 +1,10 @@ #pragma once #include #include -#include +#include +#include +#include #include -#include "HashTreeMeta.h" #include "KeyConfiguration.h" @@ -13,12 +14,11 @@ class NcaProcess { public: NcaProcess(); - ~NcaProcess(); void process(); // generic - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -35,8 +35,7 @@ private: const std::string kNpdmExefsPath = "main.npdm"; // user options - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; @@ -92,7 +91,7 @@ private: struct sPartitionInfo { - fnd::IFile* reader; + fnd::SharedPtr reader; std::string fail_reason; size_t offset; size_t size; @@ -101,7 +100,7 @@ private: nn::hac::nca::FormatType format_type; nn::hac::nca::HashType hash_type; nn::hac::nca::EncryptionType enc_type; - HashTreeMeta hash_tree_meta; + fnd::LayeredIntegrityMetadata layered_intergrity_metadata; fnd::aes::sAesIvCtr aes_ctr; } mPartitions[nn::hac::nca::kPartitionNum]; diff --git a/programs/nstool/source/NpdmProcess.cpp b/programs/nstool/source/NpdmProcess.cpp index 71b9f14..c397b2e 100644 --- a/programs/nstool/source/NpdmProcess.cpp +++ b/programs/nstool/source/NpdmProcess.cpp @@ -3,21 +3,12 @@ #include "NpdmProcess.h" NpdmProcess::NpdmProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -NpdmProcess::~NpdmProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void NpdmProcess::process() { importNpdm(); @@ -50,10 +41,9 @@ void NpdmProcess::process() } } -void NpdmProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void NpdmProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void NpdmProcess::setKeyCfg(const KeyConfiguration& keycfg) @@ -80,13 +70,13 @@ void NpdmProcess::importNpdm() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mFile->size()); - mFile->read(scratch.data(), 0, scratch.size()); + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mNpdm.fromBytes(scratch.data(), scratch.size()); } diff --git a/programs/nstool/source/NpdmProcess.h b/programs/nstool/source/NpdmProcess.h index a203c0e..b4868bd 100644 --- a/programs/nstool/source/NpdmProcess.h +++ b/programs/nstool/source/NpdmProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "KeyConfiguration.h" @@ -11,11 +12,10 @@ class NpdmProcess { public: NpdmProcess(); - ~NpdmProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -25,8 +25,7 @@ public: private: const std::string kModuleName = "NpdmProcess"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/NroProcess.cpp b/programs/nstool/source/NroProcess.cpp index 577cc95..546e7fa 100644 --- a/programs/nstool/source/NroProcess.cpp +++ b/programs/nstool/source/NroProcess.cpp @@ -1,28 +1,19 @@ #include #include #include +#include #include #include #include -#include "OffsetAdjustedIFile.h" #include "NroProcess.h" NroProcess::NroProcess(): - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -NroProcess::~NroProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void NroProcess::process() { importHeader(); @@ -37,10 +28,9 @@ void NroProcess::process() mAssetProc.process(); } -void NroProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void NroProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void NroProcess::setCliOutputMode(CliOutputMode type) @@ -97,27 +87,27 @@ void NroProcess::importHeader() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - if (mFile->size() < sizeof(nn::hac::sNroHeader)) + if ((*mFile)->size() < sizeof(nn::hac::sNroHeader)) { throw fnd::Exception(kModuleName, "Corrupt NRO: file too small"); } scratch.alloc(sizeof(nn::hac::sNroHeader)); - mFile->read(scratch.data(), 0, scratch.size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mHdr.fromBytes(scratch.data(), scratch.size()); // setup homebrew extension nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data(); - if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nn::hac::nro::kNroHomebrewStructMagic && mFile->size() > mHdr.getNroSize()) + if (((le_uint64_t*)raw_hdr->reserved_0)->get() == nn::hac::nro::kNroHomebrewStructMagic && (*mFile)->size() > mHdr.getNroSize()) { mIsHomebrewNro = true; - mAssetProc.setInputFile(new OffsetAdjustedIFile(mFile, false, mHdr.getNroSize(), mFile->size() - mHdr.getNroSize()), true); + mAssetProc.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize())); mAssetProc.setCliOutputMode(mCliOutputMode); mAssetProc.setVerifyMode(mVerify); } @@ -128,11 +118,11 @@ void NroProcess::importHeader() void NroProcess::importCodeSegments() { mTextBlob.alloc(mHdr.getTextInfo().size); - mFile->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size()); + (*mFile)->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size()); mRoBlob.alloc(mHdr.getRoInfo().size); - mFile->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size()); + (*mFile)->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size()); mDataBlob.alloc(mHdr.getDataInfo().size); - mFile->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size()); + (*mFile)->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size()); } void NroProcess::displayHeader() diff --git a/programs/nstool/source/NroProcess.h b/programs/nstool/source/NroProcess.h index 7d27553..4ddd1eb 100644 --- a/programs/nstool/source/NroProcess.h +++ b/programs/nstool/source/NroProcess.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "AssetProcess.h" @@ -14,11 +15,10 @@ class NroProcess { public: NroProcess(); - ~NroProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -36,9 +36,7 @@ public: private: const std::string kModuleName = "NroProcess"; - fnd::IFile* mFile; - bool mOwnIFile; - + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index c99cd78..3012e98 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -1,27 +1,18 @@ #include #include #include +#include #include #include -#include "OffsetAdjustedIFile.h" #include "NsoProcess.h" NsoProcess::NsoProcess(): - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -NsoProcess::~NsoProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void NsoProcess::process() { importHeader(); @@ -32,10 +23,9 @@ void NsoProcess::process() processRoMeta(); } -void NsoProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void NsoProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void NsoProcess::setCliOutputMode(CliOutputMode type) @@ -72,18 +62,18 @@ void NsoProcess::importHeader() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - if (mFile->size() < sizeof(nn::hac::sNsoHeader)) + if ((*mFile)->size() < sizeof(nn::hac::sNsoHeader)) { throw fnd::Exception(kModuleName, "Corrupt NSO: file too small"); } scratch.alloc(sizeof(nn::hac::sNsoHeader)); - mFile->read(scratch.data(), 0, scratch.size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mHdr.fromBytes(scratch.data(), scratch.size()); } @@ -98,7 +88,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getTextSegmentInfo().is_compressed) { scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mFile->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); + (*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size()); mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size); fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len); if (decompressed_len != mTextBlob.size()) @@ -109,7 +99,7 @@ void NsoProcess::importCodeSegments() else { mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size); - mFile->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); + (*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size()); } if (mHdr.getTextSegmentInfo().is_hashed) { @@ -124,7 +114,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getRoSegmentInfo().is_compressed) { scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mFile->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); + (*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size()); mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size); fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len); if (decompressed_len != mRoBlob.size()) @@ -135,7 +125,7 @@ void NsoProcess::importCodeSegments() else { mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size); - mFile->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); + (*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size()); } if (mHdr.getRoSegmentInfo().is_hashed) { @@ -150,7 +140,7 @@ void NsoProcess::importCodeSegments() if (mHdr.getDataSegmentInfo().is_compressed) { scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mFile->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); + (*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size()); mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size); fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len); if (decompressed_len != mDataBlob.size()) @@ -161,7 +151,7 @@ void NsoProcess::importCodeSegments() else { mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size); - mFile->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); + (*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size()); } if (mHdr.getDataSegmentInfo().is_hashed) { diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index a74beaf..88170ae 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -13,11 +14,10 @@ class NsoProcess { public: NsoProcess(); - ~NsoProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -29,9 +29,7 @@ public: private: const std::string kModuleName = "NsoProcess"; - fnd::IFile* mFile; - bool mOwnIFile; - + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; nn::hac::npdm::InstructionType mInstructionType; diff --git a/programs/nstool/source/OffsetAdjustedIFile.cpp b/programs/nstool/source/OffsetAdjustedIFile.cpp deleted file mode 100644 index ad127f1..0000000 --- a/programs/nstool/source/OffsetAdjustedIFile.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "OffsetAdjustedIFile.h" - -OffsetAdjustedIFile::OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size) : - mOwnIFile(ownIFile), - mFile(file), - mBaseOffset(offset), - mCurrentOffset(0), - mSize(size) -{ - -} - -OffsetAdjustedIFile::~OffsetAdjustedIFile() -{ - if (mOwnIFile) - { - delete mFile; - } -} - -size_t OffsetAdjustedIFile::size() -{ - return mSize; -} - -void OffsetAdjustedIFile::seek(size_t offset) -{ - mCurrentOffset = _MIN(offset, mSize); -} - -void OffsetAdjustedIFile::read(byte_t* out, size_t len) -{ - // assert proper position in file - mFile->seek(mCurrentOffset + mBaseOffset); - mFile->read(out, len); - seek(mCurrentOffset + len); -} - -void OffsetAdjustedIFile::read(byte_t* out, size_t offset, size_t len) -{ - seek(offset); - read(out, len); -} - -void OffsetAdjustedIFile::write(const byte_t* out, size_t len) -{ - // assert proper position in file - mFile->seek(mCurrentOffset + mBaseOffset); - mFile->write(out, len); - seek(mCurrentOffset + len); -} - -void OffsetAdjustedIFile::write(const byte_t* out, size_t offset, size_t len) -{ - seek(offset); - write(out, len); -} \ No newline at end of file diff --git a/programs/nstool/source/OffsetAdjustedIFile.h b/programs/nstool/source/OffsetAdjustedIFile.h deleted file mode 100644 index 4c68558..0000000 --- a/programs/nstool/source/OffsetAdjustedIFile.h +++ /dev/null @@ -1,20 +0,0 @@ -#include - -class OffsetAdjustedIFile : public fnd::IFile -{ -public: - OffsetAdjustedIFile(fnd::IFile* file, bool ownIFile, size_t offset, size_t size); - ~OffsetAdjustedIFile(); - - size_t size(); - void seek(size_t offset); - void read(byte_t* out, size_t len); - void read(byte_t* out, size_t offset, size_t len); - void write(const byte_t* out, size_t len); - void write(const byte_t* out, size_t offset, size_t len); -private: - bool mOwnIFile; - fnd::IFile* mFile; - size_t mBaseOffset, mCurrentOffset; - size_t mSize; -}; \ No newline at end of file diff --git a/programs/nstool/source/PfsProcess.cpp b/programs/nstool/source/PfsProcess.cpp index f878a4f..999b487 100644 --- a/programs/nstool/source/PfsProcess.cpp +++ b/programs/nstool/source/PfsProcess.cpp @@ -5,8 +5,7 @@ #include "PfsProcess.h" PfsProcess::PfsProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mExtractPath(), @@ -17,14 +16,6 @@ PfsProcess::PfsProcess() : { } -PfsProcess::~PfsProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void PfsProcess::process() { importHeader(); @@ -41,10 +32,9 @@ void PfsProcess::process() extractFs(); } -void PfsProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void PfsProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void PfsProcess::setCliOutputMode(CliOutputMode type) @@ -82,14 +72,14 @@ void PfsProcess::importHeader() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // open minimum header to get full header size scratch.alloc(sizeof(nn::hac::sPfsHeader)); - mFile->read(scratch.data(), 0, scratch.size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); if (validateHeaderMagic(((nn::hac::sPfsHeader*)scratch.data())) == false) { throw fnd::Exception(kModuleName, "Corrupt Header"); @@ -98,7 +88,7 @@ void PfsProcess::importHeader() // open minimum header to get full header size scratch.alloc(pfsHeaderSize); - mFile->read(scratch.data(), 0, scratch.size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); mPfs.fromBytes(scratch.data(), scratch.size()); } @@ -162,7 +152,7 @@ void PfsProcess::validateHfs() for (size_t i = 0; i < file.size(); i++) { mCache.alloc(file[i].hash_protected_size); - mFile->read(mCache.data(), file[i].offset, file[i].hash_protected_size); + (*mFile)->read(mCache.data(), file[i].offset, file[i].hash_protected_size); fnd::sha::Sha256(mCache.data(), file[i].hash_protected_size, hash.bytes); if (hash != file[i].hash) { @@ -193,10 +183,10 @@ void PfsProcess::extractFs() printf("extract=[%s]\n", file_path.c_str()); outFile.open(file_path, outFile.Create); - mFile->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++) { - mFile->read(mCache.data(), _MIN(file[i].size - (kCacheSize * j),kCacheSize)); + (*mFile)->read(mCache.data(), _MIN(file[i].size - (kCacheSize * j),kCacheSize)); outFile.write(mCache.data(), _MIN(file[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); diff --git a/programs/nstool/source/PfsProcess.h b/programs/nstool/source/PfsProcess.h index 562dd21..bf9d61c 100644 --- a/programs/nstool/source/PfsProcess.h +++ b/programs/nstool/source/PfsProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "common.h" @@ -10,12 +11,11 @@ class PfsProcess { public: PfsProcess(); - ~PfsProcess(); void process(); // generic - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -30,8 +30,7 @@ private: const std::string kModuleName = "PfsProcess"; static const size_t kCacheSize = 0x10000; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/PkiCertProcess.cpp b/programs/nstool/source/PkiCertProcess.cpp index f9912a3..4433ae7 100644 --- a/programs/nstool/source/PkiCertProcess.cpp +++ b/programs/nstool/source/PkiCertProcess.cpp @@ -1,27 +1,18 @@ #include #include #include +#include #include -#include "OffsetAdjustedIFile.h" #include "PkiCertProcess.h" #include "PkiValidator.h" PkiCertProcess::PkiCertProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { } -PkiCertProcess::~PkiCertProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void PkiCertProcess::process() { importCerts(); @@ -33,10 +24,9 @@ void PkiCertProcess::process() displayCerts(); } -void PkiCertProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void PkiCertProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void PkiCertProcess::setKeyCfg(const KeyConfiguration& keycfg) @@ -58,13 +48,13 @@ void PkiCertProcess::importCerts() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } - scratch.alloc(mFile->size()); - mFile->read(scratch.data(), 0, scratch.size()); + scratch.alloc((*mFile)->size()); + (*mFile)->read(scratch.data(), 0, scratch.size()); nn::pki::SignedData cert; for (size_t f_pos = 0; f_pos < scratch.size(); f_pos += cert.getBytes().size()) diff --git a/programs/nstool/source/PkiCertProcess.h b/programs/nstool/source/PkiCertProcess.h index c281ae7..88ed54d 100644 --- a/programs/nstool/source/PkiCertProcess.h +++ b/programs/nstool/source/PkiCertProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -13,11 +14,10 @@ class PkiCertProcess { public: PkiCertProcess(); - ~PkiCertProcess(); void process(); - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -26,8 +26,7 @@ private: const std::string kModuleName = "PkiCertProcess"; static const size_t kSmallHexDumpLen = 0x10; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/RomfsProcess.cpp b/programs/nstool/source/RomfsProcess.cpp index cf68257..aba23fe 100644 --- a/programs/nstool/source/RomfsProcess.cpp +++ b/programs/nstool/source/RomfsProcess.cpp @@ -6,8 +6,7 @@ #include "RomfsProcess.h" RomfsProcess::RomfsProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mExtractPath(), @@ -22,14 +21,6 @@ RomfsProcess::RomfsProcess() : mRootDir.file_list.clear(); } -RomfsProcess::~RomfsProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void RomfsProcess::process() { resolveRomfs(); @@ -45,10 +36,9 @@ void RomfsProcess::process() extractFs(); } -void RomfsProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void RomfsProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void RomfsProcess::setCliOutputMode(CliOutputMode type) @@ -163,10 +153,10 @@ void RomfsProcess::extractDir(const std::string& path, const sDirectory& dir) std::cout << "extract=[" << file_path << "]" << std::endl; outFile.open(file_path, outFile.Create); - mFile->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++) { - mFile->read(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); + (*mFile)->read(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); outFile.write(mCache.data(), _MIN(dir.file_list[i].size - (kCacheSize * j),kCacheSize)); } outFile.close(); @@ -258,13 +248,13 @@ void RomfsProcess::importDirectory(uint32_t dir_offset, sDirectory& dir) void RomfsProcess::resolveRomfs() { - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // read header - mFile->read((byte_t*)&mHdr, 0, sizeof(nn::hac::sRomfsHeader)); + (*mFile)->read((byte_t*)&mHdr, 0, sizeof(nn::hac::sRomfsHeader)); // logic check on the header layout if (validateHeaderLayout(&mHdr) == false) @@ -274,13 +264,13 @@ void RomfsProcess::resolveRomfs() // read directory nodes mDirNodes.alloc(mHdr.sections[nn::hac::romfs::DIR_NODE_TABLE].size.get()); - mFile->read(mDirNodes.data(), mHdr.sections[nn::hac::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.size()); + (*mFile)->read(mDirNodes.data(), mHdr.sections[nn::hac::romfs::DIR_NODE_TABLE].offset.get(), mDirNodes.size()); //printf("[RAW DIR NODES]\n"); //fnd::SimpleTextOutput::hxdStyleDump(mDirNodes.data(), mDirNodes.size()); // read file nodes mFileNodes.alloc(mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].size.get()); - mFile->read(mFileNodes.data(), mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.size()); + (*mFile)->read(mFileNodes.data(), mHdr.sections[nn::hac::romfs::FILE_NODE_TABLE].offset.get(), mFileNodes.size()); //printf("[RAW FILE NODES]\n"); //fnd::SimpleTextOutput::hxdStyleDump(mFileNodes.data(), mFileNodes.size()); diff --git a/programs/nstool/source/RomfsProcess.h b/programs/nstool/source/RomfsProcess.h index 7132bba..9edb32c 100644 --- a/programs/nstool/source/RomfsProcess.h +++ b/programs/nstool/source/RomfsProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -77,12 +78,11 @@ public: }; RomfsProcess(); - ~RomfsProcess(); void process(); // generic - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -96,8 +96,7 @@ private: const std::string kModuleName = "RomfsProcess"; static const size_t kCacheSize = 0x10000; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/XciProcess.cpp index b68b32b..d86c630 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/XciProcess.cpp @@ -1,13 +1,12 @@ #include #include #include +#include #include -#include "OffsetAdjustedIFile.h" #include "XciProcess.h" XciProcess::XciProcess() : - mFile(nullptr), - mOwnIFile(false), + mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mListFs(false), @@ -16,14 +15,6 @@ XciProcess::XciProcess() : { } -XciProcess::~XciProcess() -{ - if (mOwnIFile) - { - delete mFile; - } -} - void XciProcess::process() { importHeader(); @@ -43,10 +34,9 @@ void XciProcess::process() processPartitionPfs(); } -void XciProcess::setInputFile(fnd::IFile* file, bool ownIFile) +void XciProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; - mOwnIFile = ownIFile; } void XciProcess::setKeyCfg(const KeyConfiguration& keycfg) @@ -78,13 +68,13 @@ void XciProcess::importHeader() { fnd::Vec scratch; - if (mFile == nullptr) + if (*mFile == nullptr) { throw fnd::Exception(kModuleName, "No file reader set."); } // read header page - mFile->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sXciHeaderPage)); + (*mFile)->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sXciHeaderPage)); // allocate memory for and decrypt sXciHeader scratch.alloc(sizeof(nn::hac::sXciHeader)); @@ -193,7 +183,7 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t fnd::Vec scratch; fnd::sha::sSha256Hash calc_hash; scratch.alloc(len); - mFile->read(scratch.data(), offset, scratch.size()); + (*mFile)->read(scratch.data(), offset, scratch.size()); fnd::sha::Sha256(scratch.data(), scratch.size(), calc_hash.bytes); return calc_hash.compare(test_hash); } @@ -216,7 +206,7 @@ void XciProcess::processRootPfs() { std::cout << "[WARNING] XCI Root HFS0: FAIL (bad hash)" << std::endl; } - mRootPfs.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()), OWN_IFILE); + mRootPfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize())); mRootPfs.setListFs(mListFs); mRootPfs.setVerifyMode(false); mRootPfs.setCliOutputMode(mCliOutputMode); @@ -236,7 +226,7 @@ void XciProcess::processPartitionPfs() } PfsProcess tmp; - tmp.setInputFile(new OffsetAdjustedIFile(mFile, SHARED_IFILE, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size), OWN_IFILE); + tmp.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size)); tmp.setListFs(mListFs); tmp.setVerifyMode(mVerify); tmp.setCliOutputMode(mCliOutputMode); diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/XciProcess.h index bb9009c..6e034e7 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/XciProcess.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include "KeyConfiguration.h" @@ -13,12 +14,11 @@ class XciProcess { public: XciProcess(); - ~XciProcess(); void process(); // generic - void setInputFile(fnd::IFile* file, bool ownIFile); + void setInputFile(const fnd::SharedPtr& file); void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -31,8 +31,7 @@ private: const std::string kModuleName = "XciProcess"; const std::string kXciMountPointName = "gamecard:/"; - fnd::IFile* mFile; - bool mOwnIFile; + fnd::SharedPtr mFile; KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/common.h b/programs/nstool/source/common.h index 883ee44..555e040 100644 --- a/programs/nstool/source/common.h +++ b/programs/nstool/source/common.h @@ -8,12 +8,6 @@ static const size_t kMasterKeyNum = 0x20; static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; -enum IFileOwnershipMode -{ - SHARED_IFILE = false, - OWN_IFILE = true -}; - enum FileType { FILE_XCI, diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 9659241..0e087c0 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "UserSettings.h" #include "XciProcess.h" @@ -35,11 +36,13 @@ int main(int argc, char** argv) try { user_set.parseCmdArgs(args); + fnd::SharedPtr inputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read)); + if (user_set.getFileType() == FILE_XCI) { XciProcess xci; - xci.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + xci.setInputFile(inputFile); xci.setKeyCfg(user_set.getKeyCfg()); xci.setCliOutputMode(user_set.getCliOutputMode()); @@ -61,7 +64,7 @@ int main(int argc, char** argv) { PfsProcess pfs; - pfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + pfs.setInputFile(inputFile); pfs.setCliOutputMode(user_set.getCliOutputMode()); pfs.setVerifyMode(user_set.isVerifyFile()); @@ -75,7 +78,7 @@ int main(int argc, char** argv) { RomfsProcess romfs; - romfs.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + romfs.setInputFile(inputFile); romfs.setCliOutputMode(user_set.getCliOutputMode()); romfs.setVerifyMode(user_set.isVerifyFile()); @@ -89,7 +92,7 @@ int main(int argc, char** argv) { NcaProcess nca; - nca.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + nca.setInputFile(inputFile); nca.setKeyCfg(user_set.getKeyCfg()); nca.setCliOutputMode(user_set.getCliOutputMode()); nca.setVerifyMode(user_set.isVerifyFile()); @@ -111,7 +114,7 @@ int main(int argc, char** argv) { NpdmProcess npdm; - npdm.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + npdm.setInputFile(inputFile); npdm.setKeyCfg(user_set.getKeyCfg()); npdm.setCliOutputMode(user_set.getCliOutputMode()); npdm.setVerifyMode(user_set.isVerifyFile()); @@ -122,7 +125,7 @@ int main(int argc, char** argv) { CnmtProcess cnmt; - cnmt.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + cnmt.setInputFile(inputFile); cnmt.setCliOutputMode(user_set.getCliOutputMode()); cnmt.setVerifyMode(user_set.isVerifyFile()); @@ -132,7 +135,7 @@ int main(int argc, char** argv) { NsoProcess obj; - obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + obj.setInputFile(inputFile); obj.setCliOutputMode(user_set.getCliOutputMode()); obj.setVerifyMode(user_set.isVerifyFile()); @@ -146,7 +149,7 @@ int main(int argc, char** argv) { NroProcess obj; - obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + obj.setInputFile(inputFile); obj.setCliOutputMode(user_set.getCliOutputMode()); obj.setVerifyMode(user_set.isVerifyFile()); @@ -169,7 +172,7 @@ int main(int argc, char** argv) { NacpProcess nacp; - nacp.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + nacp.setInputFile(inputFile); nacp.setCliOutputMode(user_set.getCliOutputMode()); nacp.setVerifyMode(user_set.isVerifyFile()); @@ -179,7 +182,7 @@ int main(int argc, char** argv) { PkiCertProcess cert; - cert.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + cert.setInputFile(inputFile); cert.setKeyCfg(user_set.getKeyCfg()); cert.setCliOutputMode(user_set.getCliOutputMode()); cert.setVerifyMode(user_set.isVerifyFile()); @@ -190,7 +193,7 @@ int main(int argc, char** argv) { EsTikProcess tik; - tik.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + tik.setInputFile(inputFile); tik.setKeyCfg(user_set.getKeyCfg()); tik.setCertificateChain(user_set.getCertificateChain()); tik.setCliOutputMode(user_set.getCliOutputMode()); @@ -202,7 +205,7 @@ int main(int argc, char** argv) { AssetProcess obj; - obj.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); + obj.setInputFile(inputFile); obj.setCliOutputMode(user_set.getCliOutputMode()); obj.setVerifyMode(user_set.isVerifyFile()); diff --git a/programs/nstool/source/version.h b/programs/nstool/source/version.h index 184fe13..4773fb4 100644 --- a/programs/nstool/source/version.h +++ b/programs/nstool/source/version.h @@ -3,5 +3,5 @@ #define BIN_NAME "nstool" #define VER_MAJOR 1 #define VER_MINOR 0 -#define VER_PATCH 3 +#define VER_PATCH 5 #define AUTHORS "jakcron" \ No newline at end of file