[fnd/nx] Moved ISerialiseableBinary from nx to fnd. AciHeader corrected specification.

This commit is contained in:
jakcron 2017-07-21 18:30:16 +08:00
parent 05b8856ee3
commit bf811f1107
23 changed files with 120 additions and 133 deletions

View file

@ -1,14 +1,11 @@
#pragma once
#include <fnd/types.h>
namespace nx
namespace fnd
{
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;
@ -18,4 +15,3 @@ namespace nx
virtual void clear() = 0;
};
}

View file

@ -118,6 +118,7 @@
<ClInclude Include="elf.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="io.h" />
<ClInclude Include="ISerialiseableBinary.h" />
<ClInclude Include="List.h" />
<ClInclude Include="memory_blob.h" />
<ClInclude Include="string_conv.h" />

View file

@ -36,6 +36,9 @@
<ClInclude Include="List.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ISerialiseableBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="memory_blob.cpp">

View file

@ -1,4 +1,4 @@
LIBS = fnd crypto nx
LIBS = fnd crypto es nx
main: build
rebuild: clean build

View file

@ -2,7 +2,6 @@
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/AciHeader.h>
#include <nx/FacBinary.h>
#include <nx/SacBinary.h>

View file

@ -105,39 +105,23 @@ void AciHeader::exportBinary()
hdr->kc().set_offset(mKc.offset);
hdr->kc().set_size(mKc.size);
hdr->set_version(mFormatVersion);
u32 flags = 0;
if (mIsProduction)
flags |= BIT(0);
hdr->set_flags(flags);
if (mType == TYPE_ACI0)
{
// set program
hdr->set_program_id(mProgramId);
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
}
else if (mType == TYPE_ACID)
{
switch (mFormatVersion)
{
case(0):
mAcidSize = getAciSize();
hdr->set_size(mAcidSize);
hdr->set_program_id_min(0);
hdr->set_program_id_max(0);
break;
case(1):
hdr->set_size(0);
hdr->set_program_id_min(mProgramIdMin);
hdr->set_program_id_max(mProgramIdMax);
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACID version");
}
mAcidSize = getAciSize();
hdr->set_size(mAcidSize);
hdr->set_program_id_min(mProgramIdMin);
hdr->set_program_id_max(mProgramIdMax);
}
}
@ -172,38 +156,18 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
if (mType == TYPE_ACI0)
{
mProgramId = hdr->program_id();
mFormatVersion = hdr->version();
mIsProduction = false;
mAcidSize = 0;
mProgramIdMin = 0;
mProgramIdMax = 0;
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
}
else if (mType == TYPE_ACID)
{
mProgramId = 0;
mFormatVersion = hdr->version();
switch (mFormatVersion)
{
case(0):
mAcidSize = hdr->size();
mProgramIdMin = 0;
mProgramIdMax = 0;
break;
case(1):
mAcidSize = 0;
mProgramIdMin = hdr->program_id_min();
mProgramIdMax = hdr->program_id_max();
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACID version");
}
mIsProduction = (hdr->flags() & BIT(0)) == BIT(0);
mAcidSize = hdr->size();
mProgramIdMin = hdr->program_id_min();
mProgramIdMax = hdr->program_id_max();
}
// the header offset is the MIN(sac.offset, fac.offset, kc.offset) - sizeof(sHeader)
@ -219,9 +183,14 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
void nx::AciHeader::clear()
{
mBinaryBlob.clear();
mHeaderOffset = 0;
mType = TYPE_ACI0;
mProgramId = 0;
mProgramIdMin = 0;
mProgramIdMax = 0;
mAcidSize = 0;
mIsProduction = false;
mFac.offset = 0;
mFac.size = 0;
mSac.offset = 0;
@ -235,16 +204,6 @@ size_t nx::AciHeader::getAciSize() const
return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader));
}
u32 nx::AciHeader::getFormatVersion() const
{
return mFormatVersion;
}
void nx::AciHeader::setFormatVersion(u32 version)
{
mFormatVersion = version;
}
size_t nx::AciHeader::getAcidSize() const
{
return mAcidSize;
@ -292,6 +251,16 @@ void AciHeader::setAciType(AciType type)
mType = type;
}
bool nx::AciHeader::isProduction() const
{
return mIsProduction;
}
void nx::AciHeader::setIsProduction(bool isProduction)
{
mIsProduction = isProduction;
}
u64 AciHeader::getProgramId() const
{
return mProgramId;

View file

@ -2,11 +2,12 @@
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class AciHeader : public ISerialiseableBinary
class AciHeader :
public fnd::ISerialiseableBinary
{
public:
enum AciType
@ -74,8 +75,8 @@ namespace nx
void setHeaderOffset(size_t offset);
AciType getAciType() const;
void setAciType(AciType type);
u32 getFormatVersion() const;
void setFormatVersion(u32 version);
bool isProduction() const;
void setIsProduction(bool isProduction);
const sSection& getFacPos() const;
void setFacSize(size_t size);
const sSection& getSacPos() const;
@ -94,9 +95,9 @@ namespace nx
{
private:
u8 signature_[4];
u32 size_; // includes prefacing signature, set only in ACID since it is signed
u32 size_; // includes prefacing signature, set only in ACID made by SDK (it enables easy resigning)
u8 reserved_0[4];
u32 version_; // set in ACID only, v0 has size, but no pid range, v1 has no size by pid range
u32 flags_; // set in ACID only
u64 program_id_; // set only in ACI0 (since ACID is generic)
u64 program_id_max_;
struct sAciSection
@ -118,8 +119,8 @@ namespace nx
u32 size() const { return le_word(size_); }
void set_size(u32 size) { size_ = le_word(size); }
u32 version() const { return le_word(version_); }
void set_version(u32 version) { version_ = le_word(version); }
u32 flags() const { return le_word(flags_); }
void set_flags(u32 flags) { flags_ = le_word(flags); }
u64 program_id() const { return le_dword(program_id_); }
void set_program_id(u64 program_id) { program_id_ = le_dword(program_id); }
@ -155,8 +156,9 @@ namespace nx
// ACI(D) variables
size_t mHeaderOffset;
AciType mType;
u32 mFormatVersion;
bool mIsProduction;
sSection mFac, mSac, mKc;
void calculateSectionOffsets();
bool isEqual(const AciHeader& other) const;
void copyFrom(const AciHeader& other);

View file

@ -1,7 +1,6 @@
#pragma once
#include <string>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/AciBinary.h>
#include <crypto/rsa.h>

View file

@ -2,7 +2,6 @@
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/FacHeader.h>

View file

@ -2,12 +2,12 @@
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class FacHeader :
public ISerialiseableBinary
public fnd::ISerialiseableBinary
{
public:
enum FsAccessFlag

View file

@ -3,7 +3,7 @@
#include <vector>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
#include <nx/ThreadInfoHandler.h>
#include <nx/SystemCallHandler.h>
#include <nx/MemoryMappingHandler.h>
@ -16,7 +16,7 @@
namespace nx
{
class KcBinary :
public ISerialiseableBinary
public fnd::ISerialiseableBinary
{
public:
KcBinary();

View file

@ -46,32 +46,43 @@ namespace crypto
TitleKeyGenarateKey
};
u8 titlekey_generate_key[0x20] = { 39, 111, 56, 188, 68, 106, 241, 86, 31, 44, 90, 111, 116, 32, 93, 197, 25, 181, 59, 188, 178, 159, 211, 175, 212, 178, 162, 4, 28, 152, 117, 126 };
// aes128-cbc keys
u8 xci_header_key[16] = { 0x01, 0xc5, 0x8f, 0xe7, 0x2d, 0x13, 0x5a, 0xb2, 0x9a, 0x3f, 0x69, 0x33, 0x95, 0x74, 0xb1 };
u8 eticket_common_key[16] = { 0x55, 0xA3, 0xF8, 0x72, 0xBD, 0xC8, 0x0C, 0x55, 0x5A, 0x65, 0x43, 0x81, 0x13, 0x9E, 0x15, 0x3B }; // lol this 3ds dev common key
// aes128-xts keys (seem to use 512 block sizes, aka 0x200 blocks)
u8 nca_body_key[2][16] =
namespace dev
{
{ 0xE5, 0x64, 0xDB, 0xFE, 0x52, 0x93, 0x3A, 0x65, 0x3C, 0x8B, 0x5E, 0xF8, 0x2C, 0x9D, 0xF4, 0xB5 },
{ 0x60, 0x7B, 0x77, 0x3E, 0x31, 0xE9, 0x6A, 0x8F, 0x8E, 0x44, 0x5C, 0x98, 0x71, 0xC0, 0x57, 0xDB },
};
// aes128-xts keys (seem to use 512 block sizes, aka 0x200 blocks)
u8 nca_body_key[2][16] =
{
{ 0xE5, 0x64, 0xDB, 0xFE, 0x52, 0x93, 0x3A, 0x65, 0x3C, 0x8B, 0x5E, 0xF8, 0x2C, 0x9D, 0xF4, 0xB5 },
{ 0x60, 0x7B, 0x77, 0x3E, 0x31, 0xE9, 0x6A, 0x8F, 0x8E, 0x44, 0x5C, 0x98, 0x71, 0xC0, 0x57, 0xDB },
};
u8 nca_header_key[2][16] =
{
{ 0xCB, 0x9A, 0x93, 0x9F, 0x82, 0x72, 0x54, 0x4A, 0x74, 0x5D, 0x28, 0x46, 0x9D, 0xCC, 0x38, 0x12 },
{ 0x06, 0x31, 0x27, 0x06, 0xAE, 0x62, 0x56, 0x8C, 0x5B, 0x7E, 0xE6, 0x9F, 0x7E, 0x01, 0x02, 0x24 },
};
u8 nca_header_key[2][16] =
{
{ 0xCB, 0x9A, 0x93, 0x9F, 0x82, 0x72, 0x54, 0x4A, 0x74, 0x5D, 0x28, 0x46, 0x9D, 0xCC, 0x38, 0x12 },
{ 0x06, 0x31, 0x27, 0x06, 0xAE, 0x62, 0x56, 0x8C, 0x5B, 0x7E, 0xE6, 0x9F, 0x7E, 0x01, 0x02, 0x24 },
};
u8 nca_otherkey[2][16] =
// aeskey, related to m_KeyAreaEncryptionKeyList (first in list?)
u8 key_area_encryption_key_0[0x10] = { 0x3A, 0x7C, 0x3E, 0x38, 0x4A, 0x8F, 0x22, 0xFF, 0x4B, 0x21, 0x57, 0x19, 0xB7, 0x81, 0xAD, 0x0C };
u8 titlekey_generate_key[0x20] = { 39, 111, 56, 188, 68, 106, 241, 86, 31, 44, 90, 111, 116, 32, 93, 197, 25, 181, 59, 188, 178, 159, 211, 175, 212, 178, 162, 4, 28, 152, 117, 126 };
// aes128-cbc keys
u8 xci_header_key[16] = { 0x01, 0xc5, 0x8f, 0xe7, 0x2d, 0x13, 0x5a, 0xb2, 0x9a, 0x3f, 0x69, 0x33, 0x95, 0x74, 0xb1 };
u8 eticket_common_key[16] = { 0x55, 0xA3, 0xF8, 0x72, 0xBD, 0xC8, 0x0C, 0x55, 0x5A, 0x65, 0x43, 0x81, 0x13, 0x9E, 0x15, 0x3B }; // lol this 3ds dev common key
}
namespace prod
{
{ 0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0 },
{ 0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2 }
};
// aeskey, related to m_KeyAreaEncryptionKeyList (first in list?)
u8 key_area_encryption_key_0[0x10] = { 0x3A, 0x7C, 0x3E, 0x38, 0x4A, 0x8F, 0x22, 0xFF, 0x4B, 0x21, 0x57, 0x19, 0xB7, 0x81, 0xAD, 0x0C };
// encrypted with ProdNcaHeaderEncryptionKek
u8 nca_enc_header_key[2][16] =
{
{ 0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0 },
{ 0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2 }
};
}
}
}

View file

@ -5,11 +5,12 @@
#include <fnd/List.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class NcaHeader : public ISerialiseableBinary
class NcaHeader :
public fnd::ISerialiseableBinary
{
public:
enum DistributionType

View file

@ -2,7 +2,6 @@
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/NpdmHeader.h>
#include <nx/AciBinary.h>
#include <nx/AcidBinary.h>

View file

@ -2,12 +2,12 @@
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class NpdmHeader :
public nx::ISerialiseableBinary
public fnd::ISerialiseableBinary
{
public:
enum InstructionType

View file

@ -3,13 +3,13 @@
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class PfsHeader :
public ISerialiseableBinary
public fnd::ISerialiseableBinary
{
public:
struct sFile

View file

@ -3,13 +3,13 @@
#include <vector>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
#include <nx/SacEntry.h>
namespace nx
{
class SacBinary :
public ISerialiseableBinary
public fnd::ISerialiseableBinary
{
public:
SacBinary();

View file

@ -2,11 +2,12 @@
#include <string>
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{
class SacEntry : public ISerialiseableBinary
class SacEntry :
public fnd::ISerialiseableBinary
{
public:
SacEntry();

View file

@ -3,7 +3,7 @@
#include <fnd/types.h>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <fnd/ISerialiseableBinary.h>
namespace nx
{

View file

@ -29,7 +29,6 @@
<ClInclude Include="IKernelCapabilityHandler.h" />
<ClInclude Include="InteruptEntry.h" />
<ClInclude Include="InteruptHandler.h" />
<ClInclude Include="ISerialiseableBinary.h" />
<ClInclude Include="KcBinary.h" />
<ClInclude Include="KernelCapability.h" />
<ClInclude Include="KernelVersionEntry.h" />
@ -161,6 +160,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>

View file

@ -27,9 +27,6 @@
<ClInclude Include="SacEntry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ISerialiseableBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FacHeader.h">
<Filter>Header Files</Filter>
</ClInclude>

View file

@ -138,7 +138,7 @@ int main(int argc, char** argv)
// nca test
if (argc == 2 || argc == 3)
{
decryptNcaSectorXts(nca, sector, 1, crypto::aes::nx::nca_header_key[0], crypto::aes::nx::nca_header_key[1]);
decryptNcaSectorXts(nca, sector, 1, crypto::aes::nx::dev::nca_header_key[0], crypto::aes::nx::dev::nca_header_key[1]);
nx::NcaHeader hdr;
hdr.importBinary(sector, kNcaSectorSize);
@ -193,6 +193,19 @@ int main(int argc, char** argv)
}
}
}
if (argc == 4)
{
printf("encrypt test\n");
u8 sect[kNcaSectorSize] = { 0 };
u8 enc_sect[kNcaSectorSize * 6];
u8 tweak[crypto::aes::kAesBlockSize];
for (size_t i = 0; i < 6; i++)
{
crypto::aes::AesXtsMakeTweak(tweak, i);
crypto::aes::AesXtsEncryptSector(sect, kNcaSectorSize, crypto::aes::nx::dev::nca_header_key[0], crypto::aes::nx::dev::nca_header_key[1], tweak, enc_sect + i*kNcaSectorSize);
}
fnd::io::writeFile("testenc.bin", enc_sect, kNcaSectorSize * 6);
}
} catch (const fnd::Exception& e)
{

View file

@ -212,6 +212,8 @@ const std::string kSysCall[0x80] =
const std::string kMemMapPerm[2] = { "RW", "RO" };
const std::string kMemMapType[2] = { "Io", "Static" };
const std::string kAcidTarget[2] = { "Development", "Production" };
void displayNpdmHeader(const nx::NpdmHeader& hdr)
{
printf("[NPDM HEADER]\n");
@ -241,17 +243,12 @@ void displayAciHdr(const nx::AciHeader& aci)
}
else if (aci.getAciType() == nx::AciBinary::TYPE_ACID)
{
switch (aci.getFormatVersion())
{
case (0):
printf(" ACID Size: %" PRIx64 "\n", aci.getAcidSize());
break;
case (1):
printf(" ProgramID Restriction\n");
printf(" Min: %016" PRIx64 "\n", aci.getProgramIdMin());
printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax());
break;
}
printf(" ACID Size: %" PRIx64 "\n", aci.getAcidSize());
printf(" Target: %s\n", kAcidTarget[aci.isProduction()].c_str());
printf(" ProgramID Restriction\n");
printf(" Min: %016" PRIx64 "\n", aci.getProgramIdMin());
printf(" Max: %016" PRIx64 "\n", aci.getProgramIdMax());
}
}