mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
Start moving towards a more generatlised hash tree system.
This commit is contained in:
parent
f2021d851a
commit
aa1ed007eb
12 changed files with 206 additions and 71 deletions
49
lib/libnx/include/nx/HierarchicalIntergrityHeader.h
Normal file
49
lib/libnx/include/nx/HierarchicalIntergrityHeader.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <nx/hierarchicalintergrity.h>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
#include <fnd/List.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
class HierarchicalIntergrityHeader :
|
||||
public fnd::ISerialiseableBinary
|
||||
{
|
||||
public:
|
||||
|
||||
HierarchicalIntergrityHeader();
|
||||
HierarchicalIntergrityHeader(const HierarchicalIntergrityHeader& other);
|
||||
HierarchicalIntergrityHeader(const byte_t* bytes, size_t len);
|
||||
|
||||
bool operator==(const HierarchicalIntergrityHeader& other) const;
|
||||
bool operator!=(const HierarchicalIntergrityHeader& other) const;
|
||||
void operator=(const HierarchicalIntergrityHeader& other);
|
||||
|
||||
// to be used after export
|
||||
const byte_t* getBytes() const;
|
||||
size_t getSize() const;
|
||||
|
||||
// export/import binary
|
||||
void exportBinary();
|
||||
void importBinary(const byte_t* bytes, size_t len);
|
||||
|
||||
// variables
|
||||
void clear();
|
||||
|
||||
|
||||
private:
|
||||
const std::string kModuleName = "HIERARCHICAL_INTERGRITY_HEADER";
|
||||
|
||||
// binary
|
||||
fnd::MemoryBlob mBinaryBlob;
|
||||
|
||||
// data
|
||||
|
||||
|
||||
uint64_t blockNumToSize(uint32_t block_num) const;
|
||||
uint32_t sizeToBlockNum(uint64_t real_size) const;
|
||||
bool isEqual(const HierarchicalIntergrityHeader& other) const;
|
||||
void copyFrom(const HierarchicalIntergrityHeader& other);
|
||||
};
|
||||
|
||||
}
|
49
lib/libnx/include/nx/HierarchicalSha256Header.h
Normal file
49
lib/libnx/include/nx/HierarchicalSha256Header.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <nx/hierarchicalsha256.h>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
#include <fnd/List.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
class HierarchicalSha256Header :
|
||||
public fnd::ISerialiseableBinary
|
||||
{
|
||||
public:
|
||||
|
||||
HierarchicalSha256Header();
|
||||
HierarchicalSha256Header(const HierarchicalSha256Header& other);
|
||||
HierarchicalSha256Header(const byte_t* bytes, size_t len);
|
||||
|
||||
bool operator==(const HierarchicalSha256Header& other) const;
|
||||
bool operator!=(const HierarchicalSha256Header& other) const;
|
||||
void operator=(const HierarchicalSha256Header& other);
|
||||
|
||||
// to be used after export
|
||||
const byte_t* getBytes() const;
|
||||
size_t getSize() const;
|
||||
|
||||
// export/import binary
|
||||
void exportBinary();
|
||||
void importBinary(const byte_t* bytes, size_t len);
|
||||
|
||||
// variables
|
||||
void clear();
|
||||
|
||||
|
||||
private:
|
||||
const std::string kModuleName = "HIERARCHICAL_SHA256_HEADER";
|
||||
|
||||
// binary
|
||||
fnd::MemoryBlob mBinaryBlob;
|
||||
|
||||
// data
|
||||
|
||||
|
||||
uint64_t blockNumToSize(uint32_t block_num) const;
|
||||
uint32_t sizeToBlockNum(uint64_t real_size) const;
|
||||
bool isEqual(const HierarchicalSha256Header& other) const;
|
||||
void copyFrom(const HierarchicalSha256Header& other);
|
||||
};
|
||||
|
||||
}
|
36
lib/libnx/include/nx/hierarchicalintegrity.h
Normal file
36
lib/libnx/include/nx/hierarchicalintegrity.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
// Also known as HierarchicalIntegrity
|
||||
namespace hierarchicalintegrity
|
||||
{
|
||||
const std::string kStructSig = "IVFC";
|
||||
static const size_t kMaxLayerNum = 7;
|
||||
static const uint32_t kTypeId = 0x20000;
|
||||
static const size_t kMaxMasterHashNum = 3;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct sHierarchicalIntegrityHeader
|
||||
{
|
||||
char signature[4];
|
||||
le_uint32_t type_id;
|
||||
le_uint32_t master_hash_size;
|
||||
le_uint32_t layer_num;
|
||||
struct sLayer
|
||||
{
|
||||
le_uint64_t offset;
|
||||
le_uint64_t size;
|
||||
le_uint32_t block_size;
|
||||
byte_t reserved[4];
|
||||
} layer[hierarchicalintegrity::kMaxLayerNum];
|
||||
byte_t reserved_00[0x8];
|
||||
crypto::sha::sSha256Hash master_hash[hierarchicalintegrity::kMaxMasterHashNum];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
|
@ -9,6 +9,8 @@ namespace nx
|
|||
namespace hierarchicalsha256
|
||||
{
|
||||
static const size_t kDefaultLevelNum = 2;
|
||||
|
||||
static const size_t kMaxLayoutNum = 2;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
@ -16,12 +18,12 @@ namespace nx
|
|||
{
|
||||
crypto::sha::sSha256Hash master_hash;
|
||||
le_uint32_t hash_block_size;
|
||||
le_uint32_t hash_level_num;
|
||||
le_uint32_t layer_num;
|
||||
struct sLayout
|
||||
{
|
||||
le_uint64_t offset;
|
||||
le_uint64_t size;
|
||||
} hash_data, hash_target;
|
||||
} layer[hierarchicalsha256::kMaxLayoutNum];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
// Also known as HierarchicalIntegrity
|
||||
namespace ivfc
|
||||
{
|
||||
const std::string kIvfcSig = "IVFC";
|
||||
static const size_t kMaxIvfcLevel = 7;
|
||||
static const uint32_t kIvfcId = 0x20000;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct sIvfcHeader
|
||||
{
|
||||
char signature[4];
|
||||
le_uint32_t id;
|
||||
le_uint32_t master_hash_size;
|
||||
le_uint32_t level_num;
|
||||
struct sIvfcLevelHeader
|
||||
{
|
||||
le_uint64_t logical_offset;
|
||||
le_uint64_t hash_data_size;
|
||||
le_uint32_t block_size;
|
||||
byte_t reserved[4];
|
||||
} level_header[ivfc::kMaxIvfcLevel];
|
||||
byte_t reserved_00[0x8];
|
||||
crypto::sha::sSha256Hash master_hash;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#include <crypto/sha.h>
|
||||
#include <crypto/rsa.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
#include <nx/ivfc.h>
|
||||
#include <nx/hierarchicalintegrity.h>
|
||||
#include <nx/hierarchicalsha256.h>
|
||||
|
||||
namespace nx
|
||||
|
@ -123,7 +123,7 @@ namespace nx
|
|||
union {
|
||||
byte_t hash_superblock[nca::kFsHeaderHashSuperblockLen];
|
||||
nx::sHierarchicalSha256Header hierarchicalsha256_header;
|
||||
nx::sIvfcHeader ivfc_header;
|
||||
nx::sHierarchicalIntegrityHeader hierarchicalintergrity_header;
|
||||
};
|
||||
crypto::aes::sAesIvCtr base_ctr;
|
||||
byte_t reserved_1[0xB8];
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
<ClInclude Include="include\nx\FacHeader.h" />
|
||||
<ClInclude Include="include\nx\HandleTableSizeEntry.h" />
|
||||
<ClInclude Include="include\nx\HandleTableSizeHandler.h" />
|
||||
<ClInclude Include="include\nx\HierarchicalIntergrityHeader.h" />
|
||||
<ClInclude Include="include\nx\hierarchicalsha256.h" />
|
||||
<ClInclude Include="include\nx\HierarchicalSha256Header.h" />
|
||||
<ClInclude Include="include\nx\IKernelCapabilityHandler.h" />
|
||||
<ClInclude Include="include\nx\InteruptEntry.h" />
|
||||
<ClInclude Include="include\nx\InteruptHandler.h" />
|
||||
<ClInclude Include="include\nx\ivfc.h" />
|
||||
<ClInclude Include="include\nx\hierarchicalintegrity.h" />
|
||||
<ClInclude Include="include\nx\KcBinary.h" />
|
||||
<ClInclude Include="include\nx\KernelCapability.h" />
|
||||
<ClInclude Include="include\nx\KernelVersionEntry.h" />
|
||||
|
@ -75,6 +77,8 @@
|
|||
<ClCompile Include="source\FacHeader.cpp" />
|
||||
<ClCompile Include="source\HandleTableSizeEntry.cpp" />
|
||||
<ClCompile Include="source\HandleTableSizeHandler.cpp" />
|
||||
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp" />
|
||||
<ClCompile Include="source\HierarchicalSha256Header.cpp" />
|
||||
<ClCompile Include="source\InteruptEntry.cpp" />
|
||||
<ClCompile Include="source\InteruptHandler.cpp" />
|
||||
<ClCompile Include="source\KcBinary.cpp" />
|
||||
|
|
|
@ -123,9 +123,6 @@
|
|||
<ClInclude Include="include\nx\AesKeygen.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\ivfc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\NcaUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -150,6 +147,15 @@
|
|||
<ClInclude Include="include\nx\cnmt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\hierarchicalintegrity.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\HierarchicalSha256Header.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\HierarchicalIntergrityHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\AciBinary.cpp">
|
||||
|
@ -254,6 +260,12 @@
|
|||
<ClCompile Include="source\ContentMetaBinary.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalSha256Header.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
|
|
0
lib/libnx/source/HierarchicalIntegrityHeader.cpp
Normal file
0
lib/libnx/source/HierarchicalIntegrityHeader.cpp
Normal file
0
lib/libnx/source/HierarchicalSha256Header.cpp
Normal file
0
lib/libnx/source/HierarchicalSha256Header.cpp
Normal file
|
@ -219,20 +219,33 @@ void NcaProcess::generatePartitionConfiguration()
|
|||
// determine the data offset & size
|
||||
if (mPartitions[partition.index].hash_type == nx::nca::HASH_HIERARCHICAL_SHA256)
|
||||
{
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].hierarchicalsha256_header.hash_target.offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].hierarchicalsha256_header.hash_target.size.get();
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].hierarchicalsha256_header.layer[1].offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].hierarchicalsha256_header.layer[1].size.get();
|
||||
}
|
||||
else if (mPartitions[partition.index].hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||
{
|
||||
for (size_t j = 0; j < nx::ivfc::kMaxIvfcLevel; j++)
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].hierarchicalintergrity_header.layer[5].offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].hierarchicalintergrity_header.layer[5].size.get();
|
||||
/*
|
||||
if (mPartitions[partition.index].hierarchicalintergrity_header.layer_num.get() > nx::hierarchicalintegrity::kMaxLayerNum)
|
||||
{
|
||||
if (mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].logical_offset.get() != 0)
|
||||
{
|
||||
mPartitions[partition.index].data_offset = mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].logical_offset.get();
|
||||
mPartitions[partition.index].data_size = mPartitions[partition.index].ivfc_header.level_header[nx::ivfc::kMaxIvfcLevel-1-j].hash_data_size.get();
|
||||
break;
|
||||
}
|
||||
error.clear();
|
||||
error << "NCA FS Header [" << partition.index << "] HierarchicalIntergrity header has an unsupported layer num (" << mPartitions[partition.index].hierarchicalintergrity_header.layer_num.get() << ")\n";
|
||||
throw fnd::Exception(kModuleName, error.str());
|
||||
}
|
||||
const nx::sHierarchicalIntegrityHeader& hdr = mPartitions[partition.index].hierarchicalintergrity_header;
|
||||
|
||||
for (size_t j = 0; j < nx::hierarchicalintegrity::kMaxLayerNum; j++)
|
||||
{
|
||||
size_t index = nx::hierarchicalintegrity::kMaxLayerNum - 1 - j;
|
||||
if (hdr.layer[index].offset.get() != 0)
|
||||
{
|
||||
mPartitions[partition.index].data_offset = hdr.layer[index].offset.get();
|
||||
mPartitions[partition.index].data_size = hdr.layer[index].size.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (mPartitions[partition.index].hash_type == nx::nca::HASH_NONE)
|
||||
{
|
||||
|
@ -389,19 +402,24 @@ void NcaProcess::displayHeader()
|
|||
}
|
||||
if (fs_header.hash_type == nx::nca::HASH_HIERARCHICAL_INTERGRITY)
|
||||
{
|
||||
nx::sHierarchicalIntegrityHeader& hash_hdr = fs_header.hierarchicalintergrity_header;
|
||||
printf(" HierarchicalIntegrity Header:\n");
|
||||
printf(" Id: 0x%x\n", fs_header.ivfc_header.id.get());
|
||||
printf(" MasterHashSize: 0x%x\n", fs_header.ivfc_header.master_hash_size.get());
|
||||
printf(" LevelNum: %d\n", fs_header.ivfc_header.level_num.get());
|
||||
for (size_t i = 0; i < fs_header.ivfc_header.level_num.get(); i++)
|
||||
printf(" TypeId: 0x%x\n", hash_hdr.type_id.get());
|
||||
printf(" MasterHashSize: 0x%x\n", hash_hdr.master_hash_size.get());
|
||||
printf(" LayerNum: %d\n", hash_hdr.layer_num.get());
|
||||
for (size_t i = 0; i < hash_hdr.layer_num.get(); i++)
|
||||
{
|
||||
printf(" Level %d:\n", i);
|
||||
printf(" LogicalOffset: 0x%" PRIx64 "\n", fs_header.ivfc_header.level_header[i].logical_offset.get());
|
||||
printf(" HashDataSize: 0x%" PRIx64 "\n", fs_header.ivfc_header.level_header[i].hash_data_size.get());
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", fs_header.ivfc_header.level_header[i].block_size.get());
|
||||
printf(" Layer %d:\n", i);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", hash_hdr.layer[i].offset.get());
|
||||
printf(" Size: 0x%" PRIx64 "\n", hash_hdr.layer[i].size.get());
|
||||
printf(" BlockSize: 0x%" PRIx32 "\n", hash_hdr.layer[i].block_size.get());
|
||||
}
|
||||
printf(" Master Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(fs_header.ivfc_header.master_hash.bytes, 0x20);
|
||||
for (size_t j = 0; j < hash_hdr.master_hash_size.get() / sizeof(crypto::sha::sSha256Hash); j++)
|
||||
{
|
||||
printf(" Master Hash %d: ", j);
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.master_hash[j].bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -410,14 +428,15 @@ void NcaProcess::displayHeader()
|
|||
nx::sHierarchicalSha256Header& hash_hdr = fs_header.hierarchicalsha256_header;
|
||||
printf(" HierarchicalSha256 Header:\n");
|
||||
printf(" Master Hash: ");
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.master_hash.bytes, 0x20);
|
||||
fnd::SimpleTextOutput::hexDump(hash_hdr.master_hash.bytes, sizeof(crypto::sha::sSha256Hash));
|
||||
printf(" HashBlockSize: 0x%x\n", hash_hdr.hash_block_size.get());
|
||||
printf(" HashLevelNum: 0x%x\n", hash_hdr.hash_level_num.get());
|
||||
printf(" HashDataOffset: 0x%" PRIx64 "\n", hash_hdr.hash_data.offset.get());
|
||||
printf(" HashDataSize: 0x%" PRIx64 "\n", hash_hdr.hash_data.size.get());
|
||||
printf(" HashTargetOffset: 0x%" PRIx64 "\n", hash_hdr.hash_target.offset.get());
|
||||
printf(" HashTargetSize: 0x%" PRIx64 "\n", hash_hdr.hash_target.size.get());
|
||||
|
||||
printf(" LayerNum: %d\n", hash_hdr.layer_num.get());
|
||||
for (size_t i = 0; i < hash_hdr.layer_num.get(); i++)
|
||||
{
|
||||
printf(" Layer %d:\n", i);
|
||||
printf(" Offset: 0x%" PRIx64 "\n", hash_hdr.layer[i].offset.get());
|
||||
printf(" Size: 0x%" PRIx64 "\n", hash_hdr.layer[i].size.get());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
union {
|
||||
byte_t hash_superblock[nx::nca::kFsHeaderHashSuperblockLen];
|
||||
nx::sHierarchicalSha256Header hierarchicalsha256_header;
|
||||
nx::sIvfcHeader ivfc_header;
|
||||
nx::sHierarchicalIntegrityHeader hierarchicalintergrity_header;
|
||||
};
|
||||
} mPartitions[nx::nca::kPartitionNum];
|
||||
|
||||
|
|
Loading…
Reference in a new issue