Merge pull request #51 from jakcron/fnd-ifile-wrappers

Move fnd::IFile wrappers in NSTool to libfnd
This commit is contained in:
Jack 2018-10-06 16:48:57 +08:00 committed by GitHub
commit d63eff128f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 497 additions and 528 deletions

View file

@ -0,0 +1,32 @@
#pragma once
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
#include <fnd/Vec.h>
#include <fnd/aes.h>
namespace fnd
{
class AesCtrWrappedIFile : public fnd::IFile
{
public:
AesCtrWrappedIFile(const fnd::SharedPtr<fnd::IFile>& 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<fnd::IFile> mFile;
fnd::aes::sAes128Key mKey;
fnd::aes::sAesIvCtr mBaseCtr, mCurrentCtr;
size_t mFileOffset;
fnd::Vec<byte_t> mCache;
};
}

View file

@ -0,0 +1,59 @@
#pragma once
#include <fnd/types.h>
#include <fnd/List.h>
#include <fnd/sha.h>
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<sLayer>& getHashLayerInfo() const;
void setHashLayerInfo(const fnd::List<sLayer>& layer_info);
const sLayer& getDataLayer() const;
void setDataLayerInfo(const sLayer& data_info);
const fnd::List<fnd::sha::sSha256Hash>& getMasterHashList() const;
void setMasterHashList(const fnd::List<fnd::sha::sSha256Hash>& master_hash_list);
bool getAlignHashToBlock() const;
void setAlignHashToBlock(bool doAlign);
private:
// data
fnd::List<sLayer> mLayerInfo;
sLayer mDataLayer;
fnd::List<fnd::sha::sSha256Hash> mMasterHashList;
bool mDoAlignHashToBlock;
};
}

View file

@ -0,0 +1,47 @@
#pragma once
#include <sstream>
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
#include <fnd/Vec.h>
#include <fnd/List.h>
#include <fnd/LayeredIntegrityMetadata.h>
namespace fnd
{
class LayeredIntegrityWrappedIFile : public fnd::IFile
{
public:
LayeredIntegrityWrappedIFile(const fnd::SharedPtr<fnd::IFile>& 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<fnd::IFile> mFile;
// data file
fnd::SharedPtr<fnd::IFile> mData;
size_t mDataOffset;
size_t mDataBlockSize;
fnd::List<fnd::sha::sSha256Hash> mDataHashLayer;
bool mAlignHashCalcToBlock;
fnd::Vec<byte_t> 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);
};
}

View file

