diff --git a/programs/nstool/nstool.vcxproj b/programs/nstool/nstool.vcxproj index d0605d4..15f0e71 100644 --- a/programs/nstool/nstool.vcxproj +++ b/programs/nstool/nstool.vcxproj @@ -184,9 +184,9 @@ - - + + @@ -209,9 +209,9 @@ - - + + diff --git a/programs/nstool/nstool.vcxproj.filters b/programs/nstool/nstool.vcxproj.filters index 2cf288a..f7b8765 100644 --- a/programs/nstool/nstool.vcxproj.filters +++ b/programs/nstool/nstool.vcxproj.filters @@ -28,21 +28,24 @@ Header Files + + Header Files + Header Files Header Files - - Header Files - - - Header Files - Header Files + + Header Files + + + Header Files + Header Files @@ -88,9 +91,6 @@ Header Files - - Header Files - @@ -108,15 +108,15 @@ Source Files - - Source Files - - - Source Files - Source Files + + Source Files + + + Source Files + Source Files 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/LayeredIntegrityMetadata.cpp b/programs/nstool/source/LayeredIntegrityMetadata.cpp new file mode 100644 index 0000000..296e84e --- /dev/null +++ b/programs/nstool/source/LayeredIntegrityMetadata.cpp @@ -0,0 +1,71 @@ +#include "LayeredIntegrityMetadata.h" + +LayeredIntegrityMetadata::LayeredIntegrityMetadata() : + mLayerInfo(), + mDataLayer(), + mMasterHashList(), + mDoAlignHashToBlock(false) +{ + +} + +void LayeredIntegrityMetadata::operator=(const LayeredIntegrityMetadata& other) +{ + mLayerInfo = other.mLayerInfo; + mDataLayer = other.mDataLayer; + mMasterHashList = other.mMasterHashList; + mDoAlignHashToBlock = other.mDoAlignHashToBlock; +} + +bool LayeredIntegrityMetadata::operator==(const LayeredIntegrityMetadata& other) const +{ + return (mLayerInfo == other.mLayerInfo) \ + && (mDataLayer == other.mDataLayer) \ + && (mMasterHashList == other.mMasterHashList) \ + && (mDoAlignHashToBlock == other.mDoAlignHashToBlock); +} + +bool LayeredIntegrityMetadata::operator!=(const LayeredIntegrityMetadata& other) const +{ + return !(*this == other); +} + +const fnd::List& LayeredIntegrityMetadata::getHashLayerInfo() const +{ + return mLayerInfo; +} + +void LayeredIntegrityMetadata::setHashLayerInfo(const fnd::List& layer_info) +{ + mLayerInfo = layer_info; +} + +const LayeredIntegrityMetadata::sLayer& LayeredIntegrityMetadata::getDataLayer() const +{ + return mDataLayer; +} + +void LayeredIntegrityMetadata::setDataLayerInfo(const sLayer& data_info) +{ + mDataLayer = data_info; +} + +const fnd::List& LayeredIntegrityMetadata::getMasterHashList() const +{ + return mMasterHashList; +} + +void LayeredIntegrityMetadata::setMasterHashList(const fnd::List& master_hash_list) +{ + mMasterHashList = master_hash_list; +} + +bool LayeredIntegrityMetadata::getAlignHashToBlock() const +{ + return mDoAlignHashToBlock; +} + +void LayeredIntegrityMetadata::setAlignHashToBlock(bool doAlign) +{ + mDoAlignHashToBlock = doAlign; +} \ No newline at end of file diff --git a/programs/nstool/source/HashTreeMeta.h b/programs/nstool/source/LayeredIntegrityMetadata.h similarity index 64% rename from programs/nstool/source/HashTreeMeta.h rename to programs/nstool/source/LayeredIntegrityMetadata.h index 1568b5e..dffa39c 100644 --- a/programs/nstool/source/HashTreeMeta.h +++ b/programs/nstool/source/LayeredIntegrityMetadata.h @@ -2,15 +2,9 @@ #include #include -class HashTreeMeta +class LayeredIntegrityMetadata { public: - enum HashTreeType - { - HASH_TYPE_INTEGRITY, - HASH_TYPE_SHA256 - }; - struct sLayer { size_t offset; @@ -35,20 +29,17 @@ public: } }; - HashTreeMeta(); - HashTreeMeta(const byte_t* data, size_t len, HashTreeType type); + LayeredIntegrityMetadata(); - 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); + 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 setDataLayer(const sLayer& data_info); + void setDataLayerInfo(const sLayer& data_info); const fnd::List& getMasterHashList() const; void setMasterHashList(const fnd::List& master_hash_list); @@ -56,13 +47,9 @@ public: 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.cpp b/programs/nstool/source/LayeredIntegrityWrappedIFile.cpp similarity index 86% rename from programs/nstool/source/HashTreeWrappedIFile.cpp rename to programs/nstool/source/LayeredIntegrityWrappedIFile.cpp index 54168de..41b9faa 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.cpp +++ b/programs/nstool/source/LayeredIntegrityWrappedIFile.cpp @@ -1,8 +1,8 @@ #include "common.h" -#include "HashTreeWrappedIFile.h" +#include "LayeredIntegrityWrappedIFile.h" #include "OffsetAdjustedIFile.h" -HashTreeWrappedIFile::HashTreeWrappedIFile(const fnd::SharedPtr& file, const HashTreeMeta& hdr) : +LayeredIntegrityWrappedIFile::LayeredIntegrityWrappedIFile(const fnd::SharedPtr& file, const LayeredIntegrityMetadata& hdr) : mFile(file), mData(nullptr), mDataHashLayer(), @@ -11,17 +11,17 @@ HashTreeWrappedIFile::HashTreeWrappedIFile(const fnd::SharedPtr& fil initialiseDataLayer(hdr); } -size_t HashTreeWrappedIFile::size() +size_t LayeredIntegrityWrappedIFile::size() { return (*mData)->size(); } -void HashTreeWrappedIFile::seek(size_t offset) +void LayeredIntegrityWrappedIFile::seek(size_t offset) { mDataOffset = offset; } -void HashTreeWrappedIFile::read(byte_t* out, size_t len) +void LayeredIntegrityWrappedIFile::read(byte_t* out, size_t len) { struct sBlockPosition { @@ -72,23 +72,23 @@ void HashTreeWrappedIFile::read(byte_t* out, size_t len) seek(mDataOffset + len); } -void HashTreeWrappedIFile::read(byte_t* out, size_t offset, size_t len) +void 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 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 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 LayeredIntegrityWrappedIFile::initialiseDataLayer(const LayeredIntegrityMetadata& hdr) { fnd::sha::sSha256Hash hash; fnd::Vec cur, prev; @@ -106,7 +106,7 @@ 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 LayeredIntegrityMetadata::sLayer& layer = hdr.getHashLayerInfo()[i]; // allocate layer cur.alloc(align(layer.size, layer.block_size)); @@ -152,7 +152,7 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr) mCache.alloc(cache_size); } -void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num) +void LayeredIntegrityWrappedIFile::readData(size_t block_offset, size_t block_num) { fnd::sha::sSha256Hash hash; diff --git a/programs/nstool/source/HashTreeWrappedIFile.h b/programs/nstool/source/LayeredIntegrityWrappedIFile.h similarity index 78% rename from programs/nstool/source/HashTreeWrappedIFile.h rename to programs/nstool/source/LayeredIntegrityWrappedIFile.h index dd3f70c..3aa781b 100644 --- a/programs/nstool/source/HashTreeWrappedIFile.h +++ b/programs/nstool/source/LayeredIntegrityWrappedIFile.h @@ -4,13 +4,13 @@ #include #include #include -#include "HashTreeMeta.h" +#include "LayeredIntegrityMetadata.h" -class HashTreeWrappedIFile : public fnd::IFile +class LayeredIntegrityWrappedIFile : public fnd::IFile { public: - HashTreeWrappedIFile(const fnd::SharedPtr& file, const HashTreeMeta& hdr); + LayeredIntegrityWrappedIFile(const fnd::SharedPtr& file, const LayeredIntegrityMetadata& hdr); size_t size(); void seek(size_t offset); @@ -19,7 +19,7 @@ public: 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"; + const std::string kModuleName = "LayeredIntegrityWrappedIFile"; static const size_t kDefaultCacheSize = 0x10000; std::stringstream mErrorSs; @@ -40,6 +40,6 @@ private: 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 initialiseDataLayer(const LayeredIntegrityMetadata& hdr); void readData(size_t block_offset, size_t block_num); }; \ No newline at end of file diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index aa4f504..676bcc3 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -10,7 +10,7 @@ #include "NpdmProcess.h" #include "OffsetAdjustedIFile.h" #include "AesCtrWrappedIFile.h" -#include "HashTreeWrappedIFile.h" +#include "LayeredIntegrityWrappedIFile.h" NcaProcess::NcaProcess() : mFile(), @@ -258,9 +258,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; + 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++) + { + 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; + 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++) + { + 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 @@ -304,7 +364,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) { - info.reader = new HashTreeWrappedIFile(info.reader, info.hash_tree_meta); + info.reader = new LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata); } else if (info.hash_type != nn::hac::nca::HASH_NONE) { @@ -440,7 +500,7 @@ void NcaProcess::displayHeader() } if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) { - HashTreeMeta& hash_hdr = info.hash_tree_meta; + LayeredIntegrityMetadata& hash_hdr = info.layered_intergrity_metadata; std::cout << " HierarchicalIntegrity Header:" << std::endl; for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) { @@ -463,7 +523,7 @@ void NcaProcess::displayHeader() } else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) { - HashTreeMeta& hash_hdr = info.hash_tree_meta; + 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; diff --git a/programs/nstool/source/NcaProcess.h b/programs/nstool/source/NcaProcess.h index c5b0429..4d98268 100644 --- a/programs/nstool/source/NcaProcess.h +++ b/programs/nstool/source/NcaProcess.h @@ -4,7 +4,7 @@ #include #include #include -#include "HashTreeMeta.h" +#include "LayeredIntegrityMetadata.h" #include "KeyConfiguration.h" @@ -100,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; + LayeredIntegrityMetadata layered_intergrity_metadata; fnd::aes::sAesIvCtr aes_ctr; } mPartitions[nn::hac::nca::kPartitionNum];