diff --git a/lib/libhac/include/nn/hac/XciHeader.h b/lib/libhac/include/nn/hac/GameCardHeader.h similarity index 90% rename from lib/libhac/include/nn/hac/XciHeader.h rename to lib/libhac/include/nn/hac/GameCardHeader.h index 6fc2fcb..6da8ff8 100644 --- a/lib/libhac/include/nn/hac/XciHeader.h +++ b/lib/libhac/include/nn/hac/GameCardHeader.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include @@ -7,16 +7,16 @@ namespace nn { namespace hac { - class XciHeader : + class GameCardHeader : public fnd::IByteModel { public: - XciHeader(); - XciHeader(const XciHeader& other); + GameCardHeader(); + GameCardHeader(const GameCardHeader& other); - void operator=(const XciHeader& other); - bool operator==(const XciHeader& other) const; - bool operator!=(const XciHeader& other) const; + void operator=(const GameCardHeader& other); + bool operator==(const GameCardHeader& other) const; + bool operator!=(const GameCardHeader& other) const; // IByteModel void toBytes(); @@ -86,7 +86,7 @@ namespace hac void setUppId(uint64_t id); private: - const std::string kModuleName = "XCI_HEADER"; + const std::string kModuleName = "GAMECARD_HEADER"; // binary fnd::Vec mRawBinary; @@ -111,7 +111,7 @@ namespace hac uint32_t mSelKey; uint32_t mLimAreaPage; - // Encrypted Data + // Encrypted/Extended Data uint32_t mFwVersion[2]; uint32_t mAccCtrl1; uint32_t mWait1TimeRead; diff --git a/lib/libhac/include/nn/hac/XciUtils.h b/lib/libhac/include/nn/hac/GameCardUtils.h similarity index 64% rename from lib/libhac/include/nn/hac/XciUtils.h rename to lib/libhac/include/nn/hac/GameCardUtils.h index da7e0d3..16c07e7 100644 --- a/lib/libhac/include/nn/hac/XciUtils.h +++ b/lib/libhac/include/nn/hac/GameCardUtils.h @@ -1,15 +1,15 @@ #pragma once -#include +#include namespace nn { namespace hac { - class XciUtils + class GameCardUtils { public: static inline uint64_t blockToAddr(uint32_t block) { return ((uint64_t)block) << 9; } - static void getXciHeaderAesIv(const nn::hac::sXciHeader* hdr, byte_t* iv); + static void getXciHeaderAesIv(const nn::hac::sGcHeader* hdr, byte_t* iv); static void decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key); }; } diff --git a/lib/libhac/include/nn/hac/define/xci.h b/lib/libhac/include/nn/hac/define/gc.h similarity index 90% rename from lib/libhac/include/nn/hac/define/xci.h rename to lib/libhac/include/nn/hac/define/gc.h index 382eab3..ae710ca 100644 --- a/lib/libhac/include/nn/hac/define/xci.h +++ b/lib/libhac/include/nn/hac/define/gc.h @@ -10,9 +10,9 @@ namespace nn { namespace hac { - namespace xci + namespace gc { - static const uint32_t kXciStructMagic = _MAKE_STRUCT_MAGIC_U32("HEAD"); + static const uint32_t kGcHeaderStructMagic = _MAKE_STRUCT_MAGIC_U32("HEAD"); static const uint32_t kHeaderEncOffset = 0x90; static const uint32_t kHeaderEncSize = 0x70; static const uint32_t kPageSize = 0x200; @@ -68,7 +68,7 @@ namespace hac } #pragma pack(push,1) - struct sXciHeader + struct sGcHeader { le_uint32_t st_magic; le_uint32_t rom_area_start_page; @@ -99,16 +99,16 @@ namespace hac le_uint32_t fw_mode; le_uint32_t upp_version; byte_t reserved_01[0x4]; - byte_t upp_hash[xci::kUppHashLen]; + byte_t upp_hash[gc::kUppHashLen]; le_uint64_t upp_id; byte_t reserved_02[0x38]; // END ENCRYPTION }; - struct sXciHeaderPage + struct sGcHeaderPage { byte_t signature[fnd::rsa::kRsa2048Size]; - sXciHeader header; + sGcHeader header; }; // sizeof() = 512 (1 page) struct sInitialData @@ -123,9 +123,9 @@ namespace hac struct sKeyDataArea { sInitialData initial_data; // AES128-CCM encrypted {titlekey[16]} - byte_t encrypted_00[xci::kPageSize * 6]; // AES128-CTR encrypted {titlekey[16]} + byte_t encrypted_00[gc::kPageSize * 6]; // AES128-CTR encrypted {titlekey[16]} byte_t encrypted_00_aesctr_data[fnd::rsa::kRsa2048Size]; // RSA2048-OAEP-SHA256 encrypted AES-CTR data used for encrypted_00 {key[16],iv[16]} - byte_t reserved[xci::kPageSize - fnd::rsa::kRsa2048Size]; + byte_t reserved[gc::kPageSize - fnd::rsa::kRsa2048Size]; }; // sizeof() = 512*8 (8 pages) #pragma pack(pop) diff --git a/lib/libhac/libhac.vcxproj b/lib/libhac/libhac.vcxproj index 46790e8..483f783 100644 --- a/lib/libhac/libhac.vcxproj +++ b/lib/libhac/libhac.vcxproj @@ -38,6 +38,7 @@ + @@ -50,9 +51,10 @@ - + + @@ -83,8 +85,6 @@ - - @@ -101,6 +101,8 @@ + + @@ -130,8 +132,6 @@ - - 15.0 diff --git a/lib/libhac/libhac.vcxproj.filters b/lib/libhac/libhac.vcxproj.filters index 67d059e..39c36cb 100644 --- a/lib/libhac/libhac.vcxproj.filters +++ b/lib/libhac/libhac.vcxproj.filters @@ -27,6 +27,9 @@ Header Files\define + + Header Files\define + Header Files\define @@ -63,9 +66,6 @@ Header Files\define - - Header Files\define - Header Files @@ -108,6 +108,12 @@ Header Files + + Header Files + + + Header Files + Header Files @@ -198,12 +204,6 @@ Header Files - - Header Files - - - Header Files - @@ -248,6 +248,12 @@ Source Files + + Source Files + + + Source Files + Source Files @@ -335,11 +341,5 @@ Source Files - - Source Files - - - Source Files - \ No newline at end of file diff --git a/lib/libhac/source/XciHeader.cpp b/lib/libhac/source/GameCardHeader.cpp similarity index 54% rename from lib/libhac/source/XciHeader.cpp rename to lib/libhac/source/GameCardHeader.cpp index e786a7f..dc6bb7d 100644 --- a/lib/libhac/source/XciHeader.cpp +++ b/lib/libhac/source/GameCardHeader.cpp @@ -1,16 +1,16 @@ -#include +#include -nn::hac::XciHeader::XciHeader() +nn::hac::GameCardHeader::GameCardHeader() { clear(); } -nn::hac::XciHeader::XciHeader(const XciHeader& other) +nn::hac::GameCardHeader::GameCardHeader(const GameCardHeader& other) { *this = other; } -void nn::hac::XciHeader::operator=(const XciHeader& other) +void nn::hac::GameCardHeader::operator=(const GameCardHeader& other) { mRomAreaStartPage = other.mRomAreaStartPage; mBackupAreaStartPage = other.mBackupAreaStartPage; @@ -39,11 +39,11 @@ void nn::hac::XciHeader::operator=(const XciHeader& other) mWait2TimeWrite = other.mWait2TimeWrite; mFwMode = other.mFwMode; mUppVersion = other.mUppVersion; - memcpy(mUppHash, other.mUppHash, xci::kUppHashLen); + memcpy(mUppHash, other.mUppHash, gc::kUppHashLen); mUppId = other.mUppId; } -bool nn::hac::XciHeader::operator==(const XciHeader& other) const +bool nn::hac::GameCardHeader::operator==(const GameCardHeader& other) const { return (mRomAreaStartPage == other.mRomAreaStartPage) && (mBackupAreaStartPage == other.mBackupAreaStartPage) @@ -72,42 +72,42 @@ bool nn::hac::XciHeader::operator==(const XciHeader& other) const && (mWait2TimeWrite == other.mWait2TimeWrite) && (mFwMode == other.mFwMode) && (mUppVersion == other.mUppVersion) - && (memcmp(mUppHash, other.mUppHash, xci::kUppHashLen) == 0) + && (memcmp(mUppHash, other.mUppHash, gc::kUppHashLen) == 0) && (mUppId == other.mUppId); } -bool nn::hac::XciHeader::operator!=(const XciHeader& other) const +bool nn::hac::GameCardHeader::operator!=(const GameCardHeader& other) const { return !(*this == other); } -void nn::hac::XciHeader::toBytes() +void nn::hac::GameCardHeader::toBytes() { - fnd::Exception(kModuleName, "exportBinary() not implemented"); + fnd::Exception(kModuleName, "toBytes() not implemented"); } -void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) +void nn::hac::GameCardHeader::fromBytes(const byte_t* data, size_t len) { // check input data size - if (len < sizeof(sXciHeader)) + if (len < sizeof(sGcHeader)) { - throw fnd::Exception(kModuleName, "XCI header size is too small"); + throw fnd::Exception(kModuleName, "GameCardImage header size is too small"); } // clear internal members clear(); // allocate internal local binary copy - mRawBinary.alloc(sizeof(sXciHeader)); + mRawBinary.alloc(sizeof(sGcHeader)); memcpy(mRawBinary.data(), data, mRawBinary.size()); - // get sXciHeader ptr - const nn::hac::sXciHeader* hdr = (const nn::hac::sXciHeader*)mRawBinary.data(); + // get sGcHeader ptr + const nn::hac::sGcHeader* hdr = (const nn::hac::sGcHeader*)mRawBinary.data(); - // check XCI signature - if (hdr->st_magic.get() != xci::kXciStructMagic) + // check GameCardImage signature + if (hdr->st_magic.get() != gc::kGcHeaderStructMagic) { - throw fnd::Exception(kModuleName, "XCI header corrupt"); + throw fnd::Exception(kModuleName, "GameCardImage header corrupt"); } mRomAreaStartPage = hdr->rom_area_start_page.get(); @@ -133,8 +133,8 @@ void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) // 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(); + mFwVersion[gc::FWVER_MAJOR] = hdr->fw_version[gc::FWVER_MAJOR].get(); + mFwVersion[gc::FWVER_MINOR] = hdr->fw_version[gc::FWVER_MINOR].get(); mAccCtrl1 = hdr->acc_ctrl_1.get(); mWait1TimeRead = hdr->wait_1_time_read.get(); mWait2TimeRead = hdr->wait_2_time_read.get(); @@ -142,19 +142,19 @@ void nn::hac::XciHeader::fromBytes(const byte_t* data, size_t len) mWait2TimeWrite = hdr->wait_2_time_write.get(); mFwMode = hdr->fw_mode.get(); mUppVersion = hdr->upp_version.get(); - memcpy(mUppHash, hdr->upp_hash, xci::kUppHashLen); + memcpy(mUppHash, hdr->upp_hash, gc::kUppHashLen); mUppId = hdr->upp_id.get(); } } -const fnd::Vec& nn::hac::XciHeader::getBytes() const +const fnd::Vec& nn::hac::GameCardHeader::getBytes() const { return mRawBinary; } // variables -void nn::hac::XciHeader::clear() +void nn::hac::GameCardHeader::clear() { mRomAreaStartPage = 0; mBackupAreaStartPage = 0; @@ -183,297 +183,297 @@ void nn::hac::XciHeader::clear() mWait2TimeWrite = 0; mFwMode = 0; mUppVersion = 0; - memset(mUppHash, 0, xci::kUppHashLen); + memset(mUppHash, 0, gc::kUppHashLen); mUppId = 0; } -uint32_t nn::hac::XciHeader::getRomAreaStartPage() const +uint32_t nn::hac::GameCardHeader::getRomAreaStartPage() const { return mRomAreaStartPage; } -void nn::hac::XciHeader::setRomAreaStartPage(uint32_t startPage) +void nn::hac::GameCardHeader::setRomAreaStartPage(uint32_t startPage) { mRomAreaStartPage = startPage; } -uint32_t nn::hac::XciHeader::getBackupAreaStartPage() const +uint32_t nn::hac::GameCardHeader::getBackupAreaStartPage() const { return mBackupAreaStartPage; } -void nn::hac::XciHeader::setBackupAreaStartPage(uint32_t startPage) +void nn::hac::GameCardHeader::setBackupAreaStartPage(uint32_t startPage) { mBackupAreaStartPage = startPage; } -byte_t nn::hac::XciHeader::getKekIndex() const +byte_t nn::hac::GameCardHeader::getKekIndex() const { return mKekIndex; } -void nn::hac::XciHeader::setKekIndex(byte_t kekIndex) +void nn::hac::GameCardHeader::setKekIndex(byte_t kekIndex) { mKekIndex = kekIndex; } -byte_t nn::hac::XciHeader::getTitleKeyDecIndex() const +byte_t nn::hac::GameCardHeader::getTitleKeyDecIndex() const { return mTitleKeyDecIndex; } -void nn::hac::XciHeader::setTitleKeyDecIndex(byte_t index) +void nn::hac::GameCardHeader::setTitleKeyDecIndex(byte_t index) { mTitleKeyDecIndex = index; } -byte_t nn::hac::XciHeader::getRomSizeType() const +byte_t nn::hac::GameCardHeader::getRomSizeType() const { return mRomSize; } -void nn::hac::XciHeader::setRomSizeType(byte_t romSizeType) +void nn::hac::GameCardHeader::setRomSizeType(byte_t romSizeType) { mRomSize = romSizeType; } -byte_t nn::hac::XciHeader::getCardHeaderVersion() const +byte_t nn::hac::GameCardHeader::getCardHeaderVersion() const { return mCardHeaderVersion; } -void nn::hac::XciHeader::setCardHeaderVersion(byte_t version) +void nn::hac::GameCardHeader::setCardHeaderVersion(byte_t version) { mCardHeaderVersion = version; } -byte_t nn::hac::XciHeader::getFlags() const +byte_t nn::hac::GameCardHeader::getFlags() const { return mFlags; } -void nn::hac::XciHeader::setFlags(byte_t flags) +void nn::hac::GameCardHeader::setFlags(byte_t flags) { mFlags = flags; } -uint64_t nn::hac::XciHeader::getPackageId() const +uint64_t nn::hac::GameCardHeader::getPackageId() const { return mPackageId; } -void nn::hac::XciHeader::setPackageId(uint64_t id) +void nn::hac::GameCardHeader::setPackageId(uint64_t id) { mPackageId = id; } -uint32_t nn::hac::XciHeader::getValidDataEndPage() const +uint32_t nn::hac::GameCardHeader::getValidDataEndPage() const { return mValidDataEndPage; } -void nn::hac::XciHeader::setValidDataEndPage(uint32_t page) +void nn::hac::GameCardHeader::setValidDataEndPage(uint32_t page) { mValidDataEndPage = page; } -const fnd::aes::sAesIvCtr& nn::hac::XciHeader::getAesCbcIv() const +const fnd::aes::sAesIvCtr& nn::hac::GameCardHeader::getAesCbcIv() const { return mAesCbcIv; } -void nn::hac::XciHeader::setAesCbcIv(const fnd::aes::sAesIvCtr& iv) +void nn::hac::GameCardHeader::setAesCbcIv(const fnd::aes::sAesIvCtr& iv) { mAesCbcIv = iv; } -uint64_t nn::hac::XciHeader::getPartitionFsAddress() const +uint64_t nn::hac::GameCardHeader::getPartitionFsAddress() const { return mPartitionFsHeaderAddress; } -void nn::hac::XciHeader::setPartitionFsAddress(uint64_t address) +void nn::hac::GameCardHeader::setPartitionFsAddress(uint64_t address) { mPartitionFsHeaderAddress = address; } -uint64_t nn::hac::XciHeader::getPartitionFsSize() const +uint64_t nn::hac::GameCardHeader::getPartitionFsSize() const { return mPartitionFsHeaderSize; } -void nn::hac::XciHeader::setPartitionFsSize(uint64_t size) +void nn::hac::GameCardHeader::setPartitionFsSize(uint64_t size) { mPartitionFsHeaderSize = size; } -const fnd::sha::sSha256Hash& nn::hac::XciHeader::getPartitionFsHash() const +const fnd::sha::sSha256Hash& nn::hac::GameCardHeader::getPartitionFsHash() const { return mPartitionFsHeaderHash; } -void nn::hac::XciHeader::setPartitionFsHash(const fnd::sha::sSha256Hash& hash) +void nn::hac::GameCardHeader::setPartitionFsHash(const fnd::sha::sSha256Hash& hash) { mPartitionFsHeaderHash = hash; } -const fnd::sha::sSha256Hash& nn::hac::XciHeader::getInitialDataHash() const +const fnd::sha::sSha256Hash& nn::hac::GameCardHeader::getInitialDataHash() const { return mInitialDataHash; } -void nn::hac::XciHeader::setInitialDataHash(const fnd::sha::sSha256Hash& hash) +void nn::hac::GameCardHeader::setInitialDataHash(const fnd::sha::sSha256Hash& hash) { mInitialDataHash = hash; } -uint32_t nn::hac::XciHeader::getSelSec() const +uint32_t nn::hac::GameCardHeader::getSelSec() const { return mSelSec; } -void nn::hac::XciHeader::setSelSec(uint32_t sel_sec) +void nn::hac::GameCardHeader::setSelSec(uint32_t sel_sec) { mSelSec = sel_sec; } -uint32_t nn::hac::XciHeader::getSelT1Key() const +uint32_t nn::hac::GameCardHeader::getSelT1Key() const { return mSelT1Key; } -void nn::hac::XciHeader::setSelT1Key(uint32_t sel_t1_key) +void nn::hac::GameCardHeader::setSelT1Key(uint32_t sel_t1_key) { mSelT1Key = sel_t1_key; } -uint32_t nn::hac::XciHeader::getSelKey() const +uint32_t nn::hac::GameCardHeader::getSelKey() const { return mSelKey; } -void nn::hac::XciHeader::setSelKey(uint32_t sel_key) +void nn::hac::GameCardHeader::setSelKey(uint32_t sel_key) { mSelKey = sel_key; } -uint32_t nn::hac::XciHeader::getLimAreaPage() const +uint32_t nn::hac::GameCardHeader::getLimAreaPage() const { return mLimAreaPage; } -void nn::hac::XciHeader::setLimAreaPage(uint32_t page) +void nn::hac::GameCardHeader::setLimAreaPage(uint32_t page) { mLimAreaPage = page; } -uint32_t nn::hac::XciHeader::getFwVerMajor() const +uint32_t nn::hac::GameCardHeader::getFwVerMajor() const { - return mFwVersion[xci::FWVER_MAJOR]; + return mFwVersion[gc::FWVER_MAJOR]; } -void nn::hac::XciHeader::setFwVerMajor(uint32_t ver) +void nn::hac::GameCardHeader::setFwVerMajor(uint32_t ver) { - mFwVersion[xci::FWVER_MAJOR] = ver; + mFwVersion[gc::FWVER_MAJOR] = ver; } -uint32_t nn::hac::XciHeader::getFwVerMinor() const +uint32_t nn::hac::GameCardHeader::getFwVerMinor() const { - return mFwVersion[xci::FWVER_MINOR]; + return mFwVersion[gc::FWVER_MINOR]; } -void nn::hac::XciHeader::setFwVerMinor(uint32_t ver) +void nn::hac::GameCardHeader::setFwVerMinor(uint32_t ver) { - mFwVersion[xci::FWVER_MINOR] = ver; + mFwVersion[gc::FWVER_MINOR] = ver; } -uint32_t nn::hac::XciHeader::getAccCtrl1() const +uint32_t nn::hac::GameCardHeader::getAccCtrl1() const { return mAccCtrl1; } -void nn::hac::XciHeader::setAccCtrl1(uint32_t acc_ctrl_1) +void nn::hac::GameCardHeader::setAccCtrl1(uint32_t acc_ctrl_1) { mAccCtrl1 = acc_ctrl_1; } -uint32_t nn::hac::XciHeader::getWait1TimeRead() const +uint32_t nn::hac::GameCardHeader::getWait1TimeRead() const { return mWait1TimeRead; } -void nn::hac::XciHeader::setWait1TimeRead(uint32_t seconds) +void nn::hac::GameCardHeader::setWait1TimeRead(uint32_t seconds) { mWait1TimeRead = seconds; } -uint32_t nn::hac::XciHeader::getWait2TimeRead() const +uint32_t nn::hac::GameCardHeader::getWait2TimeRead() const { return mWait2TimeRead; } -void nn::hac::XciHeader::setWait2TimeRead(uint32_t seconds) +void nn::hac::GameCardHeader::setWait2TimeRead(uint32_t seconds) { mWait2TimeRead = seconds; } -uint32_t nn::hac::XciHeader::getWait1TimeWrite() const +uint32_t nn::hac::GameCardHeader::getWait1TimeWrite() const { return mWait1TimeWrite; } -void nn::hac::XciHeader::setWait1TimeWrite(uint32_t seconds) +void nn::hac::GameCardHeader::setWait1TimeWrite(uint32_t seconds) { mWait1TimeWrite = seconds; } -uint32_t nn::hac::XciHeader::getWait2TimeWrite() const +uint32_t nn::hac::GameCardHeader::getWait2TimeWrite() const { return mWait2TimeWrite; } -void nn::hac::XciHeader::setWait2TimeWrite(uint32_t seconds) +void nn::hac::GameCardHeader::setWait2TimeWrite(uint32_t seconds) { mWait2TimeWrite = seconds; } -uint32_t nn::hac::XciHeader::getFwMode() const +uint32_t nn::hac::GameCardHeader::getFwMode() const { return mFwMode; } -void nn::hac::XciHeader::setFwMode(uint32_t fw_mode) +void nn::hac::GameCardHeader::setFwMode(uint32_t fw_mode) { mFwMode = fw_mode; } -uint32_t nn::hac::XciHeader::getUppVersion() const +uint32_t nn::hac::GameCardHeader::getUppVersion() const { return mUppVersion; } -void nn::hac::XciHeader::setUppVersion(uint32_t version) +void nn::hac::GameCardHeader::setUppVersion(uint32_t version) { mUppVersion = version; } -const byte_t* nn::hac::XciHeader::getUppHash() const +const byte_t* nn::hac::GameCardHeader::getUppHash() const { return mUppHash; } -void nn::hac::XciHeader::setUppHash(const byte_t* hash) +void nn::hac::GameCardHeader::setUppHash(const byte_t* hash) { - memcpy(mUppHash, hash, xci::kUppHashLen); + memcpy(mUppHash, hash, gc::kUppHashLen); } -uint64_t nn::hac::XciHeader::getUppId() const +uint64_t nn::hac::GameCardHeader::getUppId() const { return mUppId; } -void nn::hac::XciHeader::setUppId(uint64_t id) +void nn::hac::GameCardHeader::setUppId(uint64_t id) { mUppId = id; } diff --git a/lib/libhac/source/GameCardUtils.cpp b/lib/libhac/source/GameCardUtils.cpp new file mode 100644 index 0000000..891736e --- /dev/null +++ b/lib/libhac/source/GameCardUtils.cpp @@ -0,0 +1,22 @@ +#include + +void nn::hac::GameCardUtils::getXciHeaderAesIv(const nn::hac::sGcHeader* hdr, byte_t* iv) +{ + for (size_t i = 0; i < 16; i++) + { + iv[15-i] = hdr->aescbc_iv.iv[i]; + } +} + +void nn::hac::GameCardUtils::decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key) +{ + byte_t iv[fnd::aes::kAesBlockSize]; + + getXciHeaderAesIv((const nn::hac::sGcHeader*)src, iv); + + // copy plain + memcpy(dst, src, nn::hac::gc::kHeaderEncOffset); + + // decrypt encrypted data + fnd::aes::AesCbcDecrypt(src + nn::hac::gc::kHeaderEncOffset, nn::hac::gc::kHeaderEncSize, key, iv, dst + nn::hac::gc::kHeaderEncOffset); +} \ No newline at end of file diff --git a/lib/libhac/source/XciUtils.cpp b/lib/libhac/source/XciUtils.cpp deleted file mode 100644 index 1954699..0000000 --- a/lib/libhac/source/XciUtils.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -void nn::hac::XciUtils::getXciHeaderAesIv(const nn::hac::sXciHeader* hdr, byte_t* iv) -{ - for (size_t i = 0; i < 16; i++) - { - iv[15-i] = hdr->aescbc_iv.iv[i]; - } -} - -void nn::hac::XciUtils::decryptXciHeader(const byte_t* src, byte_t* dst, const byte_t* key) -{ - byte_t iv[fnd::aes::kAesBlockSize]; - - getXciHeaderAesIv((const nn::hac::sXciHeader*)src, iv); - - // copy plain - memcpy(dst, src, nn::hac::xci::kHeaderEncOffset); - - // decrypt encrypted data - fnd::aes::AesCbcDecrypt(src + nn::hac::xci::kHeaderEncOffset, nn::hac::xci::kHeaderEncSize, key, iv, dst + nn::hac::xci::kHeaderEncOffset); -} \ No newline at end of file diff --git a/programs/nstool/nstool.vcxproj b/programs/nstool/nstool.vcxproj index 0cec4b7..6d7f5a9 100644 --- a/programs/nstool/nstool.vcxproj +++ b/programs/nstool/nstool.vcxproj @@ -197,7 +197,7 @@ - + @@ -218,7 +218,7 @@ - + diff --git a/programs/nstool/nstool.vcxproj.filters b/programs/nstool/nstool.vcxproj.filters index de89389..7b51530 100644 --- a/programs/nstool/nstool.vcxproj.filters +++ b/programs/nstool/nstool.vcxproj.filters @@ -76,7 +76,7 @@ Header Files - + Header Files @@ -135,7 +135,7 @@ Source Files - + Source Files diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/GameCardProcess.cpp similarity index 76% rename from programs/nstool/source/XciProcess.cpp rename to programs/nstool/source/GameCardProcess.cpp index 02fd089..d4c52d0 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/GameCardProcess.cpp @@ -2,10 +2,10 @@ #include #include #include -#include -#include "XciProcess.h" +#include +#include "GameCardProcess.h" -XciProcess::XciProcess() : +GameCardProcess::GameCardProcess() : mFile(), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), @@ -15,7 +15,7 @@ XciProcess::XciProcess() : { } -void XciProcess::process() +void GameCardProcess::process() { importHeader(); @@ -34,37 +34,37 @@ void XciProcess::process() processPartitionPfs(); } -void XciProcess::setInputFile(const fnd::SharedPtr& file) +void GameCardProcess::setInputFile(const fnd::SharedPtr& file) { mFile = file; } -void XciProcess::setKeyCfg(const KeyConfiguration& keycfg) +void GameCardProcess::setKeyCfg(const KeyConfiguration& keycfg) { mKeyCfg = keycfg; } -void XciProcess::setCliOutputMode(CliOutputMode type) +void GameCardProcess::setCliOutputMode(CliOutputMode type) { mCliOutputMode = type; } -void XciProcess::setVerifyMode(bool verify) +void GameCardProcess::setVerifyMode(bool verify) { mVerify = verify; } -void XciProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) +void GameCardProcess::setPartitionForExtract(const std::string& partition_name, const std::string& extract_path) { mExtractInfo.addElement({partition_name, extract_path}); } -void XciProcess::setListFs(bool list_fs) +void GameCardProcess::setListFs(bool list_fs) { mListFs = list_fs; } -void XciProcess::importHeader() +void GameCardProcess::importHeader() { fnd::Vec scratch; @@ -74,22 +74,22 @@ void XciProcess::importHeader() } // read header page - (*mFile)->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sXciHeaderPage)); + (*mFile)->read((byte_t*)&mHdrPage, 0, sizeof(nn::hac::sGcHeaderPage)); // allocate memory for and decrypt sXciHeader - scratch.alloc(sizeof(nn::hac::sXciHeader)); + scratch.alloc(sizeof(nn::hac::sGcHeader)); fnd::aes::sAes128Key header_key; mKeyCfg.getXciHeaderKey(header_key); - nn::hac::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), header_key.key); + nn::hac::GameCardUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), header_key.key); // deserialise header mHdr.fromBytes(scratch.data(), scratch.size()); } -void XciProcess::displayHeader() +void GameCardProcess::displayHeader() { - std::cout << "[XCI Header]" << std::endl; + std::cout << "[GameCard Header]" << std::endl; std::cout << " CardHeaderVersion: " << std::dec << (uint32_t)mHdr.getCardHeaderVersion() << std::endl; std::cout << " RomSize: " << getRomSizeStr(mHdr.getRomSizeType()); if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED)) @@ -128,22 +128,22 @@ void XciProcess::displayHeader() { std::cout << " RomAreaStartPage: 0x" << std::hex << mHdr.getRomAreaStartPage(); if (mHdr.getRomAreaStartPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getRomAreaStartPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getRomAreaStartPage()) << ")"; std::cout << std::endl; std::cout << " BackupAreaStartPage: 0x" << std::hex << mHdr.getBackupAreaStartPage(); if (mHdr.getBackupAreaStartPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getBackupAreaStartPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getBackupAreaStartPage()) << ")"; std::cout << std::endl; std::cout << " ValidDataEndPage: 0x" << std::hex << mHdr.getValidDataEndPage(); if (mHdr.getValidDataEndPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getValidDataEndPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getValidDataEndPage()) << ")"; std::cout << std::endl; std::cout << " LimArea: 0x" << std::hex << mHdr.getLimAreaPage(); if (mHdr.getLimAreaPage() != (uint32_t)(-1)) - std::cout << " (0x" << std::hex << nn::hac::XciUtils::blockToAddr(mHdr.getLimAreaPage()) << ")"; + std::cout << " (0x" << std::hex << nn::hac::GameCardUtils::blockToAddr(mHdr.getLimAreaPage()) << ")"; std::cout << std::endl; std::cout << " PartitionFs Header:" << std::endl; @@ -160,7 +160,7 @@ void XciProcess::displayHeader() if (mHdr.getFwVerMinor() != 0) { - std::cout << "[XCI Extended Header]" << std::endl; + std::cout << "[GameCard Extended Header]" << std::endl; std::cout << " FwVersion: v" << std::dec << mHdr.getFwVerMajor() << "." << mHdr.getFwVerMinor() << std::endl; std::cout << " AccCtrl1: 0x" << std::hex << mHdr.getAccCtrl1() << std::endl; std::cout << " CardClockRate: " << getCardClockRate(mHdr.getAccCtrl1()) << std::endl; @@ -178,7 +178,7 @@ void XciProcess::displayHeader() } } -bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) +bool GameCardProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* test_hash) { fnd::Vec scratch; fnd::sha::sSha256Hash calc_hash; @@ -188,23 +188,23 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t return calc_hash.compare(test_hash); } -void XciProcess::validateXciSignature() +void GameCardProcess::validateXciSignature() { fnd::rsa::sRsa2048Key header_sign_key; fnd::sha::sSha256Hash calc_hash; - fnd::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nn::hac::sXciHeader), calc_hash.bytes); + fnd::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nn::hac::sGcHeader), calc_hash.bytes); mKeyCfg.getXciHeaderSignKey(header_sign_key); if (fnd::rsa::pkcs::rsaVerify(header_sign_key, fnd::sha::HASH_SHA256, calc_hash.bytes, mHdrPage.signature) != 0) { - std::cout << "[WARNING] XCI Header Signature: FAIL" << std::endl; + std::cout << "[WARNING] GameCard Header Signature: FAIL" << std::endl; } } -void XciProcess::processRootPfs() +void GameCardProcess::processRootPfs() { if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize(), mHdr.getPartitionFsHash().bytes) == false) { - std::cout << "[WARNING] XCI Root HFS0: FAIL (bad hash)" << std::endl; + std::cout << "[WARNING] GameCard Root HFS0: FAIL (bad hash)" << std::endl; } mRootPfs.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getPartitionFsAddress(), mHdr.getPartitionFsSize())); mRootPfs.setListFs(mListFs); @@ -214,7 +214,7 @@ void XciProcess::processRootPfs() mRootPfs.process(); } -void XciProcess::processPartitionPfs() +void GameCardProcess::processPartitionPfs() { const fnd::List& rootPartitions = mRootPfs.getPfsHeader().getFileList(); for (size_t i = 0; i < rootPartitions.size(); i++) @@ -222,7 +222,7 @@ void XciProcess::processPartitionPfs() // this must be validated here because only the size of the root partiton header is known at verification time if (mVerify && validateRegionOfFile(mHdr.getPartitionFsAddress() + rootPartitions[i].offset, rootPartitions[i].hash_protected_size, rootPartitions[i].hash.bytes) == false) { - std::cout << "[WARNING] XCI " << rootPartitions[i].name << " Partition HFS0: FAIL (bad hash)" << std::endl; + std::cout << "[WARNING] GameCard " << rootPartitions[i].name << " Partition HFS0: FAIL (bad hash)" << std::endl; } PfsProcess tmp; @@ -238,28 +238,28 @@ void XciProcess::processPartitionPfs() } } -const char* XciProcess::getRomSizeStr(byte_t rom_size) const +const char* GameCardProcess::getRomSizeStr(byte_t rom_size) const { const char* str = nullptr; switch (rom_size) { - case (nn::hac::xci::ROM_SIZE_1GB): + case (nn::hac::gc::ROM_SIZE_1GB): str = "1GB"; break; - case (nn::hac::xci::ROM_SIZE_2GB): + case (nn::hac::gc::ROM_SIZE_2GB): str = "2GB"; break; - case (nn::hac::xci::ROM_SIZE_4GB): + case (nn::hac::gc::ROM_SIZE_4GB): str = "4GB"; break; - case (nn::hac::xci::ROM_SIZE_8GB): + case (nn::hac::gc::ROM_SIZE_8GB): str = "8GB"; break; - case (nn::hac::xci::ROM_SIZE_16GB): + case (nn::hac::gc::ROM_SIZE_16GB): str = "16GB"; break; - case (nn::hac::xci::ROM_SIZE_32GB): + case (nn::hac::gc::ROM_SIZE_32GB): str = "32GB"; break; default: @@ -270,19 +270,19 @@ const char* XciProcess::getRomSizeStr(byte_t rom_size) const return str; } -const char* XciProcess::getHeaderFlagStr(byte_t flag) const +const char* GameCardProcess::getHeaderFlagStr(byte_t flag) const { const char* str = nullptr; switch (flag) { - case (nn::hac::xci::FLAG_AUTOBOOT): + case (nn::hac::gc::FLAG_AUTOBOOT): str = "AutoBoot"; break; - case (nn::hac::xci::FLAG_HISTORY_ERASE): + case (nn::hac::gc::FLAG_HISTORY_ERASE): str = "HistoryErase"; break; - case (nn::hac::xci::FLAG_REPAIR_TOOL): + case (nn::hac::gc::FLAG_REPAIR_TOOL): str = "RepairTool"; break; default: @@ -294,16 +294,16 @@ const char* XciProcess::getHeaderFlagStr(byte_t flag) const } -const char* XciProcess::getCardClockRate(uint32_t acc_ctrl_1) const +const char* GameCardProcess::getCardClockRate(uint32_t acc_ctrl_1) const { const char* str = nullptr; switch (acc_ctrl_1) { - case (nn::hac::xci::CLOCK_RATE_25): + case (nn::hac::gc::CLOCK_RATE_25): str = "20 MHz"; break; - case (nn::hac::xci::CLOCK_RATE_50): + case (nn::hac::gc::CLOCK_RATE_50): str = "50 MHz"; break; default: diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/GameCardProcess.h similarity index 88% rename from programs/nstool/source/XciProcess.h rename to programs/nstool/source/GameCardProcess.h index 6e034e7..d1cba42 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/GameCardProcess.h @@ -4,16 +4,16 @@ #include #include #include -#include +#include #include "KeyConfiguration.h" #include "PfsProcess.h" #include "common.h" -class XciProcess +class GameCardProcess { public: - XciProcess(); + GameCardProcess(); void process(); @@ -28,7 +28,7 @@ public: void setListFs(bool list_fs); private: - const std::string kModuleName = "XciProcess"; + const std::string kModuleName = "GameCardProcess"; const std::string kXciMountPointName = "gamecard:/"; fnd::SharedPtr mFile; @@ -55,8 +55,8 @@ private: bool mListFs; - nn::hac::sXciHeaderPage mHdrPage; - nn::hac::XciHeader mHdr; + nn::hac::sGcHeaderPage mHdrPage; + nn::hac::GameCardHeader mHdr; PfsProcess mRootPfs; fnd::List mExtractInfo; diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index 94e0d1c..202d99e 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -590,8 +590,8 @@ FileType UserSettings::getFileTypeFromString(const std::string& type_str) std::transform(str.begin(), str.end(), str.begin(), ::tolower); FileType type; - if (str == "xci") - type = FILE_XCI; + if (str == "gc" || str == "gamecard" || str == "xci") + type = FILE_GC; else if (str == "nsp") type = FILE_NSP; else if (str == "partitionfs" || str == "hashedpartitionfs" \ @@ -600,9 +600,9 @@ FileType UserSettings::getFileTypeFromString(const std::string& type_str) type = FILE_PARTITIONFS; else if (str == "romfs") type = FILE_ROMFS; - else if (str == "nca") + else if (str == "nca" || str == "contentarchive") type = FILE_NCA; - else if (str == "meta") + else if (str == "meta" || str == "npdm") type = FILE_META; else if (str == "cnmt") type = FILE_CNMT; @@ -645,8 +645,8 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path) #define _ASSERT_SIZE(sz) (scratch.size() >= (sz)) // test npdm - if (_ASSERT_SIZE(sizeof(nn::hac::sXciHeaderPage)) && _TYPE_PTR(nn::hac::sXciHeaderPage)->header.st_magic.get() == nn::hac::xci::kXciStructMagic) - file_type = FILE_XCI; + if (_ASSERT_SIZE(sizeof(nn::hac::sGcHeaderPage)) && _TYPE_PTR(nn::hac::sGcHeaderPage)->header.st_magic.get() == nn::hac::gc::kGcHeaderStructMagic) + file_type = FILE_GC; // test pfs0 else if (_ASSERT_SIZE(sizeof(nn::hac::sPfsHeader)) && _TYPE_PTR(nn::hac::sPfsHeader)->st_magic.get() == nn::hac::pfs::kPfsStructMagic) file_type = FILE_PARTITIONFS; diff --git a/programs/nstool/source/common.h b/programs/nstool/source/common.h index 614ab26..6c464e7 100644 --- a/programs/nstool/source/common.h +++ b/programs/nstool/source/common.h @@ -10,7 +10,7 @@ static const size_t kNcaKeakNum = nn::hac::nca::kKeyAreaEncryptionKeyNum; enum FileType { - FILE_XCI, + FILE_GC, FILE_NSP, FILE_PARTITIONFS, FILE_ROMFS, diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 4f1776a..655ec34 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -3,7 +3,7 @@ #include #include #include "UserSettings.h" -#include "XciProcess.h" +#include "GameCardProcess.h" #include "PfsProcess.h" #include "RomfsProcess.h" #include "NcaProcess.h" @@ -38,9 +38,9 @@ int main(int argc, char** argv) fnd::SharedPtr inputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read)); - if (user_set.getFileType() == FILE_XCI) + if (user_set.getFileType() == FILE_GC) { - XciProcess xci; + GameCardProcess xci; xci.setInputFile(inputFile); @@ -49,13 +49,13 @@ int main(int argc, char** argv) xci.setVerifyMode(user_set.isVerifyFile()); if (user_set.getXciUpdatePath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kUpdatePartitionStr, user_set.getXciUpdatePath().var); + xci.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, user_set.getXciUpdatePath().var); if (user_set.getXciLogoPath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kLogoPartitionStr, user_set.getXciLogoPath().var); + xci.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, user_set.getXciLogoPath().var); if (user_set.getXciNormalPath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kNormalPartitionStr, user_set.getXciNormalPath().var); + xci.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().var); if (user_set.getXciSecurePath().isSet) - xci.setPartitionForExtract(nn::hac::xci::kSecurePartitionStr, user_set.getXciSecurePath().var); + xci.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().var); xci.setListFs(user_set.isListFs()); xci.process();