@ -0,0 +1,23 @@
#pragma once
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
namespace fnd
{
class OffsetAdjustedIFile : public fnd::IFile
{
public:
OffsetAdjustedIFile(const fnd::SharedPtr<fnd::IFile>& 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<fnd::IFile> mFile;
size_t mBaseOffset, mCurrentOffset;
size_t mSize;
};
}

View file

@ -122,6 +122,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="include\fnd\aes.h" /> <ClInclude Include="include\fnd\aes.h" />
<ClInclude Include="include\fnd\AesCtrWrappedIFile.h" />
<ClInclude Include="include\fnd\base64.h" /> <ClInclude Include="include\fnd\base64.h" />
<ClInclude Include="include\fnd\BitMath.h" /> <ClInclude Include="include\fnd\BitMath.h" />
<ClInclude Include="include\fnd\ecdsa.h" /> <ClInclude Include="include\fnd\ecdsa.h" />
@ -131,8 +132,11 @@
<ClInclude Include="include\fnd\IFile.h" /> <ClInclude Include="include\fnd\IFile.h" />
<ClInclude Include="include\fnd\io.h" /> <ClInclude Include="include\fnd\io.h" />
<ClInclude Include="include\fnd\ISerialisable.h" /> <ClInclude Include="include\fnd\ISerialisable.h" />
<ClInclude Include="include\fnd\LayeredIntegrityMetadata.h" />
<ClInclude Include="include\fnd\LayeredIntegrityWrappedIFile.h" />
<ClInclude Include="include\fnd\List.h" /> <ClInclude Include="include\fnd\List.h" />
<ClInclude Include="include\fnd\lz4.h" /> <ClInclude Include="include\fnd\lz4.h" />
<ClInclude Include="include\fnd\OffsetAdjustedIFile.h" />
<ClInclude Include="include\fnd\ResourceFileReader.h" /> <ClInclude Include="include\fnd\ResourceFileReader.h" />
<ClInclude Include="include\fnd\rsa.h" /> <ClInclude Include="include\fnd\rsa.h" />
<ClInclude Include="include\fnd\sha.h" /> <ClInclude Include="include\fnd\sha.h" />
@ -144,11 +148,15 @@
<ClInclude Include="include\fnd\Vec.h" /> <ClInclude Include="include\fnd\Vec.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="source\AesCtrWrappedIFile.cpp" />
<ClCompile Include="source\aes_wrapper.cpp" /> <ClCompile Include="source\aes_wrapper.cpp" />
<ClCompile Include="source\base64_wrapper.cpp" /> <ClCompile Include="source\base64_wrapper.cpp" />
<ClCompile Include="source\Exception.cpp" /> <ClCompile Include="source\Exception.cpp" />
<ClCompile Include="source\io.cpp" /> <ClCompile Include="source\io.cpp" />
<ClCompile Include="source\LayeredIntegrityMetadata.cpp" />
<ClCompile Include="source\LayeredIntegrityWrappedIFile.cpp" />
<ClCompile Include="source\lz4_wrapper.cpp" /> <ClCompile Include="source\lz4_wrapper.cpp" />
<ClCompile Include="source\OffsetAdjustedIFile.cpp" />
<ClCompile Include="source\ResourceFileReader.cpp" /> <ClCompile Include="source\ResourceFileReader.cpp" />
<ClCompile Include="source\rsa_wrapper.cpp" /> <ClCompile Include="source\rsa_wrapper.cpp" />
<ClCompile Include="source\sha_wrapper.cpp" /> <ClCompile Include="source\sha_wrapper.cpp" />

View file

@ -21,6 +21,9 @@
<ClInclude Include="include\fnd\aes.h"> <ClInclude Include="include\fnd\aes.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\fnd\AesCtrWrappedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fnd\base64.h"> <ClInclude Include="include\fnd\base64.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -48,12 +51,21 @@
<ClInclude Include="include\fnd\ISerialisable.h"> <ClInclude Include="include\fnd\ISerialisable.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\fnd\LayeredIntegrityMetadata.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fnd\LayeredIntegrityWrappedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fnd\List.h"> <ClInclude Include="include\fnd\List.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\fnd\lz4.h"> <ClInclude Include="include\fnd\lz4.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\fnd\OffsetAdjustedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fnd\ResourceFileReader.h"> <ClInclude Include="include\fnd\ResourceFileReader.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -86,6 +98,9 @@
<ClCompile Include="source\aes_wrapper.cpp"> <ClCompile Include="source\aes_wrapper.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\AesCtrWrappedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\base64_wrapper.cpp"> <ClCompile Include="source\base64_wrapper.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -95,9 +110,18 @@
<ClCompile Include="source\io.cpp"> <ClCompile Include="source\io.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\LayeredIntegrityMetadata.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\LayeredIntegrityWrappedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\lz4_wrapper.cpp"> <ClCompile Include="source\lz4_wrapper.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\OffsetAdjustedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\ResourceFileReader.cpp"> <ClCompile Include="source\ResourceFileReader.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View file

@ -0,0 +1,80 @@
#include <fnd/AesCtrWrappedIFile.h>
fnd::AesCtrWrappedIFile::AesCtrWrappedIFile(const fnd::SharedPtr<fnd::IFile>& 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);
}

View file

