mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-23 03:05:27 +00:00
[nx] Add XciHeader
This commit is contained in:
parent
fac2753afd
commit
17c16cfa7a
134
lib/libnx/include/nx/XciHeader.h
Normal file
134
lib/libnx/include/nx/XciHeader.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
#pragma once
|
||||||
|
#include <nx/xci.h>
|
||||||
|
#include <fnd/MemoryBlob.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
|
||||||
|
namespace nx
|
||||||
|
{
|
||||||
|
class XciHeader :
|
||||||
|
public fnd::ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XciHeader();
|
||||||
|
XciHeader(const XciHeader& other);
|
||||||
|
XciHeader(const byte_t* bytes, size_t len);
|
||||||
|
|
||||||
|
bool operator==(const XciHeader& other) const;
|
||||||
|
bool operator!=(const XciHeader& other) const;
|
||||||
|
void operator=(const XciHeader& 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();
|
||||||
|
uint32_t getRomAreaStartPage() const;
|
||||||
|
void setRomAreaStartPage(uint32_t startPage);
|
||||||
|
uint32_t getBackupAreaStartPage() const;
|
||||||
|
void setBackupAreaStartPage(uint32_t startPage);
|
||||||
|
byte_t getKekIndex() const;
|
||||||
|
void setKekIndex(byte_t kekIndex);
|
||||||
|
byte_t getTitleKeyDecIndex() const;
|
||||||
|
void setTitleKeyDecIndex(byte_t index);
|
||||||
|
byte_t getRomSizeType() const;
|
||||||
|
void setRomSizeType(byte_t romSizeType);
|
||||||
|
byte_t getCardHeaderVersion() const;
|
||||||
|
void setCardHeaderVersion(byte_t version);
|
||||||
|
byte_t getFlags() const;
|
||||||
|
void setFlags(byte_t flags);
|
||||||
|
uint64_t getPackageId() const;
|
||||||
|
void setPackageId(uint64_t id);
|
||||||
|
uint32_t getValidDataEndPage() const;
|
||||||
|
void setValidDataEndPage(uint32_t page);
|
||||||
|
const crypto::aes::sAesIvCtr& getAesCbcIv() const;
|
||||||
|
void setAesCbcIv(const crypto::aes::sAesIvCtr& iv);
|
||||||
|
uint64_t getPartitionFsAddress() const;
|
||||||
|
void setPartitionFsAddress(uint64_t address);
|
||||||
|
uint64_t getPartitionFsSize() const;
|
||||||
|
void setPartitionFsSize(uint64_t size);
|
||||||
|
const crypto::sha::sSha256Hash& getPartitionFsHash() const;
|
||||||
|
void setPartitionFsHash(const crypto::sha::sSha256Hash& hash);
|
||||||
|
const crypto::sha::sSha256Hash& getInitialDataHash() const;
|
||||||
|
void setInitialDataHash(const crypto::sha::sSha256Hash& hash);
|
||||||
|
uint32_t getSelSec() const;
|
||||||
|
void setSelSec(uint32_t sel_sec);
|
||||||
|
uint32_t getSelT1Key() const;
|
||||||
|
void setSelT1Key(uint32_t sel_t1_key);
|
||||||
|
uint32_t getSelKey() const;
|
||||||
|
void setSelKey(uint32_t sel_key);
|
||||||
|
uint32_t getLimAreaPage() const;
|
||||||
|
void setLimAreaPage(uint32_t page);
|
||||||
|
|
||||||
|
uint32_t getFwVerMajor() const;
|
||||||
|
void setFwVerMajor(uint32_t ver);
|
||||||
|
uint32_t getFwVerMinor() const;
|
||||||
|
void setFwVerMinor(uint32_t ver);
|
||||||
|
uint32_t getAccCtrl1() const;
|
||||||
|
void setAccCtrl1(uint32_t acc_ctrl_1);
|
||||||
|
uint32_t getWait1TimeRead() const;
|
||||||
|
void setWait1TimeRead(uint32_t seconds);
|
||||||
|
uint32_t getWait2TimeRead() const;
|
||||||
|
void setWait2TimeRead(uint32_t seconds);
|
||||||
|
uint32_t getWait1TimeWrite() const;
|
||||||
|
void setWait1TimeWrite(uint32_t seconds);
|
||||||
|
uint32_t getWait2TimeWrite() const;
|
||||||
|
void setWait2TimeWrite(uint32_t seconds);
|
||||||
|
uint32_t getFwMode() const;
|
||||||
|
void setFwMode(uint32_t fw_mode);
|
||||||
|
uint32_t getUppVersion() const;
|
||||||
|
void setUppVersion(uint32_t version);
|
||||||
|
const byte_t* getUppHash() const;
|
||||||
|
void setUppHash(const byte_t* hash);
|
||||||
|
uint64_t getUppId() const;
|
||||||
|
void setUppId(uint64_t id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "XCI_HEADER";
|
||||||
|
|
||||||
|
// binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// data
|
||||||
|
uint32_t mRomAreaStartPage;
|
||||||
|
uint32_t mBackupAreaStartPage;
|
||||||
|
byte_t mKekIndex;
|
||||||
|
byte_t mTitleKeyDecIndex;
|
||||||
|
byte_t mRomSize;
|
||||||
|
byte_t mCardHeaderVersion;
|
||||||
|
byte_t mFlags;
|
||||||
|
uint64_t mPackageId;
|
||||||
|
uint32_t mValidDataEndPage;
|
||||||
|
crypto::aes::sAesIvCtr mAesCbcIv;
|
||||||
|
uint64_t mPartitionFsHeaderAddress;
|
||||||
|
uint64_t mPartitionFsHeaderSize;
|
||||||
|
crypto::sha::sSha256Hash mPartitionFsHeaderHash;
|
||||||
|
crypto::sha::sSha256Hash mInitialDataHash;
|
||||||
|
uint32_t mSelSec;
|
||||||
|
uint32_t mSelT1Key;
|
||||||
|
uint32_t mSelKey;
|
||||||
|
uint32_t mLimAreaPage;
|
||||||
|
|
||||||
|
// Encrypted Data
|
||||||
|
uint32_t mFwVersion[2];
|
||||||
|
uint32_t mAccCtrl1;
|
||||||
|
uint32_t mWait1TimeRead;
|
||||||
|
uint32_t mWait2TimeRead;
|
||||||
|
uint32_t mWait1TimeWrite;
|
||||||
|
uint32_t mWait2TimeWrite;
|
||||||
|
uint32_t mFwMode;
|
||||||
|
uint32_t mUppVersion;
|
||||||
|
byte_t mUppHash[8];
|
||||||
|
uint64_t mUppId;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
bool isEqual(const XciHeader& other) const;
|
||||||
|
void copyFrom(const XciHeader& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
13
lib/libnx/include/nx/XciUtils.h
Normal file
13
lib/libnx/include/nx/XciUtils.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
#include <nx/xci.h>
|
||||||
|
|
||||||
|
namespace nx
|
||||||
|
{
|
||||||
|
class XciUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline uint64_t blockToAddr(uint32_t block) { return ((uint64_t)block) << 9; }
|
||||||
|
static void getXciHeaderAesIv(const nx::sXciHeader* hdr, byte_t* iv);
|
||||||
|
static void decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/List.h>
|
#include <fnd/List.h>
|
||||||
#include <crypto/aes.h>
|
#include <crypto/aes.h>
|
||||||
#include <crypto/sha.h>
|
#include <crypto/sha.h>
|
||||||
|
#include <crypto/rsa.h>
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
|
||||||
namespace nx
|
namespace nx
|
||||||
|
@ -13,6 +15,7 @@ namespace nx
|
||||||
static const uint32_t kHeaderEncOffset = 0x90;
|
static const uint32_t kHeaderEncOffset = 0x90;
|
||||||
static const uint32_t kHeaderEncSize = 0x70;
|
static const uint32_t kHeaderEncSize = 0x70;
|
||||||
static const uint32_t kPageSize = 0x200;
|
static const uint32_t kPageSize = 0x200;
|
||||||
|
static const uint32_t kUppHashLen = 8;
|
||||||
static const uint32_t kCardKeyAreaPageCount = 8;
|
static const uint32_t kCardKeyAreaPageCount = 8;
|
||||||
static const uint32_t kCardHeaderPageCount = 1;
|
static const uint32_t kCardHeaderPageCount = 1;
|
||||||
static const uint32_t kReservedAreaPageCount = 55;
|
static const uint32_t kReservedAreaPageCount = 55;
|
||||||
|
@ -21,6 +24,12 @@ namespace nx
|
||||||
static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount;
|
static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount;
|
||||||
|
|
||||||
|
|
||||||
|
enum KekIndex
|
||||||
|
{
|
||||||
|
KEK_XCIE,
|
||||||
|
KEK_XCIR
|
||||||
|
};
|
||||||
|
|
||||||
enum RomSize
|
enum RomSize
|
||||||
{
|
{
|
||||||
ROM_SIZE_1GB = 0xFA,
|
ROM_SIZE_1GB = 0xFA,
|
||||||
|
@ -63,12 +72,12 @@ namespace nx
|
||||||
byte_t flags;
|
byte_t flags;
|
||||||
le_uint64_t package_id;
|
le_uint64_t package_id;
|
||||||
le_uint32_t valid_data_end_page;
|
le_uint32_t valid_data_end_page;
|
||||||
byte_t reserved_01[4];
|
byte_t reserved_00[4];
|
||||||
byte_t encryption_iv[16];
|
crypto::aes::sAesIvCtr aescbc_iv;
|
||||||
le_uint64_t partition_fs_header_address;
|
le_uint64_t partition_fs_header_address;
|
||||||
le_uint64_t partition_fs_header_size;
|
le_uint64_t partition_fs_header_size;
|
||||||
byte_t partition_fs_header_hash[0x20];
|
crypto::sha::sSha256Hash partition_fs_header_hash;
|
||||||
byte_t initial_data_hash[0x20];
|
crypto::sha::sSha256Hash initial_data_hash;
|
||||||
le_uint32_t sel_sec;
|
le_uint32_t sel_sec;
|
||||||
le_uint32_t sel_t1_key;
|
le_uint32_t sel_t1_key;
|
||||||
le_uint32_t sel_key;
|
le_uint32_t sel_key;
|
||||||
|
@ -82,13 +91,19 @@ namespace nx
|
||||||
le_uint32_t wait_2_time_write;
|
le_uint32_t wait_2_time_write;
|
||||||
le_uint32_t fw_mode;
|
le_uint32_t fw_mode;
|
||||||
le_uint32_t upp_version;
|
le_uint32_t upp_version;
|
||||||
byte_t reserved_03[0x4];
|
byte_t reserved_01[0x4];
|
||||||
byte_t upp_hash[8];
|
byte_t upp_hash[xci::kUppHashLen];
|
||||||
le_uint64_t upp_id;
|
le_uint64_t upp_id;
|
||||||
byte_t reserved_04[0x38];
|
byte_t reserved_02[0x38];
|
||||||
// END ENCRYPTION
|
// END ENCRYPTION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sXciHeaderPage
|
||||||
|
{
|
||||||
|
byte_t signature[crypto::rsa::kRsa2048Size];
|
||||||
|
sXciHeader header;
|
||||||
|
}; // sizeof() = 512 (1 page)
|
||||||
|
|
||||||
struct sInitialData
|
struct sInitialData
|
||||||
{
|
{
|
||||||
byte_t key_source[16]; // { package_id[8], zeros[8]}
|
byte_t key_source[16]; // { package_id[8], zeros[8]}
|
||||||
|
|
499
lib/libnx/source/XciHeader.cpp
Normal file
499
lib/libnx/source/XciHeader.cpp
Normal file
|
@ -0,0 +1,499 @@
|
||||||
|
#include <nx/XciHeader.h>
|
||||||
|
|
||||||
|
bool nx::XciHeader::isEqual(const XciHeader& other) const
|
||||||
|
{
|
||||||
|
return ( mRomAreaStartPage == other.mRomAreaStartPage \
|
||||||
|
& mBackupAreaStartPage == other.mBackupAreaStartPage \
|
||||||
|
& mKekIndex == other.mKekIndex \
|
||||||
|
& mTitleKeyDecIndex == other.mTitleKeyDecIndex \
|
||||||
|
& mRomSize == other.mRomSize \
|
||||||
|
& mCardHeaderVersion == other.mCardHeaderVersion \
|
||||||
|
& mFlags == other.mFlags \
|
||||||
|
& mPackageId == other.mPackageId \
|
||||||
|
& mValidDataEndPage == other.mValidDataEndPage \
|
||||||
|
& mAesCbcIv == other.mAesCbcIv \
|
||||||
|
& mPartitionFsHeaderAddress == other.mPartitionFsHeaderAddress \
|
||||||
|
& mPartitionFsHeaderSize == other.mPartitionFsHeaderSize \
|
||||||
|
& mPartitionFsHeaderHash == other.mPartitionFsHeaderHash \
|
||||||
|
& mInitialDataHash == other.mInitialDataHash \
|
||||||
|
& mSelSec == other.mSelSec \
|
||||||
|
& mSelT1Key == other.mSelT1Key \
|
||||||
|
& mSelKey == other.mSelKey \
|
||||||
|
& mLimAreaPage == other.mLimAreaPage \
|
||||||
|
& mFwVersion[0] == other.mFwVersion[0] \
|
||||||
|
& mFwVersion[1] == other.mFwVersion[1] \
|
||||||
|
& mAccCtrl1 == other.mAccCtrl1 \
|
||||||
|
& mWait1TimeRead == other.mWait1TimeRead \
|
||||||
|
& mWait2TimeRead == other.mWait2TimeRead \
|
||||||
|
& mWait1TimeWrite == other.mWait1TimeWrite \
|
||||||
|
& mWait2TimeWrite == other.mWait2TimeWrite \
|
||||||
|
& mFwMode == other.mFwMode \
|
||||||
|
& mUppVersion == other.mUppVersion \
|
||||||
|
& memcmp(mUppHash, other.mUppHash, xci::kUppHashLen) \
|
||||||
|
& mUppId == other.mUppId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::copyFrom(const XciHeader& other)
|
||||||
|
{
|
||||||
|
mRomAreaStartPage = other.mRomAreaStartPage;
|
||||||
|
mBackupAreaStartPage = other.mBackupAreaStartPage;
|
||||||
|
mKekIndex = other.mKekIndex;
|
||||||
|
mTitleKeyDecIndex = other.mTitleKeyDecIndex;
|
||||||
|
mRomSize = other.mRomSize;
|
||||||
|
mCardHeaderVersion = other.mCardHeaderVersion;
|
||||||
|
mFlags = other.mFlags;
|
||||||
|
mPackageId = other.mPackageId;
|
||||||
|
mValidDataEndPage = other.mValidDataEndPage;
|
||||||
|
mAesCbcIv = other.mAesCbcIv;
|
||||||
|
mPartitionFsHeaderAddress = other.mPartitionFsHeaderAddress;
|
||||||
|
mPartitionFsHeaderSize = other.mPartitionFsHeaderSize;
|
||||||
|
mPartitionFsHeaderHash = other.mPartitionFsHeaderHash;
|
||||||
|
mInitialDataHash = other.mInitialDataHash;
|
||||||
|
mSelSec = other.mSelSec;
|
||||||
|
mSelT1Key = other.mSelT1Key;
|
||||||
|
mSelKey = other.mSelKey;
|
||||||
|
mLimAreaPage = other.mLimAreaPage;
|
||||||
|
mFwVersion[0] = other.mFwVersion[0];
|
||||||
|
mFwVersion[1] = other.mFwVersion[1];
|
||||||
|
mAccCtrl1 = other.mAccCtrl1;
|
||||||
|
mWait1TimeRead = other.mWait1TimeRead;
|
||||||
|
mWait2TimeRead = other.mWait2TimeRead;
|
||||||
|
mWait1TimeWrite = other.mWait1TimeWrite;
|
||||||
|
mWait2TimeWrite = other.mWait2TimeWrite;
|
||||||
|
mFwMode = other.mFwMode;
|
||||||
|
mUppVersion = other.mUppVersion;
|
||||||
|
memcpy(mUppHash, other.mUppHash, xci::kUppHashLen);
|
||||||
|
mUppId = other.mUppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::XciHeader::XciHeader()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nx::XciHeader::XciHeader(const XciHeader& other)
|
||||||
|
{
|
||||||
|
importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
nx::XciHeader::XciHeader(const byte_t* bytes, size_t len)
|
||||||
|
{
|
||||||
|
importBinary(bytes, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nx::XciHeader::operator==(const XciHeader& other) const
|
||||||
|
{
|
||||||
|
return isEqual(other);
|
||||||
|
}
|
||||||
|
bool nx::XciHeader::operator!=(const XciHeader& other) const
|
||||||
|
{
|
||||||
|
return isEqual(other) == false;
|
||||||
|
}
|
||||||
|
void nx::XciHeader::operator=(const XciHeader& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to be used after export
|
||||||
|
const byte_t* nx::XciHeader::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nx::XciHeader::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void nx::XciHeader::exportBinary()
|
||||||
|
{
|
||||||
|
fnd::Exception(kModuleName, "exportBinary() not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::importBinary(const byte_t* bytes, size_t len)
|
||||||
|
{
|
||||||
|
// check input data size
|
||||||
|
if (len < sizeof(sXciHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "XCI header size is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear internal members
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// allocate internal local binary copy
|
||||||
|
mBinaryBlob.alloc(sizeof(sXciHeader));
|
||||||
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
|
||||||
|
// get sXciHeader ptr
|
||||||
|
const nx::sXciHeader* hdr = (const nx::sXciHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
|
// check XCI signature
|
||||||
|
if (std::string(hdr->signature, 4) != xci::kXciSig)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "XCI header corrupt");
|
||||||
|
}
|
||||||
|
|
||||||
|
mRomAreaStartPage = hdr->rom_area_start_page.get();
|
||||||
|
mBackupAreaStartPage = hdr->backup_area_start_page.get();
|
||||||
|
mKekIndex = hdr->key_flag & 7;
|
||||||
|
mTitleKeyDecIndex = (hdr->key_flag >> 4) & 7;
|
||||||
|
mRomSize = hdr->rom_size;
|
||||||
|
mCardHeaderVersion = hdr->card_header_version;
|
||||||
|
mFlags = hdr->flags;
|
||||||
|
mPackageId = hdr->package_id.get();
|
||||||
|
mValidDataEndPage = hdr->valid_data_end_page.get();
|
||||||
|
for (size_t i = 0; i < crypto::aes::kAesBlockSize; i++)
|
||||||
|
mAesCbcIv.iv[i] = hdr->aescbc_iv.iv[15-i];
|
||||||
|
mPartitionFsHeaderAddress = hdr->partition_fs_header_address.get();
|
||||||
|
mPartitionFsHeaderSize = hdr->partition_fs_header_size.get();
|
||||||
|
mPartitionFsHeaderHash = hdr->partition_fs_header_hash;
|
||||||
|
mInitialDataHash = hdr->initial_data_hash;
|
||||||
|
mSelSec = hdr->sel_sec.get();
|
||||||
|
mSelT1Key = hdr->sel_t1_key.get();
|
||||||
|
mSelKey = hdr->sel_key.get();
|
||||||
|
mLimAreaPage = hdr->lim_area.get();
|
||||||
|
|
||||||
|
// if decrypted
|
||||||
|
if (hdr->reserved_02[sizeof(hdr->reserved_02)-1] == 0x00 && hdr->reserved_02[sizeof(hdr->reserved_02)-2] == 0x00)
|
||||||
|
{
|
||||||
|
mFwVersion[xci::FWVER_MAJOR] = hdr->fw_version[xci::FWVER_MAJOR].get();
|
||||||
|
mFwVersion[xci::FWVER_MINOR] = hdr->fw_version[xci::FWVER_MINOR].get();
|
||||||
|
mAccCtrl1 = hdr->acc_ctrl_1.get();
|
||||||
|
mWait1TimeRead = hdr->wait_1_time_read.get();
|
||||||
|
mWait2TimeRead = hdr->wait_2_time_read.get();
|
||||||
|
mWait1TimeWrite = hdr->wait_1_time_write.get();
|
||||||
|
mWait2TimeWrite = hdr->wait_2_time_write.get();
|
||||||
|
mFwMode = hdr->fw_mode.get();
|
||||||
|
mUppVersion = hdr->upp_version.get();
|
||||||
|
memcpy(mUppHash, hdr->upp_hash, xci::kUppHashLen);
|
||||||
|
mUppId = hdr->upp_id.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void nx::XciHeader::clear()
|
||||||
|
{
|
||||||
|
mRomAreaStartPage = 0;
|
||||||
|
mBackupAreaStartPage = 0;
|
||||||
|
mKekIndex = 0;
|
||||||
|
mTitleKeyDecIndex = 0;
|
||||||
|
mRomSize = 0;
|
||||||
|
mCardHeaderVersion = 0;
|
||||||
|
mFlags = 0;
|
||||||
|
mPackageId = 0;
|
||||||
|
mValidDataEndPage = 0;
|
||||||
|
memset(mAesCbcIv.iv, 0, sizeof(mAesCbcIv));
|
||||||
|
mPartitionFsHeaderAddress = 0;
|
||||||
|
mPartitionFsHeaderSize = 0;
|
||||||
|
memset(mPartitionFsHeaderHash.bytes, 0, sizeof(mPartitionFsHeaderHash));
|
||||||
|
memset(mInitialDataHash.bytes, 0, sizeof(mInitialDataHash));
|
||||||
|
mSelSec = 0;
|
||||||
|
mSelT1Key = 0;
|
||||||
|
mSelKey = 0;
|
||||||
|
mLimAreaPage = 0;
|
||||||
|
mFwVersion[0] = 0;
|
||||||
|
mFwVersion[1] = 0;
|
||||||
|
mAccCtrl1 = 0;
|
||||||
|
mWait1TimeRead = 0;
|
||||||
|
mWait2TimeRead = 0;
|
||||||
|
mWait1TimeWrite = 0;
|
||||||
|
mWait2TimeWrite = 0;
|
||||||
|
mFwMode = 0;
|
||||||
|
mUppVersion = 0;
|
||||||
|
memset(mUppHash, 0, xci::kUppHashLen);
|
||||||
|
mUppId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getRomAreaStartPage() const
|
||||||
|
{
|
||||||
|
return mRomAreaStartPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setRomAreaStartPage(uint32_t startPage)
|
||||||
|
{
|
||||||
|
mRomAreaStartPage = startPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getBackupAreaStartPage() const
|
||||||
|
{
|
||||||
|
return mBackupAreaStartPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setBackupAreaStartPage(uint32_t startPage)
|
||||||
|
{
|
||||||
|
mBackupAreaStartPage = startPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nx::XciHeader::getKekIndex() const
|
||||||
|
{
|
||||||
|
return mKekIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setKekIndex(byte_t kekIndex)
|
||||||
|
{
|
||||||
|
mKekIndex = kekIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nx::XciHeader::getTitleKeyDecIndex() const
|
||||||
|
{
|
||||||
|
return mTitleKeyDecIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setTitleKeyDecIndex(byte_t index)
|
||||||
|
{
|
||||||
|
mTitleKeyDecIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nx::XciHeader::getRomSizeType() const
|
||||||
|
{
|
||||||
|
return mRomSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setRomSizeType(byte_t romSizeType)
|
||||||
|
{
|
||||||
|
mRomSize = romSizeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nx::XciHeader::getCardHeaderVersion() const
|
||||||
|
{
|
||||||
|
return mCardHeaderVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setCardHeaderVersion(byte_t version)
|
||||||
|
{
|
||||||
|
mCardHeaderVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t nx::XciHeader::getFlags() const
|
||||||
|
{
|
||||||
|
return mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setFlags(byte_t flags)
|
||||||
|
{
|
||||||
|
mFlags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nx::XciHeader::getPackageId() const
|
||||||
|
{
|
||||||
|
return mPackageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setPackageId(uint64_t id)
|
||||||
|
{
|
||||||
|
mPackageId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getValidDataEndPage() const
|
||||||
|
{
|
||||||
|
return mValidDataEndPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setValidDataEndPage(uint32_t page)
|
||||||
|
{
|
||||||
|
mValidDataEndPage = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::aes::sAesIvCtr& nx::XciHeader::getAesCbcIv() const
|
||||||
|
{
|
||||||
|
return mAesCbcIv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setAesCbcIv(const crypto::aes::sAesIvCtr& iv)
|
||||||
|
{
|
||||||
|
mAesCbcIv = iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nx::XciHeader::getPartitionFsAddress() const
|
||||||
|
{
|
||||||
|
return mPartitionFsHeaderAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setPartitionFsAddress(uint64_t address)
|
||||||
|
{
|
||||||
|
mPartitionFsHeaderAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nx::XciHeader::getPartitionFsSize() const
|
||||||
|
{
|
||||||
|
return mPartitionFsHeaderSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setPartitionFsSize(uint64_t size)
|
||||||
|
{
|
||||||
|
mPartitionFsHeaderSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::sha::sSha256Hash& nx::XciHeader::getPartitionFsHash() const
|
||||||
|
{
|
||||||
|
return mPartitionFsHeaderHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setPartitionFsHash(const crypto::sha::sSha256Hash& hash)
|
||||||
|
{
|
||||||
|
mPartitionFsHeaderHash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
const crypto::sha::sSha256Hash& nx::XciHeader::getInitialDataHash() const
|
||||||
|
{
|
||||||
|
return mInitialDataHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setInitialDataHash(const crypto::sha::sSha256Hash& hash)
|
||||||
|
{
|
||||||
|
mInitialDataHash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getSelSec() const
|
||||||
|
{
|
||||||
|
return mSelSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setSelSec(uint32_t sel_sec)
|
||||||
|
{
|
||||||
|
mSelSec = sel_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getSelT1Key() const
|
||||||
|
{
|
||||||
|
return mSelT1Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setSelT1Key(uint32_t sel_t1_key)
|
||||||
|
{
|
||||||
|
mSelT1Key = sel_t1_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getSelKey() const
|
||||||
|
{
|
||||||
|
return mSelKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setSelKey(uint32_t sel_key)
|
||||||
|
{
|
||||||
|
mSelKey = sel_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getLimAreaPage() const
|
||||||
|
{
|
||||||
|
return mLimAreaPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setLimAreaPage(uint32_t page)
|
||||||
|
{
|
||||||
|
mLimAreaPage = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getFwVerMajor() const
|
||||||
|
{
|
||||||
|
return mFwVersion[xci::FWVER_MAJOR];
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setFwVerMajor(uint32_t ver)
|
||||||
|
{
|
||||||
|
mFwVersion[xci::FWVER_MAJOR] = ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getFwVerMinor() const
|
||||||
|
{
|
||||||
|
return mFwVersion[xci::FWVER_MINOR];
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setFwVerMinor(uint32_t ver)
|
||||||
|
{
|
||||||
|
mFwVersion[xci::FWVER_MINOR] = ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getAccCtrl1() const
|
||||||
|
{
|
||||||
|
return mAccCtrl1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setAccCtrl1(uint32_t acc_ctrl_1)
|
||||||
|
{
|
||||||
|
mAccCtrl1 = acc_ctrl_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getWait1TimeRead() const
|
||||||
|
{
|
||||||
|
return mWait1TimeRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setWait1TimeRead(uint32_t seconds)
|
||||||
|
{
|
||||||
|
mWait1TimeRead = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getWait2TimeRead() const
|
||||||
|
{
|
||||||
|
return mWait2TimeRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setWait2TimeRead(uint32_t seconds)
|
||||||
|
{
|
||||||
|
mWait2TimeRead = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getWait1TimeWrite() const
|
||||||
|
{
|
||||||
|
return mWait1TimeWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setWait1TimeWrite(uint32_t seconds)
|
||||||
|
{
|
||||||
|
mWait1TimeWrite = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getWait2TimeWrite() const
|
||||||
|
{
|
||||||
|
return mWait2TimeWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setWait2TimeWrite(uint32_t seconds)
|
||||||
|
{
|
||||||
|
mWait2TimeWrite = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getFwMode() const
|
||||||
|
{
|
||||||
|
return mFwMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setFwMode(uint32_t fw_mode)
|
||||||
|
{
|
||||||
|
mFwMode = fw_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nx::XciHeader::getUppVersion() const
|
||||||
|
{
|
||||||
|
return mUppVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setUppVersion(uint32_t version)
|
||||||
|
{
|
||||||
|
mUppVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_t* nx::XciHeader::getUppHash() const
|
||||||
|
{
|
||||||
|
return mUppHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setUppHash(const byte_t* hash)
|
||||||
|
{
|
||||||
|
memcpy(mUppHash, hash, xci::kUppHashLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nx::XciHeader::getUppId() const
|
||||||
|
{
|
||||||
|
return mUppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciHeader::setUppId(uint64_t id)
|
||||||
|
{
|
||||||
|
mUppId = id;
|
||||||
|
}
|
||||||
|
|
22
lib/libnx/source/XciUtils.cpp
Normal file
22
lib/libnx/source/XciUtils.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <nx/XciUtils.h>
|
||||||
|
|
||||||
|
void nx::XciUtils::getXciHeaderAesIv(const nx::sXciHeader* hdr, byte_t* iv)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
iv[15-i] = hdr->aescbc_iv.iv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nx::XciUtils::decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key)
|
||||||
|
{
|
||||||
|
byte_t iv[crypto::aes::kAesBlockSize];
|
||||||
|
|
||||||
|
getXciHeaderAesIv((const nx::sXciHeader*)src, iv);
|
||||||
|
|
||||||
|
// copy plain
|
||||||
|
memcpy(dst, src, nx::xci::kHeaderEncOffset);
|
||||||
|
|
||||||
|
// decrypt encrypted data
|
||||||
|
crypto::aes::AesCbcDecrypt(src + nx::xci::kHeaderEncOffset, nx::xci::kHeaderEncSize, key, iv, dst + nx::xci::kHeaderEncOffset);
|
||||||
|
}
|
Loading…
Reference in a new issue