[nx] Add ISerialiseableInterface, which AciHeader and NcaHeader inherit from. Also added SacEntry.

This commit is contained in:
jakcron 2017-07-06 13:30:27 +10:00
parent bd8a232160
commit 337a5eff25
9 changed files with 260 additions and 19 deletions

View file

@ -19,20 +19,45 @@ void AciHeader::calculateSectionOffsets()
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
}
AciHeader::AciHeader()
{
clearVariables();
}
AciHeader::AciHeader(const AciHeader & other)
{
importBinary(other.getBytes(), other.getSize());
}
AciHeader::AciHeader(const u8 * bytes)
{
importBinary(bytes);
}
bool AciHeader::operator==(const AciHeader & other)
{
return memcmp(this->getBytes(), other.getBytes(), this->getSize());
}
void AciHeader::operator=(const AciHeader & other)
{
this->importBinary(other.getBytes(), other.getSize());
}
const u8 * AciHeader::getBytes() const
{
return mBinaryBlob.data();
return mBinaryBlob.getBytes();
}
size_t AciHeader::getSize() const
{
return mBinaryBlob.size();
return mBinaryBlob.getSize();
}
void AciHeader::exportBinary()
{
mBinaryBlob.alloc(sizeof(sAciHeader));
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data();
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
// set type
switch (mType)
@ -65,9 +90,9 @@ void AciHeader::importBinary(const u8 * bytes)
clearVariables();
mBinaryBlob.alloc(sizeof(sAciHeader));
memcpy(mBinaryBlob.data(), bytes, sizeof(sAciHeader));
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader));
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data();
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
if (memcmp(hdr->signature(), kAciStructSig.c_str(), 4) == 0)
{
@ -91,6 +116,15 @@ void AciHeader::importBinary(const u8 * bytes)
mKc.size = hdr->kc().size();
}
void AciHeader::importBinary(const u8 * bytes, size_t len)
{
if (len < sizeof(sAciHeader))
{
throw fnd::Exception(kModuleName, "ACI header too small");
}
importBinary(bytes);
}
AciHeader::AciType AciHeader::getAciType() const
{
return mType;

View file

@ -1,9 +1,10 @@
#pragma once
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <string>
#include <nx/ISerialiseableBinary.h>
class AciHeader
class AciHeader : public ISerialiseableBinary
{
public:
enum AciType
@ -18,6 +19,13 @@ public:
size_t size;
};
AciHeader();
AciHeader(const AciHeader& other);
AciHeader(const u8* bytes);
bool operator==(const AciHeader& other);
void operator=(const AciHeader& other);
// to be used after export
const u8* getBytes() const;
size_t getSize() const;
@ -25,6 +33,7 @@ public:
// export/import binary
void exportBinary();
void importBinary(const u8* bytes);
void importBinary(const u8* bytes, size_t len);
// variables
AciType getAciType() const;
@ -56,13 +65,13 @@ private:
{
private:
u32 offset_; // aligned by 0x10 from the last one
u32 size_;
u32 mSize;
public:
u32 offset() const { return le_word(offset_); }
void set_offset(u32 offset) { offset_ = le_word(offset); }
u32 size() const { return le_word(size_); }
void set_size(u32 size) { size_ = le_word(size); }
u32 size() const { return le_word(mSize); }
void set_size(u32 size) { mSize = le_word(size); }
} fac_, sac_, kc_;
u8 reserved_3[8];
public:

View file

@ -0,0 +1,17 @@
#pragma once
#include <fnd/types.h>
class ISerialiseableBinary
{
public:
virtual bool operator==(const ISerialiseableBinary& other) = 0;
virtual void operator=(const ISerialiseableBinary& other) = 0;
virtual const u8* getBytes() const = 0;
virtual size_t getSize() const = 0;
virtual void exportBinary() = 0;
virtual void importBinary(const u8* bytes) = 0;
virtual void importBinary(const u8* bytes, size_t len) = 0;
};

View file

@ -4,7 +4,7 @@
void NcaHeader::exportBinary()
{
mBinaryBlob.alloc(sizeof(sNcaHeader));
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.data();
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes();
hdr->set_signature(kNcaSig.c_str());
hdr->set_block_size(kDefaultBlockSize);
@ -36,9 +36,9 @@ void NcaHeader::importBinary(const u8 * bytes)
clearVariables();
mBinaryBlob.alloc(sizeof(sNcaHeader));
memcpy(mBinaryBlob.data(), bytes, sizeof(sNcaHeader));
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader));
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.data();
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes();
if (memcmp(hdr->signature(), kNcaSig.c_str(), 4) != 0)
{
@ -68,6 +68,15 @@ void NcaHeader::importBinary(const u8 * bytes)
}
}
void NcaHeader::importBinary(const u8 * bytes, size_t len)
{
if (len < sizeof(sNcaHeader))
{
throw fnd::Exception(kModuleName, "NCA header size is too small");
}
importBinary(bytes);
}
u64 NcaHeader::getNcaSize() const
{
return mNcaSize;
@ -157,12 +166,22 @@ NcaHeader::NcaHeader(const u8 * bytes)
importBinary(bytes);
}
bool NcaHeader::operator==(const NcaHeader & other)
{
return memcmp(this->getBytes(), other.getBytes(), this->getSize()) == 0;
}
void NcaHeader::operator=(const NcaHeader & other)
{
this->importBinary(other.getBytes(), other.getSize());
}
const u8 * NcaHeader::getBytes() const
{
return mBinaryBlob.data();
return mBinaryBlob.getBytes();
}
size_t NcaHeader::getSize() const
{
return mBinaryBlob.size();
return mBinaryBlob.getSize();
}