@ -0,0 +1,71 @@
#include <fnd/LayeredIntegrityMetadata.h>
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::sLayer>& fnd::LayeredIntegrityMetadata::getHashLayerInfo() const
{
return mLayerInfo;
}
void fnd::LayeredIntegrityMetadata::setHashLayerInfo(const fnd::List<sLayer>& 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::sha::sSha256Hash>& fnd::LayeredIntegrityMetadata::getMasterHashList() const
{
return mMasterHashList;
}
void fnd::LayeredIntegrityMetadata::setMasterHashList(const fnd::List<fnd::sha::sSha256Hash>& master_hash_list)
{
mMasterHashList = master_hash_list;
}
bool fnd::LayeredIntegrityMetadata::getAlignHashToBlock() const
{
return mDoAlignHashToBlock;
}
void fnd::LayeredIntegrityMetadata::setAlignHashToBlock(bool doAlign)
{
mDoAlignHashToBlock = doAlign;
}

View file

@ -1,8 +1,7 @@
#include "common.h" #include <fnd/LayeredIntegrityWrappedIFile.h>
#include "HashTreeWrappedIFile.h" #include <fnd/OffsetAdjustedIFile.h>
#include "OffsetAdjustedIFile.h"
HashTreeWrappedIFile::HashTreeWrappedIFile(const fnd::SharedPtr<fnd::IFile>& file, const HashTreeMeta& hdr) : fnd::LayeredIntegrityWrappedIFile::LayeredIntegrityWrappedIFile(const fnd::SharedPtr<fnd::IFile>& file, const fnd::LayeredIntegrityMetadata& hdr) :
mFile(file), mFile(file),
mData(nullptr), mData(nullptr),
mDataHashLayer(), mDataHashLayer(),
@ -11,17 +10,17 @@ HashTreeWrappedIFile::HashTreeWrappedIFile(const fnd::SharedPtr<fnd::IFile>& fil
initialiseDataLayer(hdr); initialiseDataLayer(hdr);
} }
size_t HashTreeWrappedIFile::size() size_t fnd::LayeredIntegrityWrappedIFile::size()
{ {
return (*mData)->size(); return (*mData)->size();
} }
void HashTreeWrappedIFile::seek(size_t offset) void fnd::LayeredIntegrityWrappedIFile::seek(size_t offset)
{ {
mDataOffset = offset; mDataOffset = offset;
} }
void HashTreeWrappedIFile::read(byte_t* out, size_t len) void fnd::LayeredIntegrityWrappedIFile::read(byte_t* out, size_t len)
{ {
struct sBlockPosition struct sBlockPosition
{ {
@ -72,23 +71,23 @@ void HashTreeWrappedIFile::read(byte_t* out, size_t len)
seek(mDataOffset + len); 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); seek(offset);
read(out, len); 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"); 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"); 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::sha::sSha256Hash hash;
fnd::Vec<byte_t> cur, prev; fnd::Vec<byte_t> cur, prev;
@ -106,7 +105,7 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr)
for (size_t i = 0; i < hdr.getHashLayerInfo().size(); i++) for (size_t i = 0; i < hdr.getHashLayerInfo().size(); i++)
{ {
// get block size // get block size
const HashTreeMeta::sLayer& layer = hdr.getHashLayerInfo()[i]; const fnd::LayeredIntegrityMetadata::sLayer& layer = hdr.getHashLayerInfo()[i];
// allocate layer // allocate layer
cur.alloc(align(layer.size, layer.block_size)); cur.alloc(align(layer.size, layer.block_size));
@ -139,20 +138,17 @@ void HashTreeWrappedIFile::initialiseDataLayer(const HashTreeMeta& hdr)
} }
// generate reader for data layer // generate reader for data layer
mData = new OffsetAdjustedIFile(mFile, hdr.getDataLayer().offset, hdr.getDataLayer().size); mData = new fnd::OffsetAdjustedIFile(mFile, hdr.getDataLayer().offset, hdr.getDataLayer().size);
mDataOffset = 0; mDataOffset = 0;
mDataBlockSize = hdr.getDataLayer().block_size; mDataBlockSize = hdr.getDataLayer().block_size;
// allocate scratchpad // allocate cache
//mScratch.alloc(mDataBlockSize * 0x10);
size_t cache_size = align(kDefaultCacheSize, mDataBlockSize); size_t cache_size = align(kDefaultCacheSize, mDataBlockSize);
mCacheBlockNum = cache_size / 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); 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)
{ {
fnd::sha::sSha256Hash hash; fnd::sha::sSha256Hash hash;
@ -180,8 +176,6 @@ void HashTreeWrappedIFile::readData(size_t block_offset, size_t block_num)
throw fnd::Exception(kModuleName, "Read excessive of cache size"); throw fnd::Exception(kModuleName, "Read excessive of cache size");
} }
//printf("readlen=0x%" PRIx64 "\n", read_len);
// validate blocks // validate blocks
size_t validate_size; size_t validate_size;
for (size_t i = 0; i < block_num; i++) for (size_t i = 0; i < block_num; i++)

