diff --git a/lib/libnx/include/nx/NcaHeader.h b/lib/libnx/include/nx/NcaHeader.h index 8dc0cea..4c11b50 100644 --- a/lib/libnx/include/nx/NcaHeader.h +++ b/lib/libnx/include/nx/NcaHeader.h @@ -13,6 +13,12 @@ namespace nx public fnd::ISerialiseableBinary { public: + enum FormatVersion + { + NCA2_FORMAT, + NCA3_FORMAT + }; + enum DistributionType { DIST_DOWNLOAD, @@ -133,72 +139,26 @@ namespace nx struct sNcaHeader { - private: - u8 signature_[4]; - u8 distribution_type_; - u8 content_type_; - u8 key_generation_; - u8 key_area_encryption_key_index_; - u64 nca_size_; - u64 program_id_; - u32 content_index_; - u32 sdk_addon_version_; - u8 reserved_2[0x20]; + char signature[4]; + byte_t distribution_type; + byte_t content_type; + byte_t key_generation; + byte_t key_area_encryption_key_index; + le_uint64_t nca_size; + le_uint64_t program_id; + le_uint32_t content_index; + le_uint32_t sdk_addon_version; + byte_t reserved_2[0x20]; struct sNcaSection { - private: - u32 start_; // block units - u32 end_; // block units - u8 enabled_; - u8 reserved[7]; - public: - u32 start() const { return le_word(start_); } - void set_start(u32 offset) { start_ = le_word(offset); } - - u32 end() const { return le_word(end_); } - void set_end(u32 offset) { end_ = le_word(offset); } - - u8 enabled() const { return enabled_; } - void set_enabled(u8 is_enabled) { enabled_ = is_enabled; } - } section_[kSectionNum]; - crypto::sha::sSha256Hash section_hash_[kSectionNum]; - crypto::aes::sAes128Key enc_aes_keys_[kAesKeyNum]; - public: - const char* signature() const { return (const char*)signature_; } - void set_signature(const char* signature) { memcpy(signature_, signature, 4); } - - u8 distribution_type() const { return distribution_type_; } - void set_distribution_type(u8 type) { distribution_type_ = type; } - - u8 content_type() const { return content_type_; } - void set_content_type(u8 type) { content_type_ = type; } - - u8 key_generation() const { return key_generation_; } - void set_key_generation(u8 type) { key_generation_ = type; } - - u8 key_area_encryption_key_index() const { return key_area_encryption_key_index_; } - void set_key_area_encryption_key_index(u8 index) { key_area_encryption_key_index_ = index; } - - u64 nca_size() const { return le_dword(nca_size_); } - void set_nca_size(u64 nca_size) { nca_size_ = le_dword(nca_size); } - - u64 program_id() const { return le_dword(program_id_); } - void set_program_id(u64 program_id) { program_id_ = le_dword(program_id); } - - u32 content_index() const { return le_word(content_index_); } - void set_content_index(u32 index) { content_index_ = le_word(index); } - - u32 sdk_addon_version() const { return le_word(sdk_addon_version_); } - void set_sdk_addon_version(u32 version) { sdk_addon_version_ = le_word(version); } - - const sNcaSection& section(u8 index) const { return section_[index%kSectionNum]; } - sNcaSection& section(u8 index) { return section_[index%kSectionNum]; } - - const crypto::sha::sSha256Hash& section_hash(u8 index) const { return section_hash_[index%kSectionNum]; } - crypto::sha::sSha256Hash& section_hash(u8 index) { return section_hash_[index%kSectionNum]; } - - const crypto::aes::sAes128Key& enc_aes_key(u8 index) const { return enc_aes_keys_[index%kAesKeyNum]; } - crypto::aes::sAes128Key& enc_aes_key(u8 index) { return enc_aes_keys_[index%kAesKeyNum]; } + le_uint32_t start; // block units + le_uint32_t end; // block units + byte_t enabled; + byte_t reserved[7]; + } section[kSectionNum]; + crypto::sha::sSha256Hash section_hash[kSectionNum]; + crypto::aes::sAes128Key enc_aes_key[kAesKeyNum]; + }; #pragma pack (pop) diff --git a/lib/libnx/source/NcaHeader.cpp b/lib/libnx/source/NcaHeader.cpp index ca19423..9b2d19a 100644 --- a/lib/libnx/source/NcaHeader.cpp +++ b/lib/libnx/source/NcaHeader.cpp @@ -8,15 +8,15 @@ void NcaHeader::exportBinary() mBinaryBlob.alloc(sizeof(sNcaHeader)); sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes(); - hdr->set_signature(kNcaSig.c_str()); - hdr->set_distribution_type(mDistributionType); - hdr->set_content_type(mContentType); - hdr->set_key_generation(mEncryptionType); - hdr->set_key_area_encryption_key_index(mKeyIndex); - hdr->set_nca_size(mNcaSize); - hdr->set_program_id(mProgramId); - hdr->set_content_index(mContentIndex); - hdr->set_sdk_addon_version(mSdkAddonVersion); + strncpy(hdr->signature, kNcaSig.c_str(), 4); + hdr->distribution_type = mDistributionType; + hdr->content_type = mContentType; + hdr->key_generation = mEncryptionType; + hdr->key_area_encryption_key_index = mKeyIndex; + hdr->nca_size = mNcaSize; + hdr->program_id = mProgramId; + hdr->content_index = mContentIndex; + hdr->sdk_addon_version = mSdkAddonVersion; // TODO: properly reconstruct NCA layout? atm in hands of user @@ -25,15 +25,15 @@ void NcaHeader::exportBinary() // determine section index u8 section = mSections.getSize() - 1 - i; - hdr->section(section).set_start(sizeToBlockNum(mSections[i].offset)); - hdr->section(section).set_end(sizeToBlockNum(mSections[i].offset) + sizeToBlockNum(mSections[i].size)); - hdr->section(section).set_enabled(1); - hdr->section_hash(section) = mSections[i].hash; + hdr->section[section].start = sizeToBlockNum(mSections[i].offset); + hdr->section[section].end = (sizeToBlockNum(mSections[i].offset) + sizeToBlockNum(mSections[i].size)); + hdr->section[section].enabled = true; + hdr->section_hash[section] = mSections[i].hash; } for (size_t i = 0; i < kAesKeyNum; i++) { - hdr->enc_aes_key(i) = mEncAesKeys[i]; + hdr->enc_aes_key[i] = mEncAesKeys[i]; } } @@ -51,19 +51,19 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len) sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes(); - if (memcmp(hdr->signature(), kNcaSig.c_str(), 4) != 0) + if (memcmp(hdr->signature, kNcaSig.c_str(), 4) != 0) { throw fnd::Exception(kModuleName, "NCA header corrupt"); } - mDistributionType = (DistributionType)hdr->distribution_type(); - mContentType = (ContentType)hdr->content_type(); - mEncryptionType = (EncryptionType)hdr->key_generation(); - mKeyIndex = (EncryptionKeyIndex)hdr->key_area_encryption_key_index(); - mNcaSize = hdr->nca_size(); - mProgramId = hdr->program_id(); - mContentIndex = hdr->content_index(); - mSdkAddonVersion = hdr->sdk_addon_version(); + mDistributionType = (DistributionType)hdr->distribution_type; + mContentType = (ContentType)hdr->content_type; + mEncryptionType = (EncryptionType)hdr->key_generation; + mKeyIndex = (EncryptionKeyIndex)hdr->key_area_encryption_key_index; + mNcaSize = *hdr->nca_size; + mProgramId = *hdr->program_id; + mContentIndex = *hdr->content_index; + mSdkAddonVersion = *hdr->sdk_addon_version; for (size_t i = 0; i < kSectionNum; i++) { @@ -71,7 +71,7 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len) u8 section = kSectionNum - 1 - i; // skip sections that don't exist - if (hdr->section(section).start() == 0 && hdr->section(section).end() == 0) continue; + if (*hdr->section[section].start == 0 && *hdr->section[section].end == 0) continue; EncryptionType encType = mEncryptionType; if (encType == CRYPT_AUTO) @@ -87,12 +87,12 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len) } // add high level struct - mSections.addElement({ blockNumToSize(hdr->section(section).start()), blockNumToSize(hdr->section(section).end() - hdr->section(section).start()), encType, hdr->section_hash(section) }); + mSections.addElement({ blockNumToSize(*hdr->section[section].start), blockNumToSize(hdr->section[section].end.get() - hdr->section[section].start.get()), encType, hdr->section_hash[section] }); } for (size_t i = 0; i < kAesKeyNum; i++) { - mEncAesKeys.addElement(hdr->enc_aes_key(i)); + mEncAesKeys.addElement(hdr->enc_aes_key[i]); } }