View file

@ -1,12 +1,13 @@
#pragma once
#include <vector>
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
#include <vector>
#include <string>
#include <nx/ISerialiseableBinary.h>
class NcaHeader
class NcaHeader : public ISerialiseableBinary
{
public:
struct sSection
@ -19,10 +20,15 @@ public:
crypto::sha::sSha256Hash hash;
};
static const size_t kDefaultBlockSize = 0x200;
NcaHeader();
NcaHeader(const NcaHeader& other);
NcaHeader(const u8* bytes);
bool operator==(const NcaHeader& other);
void operator=(const NcaHeader& other);
// to be used after export
const u8* getBytes() const;
size_t getSize() const;
@ -30,6 +36,7 @@ public:
// export/import binary
void exportBinary();
void importBinary(const u8* bytes);
void importBinary(const u8* bytes, size_t len);
// variables
u64 getNcaSize() const;
@ -45,7 +52,6 @@ public:
private:
const std::string kModuleName = "NCA_HEADER";
const std::string kNcaSig = "NCA2";
static const size_t kDefaultBlockSize = 0x200;
static const size_t kSectionNum = 4;
static const size_t kAesKeyNum = 4;

101
lib/nx/SacEntry.cpp Normal file
View file

@ -0,0 +1,101 @@
#include "SacEntry.h"
SacEntry::SacEntry() :
mIsServer(false),
mName("")
{
}
SacEntry::SacEntry(const SacEntry & other)
{
importBinary(other.getBytes(), other.getSize());
}
SacEntry::SacEntry(const u8 * bytes)
{
importBinary(bytes);
}
const u8 * SacEntry::getBytes() const
{
return mBinaryBlob.getBytes();
}
size_t SacEntry::getSize() const
{
return mBinaryBlob.getSize();
}
void SacEntry::exportBinary()
{
try {
mBinaryBlob.alloc(mName.size() + 1);
}
catch (const fnd::Exception& e)
{
throw fnd::Exception(kModuleName, "Failed to allocate memory for SacEntry: " + std::string(e.what()));
}
if (mName.length() > kMaxServiceNameLen)
{
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
}
// copy data into binary blob
mBinaryBlob[0] = (mIsServer ? SAC_IS_SERVER : 0) | (mName.length() & SAC_NAME_LEN_MASK);
memcpy(mBinaryBlob.getBytes() + 1, mName.c_str(), mName.length());
}
void SacEntry::importBinary(const u8 * bytes)
{
bool isServer = (bytes[0] & SAC_IS_SERVER) == SAC_IS_SERVER;
size_t nameLen = (bytes[0] & SAC_NAME_LEN_MASK);
if (nameLen == 0)
{
throw fnd::Exception(kModuleName, "SAC entry has no service name");
}
else if (nameLen > kMaxServiceNameLen)
{
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
}
mBinaryBlob.alloc(nameLen + 1);
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
mIsServer = isServer;
mName = std::string((const char*)(mBinaryBlob.getBytes() + 1), nameLen);
}
void SacEntry::importBinary(const u8 * bytes, size_t len)
{
importBinary(bytes);
if (getSize() != len)
{
throw fnd::Exception(kModuleName, "SAC Entry has unexpected size");
}
}
bool SacEntry::isServer() const
{
return mIsServer;
}
void SacEntry::setIsServer(bool isServer)
{
mIsServer = isServer;
}
const std::string & SacEntry::getName() const
{
return mName;
}
void SacEntry::setName(const std::string & name)
{
if (name.length() > kMaxServiceNameLen)
{
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
}
mName = name;
}

43
lib/nx/SacEntry.h Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
class SacEntry : public ISerialiseableBinary
{
SacEntry();
SacEntry(const SacEntry& other);
SacEntry(const u8* bytes);
// to be used after export
const u8* getBytes() const;
size_t getSize() const;
// export/import binary
void exportBinary();
void importBinary(const u8* bytes);
void importBinary(const u8* bytes, size_t len);
// variables
bool isServer() const;
void setIsServer(bool isServer);
const std::string& getName() const;
void setName(const std::string& name);
private:
const std::string kModuleName = "SAC_ENTRY";
static const size_t kMaxServiceNameLen = 8;
enum SacEntryFlag
{
SAC_IS_SERVER = BIT(7),
SAC_NAME_LEN_MASK = BIT(7)-1
};
// raw binary
fnd::MemoryBlob mBinaryBlob;
// variables
bool mIsServer;
std::string mName;
};

View file

@ -20,12 +20,15 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="AciHeader.h" />
<ClInclude Include="ISerialiseableBinary.h" />
<ClInclude Include="NcaHeader.h" />
<ClInclude Include="NXCrypto.h" />
<ClInclude Include="SacEntry.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AciHeader.cpp" />
<ClCompile Include="NcaHeader.cpp" />
<ClCompile Include="SacEntry.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>

View file

@ -24,6 +24,12 @@
<ClInclude Include="AciHeader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SacEntry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ISerialiseableBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="NcaHeader.cpp">
@ -32,5 +38,8 @@
<ClCompile Include="AciHeader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SacEntry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>