View file

@ -0,0 +1,47 @@
#include <fnd/OffsetAdjustedIFile.h>
fnd::OffsetAdjustedIFile::OffsetAdjustedIFile(const fnd::SharedPtr<fnd::IFile>& 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);
}

View file

@ -178,21 +178,17 @@
<None Include="README.md" /> <None Include="README.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="source\AesCtrWrappedIFile.h" />
<ClInclude Include="source\AssetProcess.h" /> <ClInclude Include="source\AssetProcess.h" />
<ClInclude Include="source\CnmtProcess.h" /> <ClInclude Include="source\CnmtProcess.h" />
<ClInclude Include="source\common.h" /> <ClInclude Include="source\common.h" />
<ClInclude Include="source\ElfSymbolParser.h" /> <ClInclude Include="source\ElfSymbolParser.h" />
<ClInclude Include="source\EsTikProcess.h" /> <ClInclude Include="source\EsTikProcess.h" />
<ClInclude Include="source\HashTreeMeta.h" />
<ClInclude Include="source\HashTreeWrappedIFile.h" />
<ClInclude Include="source\KeyConfiguration.h" /> <ClInclude Include="source\KeyConfiguration.h" />
<ClInclude Include="source\NacpProcess.h" /> <ClInclude Include="source\NacpProcess.h" />
<ClInclude Include="source\NcaProcess.h" /> <ClInclude Include="source\NcaProcess.h" />
<ClInclude Include="source\NpdmProcess.h" /> <ClInclude Include="source\NpdmProcess.h" />
<ClInclude Include="source\NroProcess.h" /> <ClInclude Include="source\NroProcess.h" />
<ClInclude Include="source\NsoProcess.h" /> <ClInclude Include="source\NsoProcess.h" />
<ClInclude Include="source\OffsetAdjustedIFile.h" />
<ClInclude Include="source\PfsProcess.h" /> <ClInclude Include="source\PfsProcess.h" />
<ClInclude Include="source\PkiCertProcess.h" /> <ClInclude Include="source\PkiCertProcess.h" />
<ClInclude Include="source\PkiValidator.h" /> <ClInclude Include="source\PkiValidator.h" />
@ -204,13 +200,10 @@
<ClInclude Include="source\XciProcess.h" /> <ClInclude Include="source\XciProcess.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="source\AesCtrWrappedIFile.cpp" />
<ClCompile Include="source\AssetProcess.cpp" /> <ClCompile Include="source\AssetProcess.cpp" />
<ClCompile Include="source\CnmtProcess.cpp" /> <ClCompile Include="source\CnmtProcess.cpp" />
<ClCompile Include="source\ElfSymbolParser.cpp" /> <ClCompile Include="source\ElfSymbolParser.cpp" />
<ClCompile Include="source\EsTikProcess.cpp" /> <ClCompile Include="source\EsTikProcess.cpp" />
<ClCompile Include="source\HashTreeMeta.cpp" />
<ClCompile Include="source\HashTreeWrappedIFile.cpp" />
<ClCompile Include="source\KeyConfiguration.cpp" /> <ClCompile Include="source\KeyConfiguration.cpp" />
<ClCompile Include="source\main.cpp" /> <ClCompile Include="source\main.cpp" />
<ClCompile Include="source\NacpProcess.cpp" /> <ClCompile Include="source\NacpProcess.cpp" />
@ -218,7 +211,6 @@
<ClCompile Include="source\NpdmProcess.cpp" /> <ClCompile Include="source\NpdmProcess.cpp" />
<ClCompile Include="source\NroProcess.cpp" /> <ClCompile Include="source\NroProcess.cpp" />
<ClCompile Include="source\NsoProcess.cpp" /> <ClCompile Include="source\NsoProcess.cpp" />
<ClCompile Include="source\OffsetAdjustedIFile.cpp" />
<ClCompile Include="source\PfsProcess.cpp" /> <ClCompile Include="source\PfsProcess.cpp" />
<ClCompile Include="source\PkiCertProcess.cpp" /> <ClCompile Include="source\PkiCertProcess.cpp" />
<ClCompile Include="source\PkiValidator.cpp" /> <ClCompile Include="source\PkiValidator.cpp" />

View file

@ -19,27 +19,21 @@
<None Include="README.md" /> <None Include="README.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="source\AesCtrWrappedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\AssetProcess.h"> <ClInclude Include="source\AssetProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\CnmtProcess.h"> <ClInclude Include="source\CnmtProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\ElfSymbolParser.h"> <ClInclude Include="source\ElfSymbolParser.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\EsTikProcess.h"> <ClInclude Include="source\EsTikProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\HashTreeMeta.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\HashTreeWrappedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\KeyConfiguration.h"> <ClInclude Include="source\KeyConfiguration.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -58,9 +52,6 @@
<ClInclude Include="source\NsoProcess.h"> <ClInclude Include="source\NsoProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\OffsetAdjustedIFile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\PfsProcess.h"> <ClInclude Include="source\PfsProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -88,14 +79,8 @@
<ClInclude Include="source\XciProcess.h"> <ClInclude Include="source\XciProcess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="source\common.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="source\AesCtrWrappedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\AssetProcess.cpp"> <ClCompile Include="source\AssetProcess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -108,12 +93,6 @@
<ClCompile Include="source\EsTikProcess.cpp"> <ClCompile Include="source\EsTikProcess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\HashTreeMeta.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\HashTreeWrappedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\KeyConfiguration.cpp"> <ClCompile Include="source\KeyConfiguration.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -135,9 +114,6 @@
<ClCompile Include="source\NsoProcess.cpp"> <ClCompile Include="source\NsoProcess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="source\OffsetAdjustedIFile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\PfsProcess.cpp"> <ClCompile Include="source\PfsProcess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View file

@ -1,105 +0,0 @@
#include "AesCtrWrappedIFile.h"
AesCtrWrappedIFile::AesCtrWrappedIFile(const fnd::SharedPtr<fnd::IFile>& file, const fnd::aes::sAes128Key& key, const fnd::aes::sAesIvCtr& ctr) :
mFile(file),
mKey(key),
mBaseCtr(ctr),
mFileOffset(0)
{
mCache.alloc(kCacheSizeAllocSize);
}
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);
}

View file

@ -1,28 +0,0 @@
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
#include <fnd/Vec.h>
#include <fnd/aes.h>
class AesCtrWrappedIFile : public fnd::IFile
{
public:
AesCtrWrappedIFile(const fnd::SharedPtr<fnd::IFile>& 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<fnd::IFile> mFile;
fnd::aes::sAes128Key mKey;
fnd::aes::sAesIvCtr mBaseCtr, mCurrentCtr;
size_t mFileOffset;
fnd::Vec<byte_t> mCache;
};

View file

@ -1,9 +1,9 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleFile.h> #include <fnd/SimpleFile.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <fnd/Vec.h> #include <fnd/Vec.h>
#include "AssetProcess.h" #include "AssetProcess.h"
#include "OffsetAdjustedIFile.h"
AssetProcess::AssetProcess() : AssetProcess::AssetProcess() :
@ -109,7 +109,7 @@ void AssetProcess::processSections()
outfile.close(); outfile.close();
} }
mNacp.setInputFile(new OffsetAdjustedIFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size)); mNacp.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size));
mNacp.setCliOutputMode(mCliOutputMode); mNacp.setCliOutputMode(mCliOutputMode);
mNacp.setVerifyMode(mVerify); mNacp.setVerifyMode(mVerify);
@ -121,7 +121,7 @@ void AssetProcess::processSections()
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"); throw fnd::Exception(kModuleName, "ASET geometry for romfs beyond file size");
mRomfs.setInputFile(new OffsetAdjustedIFile(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size)); mRomfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size));
mRomfs.setCliOutputMode(mCliOutputMode); mRomfs.setCliOutputMode(mCliOutputMode);
mRomfs.setVerifyMode(mVerify); mRomfs.setVerifyMode(mVerify);

View file

@ -1,7 +1,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include "OffsetAdjustedIFile.h" #include <fnd/OffsetAdjustedIFile.h>
#include "CnmtProcess.h" #include "CnmtProcess.h"
CnmtProcess::CnmtProcess() : CnmtProcess::CnmtProcess() :

View file

@ -1,8 +1,8 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <nn/pki/SignUtils.h> #include <nn/pki/SignUtils.h>
#include "OffsetAdjustedIFile.h"
#include "EsTikProcess.h" #include "EsTikProcess.h"
#include "PkiValidator.h" #include "PkiValidator.h"

View file

@ -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::sLayer>& HashTreeMeta::getHashLayerInfo() const
{
return mLayerInfo;
}
void HashTreeMeta::setHashLayerInfo(const fnd::List<sLayer>& 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<fnd::sha::sSha256Hash>& HashTreeMeta::getMasterHashList() const
{
return mMasterHashList;
}
void HashTreeMeta::setMasterHashList(const fnd::List<fnd::sha::sSha256Hash>& 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());
}

View file

@ -1,68 +0,0 @@
#pragma once
#include <nn/hac/HierarchicalIntegrityHeader.h>
#include <nn/hac/HierarchicalSha256Header.h>
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<sLayer>& getHashLayerInfo() const;
void setHashLayerInfo(const fnd::List<sLayer>& layer_info);
const sLayer& getDataLayer() const;
void setDataLayer(const sLayer& data_info);
const fnd::List<fnd::sha::sSha256Hash>& getMasterHashList() const;
void setMasterHashList(const fnd::List<fnd::sha::sSha256Hash>& master_hash_list);
bool getAlignHashToBlock() const;
void setAlignHashToBlock(bool doAlign);
private:
// data
fnd::List<sLayer> mLayerInfo;
sLayer mDataLayer;
fnd::List<fnd::sha::sSha256Hash> mMasterHashList;
bool mDoAlignHashToBlock;
void importHierarchicalIntergityHeader(const nn::hac::HierarchicalIntegrityHeader& hdr);
void importHierarchicalSha256Header(const nn::hac::HierarchicalSha256Header& hdr);
};

View file

@ -1,45 +0,0 @@
#pragma once
#include <sstream>
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
#include <fnd/Vec.h>
#include <fnd/sha.h>
#include "HashTreeMeta.h"
class HashTreeWrappedIFile : public fnd::IFile
{
public:
HashTreeWrappedIFile(const fnd::SharedPtr<fnd::IFile>& file, const HashTreeMeta& 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 = "HashTreeWrappedIFile";
static const size_t kDefaultCacheSize = 0x10000;
std::stringstream mErrorSs;
fnd::SharedPtr<fnd::IFile> mFile;
// data file
fnd::SharedPtr<fnd::IFile> mData;
size_t mDataOffset;
size_t mDataBlockSize;
fnd::List<fnd::sha::sSha256Hash> mDataHashLayer;
bool mAlignHashCalcToBlock;
fnd::Vec<byte_t> 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);
};

View file

@ -2,7 +2,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include "OffsetAdjustedIFile.h" #include <fnd/OffsetAdjustedIFile.h>
#include "NacpProcess.h" #include "NacpProcess.h"
NacpProcess::NacpProcess() : NacpProcess::NacpProcess() :

View file

@ -2,15 +2,18 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <fnd/AesCtrWrappedIFile.h>
#include <fnd/LayeredIntegrityWrappedIFile.h>
#include <nn/hac/NcaUtils.h> #include <nn/hac/NcaUtils.h>
#include <nn/hac/AesKeygen.h> #include <nn/hac/AesKeygen.h>
#include <nn/hac/HierarchicalSha256Header.h>
#include <nn/hac/HierarchicalIntegrityHeader.h>
#include "NcaProcess.h" #include "NcaProcess.h"
#include "PfsProcess.h" #include "PfsProcess.h"
#include "RomfsProcess.h" #include "RomfsProcess.h"
#include "NpdmProcess.h" #include "NpdmProcess.h"
#include "OffsetAdjustedIFile.h"
#include "AesCtrWrappedIFile.h"
#include "HashTreeWrappedIFile.h"
NcaProcess::NcaProcess() : NcaProcess::NcaProcess() :
mFile(), mFile(),
@ -258,9 +261,69 @@ void NcaProcess::generatePartitionConfiguration()
info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type; info.hash_type = (nn::hac::nca::HashType)fs_header.hash_type;
info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type; info.enc_type = (nn::hac::nca::EncryptionType)fs_header.encryption_type;
if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) 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<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
fnd::LayeredIntegrityMetadata::sLayer data_layer;
fnd::List<fnd::sha::sSha256Hash> 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) 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<fnd::LayeredIntegrityMetadata::sLayer> hash_layers;
fnd::LayeredIntegrityMetadata::sLayer data_layer;
fnd::List<fnd::sha::sSha256Hash> 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 // create reader
try try
@ -280,13 +343,13 @@ void NcaProcess::generatePartitionConfiguration()
// create reader based on encryption type0 // create reader based on encryption type0
if (info.enc_type == nn::hac::nca::CRYPT_NONE) if (info.enc_type == nn::hac::nca::CRYPT_NONE)
{ {
info.reader = new OffsetAdjustedIFile(mFile, info.offset, info.size); info.reader = new fnd::OffsetAdjustedIFile(mFile, info.offset, info.size);
} }
else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR) else if (info.enc_type == nn::hac::nca::CRYPT_AESCTR)
{ {
if (mContentKey.aes_ctr.isSet == false) if (mContentKey.aes_ctr.isSet == false)
throw fnd::Exception(kModuleName, "AES-CTR Key was not determined"); throw fnd::Exception(kModuleName, "AES-CTR Key was not determined");
info.reader = new OffsetAdjustedIFile(new AesCtrWrappedIFile(mFile, mContentKey.aes_ctr.var, info.aes_ctr), 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) else if (info.enc_type == nn::hac::nca::CRYPT_AESXTS || info.enc_type == nn::hac::nca::CRYPT_AESCTREX)
{ {
@ -304,7 +367,7 @@ void NcaProcess::generatePartitionConfiguration()
// filter out unrecognised hash types, and hash based readers // 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) 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 fnd::LayeredIntegrityWrappedIFile(info.reader, info.layered_intergrity_metadata);
} }
else if (info.hash_type != nn::hac::nca::HASH_NONE) else if (info.hash_type != nn::hac::nca::HASH_NONE)
{ {
@ -348,7 +411,7 @@ void NcaProcess::validateNcaSignatures()
const nn::hac::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath); const nn::hac::PfsHeader::sFile& file = exefs.getPfsHeader().getFileList().getElement(kNpdmExefsPath);
NpdmProcess npdm; NpdmProcess npdm;
npdm.setInputFile(new OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size)); npdm.setInputFile(new fnd::OffsetAdjustedIFile(mPartitions[nn::hac::nca::PARTITION_CODE].reader, file.offset, file.size));
npdm.setCliOutputMode(0); npdm.setCliOutputMode(0);
npdm.process(); npdm.process();
@ -440,7 +503,7 @@ void NcaProcess::displayHeader()
} }
if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_INTERGRITY) 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; std::cout << " HierarchicalIntegrity Header:" << std::endl;
for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++) for (size_t j = 0; j < hash_hdr.getHashLayerInfo().size(); j++)
{ {
@ -463,7 +526,7 @@ void NcaProcess::displayHeader()
} }
else if (info.hash_type == nn::hac::nca::HASH_HIERARCHICAL_SHA256) 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 << " HierarchicalSha256 Header:" << std::endl;
std::cout << " Master Hash:" << std::endl; std::cout << " Master Hash:" << std::endl;
std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes, 0x10, true, ":") << std::endl; std::cout << " " << fnd::SimpleTextOutput::arrayToString(hash_hdr.getMasterHashList()[0].bytes, 0x10, true, ":") << std::endl;

View file

@ -3,8 +3,8 @@
#include <fnd/types.h> #include <fnd/types.h>
#include <fnd/IFile.h> #include <fnd/IFile.h>
#include <fnd/SharedPtr.h> #include <fnd/SharedPtr.h>
#include <fnd/LayeredIntegrityMetadata.h>
#include <nn/hac/NcaHeader.h> #include <nn/hac/NcaHeader.h>
#include "HashTreeMeta.h"
#include "KeyConfiguration.h" #include "KeyConfiguration.h"
@ -100,7 +100,7 @@ private:
nn::hac::nca::FormatType format_type; nn::hac::nca::FormatType format_type;
nn::hac::nca::HashType hash_type; nn::hac::nca::HashType hash_type;
nn::hac::nca::EncryptionType enc_type; nn::hac::nca::EncryptionType enc_type;
HashTreeMeta hash_tree_meta; fnd::LayeredIntegrityMetadata layered_intergrity_metadata;
fnd::aes::sAesIvCtr aes_ctr; fnd::aes::sAesIvCtr aes_ctr;
} mPartitions[nn::hac::nca::kPartitionNum]; } mPartitions[nn::hac::nca::kPartitionNum];

View file

@ -1,10 +1,10 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <fnd/Vec.h> #include <fnd/Vec.h>
#include <fnd/lz4.h> #include <fnd/lz4.h>
#include <nn/hac/nro-hb.h> #include <nn/hac/nro-hb.h>
#include "OffsetAdjustedIFile.h"
#include "NroProcess.h" #include "NroProcess.h"
NroProcess::NroProcess(): NroProcess::NroProcess():
@ -107,7 +107,7 @@ void NroProcess::importHeader()
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; mIsHomebrewNro = true;
mAssetProc.setInputFile(new OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize())); mAssetProc.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize()));
mAssetProc.setCliOutputMode(mCliOutputMode); mAssetProc.setCliOutputMode(mCliOutputMode);
mAssetProc.setVerifyMode(mVerify); mAssetProc.setVerifyMode(mVerify);
} }

View file

@ -1,9 +1,9 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <fnd/Vec.h> #include <fnd/Vec.h>
#include <fnd/lz4.h> #include <fnd/lz4.h>
#include "OffsetAdjustedIFile.h"
#include "NsoProcess.h" #include "NsoProcess.h"
NsoProcess::NsoProcess(): NsoProcess::NsoProcess():

View file

@ -1,47 +0,0 @@
#include "OffsetAdjustedIFile.h"
OffsetAdjustedIFile::OffsetAdjustedIFile(const fnd::SharedPtr<fnd::IFile>& file, size_t offset, size_t size) :
mFile(file),
mBaseOffset(offset),
mCurrentOffset(0),
mSize(size)
{
}
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);
}

View file

@ -1,19 +0,0 @@
#include <fnd/IFile.h>
#include <fnd/SharedPtr.h>
class OffsetAdjustedIFile : public fnd::IFile
{
public:
OffsetAdjustedIFile(const fnd::SharedPtr<fnd::IFile>& 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<fnd::IFile> mFile;
size_t mBaseOffset, mCurrentOffset;
size_t mSize;
};

View file

@ -1,8 +1,8 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <nn/pki/SignUtils.h> #include <nn/pki/SignUtils.h>
#include "OffsetAdjustedIFile.h"
#include "PkiCertProcess.h" #include "PkiCertProcess.h"
#include "PkiValidator.h" #include "PkiValidator.h"

View file

@ -1,8 +1,8 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fnd/SimpleTextOutput.h> #include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <nn/hac/XciUtils.h> #include <nn/hac/XciUtils.h>
#include "OffsetAdjustedIFile.h"
#include "XciProcess.h" #include "XciProcess.h"
XciProcess::XciProcess() : XciProcess::XciProcess() :
@ -206,7 +206,7 @@ void XciProcess::processRootPfs()
{ {
std::cout << "[WARNING] XCI Root HFS0: FAIL (bad hash)" << std::endl; std::cout << "[WARNING] XCI Root HFS0: FAIL (bad hash)" << std::endl;
} }
mRootPfs.setInputFile(new OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize())); mRootPfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize()));
mRootPfs.setListFs(mListFs); mRootPfs.setListFs(mListFs);
mRootPfs.setVerifyMode(false); mRootPfs.setVerifyMode(false);
mRootPfs.setCliOutputMode(mCliOutputMode); mRootPfs.setCliOutputMode(mCliOutputMode);
@ -226,7 +226,7 @@ void XciProcess::processPartitionPfs()
} }
PfsProcess tmp; PfsProcess tmp;
tmp.setInputFile(new OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size)); tmp.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].size));
tmp.setListFs(mListFs); tmp.setListFs(mListFs);
tmp.setVerifyMode(mVerify); tmp.setVerifyMode(mVerify);
tmp.setCliOutputMode(mCliOutputMode); tmp.setCliOutputMode(mCliOutputMode);