1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-26 20:22:17 +00:00
nxdumptool/include/core/nca.h

613 lines
31 KiB
C
Raw Normal View History

2020-04-16 01:06:41 +01:00
/*
* nca.h
2020-04-16 01:06:41 +01:00
*
2023-04-08 12:42:22 +01:00
* Copyright (c) 2020-2023, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
2020-04-16 01:06:41 +01:00
*
* nxdumptool is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
2020-04-16 01:06:41 +01:00
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2020-04-16 01:06:41 +01:00
*/
2020-04-11 06:28:26 +01:00
#pragma once
#ifndef __NCA_H__
#define __NCA_H__
2020-04-20 11:39:41 +01:00
#include "tik.h"
2020-04-11 06:28:26 +01:00
#ifdef __cplusplus
extern "C" {
#endif
#define NCA_FS_HEADER_COUNT 4
#define NCA_FULL_HEADER_LENGTH (sizeof(NcaHeader) + (sizeof(NcaFsHeader) * NCA_FS_HEADER_COUNT))
2020-04-11 06:28:26 +01:00
#define NCA_NCA0_MAGIC 0x4E434130 /* "NCA0". */
#define NCA_NCA2_MAGIC 0x4E434132 /* "NCA2". */
#define NCA_NCA3_MAGIC 0x4E434133 /* "NCA3". */
2020-04-11 06:28:26 +01:00
2022-06-24 18:39:15 +01:00
#define NCA_KEY_AREA_KEY_COUNT 0x10
#define NCA_KEY_AREA_SIZE (NCA_KEY_AREA_KEY_COUNT * AES_128_KEY_SIZE)
#define NCA_KEY_AREA_USED_KEY_COUNT 3
#define NCA_KEY_AREA_USED_SIZE (NCA_KEY_AREA_USED_KEY_COUNT * AES_128_KEY_SIZE)
2020-04-26 09:35:01 +01:00
#define NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT 5
2020-04-11 06:28:26 +01:00
#define NCA_IVFC_MAGIC 0x49564643 /* "IVFC". */
#define NCA_IVFC_MAX_LEVEL_COUNT 7
#define NCA_IVFC_LEVEL_COUNT (NCA_IVFC_MAX_LEVEL_COUNT - 1)
#define NCA_IVFC_BLOCK_SIZE(x) (1U << (x))
2020-04-11 06:28:26 +01:00
#define NCA_BKTR_MAGIC 0x424B5452 /* "BKTR". */
#define NCA_BKTR_VERSION 1
2020-04-11 06:28:26 +01:00
#define NCA_FS_SECTOR_SIZE 0x200
#define NCA_FS_SECTOR_OFFSET(x) ((u64)(x) * NCA_FS_SECTOR_SIZE)
#define NCA_AES_XTS_SECTOR_SIZE 0x200
2020-04-11 06:28:26 +01:00
#define NCA_SIGNATURE_AREA_SIZE 0x200 /* Signature is calculated starting at the NCA header magic word. */
2020-04-15 21:50:07 +01:00
typedef enum {
NcaDistributionType_Download = 0,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaDistributionType_GameCard = 1,
NcaDistributionType_Count = 2 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaDistributionType;
2020-04-11 06:28:26 +01:00
2020-04-15 21:50:07 +01:00
typedef enum {
2020-05-01 16:06:24 +01:00
NcaContentType_Program = 0,
NcaContentType_Meta = 1,
NcaContentType_Control = 2,
NcaContentType_Manual = 3,
NcaContentType_Data = 4,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaContentType_PublicData = 5,
NcaContentType_Count = 6 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaContentType;
2020-04-11 06:28:26 +01:00
/// 'NcaKeyGeneration_Current' will always point to the last known key generation value.
/// TODO: update on master key changes.
2020-04-15 21:50:07 +01:00
typedef enum {
NcaKeyGeneration_Since100NUP = 0, ///< 1.0.0 - 2.3.0.
NcaKeyGeneration_Since300NUP = 2, ///< 3.0.0.
NcaKeyGeneration_Since301NUP = 3, ///< 3.0.1 - 3.0.2.
NcaKeyGeneration_Since400NUP = 4, ///< 4.0.0 - 4.1.0.
NcaKeyGeneration_Since500NUP = 5, ///< 5.0.0 - 5.1.0.
NcaKeyGeneration_Since600NUP = 6, ///< 6.0.0 - 6.1.0.
NcaKeyGeneration_Since620NUP = 7, ///< 6.2.0.
NcaKeyGeneration_Since700NUP = 8, ///< 7.0.0 - 8.0.1.
NcaKeyGeneration_Since810NUP = 9, ///< 8.1.0 - 8.1.1.
NcaKeyGeneration_Since900NUP = 10, ///< 9.0.0 - 9.0.1.
NcaKeyGeneration_Since910NUP = 11, ///< 9.1.0 - 12.0.3.
NcaKeyGeneration_Since1210NUP = 12, ///< 12.1.0.
NcaKeyGeneration_Since1300NUP = 13, ///< 13.0.0 - 13.2.1.
2022-06-24 01:22:01 +01:00
NcaKeyGeneration_Since1400NUP = 14, ///< 14.0.0 - 14.1.2.
NcaKeyGeneration_Since1500NUP = 15, ///< 15.0.0 - 15.0.1.
NcaKeyGeneration_Since1600NUP = 16, ///< 16.0.0 - 16.1.0.
Rework signature/cert/tik interfaces. * signature: add comments to SignatureType enum entries about the exact signing algorithms and padding schemes used. * signature: rename signatureGetSigType() -> signatureGetTypeFromSignedBlob(). * signature: rename signatureIsValidSigType() -> signatureIsValidType(). * signature: rename signatureGetSigSize() -> signatureGetSigSizeByType(). * signature: rename signatureGetBlockSize() -> signatureGetBlockSizeByType(). * signature: rename signatureGetSig() -> signatureGetSigFromSignedBlob(). * signature: rename signatureGetPayload() -> signatureGetPayloadFromSignedBlob(). * signature: add signatureGetBlockSizeFromSignedBlob(). * cert: add more comments to the code. * cert: update code to match signature interface changes. * cert: add CERT_RSA_PUB_EXP_SIZE macro. * cert: change public_exponent field in CertPublicKeyBlockRsa* structs from u32 to u8 array. * cert: add size field to CertificateChain struct. * cert: rename certGetCommonBlock() -> certGetCommonBlockFromSignedCertBlob. * cert: rename certGetPublicKeySize() -> certGetPublicKeySizeByType(). * cert: rename certGetPublicKeyBlockSize() -> certGetPublicKeyBlockSizeByType(). * cert: rename certIsValidCertificate() -> certIsValidSignedCertBlob(). * cert: rename certGetSignedCertificateSize() -> certGetSignedCertBlobSize(). * cert: rename certGetSignedCertificateHashAreaSize() -> certGetSignedCertBlobHashAreaSize(). * cert: remove certGetPublicKey(), certGetPublicExponent() and certCalculateRawCertificateChainSize(). * cert: add certGetPublicKeyTypeFromCommonBlock(), certGetPublicKeyTypeFromSignedCertBlob(), certGetPublicKeySizeFromSignedCertBlob(), certGetPublicKeyBlockSizeFromSignedCertBlob(), certGetPublicKeyFromSignedCertBlob(), certGetPublicExponentFromSignedCertBlob(), certIsValidCertificate() (w/diff func sig), certGetCommonBlockFromCertificate(), certGetPublicKeyTypeFromCertificate(), certGetPublicKeySizeFromCertificate(), certGetPublicKeyBlockSizeFromCertificate(), certGetPublicKeyFromCertificate(), certGetPublicExponentFromCertificate() and certGetHashAreaSizeFromCertificate() functions. * cert: avoid byteswapping the public key type value in multiple places -- it is now only being done in certGetPublicKeyTypeFromCommonBlock(). * cert: call certFreeCertificateChain() in _certRetrieveCertificateChainBySignatureIssuer() before attempting to retrieve the certificate chain. * cert: other minor changes and corrections. * tik: update code to match signature interface changes. * tik: add missing comments to TikPropertyMask enum entries. * tik: add key_generation, enc_titlekey_str and dec_titlekey_str fields to Ticket struct. * tik: update tikRetrieveTicketByRightsId() to also take in a key_generation argument, instead of getting it from the rights ID (which could fail if it's using a key generation lower than HOS 3.0.1) or the key_generation field from the common ticket block (which could fail if the ticket has been tampered by certain tools). * tik: rename tikGetCommonBlock() -> tikGetCommonBlockFromSignedTicketBlob(). * tik: change function signature for tikGetTicketSectionRecordsBlockSize(). * tik: rename tikIsValidTicket() -> tikIsValidSignedTicketBlob(). * tik: rename tikGetSignedTicketSize() -> tikGetSignedTicketBlobSize(). * tik: rename tikGetSignedTicketHashAreaSize() -> tikGetSignedTicketBlobHashAreaSize(). * tik: rename tikGetEncryptedTitleKeyFromTicket() -> tikGetEncryptedTitleKey(). * tik: add tikIsValidTicket() (w/diff func sig), tikGetCommonBlockFromTicket(), tikGetHashAreaSizeFromTicket(), tikFixTamperedCommonTicket(), tikVerifyRsa2048Sha256Signature() and tikDecryptVolatileTicket() functions. Ticket signature verification is only carried out for common tickets in tikFixTamperedCommonTicket(). * tik: change argument order in tikGetTicketEntryOffsetFromTicketList() and tikRetrieveTicketEntryFromTicketBin(). * tik: add TIK_COMMON_CERT_NAME and TIK_DEV_CERT_ISSUER macros. * tik: use a scoped lock when calling tikRetrieveTicketFromEsSaveDataByRightsId(). * tik: simplify certificate chain retrieval steps in tikConvertPersonalizedTicketToCommonTicket() by always using the XS00000020 certificate. * tik: wipe license_type and property_mask fields in tikConvertPersonalizedTicketToCommonTicket(). * tik: other minor changes and corrections. Other changes include: * keys: fix key generation checks in keysGetNcaKeyAreaKeyEncryptionKey() and keysGetTicketCommonKey(). * rsa: move core logic from rsa2048VerifySha256BasedPssSignature() into a new function: rsa2048VerifySha256BasedSignature(). * rsa: add rsa2048VerifySha256BasedPkcs1v15Signature() function.
2023-10-15 16:53:46 +01:00
NcaKeyGeneration_Since1700NUP = 17, ///< 17.0.0+.
NcaKeyGeneration_Current = NcaKeyGeneration_Since1700NUP,
NcaKeyGeneration_Max = 32
} NcaKeyGeneration;
2020-04-11 06:28:26 +01:00
2020-04-15 21:50:07 +01:00
typedef enum {
NcaKeyAreaEncryptionKeyIndex_Application = 0,
NcaKeyAreaEncryptionKeyIndex_Ocean = 1,
NcaKeyAreaEncryptionKeyIndex_System = 2,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaKeyAreaEncryptionKeyIndex_Count = 3 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaKeyAreaEncryptionKeyIndex;
2020-04-11 06:28:26 +01:00
2022-04-18 22:59:25 +01:00
/// 'NcaSignatureKeyGeneration_Current' will always point to the last known key generation value.
Preliminar 15.x support. This commit uses my yet unmerged libnx PR to update ncm_types.h. PoC code hasn't been updated yet, so proper support for DLC updates will arrive at a later time. Note to self: implement a way to provide access to loaded DataPatch TitleInfo entries (linked list hell). * bktr: renamed bktrBucketInitializeSubStorageReadParams to bktrInitializeSubStorageReadParams to avoid redundancy, added debug code to dump BucketInfo and BucketTree tables if BucketTree storage initialization fails. * cnmt: updated ContentMetaAddOnContentMetaExtendedHeader struct to its 15.x equivalent, added ContentMetaLegacyAddOnContentMetaExtendedHeader struct, added ContentMetaDataPatchMetaExtendedHeader struct, updated the cnmtGetRequiredTitleId and cnmtGetRequiredTitleVersion functions to support DataPatch titles, updated cnmtInitializeContext to support both the new AddOnContent extended header and DataPatch titles, added debug code to dump the whole CNMT if context initialization fails, updated cnmtGenerateAuthoringToolXml to support DataPatch titles. * keys: updated block hashes to match 15.x keyset, use case-insensitive comparison while looking for entry names in keysReadKeysFromFile, make sure the eticket_rsa_kek is non-zero before proceeding in keysGetDecryptedEticketRsaDeviceKey. * nca: updated NcaKeyGeneration enum, added reminder about updating NcaSignatureKeyGeneration if necessary, replaced ncaFsSectionCheckHashRegionAccess with ncaFsSectionCheckPlaintextHashRegionAccess, removed all extents checks on Patch RomFS and sparse sections, updated ncaGetFsSectionTypeName to reflect if a FS section holds a sparse layer or not. * nca_storage: updated ncaStorageInitializeContext to avoid initializing a compressed storage if a sparse layer is also used (fixes issues with Them's Fightin' Herds), updated ncaStorageSetPatchOriginalSubStorage to enforce the presence of a compressed storage in a patch if the base FS holds a compressed storage. * npdm: added reminder about updating NpdmSignatureKeyGeneration if necessary, updated NpdmFsAccessControlFlags enum, updated NpdmAccessibility enum, updated NpdmSystemCallId enum, fixed typos. * title: updated all relevant functions that deal with NcmContentMetaType values to also handle DataPatch titles, added functions to handle DataPatchId values, removed titleConvertNcmContentSizeToU64 and titleConvertU64ToNcmContentSize functions in favor of ncmContentInfoSizeToU64 and ncmU64ToContentInfoSize from my unmerged libnx PR, updated internal arrays to match 15.x changes, renamed titleOrphanTitleInfoSortFunction to titleInfoEntrySortFunction and updated it to also sort entries by version and storage ID, updated titleGenerateTitleInfoEntriesForTitleStorage to sort TitleInfo entries, simplified titleDuplicateTitleInfo a bit by using macros.
2022-10-23 15:44:47 +01:00
/// TODO: update on signature keygen changes.
typedef enum {
2022-04-18 22:59:25 +01:00
NcaSignatureKeyGeneration_Since100NUP = 0, ///< 1.0.0 - 8.1.1.
Rework signature/cert/tik interfaces. * signature: add comments to SignatureType enum entries about the exact signing algorithms and padding schemes used. * signature: rename signatureGetSigType() -> signatureGetTypeFromSignedBlob(). * signature: rename signatureIsValidSigType() -> signatureIsValidType(). * signature: rename signatureGetSigSize() -> signatureGetSigSizeByType(). * signature: rename signatureGetBlockSize() -> signatureGetBlockSizeByType(). * signature: rename signatureGetSig() -> signatureGetSigFromSignedBlob(). * signature: rename signatureGetPayload() -> signatureGetPayloadFromSignedBlob(). * signature: add signatureGetBlockSizeFromSignedBlob(). * cert: add more comments to the code. * cert: update code to match signature interface changes. * cert: add CERT_RSA_PUB_EXP_SIZE macro. * cert: change public_exponent field in CertPublicKeyBlockRsa* structs from u32 to u8 array. * cert: add size field to CertificateChain struct. * cert: rename certGetCommonBlock() -> certGetCommonBlockFromSignedCertBlob. * cert: rename certGetPublicKeySize() -> certGetPublicKeySizeByType(). * cert: rename certGetPublicKeyBlockSize() -> certGetPublicKeyBlockSizeByType(). * cert: rename certIsValidCertificate() -> certIsValidSignedCertBlob(). * cert: rename certGetSignedCertificateSize() -> certGetSignedCertBlobSize(). * cert: rename certGetSignedCertificateHashAreaSize() -> certGetSignedCertBlobHashAreaSize(). * cert: remove certGetPublicKey(), certGetPublicExponent() and certCalculateRawCertificateChainSize(). * cert: add certGetPublicKeyTypeFromCommonBlock(), certGetPublicKeyTypeFromSignedCertBlob(), certGetPublicKeySizeFromSignedCertBlob(), certGetPublicKeyBlockSizeFromSignedCertBlob(), certGetPublicKeyFromSignedCertBlob(), certGetPublicExponentFromSignedCertBlob(), certIsValidCertificate() (w/diff func sig), certGetCommonBlockFromCertificate(), certGetPublicKeyTypeFromCertificate(), certGetPublicKeySizeFromCertificate(), certGetPublicKeyBlockSizeFromCertificate(), certGetPublicKeyFromCertificate(), certGetPublicExponentFromCertificate() and certGetHashAreaSizeFromCertificate() functions. * cert: avoid byteswapping the public key type value in multiple places -- it is now only being done in certGetPublicKeyTypeFromCommonBlock(). * cert: call certFreeCertificateChain() in _certRetrieveCertificateChainBySignatureIssuer() before attempting to retrieve the certificate chain. * cert: other minor changes and corrections. * tik: update code to match signature interface changes. * tik: add missing comments to TikPropertyMask enum entries. * tik: add key_generation, enc_titlekey_str and dec_titlekey_str fields to Ticket struct. * tik: update tikRetrieveTicketByRightsId() to also take in a key_generation argument, instead of getting it from the rights ID (which could fail if it's using a key generation lower than HOS 3.0.1) or the key_generation field from the common ticket block (which could fail if the ticket has been tampered by certain tools). * tik: rename tikGetCommonBlock() -> tikGetCommonBlockFromSignedTicketBlob(). * tik: change function signature for tikGetTicketSectionRecordsBlockSize(). * tik: rename tikIsValidTicket() -> tikIsValidSignedTicketBlob(). * tik: rename tikGetSignedTicketSize() -> tikGetSignedTicketBlobSize(). * tik: rename tikGetSignedTicketHashAreaSize() -> tikGetSignedTicketBlobHashAreaSize(). * tik: rename tikGetEncryptedTitleKeyFromTicket() -> tikGetEncryptedTitleKey(). * tik: add tikIsValidTicket() (w/diff func sig), tikGetCommonBlockFromTicket(), tikGetHashAreaSizeFromTicket(), tikFixTamperedCommonTicket(), tikVerifyRsa2048Sha256Signature() and tikDecryptVolatileTicket() functions. Ticket signature verification is only carried out for common tickets in tikFixTamperedCommonTicket(). * tik: change argument order in tikGetTicketEntryOffsetFromTicketList() and tikRetrieveTicketEntryFromTicketBin(). * tik: add TIK_COMMON_CERT_NAME and TIK_DEV_CERT_ISSUER macros. * tik: use a scoped lock when calling tikRetrieveTicketFromEsSaveDataByRightsId(). * tik: simplify certificate chain retrieval steps in tikConvertPersonalizedTicketToCommonTicket() by always using the XS00000020 certificate. * tik: wipe license_type and property_mask fields in tikConvertPersonalizedTicketToCommonTicket(). * tik: other minor changes and corrections. Other changes include: * keys: fix key generation checks in keysGetNcaKeyAreaKeyEncryptionKey() and keysGetTicketCommonKey(). * rsa: move core logic from rsa2048VerifySha256BasedPssSignature() into a new function: rsa2048VerifySha256BasedSignature(). * rsa: add rsa2048VerifySha256BasedPkcs1v15Signature() function.
2023-10-15 16:53:46 +01:00
NcaSignatureKeyGeneration_Since900NUP = 1, ///< 9.0.0+.
2022-04-18 22:59:25 +01:00
NcaSignatureKeyGeneration_Current = NcaSignatureKeyGeneration_Since900NUP,
NcaSignatureKeyGeneration_Max = (NcaSignatureKeyGeneration_Current + 1)
} NcaSignatureKeyGeneration;
2020-04-15 21:50:07 +01:00
typedef struct {
u32 start_sector; ///< Expressed in NCA_FS_SECTOR_SIZE sectors.
u32 end_sector; ///< Expressed in NCA_FS_SECTOR_SIZE sectors.
u32 hash_sector;
u8 reserved[0x4];
} NcaFsInfo;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaFsInfo, 0x10);
2020-04-11 06:28:26 +01:00
typedef struct {
2020-04-15 21:50:07 +01:00
u8 hash[SHA256_HASH_SIZE];
} NcaFsHeaderHash;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaFsHeaderHash, 0x20);
/// Encrypted NCA key area used to hold NCA FS section encryption keys. Zeroed out if the NCA uses titlekey crypto.
/// If a particular key entry is unused, it is zeroed out before this area is encrypted.
typedef struct {
2022-06-24 18:39:15 +01:00
union {
u8 keys[NCA_KEY_AREA_KEY_COUNT][AES_128_KEY_SIZE];
struct {
u8 aes_xts_1[AES_128_KEY_SIZE]; ///< AES-128-XTS key 0 used for NCA FS sections with NcaEncryptionType_AesXts crypto.
u8 aes_xts_2[AES_128_KEY_SIZE]; ///< AES-128-XTS key 1 used for NCA FS sections with NcaEncryptionType_AesXts crypto.
u8 aes_ctr[AES_128_KEY_SIZE]; ///< AES-128-CTR key used for NCA FS sections with NcaEncryptionType_AesCtr* and NcaEncryptionType_AesCtrEx* crypto.
u8 aes_ctr_ex[AES_128_KEY_SIZE]; ///< Unused AES-128-CTR key.
u8 aes_ctr_hw[AES_128_KEY_SIZE]; ///< Unused AES-128-CTR key.
u8 reserved[0xB0];
};
};
} NcaEncryptedKeyArea;
2022-06-24 18:39:15 +01:00
NXDT_ASSERT(NcaEncryptedKeyArea, NCA_KEY_AREA_SIZE);
/// First 0x400 bytes from every NCA.
2020-04-11 06:28:26 +01:00
typedef struct {
u8 main_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using a fixed key.
u8 acid_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using the ACID public key from the NPDM in ExeFS. Only used in Program NCAs.
u32 magic; ///< "NCA0" / "NCA2" / "NCA3".
u8 distribution_type; ///< NcaDistributionType.
u8 content_type; ///< NcaContentType.
u8 key_generation_old; ///< NcaKeyGeneration. Only uses NcaKeyGeneration_Since100NUP and NcaKeyGeneration_Since300NUP values.
u8 kaek_index; ///< NcaKeyAreaEncryptionKeyIndex.
u64 content_size;
u64 program_id;
u32 content_index;
I'm a terrible person and an even worse developer. And I don't need anyone to tell me so, thank you very much. * PoC: remove gc_dumper and nsp_dumper PoC; create nxdt_rw_poc with all gc_dumper and nsp_dumper capabilities + standalone ticket dumping + raw NCA dumping; use ftruncate() to set output file sizes whenever possible. PoC code is a mess, as always. Expect the features from the rest of the PoCs to be implemented into nxdt_rw_poc soon. * workflow: temporarily disable borealis build generation; comment out manual installation of up-to-date packages from Leseratte's mirrors because the latest devkitA64 Docker image has them all. * borealis: update to fix building issues with latest devkitA64. * bfttf: error out on invalid NCA signatures. * config: save configuration to the current working directory; parse and validate new "gamecard/write_raw_hfs_partition" flag. * defines: remove CONFIG_PATH macro; rename CONFIG_FILE_NAME. * gamecard: rename fs_ctx -> hfs_ctx everywhere; use HFS function calls to retrieve partition names. * hfs: move GameCardHashFileSystemPartitionType enum from gamecard.h and rename it to HashFileSystemPartitionType; add hfsIsValidContext(); add hfsGetPartitionNameString(). * nca/npdm: update comments to reflect latest HOS version. * nxdt_bfsar: always generate absolute SD card paths with the device name; error out on an invalid NCA signature. * nxdt_includes: include dirent.h; refactor Version struct to make it a union of all known *Version structs. * nxdt_log: don't write session separator if the logfile is empty. * nxdt_utils: log appletIsGamePlayRecordingSupported() errors; add utilsDeleteDirectoryRecursively(). * rsa: provide clearer function descriptions in header file. * services: handle usb:ds initialization. * tik: update tikConvertPersonalizedTicketToCommonTicket() to allow NULL input pointers as raw certificate chain arguments (much needed for standalone ticket dumping). * title: add titleGetApplicationIdByMetaKey(). * usb: refactor interface (de)initialization code; slightly improve ABI usage (console-side only); redefine ABI version field in StartSession command blocks; upgrade ABI to v1.1. * FatFs: rename DIR -> FDIR to avoid conflicts with definitions from stdlib's dirent.h. * gamecard_tab: display package ID from the inserted gamecard; fix displayed version numbers from bundled system updates below 3.0.0. * todo: add notes about creating devoptab devices for HFS/PFS/RomFS file tree dumping.
2023-05-24 20:05:34 +01:00
Version sdk_addon_version;
u8 key_generation; ///< NcaKeyGeneration. Uses NcaKeyGeneration_Since301NUP or greater values.
2022-04-18 22:59:25 +01:00
u8 main_signature_key_generation; ///< NcaSignatureKeyGeneration.
2020-09-24 18:03:26 +01:00
u8 reserved[0xE];
FsRightsId rights_id; ///< Used for titlekey crypto.
NcaFsInfo fs_info[NCA_FS_HEADER_COUNT]; ///< Start and end sectors for each NCA FS section.
NcaFsHeaderHash fs_header_hash[NCA_FS_HEADER_COUNT]; ///< SHA-256 hashes calculated over each NCA FS section header.
NcaEncryptedKeyArea encrypted_key_area;
} NcaHeader;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaHeader, 0x400);
2020-04-15 21:50:07 +01:00
typedef enum {
NcaFsType_RomFs = 0,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaFsType_PartitionFs = 1,
NcaFsType_Count = 2 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaFsType;
2020-04-11 06:28:26 +01:00
2020-04-15 21:50:07 +01:00
typedef enum {
2022-06-24 01:22:01 +01:00
NcaHashType_Auto = 0,
NcaHashType_None = 1, ///< Possibly used by all filesystem types.
2022-06-24 01:22:01 +01:00
NcaHashType_HierarchicalSha256 = 2, ///< Used by NcaFsType_PartitionFs.
NcaHashType_HierarchicalIntegrity = 3, ///< Used by NcaFsType_RomFs.
NcaHashType_AutoSha3 = 4,
NcaHashType_HierarchicalSha3256 = 5, ///< Used by NcaFsType_PartitionFs.
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaHashType_HierarchicalIntegritySha3 = 6, ///< Used by NcaFsType_RomFs.
NcaHashType_Count = 7 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaHashType;
2020-04-11 06:28:26 +01:00
2020-04-15 21:50:07 +01:00
typedef enum {
2022-06-24 01:22:01 +01:00
NcaEncryptionType_Auto = 0,
NcaEncryptionType_None = 1,
NcaEncryptionType_AesXts = 2,
NcaEncryptionType_AesCtr = 3,
NcaEncryptionType_AesCtrEx = 4,
NcaEncryptionType_AesCtrSkipLayerHash = 5,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaEncryptionType_AesCtrExSkipLayerHash = 6,
NcaEncryptionType_Count = 7 ///< Total values supported by this enum.
2020-04-15 21:50:07 +01:00
} NcaEncryptionType;
2020-04-11 06:28:26 +01:00
2022-06-24 18:39:15 +01:00
typedef enum {
NcaMetaDataHashType_None = 0,
NcaMetaDataHashType_HierarchicalIntegrity = 1,
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaMetaDataHashType_HierarchicalIntegritySha3 = 2,
NcaMetaDataHashType_Count = 3 ///< Total values supported by this enum.
2022-06-24 18:39:15 +01:00
} NcaMetaDataHashType;
2020-04-11 06:28:26 +01:00
typedef struct {
2020-04-15 21:50:07 +01:00
u64 offset;
u64 size;
} NcaRegion;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaRegion, 0x10);
/// Used by NcaFsType_PartitionFs and NCA0 NcaFsType_RomFs.
2020-04-11 06:28:26 +01:00
typedef struct {
2020-04-15 21:50:07 +01:00
u8 master_hash[SHA256_HASH_SIZE];
u32 hash_block_size;
u32 hash_region_count;
NcaRegion hash_region[NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT];
} NcaHierarchicalSha256Data;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaHierarchicalSha256Data, 0x78);
2020-04-11 06:28:26 +01:00
typedef struct {
u64 offset;
u64 size;
u32 block_order; ///< Use NCA_IVFC_BLOCK_SIZE to calculate the actual block size using this value.
2020-04-15 21:50:07 +01:00
u8 reserved[0x4];
} NcaHierarchicalIntegrityVerificationLevelInformation;
NXDT_ASSERT(NcaHierarchicalIntegrityVerificationLevelInformation, 0x18);
typedef struct {
u8 value[0x20];
} NcaSignatureSalt;
NXDT_ASSERT(NcaSignatureSalt, 0x20);
#pragma pack(push, 1)
typedef struct {
u32 max_level_count; ///< Always NCA_IVFC_MAX_LEVEL_COUNT.
NcaHierarchicalIntegrityVerificationLevelInformation level_information[NCA_IVFC_LEVEL_COUNT];
NcaSignatureSalt signature_salt;
} NcaInfoLevelHash;
#pragma pack(pop)
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaInfoLevelHash, 0xB4);
/// Used by NcaFsType_RomFs.
2020-04-11 06:28:26 +01:00
typedef struct {
u32 magic; ///< "IVFC".
2020-04-15 21:50:07 +01:00
u32 version;
u32 master_hash_size; ///< Always SHA256_HASH_SIZE.
NcaInfoLevelHash info_level_hash;
u8 master_hash[SHA256_HASH_SIZE];
} NcaIntegrityMetaInfo;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaIntegrityMetaInfo, 0xE0);
2020-04-11 06:28:26 +01:00
typedef struct {
union {
struct {
///< Used for NcaHashType_HierarchicalSha256 and NcaHashType_HierarchicalSha3256 (NcaFsType_PartitionFs and NCA0 NcaFsType_RomFs).
NcaHierarchicalSha256Data hierarchical_sha256_data;
u8 reserved_1[0x80];
2020-04-11 06:28:26 +01:00
};
struct {
///< Used if NcaHashType_HierarchicalIntegrity and NcaHashType_HierarchicalIntegritySha3 (NcaFsType_RomFs).
NcaIntegrityMetaInfo integrity_meta_info;
2020-04-15 21:50:07 +01:00
u8 reserved_2[0x18];
2020-04-11 06:28:26 +01:00
};
};
} NcaHashData;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaHashData, 0xF8);
2020-04-11 06:28:26 +01:00
typedef struct {
2020-04-15 21:50:07 +01:00
u32 magic; ///< "BKTR".
u32 version; ///< Always NCA_BKTR_VERSION.
2020-04-15 21:50:07 +01:00
u32 entry_count;
u8 reserved[0x4];
} NcaBucketTreeHeader;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaBucketTreeHeader, 0x10);
2020-04-11 06:28:26 +01:00
typedef struct {
u64 offset;
u64 size;
NcaBucketTreeHeader header;
} NcaBucketInfo;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaBucketInfo, 0x20);
2022-06-24 18:39:15 +01:00
/// Only used for NcaEncryptionType_AesCtrEx and NcaEncryptionType_AesCtrExSkipLayerHash (PatchRomFs).
2020-04-11 06:28:26 +01:00
typedef struct {
NcaBucketInfo indirect_bucket;
NcaBucketInfo aes_ctr_ex_bucket;
} NcaPatchInfo;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaPatchInfo, 0x40);
2020-04-11 06:28:26 +01:00
typedef struct {
2020-04-15 21:50:07 +01:00
union {
u8 value[0x8];
2020-04-15 21:50:07 +01:00
struct {
u32 generation;
u32 secure_value;
};
};
} NcaAesCtrUpperIv;
2020-04-15 21:50:07 +01:00
NXDT_ASSERT(NcaAesCtrUpperIv, 0x8);
/// Used in NCAs with sparse storage.
2020-04-15 21:50:07 +01:00
typedef struct {
NcaBucketInfo bucket;
u64 physical_offset;
u16 generation;
u8 reserved[0x6];
} NcaSparseInfo;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaSparseInfo, 0x30);
/// Used in NCAs with LZ4-compressed sections.
typedef struct {
NcaBucketInfo bucket;
2022-06-24 01:22:01 +01:00
u8 reserved[0x8];
} NcaCompressionInfo;
2022-06-24 01:22:01 +01:00
NXDT_ASSERT(NcaCompressionInfo, 0x28);
typedef struct {
u64 offset;
u64 size;
u8 hash[SHA256_HASH_SIZE];
} NcaMetaDataHashDataInfo;
NXDT_ASSERT(NcaMetaDataHashDataInfo, 0x30);
/// Four NCA FS headers are placed right after the 0x400 byte long NCA header in NCA2 and NCA3.
/// NCA0 place the FS headers at the start sector from the NcaFsInfo entries.
typedef struct {
u16 version;
2022-06-24 18:39:15 +01:00
u8 fs_type; ///< NcaFsType.
u8 hash_type; ///< NcaHashType.
u8 encryption_type; ///< NcaEncryptionType.
u8 metadata_hash_type; ///< NcaMetaDataHashType.
u8 reserved_1[0x2];
NcaHashData hash_data;
NcaPatchInfo patch_info;
NcaAesCtrUpperIv aes_ctr_upper_iv;
NcaSparseInfo sparse_info;
NcaCompressionInfo compression_info;
2022-06-24 18:39:15 +01:00
NcaMetaDataHashDataInfo metadata_hash_info;
2022-06-24 01:22:01 +01:00
u8 reserved_2[0x30];
} NcaFsHeader;
2020-04-11 06:28:26 +01:00
NXDT_ASSERT(NcaFsHeader, 0x200);
2020-04-20 11:39:41 +01:00
typedef enum {
NcaFsSectionType_PartitionFs = 0, ///< NcaFsType_PartitionFs + NcaHashType_HierarchicalSha256 OR NcaHashType_HierarchicalSha3256 + NcaEncryptionType_AesCtr OR NcaEncryptionType_AesCtrSkipLayerHash.
NcaFsSectionType_RomFs = 1, ///< NcaFsType_RomFs + NcaHashType_HierarchicalIntegrity OR NcaHashType_HierarchicalIntegritySha3 + NcaEncryptionType_AesCtr OR NcaEncryptionType_AesCtrSkipLayerHash.
NcaFsSectionType_PatchRomFs = 2, ///< NcaFsType_RomFs + NcaHashType_HierarchicalIntegrity OR NcaHashType_HierarchicalIntegritySha3 + NcaEncryptionType_AesCtrEx OR NcaEncryptionType_AesCtrExSkipLayerHash.
NcaFsSectionType_Nca0RomFs = 3, ///< NcaVersion_Nca0 + NcaFsType_RomFs + NcaHashType_HierarchicalSha256 + NcaEncryptionType_AesXts.
2020-04-22 21:53:20 +01:00
NcaFsSectionType_Invalid = 4
} NcaFsSectionType;
2020-04-11 06:28:26 +01:00
// Forward declaration for NcaFsSectionContext.
typedef struct _NcaContext NcaContext;
/// Unlike NCA contexts, we don't need to keep a hash for the NCA FS section header in NCA FS section contexts.
/// This is because the functions that modify the NCA FS section header also update the NCA FS section header hash stored in the NCA header.
2020-04-11 06:28:26 +01:00
typedef struct {
bool enabled; ///< Set to true if this NCA FS section has passed all validation checks and can be safely used.
NcaContext *nca_ctx; ///< NcaContext. Used to perform NCA reads.
NcaFsHeader header; ///< Plaintext NCA FS section header.
NcaFsHeader encrypted_header; ///< Encrypted NCA FS section header. If the plaintext NCA FS section header is modified, this will hold an encrypted copy of it.
///< Otherwise, this holds the unmodified, encrypted NCA FS section header.
u8 section_idx; ///< Index within [0, NCA_FS_HEADER_COUNT).
u64 section_offset; ///< Relative to the start of the NCA content file. Placed here for convenience.
u64 section_size; ///< Placed here for convenience.
char section_size_str[0x10]; ///< Placed here for convenience.
2022-06-24 01:22:01 +01:00
u8 hash_type; ///< NcaHashType.
2020-04-22 21:53:20 +01:00
u8 encryption_type; ///< NcaEncryptionType.
2022-06-24 01:22:01 +01:00
u8 section_type; ///< NcaFsSectionType.
///< PatchInfo-related fields.
bool has_patch_indirect_layer; ///< Set to true if this NCA FS section has an Indirect patch layer.
bool has_patch_aes_ctr_ex_layer; ///< Set to true if this NCA FS section has an AesCtrEx patch layer.
///< SparseInfo-related fields.
bool has_sparse_layer; ///< Set to true if this NCA FS section has a sparse layer.
u64 sparse_table_offset; ///< header.sparse_info.physical_offset + header.sparse_info.bucket.offset. Relative to the start of the NCA content file. Placed here for convenience.
u64 cur_sparse_virtual_offset; ///< Current sparse layer virtual offset. Used for content decryption if a sparse layer is available.
///< CompressionInfo-related fields.
bool has_compression_layer; ///< Set to true if this NCA FS section has a compression layer.
///< Hash-layer-related fields.
bool skip_hash_layer_crypto; ///< Set to true if hash layer crypto should be skipped while reading section data.
2022-06-30 17:46:45 +01:00
NcaRegion hash_region; ///< Holds the properties for the full hash layer region that precedes the actual FS section data.
///< Crypto-related fields.
u8 ctr[AES_BLOCK_SIZE]; ///< Used internally by NCA functions to update the AES-128-CTR context IV based on the desired offset.
Aes128CtrContext ctr_ctx; ///< Used internally by NCA functions to perform AES-128-CTR crypto.
Aes128XtsContext xts_decrypt_ctx; ///< Used internally by NCA functions to perform AES-128-XTS decryption.
Aes128XtsContext xts_encrypt_ctx; ///< Used internally by NCA functions to perform AES-128-XTS encryption.
///< NSP-related fields.
bool header_written; ///< Set to true after this FS section header has been written to an output dump.
} NcaFsSectionContext;
2020-04-15 21:50:07 +01:00
typedef enum {
*FormattedStringToBuffer: relax input validation Affects both utilsAppendFormattedStringToBuffer() and logWriteFormattedStringToBuffer(). Fixes logging issues within both the exception handler and memory debugging code. Other changes include: * bfttf: rename BfttfFontType_Total -> BfttfFontType_Count. * config: rename "append_authoringtool_data" -> "generate_authoringtool_data". * fs_ext: update FsGameCardCertificate struct * gamecard: fix gamecardReadLotusAsicFirmwareBlob() not returning false if FS .data segment memory couldn't be retrieved; update GameCardInfo struct to reflect a recently discovered area that's not zeroed out. * mem: expand MemoryProgramSegmentType enum; define extra macros for PID buffer size and memory page type checks; force empty memory page attribute and R/X permission checks while looking for the last FS .text segment; make memory page filtering code more readable. * npdm: rename KernelCapability enums; rename entry_value -> bitmask in all KernelCapability descriptor structs. * tik: force byte-for-byte memory lookup while dumping volatile tickets. * libs: update libusbhsfs to latest commit. * codebase: add missing comments to some enums; add missing "None" and "Count" elements to some enums. "Count" entries from enums with bitmasks will only reflect the number of available bitmask values. Enums with hex values remain unchanged. * PoC builds: use EXIT_SUCCESS and EXIT_FAILURE as return values. * nxdt_rw_poc: move "end" jump label within main() to avoid a crash if utilsInitializeResources() fails; reflect changes in config.c.
2023-07-17 00:03:05 +01:00
NcaVersion_Nca0 = 0,
NcaVersion_Nca2 = 1,
NcaVersion_Nca3 = 2,
NcaVersion_Count = 3 ///< Total values supported by this enum.
} NcaVersion;
2020-04-15 21:50:07 +01:00
typedef struct {
2022-06-24 18:39:15 +01:00
union {
u8 keys[NCA_KEY_AREA_USED_KEY_COUNT][AES_128_KEY_SIZE];
struct {
u8 aes_xts_1[AES_128_KEY_SIZE]; ///< AES-128-XTS key 0 used for NCA FS sections with NcaEncryptionType_AesXts crypto.
u8 aes_xts_2[AES_128_KEY_SIZE]; ///< AES-128-XTS key 1 used for NCA FS sections with NcaEncryptionType_AesXts crypto.
u8 aes_ctr[AES_128_KEY_SIZE]; ///< AES-128-CTR key used for NCA FS sections with NcaEncryptionType_AesCtr and NcaEncryptionType_AesCtrSkipLayerHash crypto.
};
};
} NcaDecryptedKeyArea;
2022-06-24 18:39:15 +01:00
NXDT_ASSERT(NcaDecryptedKeyArea, NCA_KEY_AREA_USED_SIZE);
struct _NcaContext {
u8 storage_id; ///< NcmStorageId.
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data from eMMC/SD.
u64 gamecard_offset; ///< Used to read NCA data from a gamecard using a FsStorage instance when storage_id == NcmStorageId_GameCard.
u64 title_id; ///< ID from the title that owns this NCA. Retrieved from NcmContentMetaKey. Placed here for convenience.
Version title_version; ///< Version from the title that owns this NCA. Retrieved from NcmContentMetaKey. Placed here for convenience.
u8 title_type; ///< NcmContentMetaType. Retrieved from NcmContentMetaKey. Placed here for convenience.
NcmContentId content_id; ///< Content ID for this NCA. Used to read NCA data from eMMC/SD. Retrieved from NcmContentInfo.
char content_id_str[0x21];
u8 hash[SHA256_HASH_SIZE]; ///< Manually calculated (if needed).
Fix building with latest libnx + QoL changes. libnx now implements fsDeviceOperatorGetGameCardIdSet(), so I got rid of my own implementation. Other changes include: * cnmt: add cnmtVerifyContentHash(). * defines: add SHA256_HASH_STR_SIZE. * fs_ext: add FsCardId1MakerCode, FsCardId1MemoryType and FsCardId2CardType enums. * fs_ext: update FsCardId* structs. * gamecard: change all package_id definitions from u64 -> u8[0x8]. * gamecard: fix misleading struct member names in GameCardHeader. * gamecard: rename gamecardGetIdSet() -> gamecardGetCardIdSet(). * gamecard_tab: fix Package ID printing. * gamecard_tab: add Card ID Set printing. * host: add executable flag to Python scripts. * keys: detect if we're dealing with a wiped eTicket RSA device key (e.g. via set:cal blanking). If so, the application will still launch, but all operations related to personalized titlekey crypto are disabled. * pfs: rename PartitionFileSystemFileContext -> PartitionFileSystemImageContext and propagate the change throughout the codebase. * pfs: rename PFS_FULL_HEADER_ALIGNMENT -> PFS_HEADER_PADDING_ALIGNMENT and update pfsWriteImageContextHeaderToMemoryBuffer() accordingly. * poc: print certain button prompts with reversed colors, in the hopes of getting the user's attention. * poc: NSP, Ticket and NCA submenus for updates and DLC updates now display the highest available title by default. * poc: simplified output path generation for extracted NCA FS section dumps. * poc: handle edge cases where a specific NCA from an update has no matching equivalent by type/ID offset in its base title (e.g. Fall Guys' HtmlDocument NCA). * poc: implement NCA checksum validation while generating NSP dumps. * romfs: update romfsInitializeContext() to allow its base_nca_fs_ctx argument to be NULL. * usb: use USB_BOS_SIZE only once. * workflow: update commit hash referenced by "rewrite-prerelease" tag on update.
2023-11-03 01:22:47 +00:00
char hash_str[SHA256_HASH_STR_SIZE];
u8 format_version; ///< NcaVersion.
u8 content_type; ///< NcmContentType. Retrieved from NcmContentInfo.
u64 content_size; ///< Retrieved from NcmContentInfo.
char content_size_str[0x10]; ///< Placed here for convenience.
u8 key_generation; ///< NcaKeyGeneration. Retrieved from the decrypted header.
u8 id_offset; ///< Retrieved from NcmContentInfo.
2020-04-15 21:50:07 +01:00
bool rights_id_available;
bool titlekey_retrieved;
bool valid_main_signature;
u8 titlekey[AES_128_KEY_SIZE]; ///< Decrypted titlekey from the ticket.
NcaHeader header; ///< Plaintext NCA header.
u8 header_hash[SHA256_HASH_SIZE]; ///< Plaintext NCA header hash. Used to determine if it's necessary to replace the NCA header while dumping this NCA.
NcaHeader encrypted_header; ///< Encrypted NCA header. If the plaintext NCA header is modified, this will hold an encrypted copy of it.
///< Otherwise, this holds the unmodified, encrypted NCA header.
NcaDecryptedKeyArea decrypted_key_area;
NcaFsSectionContext fs_ctx[NCA_FS_HEADER_COUNT];
///< NSP-related fields.
bool header_written; ///< Set to true after the NCA header and the FS section headers have been written to an output dump.
void *content_type_ctx; ///< Pointer to a content type context (e.g. ContentMetaContext, ProgramInfoContext, NacpContext, LegalInfoContext). Set to NULL if unused.
bool content_type_ctx_patch; ///< Set to true if a NCA patch generated by the content type context is needed and hasn't been completely written yet.
u32 content_type_ctx_data_idx; ///< Start index for the data generated by the content type context. Used while creating NSPs.
};
2020-04-11 06:28:26 +01:00
2020-04-28 09:58:17 +01:00
typedef struct {
bool written; ///< Set to true if this patch has already been written.
u64 offset; ///< New data offset (relative to the start of the NCA content file).
u64 size; ///< New data size.
u8 *data; ///< New data.
} NcaHashDataPatch;
2020-04-28 09:58:17 +01:00
typedef struct {
bool written; ///< Set to true if all hash region patches have been written.
NcmContentId content_id;
u32 hash_region_count;
NcaHashDataPatch hash_region_patch[NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT];
2020-04-28 09:58:17 +01:00
} NcaHierarchicalSha256Patch;
typedef struct {
bool written; ///< Set to true if all hash level patches have been written.
NcmContentId content_id;
NcaHashDataPatch hash_level_patch[NCA_IVFC_LEVEL_COUNT];
2020-04-28 09:58:17 +01:00
} NcaHierarchicalIntegrityPatch;
2020-04-22 21:53:20 +01:00
/// Functions to control the internal heap buffer used by NCA FS section crypto operations.
/// Must be called at startup.
bool ncaAllocateCryptoBuffer(void);
void ncaFreeCryptoBuffer(void);
2020-04-24 10:38:13 +01:00
/// Initializes a NCA context.
I'm a terrible person and an even worse developer. And I don't need anyone to tell me so, thank you very much. * PoC: remove gc_dumper and nsp_dumper PoC; create nxdt_rw_poc with all gc_dumper and nsp_dumper capabilities + standalone ticket dumping + raw NCA dumping; use ftruncate() to set output file sizes whenever possible. PoC code is a mess, as always. Expect the features from the rest of the PoCs to be implemented into nxdt_rw_poc soon. * workflow: temporarily disable borealis build generation; comment out manual installation of up-to-date packages from Leseratte's mirrors because the latest devkitA64 Docker image has them all. * borealis: update to fix building issues with latest devkitA64. * bfttf: error out on invalid NCA signatures. * config: save configuration to the current working directory; parse and validate new "gamecard/write_raw_hfs_partition" flag. * defines: remove CONFIG_PATH macro; rename CONFIG_FILE_NAME. * gamecard: rename fs_ctx -> hfs_ctx everywhere; use HFS function calls to retrieve partition names. * hfs: move GameCardHashFileSystemPartitionType enum from gamecard.h and rename it to HashFileSystemPartitionType; add hfsIsValidContext(); add hfsGetPartitionNameString(). * nca/npdm: update comments to reflect latest HOS version. * nxdt_bfsar: always generate absolute SD card paths with the device name; error out on an invalid NCA signature. * nxdt_includes: include dirent.h; refactor Version struct to make it a union of all known *Version structs. * nxdt_log: don't write session separator if the logfile is empty. * nxdt_utils: log appletIsGamePlayRecordingSupported() errors; add utilsDeleteDirectoryRecursively(). * rsa: provide clearer function descriptions in header file. * services: handle usb:ds initialization. * tik: update tikConvertPersonalizedTicketToCommonTicket() to allow NULL input pointers as raw certificate chain arguments (much needed for standalone ticket dumping). * title: add titleGetApplicationIdByMetaKey(). * usb: refactor interface (de)initialization code; slightly improve ABI usage (console-side only); redefine ABI version field in StartSession command blocks; upgrade ABI to v1.1. * FatFs: rename DIR -> FDIR to avoid conflicts with definitions from stdlib's dirent.h. * gamecard_tab: display package ID from the inserted gamecard; fix displayed version numbers from bundled system updates below 3.0.0. * todo: add notes about creating devoptab devices for HFS/PFS/RomFS file tree dumping.
2023-05-24 20:05:34 +01:00
/// If 'storage_id' == NcmStorageId_GameCard, the 'hfs_partition_type' argument must be a valid HashFileSystemPartitionType value.
/// If the NCA holds a populated Rights ID field, ticket data will need to be retrieved.
/// If the 'tik' argument points to a valid Ticket element, it will either be updated (if it's empty) or used to read ticket data that has already been retrieved.
/// If the 'tik' argument is NULL, the function will just retrieve the necessary ticket data on its own.
/// If ticket data can't be retrieved, the context will still be initialized, but anything that involves working with encrypted NCA FS section blocks won't be possible (e.g. ncaReadFsSection()).
bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, const NcmContentMetaKey *meta_key, const NcmContentInfo *content_info, Ticket *tik);
2020-04-22 21:53:20 +01:00
/// Reads raw encrypted data from a NCA using an input context, previously initialized by ncaInitializeContext().
/// Input offset must be relative to the start of the NCA content file.
2020-04-22 21:53:20 +01:00
bool ncaReadContentFile(NcaContext *ctx, void *out, u64 read_size, u64 offset);
2020-04-19 23:44:22 +01:00
/// Retrieves the FS section's hierarchical hash target layer extents.
2022-06-30 22:04:54 +01:00
/// Output offset is relative to the start of the FS section.
/// Either 'out_offset' or 'out_size' can be NULL, but at least one of them must be a valid pointer.
bool ncaGetFsSectionHashTargetExtents(NcaFsSectionContext *ctx, u64 *out_offset, u64 *out_size);
2022-06-30 22:04:54 +01:00
2020-04-22 21:53:20 +01:00
/// Reads decrypted data from a NCA FS section using an input context.
/// Input offset must be relative to the start of the NCA FS section.
/// If dealing with Patch RomFS sections, this function should only be used when *not* reading AesCtrEx storage data. Use ncaReadAesCtrExStorage() for that.
bool ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size, u64 offset);
/// Reads plaintext AesCtrEx storage data from a NCA Patch RomFS section using an input context and an AesCtrEx CTR value.
2020-04-30 09:25:03 +01:00
/// Input offset must be relative to the start of the NCA FS section.
bool ncaReadAesCtrExStorage(NcaFsSectionContext *ctx, void *out, u64 read_size, u64 offset, u32 ctr_val, bool decrypt);
2020-04-30 09:25:03 +01:00
/// Generates HierarchicalSha256 FS section patch data, which can be used to seamlessly replace NCA data.
/// Input offset must be relative to the start of the last HierarchicalSha256 hash region (actual underlying FS).
/// Bear in mind that this function recalculates both the NcaHashData block master hash and the NCA FS header hash from the NCA header.
2020-04-29 10:54:40 +01:00
/// As such, this function is not designed to generate more than one patch per HierarchicalSha256 FS section.
2020-04-28 09:58:17 +01:00
bool ncaGenerateHierarchicalSha256Patch(NcaFsSectionContext *ctx, const void *data, u64 data_size, u64 data_offset, NcaHierarchicalSha256Patch *out);
/// Overwrites block(s) from a buffer holding raw NCA data using previously initialized NcaContext and NcaHierarchicalSha256Patch.
/// 'buf_offset' must hold the raw NCA offset where the data stored in 'buf' was read from.
/// The 'written' fields from the input NcaHierarchicalSha256Patch and its underlying NcaHashDataPatch elements are updated by this function.
void ncaWriteHierarchicalSha256PatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset);
2020-04-28 09:58:17 +01:00
/// Generates HierarchicalIntegrity FS section patch data, which can be used to seamlessly replace NCA data.
/// Input offset must be relative to the start of the last HierarchicalIntegrity hash level (actual underlying FS).
/// Bear in mind that this function recalculates both the NcaHashData block master hash and the NCA FS header hash from the NCA header.
2020-04-29 10:54:40 +01:00
/// As such, this function is not designed to generate more than one patch per HierarchicalIntegrity FS section.
bool ncaGenerateHierarchicalIntegrityPatch(NcaFsSectionContext *ctx, const void *data, u64 data_size, u64 data_offset, NcaHierarchicalIntegrityPatch *out);
2020-04-28 09:58:17 +01:00
/// Overwrites block(s) from a buffer holding raw NCA data using a previously initialized NcaContext and NcaHierarchicalIntegrityPatch.
/// 'buf_offset' must hold the raw NCA offset where the data stored in 'buf' was read from.
/// The 'written' fields from the input NcaHierarchicalIntegrityPatch and its underlying NcaHashDataPatch elements are updated by this function.
void ncaWriteHierarchicalIntegrityPatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalIntegrityPatch *patch, void *buf, u64 buf_size, u64 buf_offset);
/// Sets the distribution type field from the underlying NCA header in the provided NCA context to NcaDistributionType_Download.
/// Needed for NSP dumps from gamecard titles.
void ncaSetDownloadDistributionType(NcaContext *ctx);
/// Removes titlekey crypto dependency from a NCA context by wiping the Rights ID from the underlying NCA header and copying the decrypted titlekey to the NCA key area.
bool ncaRemoveTitleKeyCrypto(NcaContext *ctx);
/// Encrypts NCA header and NCA FS headers.
/// The 'encrypted_header' member from the NCA context and its underlying NCA FS section contexts is updated by this function.
/// Internally uses ncaIsHeaderDirty() to determine if NCA header / NCA FS section header re-encryption is needed.
bool ncaEncryptHeader(NcaContext *ctx);
/// Used to replace the NCA header and the NCA FS section headers while writing a NCA if they were modified in any way.
/// Overwrites block(s) from a buffer holding raw NCA data using a previously initialized NcaContext.
/// 'buf_offset' must hold the raw NCA offset where the data stored in 'buf' was read from.
/// Bear in mind this function doesn't call ncaIsHeaderDirty() on its own to avoid taking up too much execution time, so it will attempt to overwrite data even if it isn't needed.
void ncaWriteEncryptedHeaderDataToMemoryBuffer(NcaContext *ctx, void *buf, u64 buf_size, u64 buf_offset);
2020-10-03 03:37:05 +01:00
/// Updates the content ID and hash from a NCA context using a provided SHA-256 checksum.
Fix building with latest libnx + QoL changes. libnx now implements fsDeviceOperatorGetGameCardIdSet(), so I got rid of my own implementation. Other changes include: * cnmt: add cnmtVerifyContentHash(). * defines: add SHA256_HASH_STR_SIZE. * fs_ext: add FsCardId1MakerCode, FsCardId1MemoryType and FsCardId2CardType enums. * fs_ext: update FsCardId* structs. * gamecard: change all package_id definitions from u64 -> u8[0x8]. * gamecard: fix misleading struct member names in GameCardHeader. * gamecard: rename gamecardGetIdSet() -> gamecardGetCardIdSet(). * gamecard_tab: fix Package ID printing. * gamecard_tab: add Card ID Set printing. * host: add executable flag to Python scripts. * keys: detect if we're dealing with a wiped eTicket RSA device key (e.g. via set:cal blanking). If so, the application will still launch, but all operations related to personalized titlekey crypto are disabled. * pfs: rename PartitionFileSystemFileContext -> PartitionFileSystemImageContext and propagate the change throughout the codebase. * pfs: rename PFS_FULL_HEADER_ALIGNMENT -> PFS_HEADER_PADDING_ALIGNMENT and update pfsWriteImageContextHeaderToMemoryBuffer() accordingly. * poc: print certain button prompts with reversed colors, in the hopes of getting the user's attention. * poc: NSP, Ticket and NCA submenus for updates and DLC updates now display the highest available title by default. * poc: simplified output path generation for extracted NCA FS section dumps. * poc: handle edge cases where a specific NCA from an update has no matching equivalent by type/ID offset in its base title (e.g. Fall Guys' HtmlDocument NCA). * poc: implement NCA checksum validation while generating NSP dumps. * romfs: update romfsInitializeContext() to allow its base_nca_fs_ctx argument to be NULL. * usb: use USB_BOS_SIZE only once. * workflow: update commit hash referenced by "rewrite-prerelease" tag on update.
2023-11-03 01:22:47 +00:00
void ncaUpdateContentIdAndHash(NcaContext *ctx, const u8 *hash);
/// Returns a pointer to a string holding the name of the section type from the provided NCA FS section context.
const char *ncaGetFsSectionTypeName(NcaFsSectionContext *ctx);
2020-04-19 23:44:22 +01:00
2020-10-03 03:37:05 +01:00
/// Helper inline functions.
NX_INLINE bool ncaIsHeaderDirty(NcaContext *ctx)
{
if (!ctx) return false;
u8 tmp_hash[SHA256_HASH_SIZE] = {0};
sha256CalculateHash(tmp_hash, &(ctx->header), sizeof(NcaHeader));
return (memcmp(tmp_hash, ctx->header_hash, SHA256_HASH_SIZE) != 0);
2020-04-15 21:50:07 +01:00
}
2020-04-11 06:28:26 +01:00
NX_INLINE bool ncaVerifyBucketInfo(NcaBucketInfo *bucket)
{
return (bucket && __builtin_bswap32(bucket->header.magic) == NCA_BKTR_MAGIC && bucket->header.version <= NCA_BKTR_VERSION && bucket->header.entry_count >= 0);
}
NX_INLINE void ncaFreeHierarchicalSha256Patch(NcaHierarchicalSha256Patch *patch)
{
if (!patch) return;
for(u32 i = 0; i < NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT; i++)
{
if (patch->hash_region_patch[i].data) free(patch->hash_region_patch[i].data);
}
memset(patch, 0, sizeof(NcaHierarchicalSha256Patch));
}
NX_INLINE void ncaFreeHierarchicalIntegrityPatch(NcaHierarchicalIntegrityPatch *patch)
{
if (!patch) return;
for(u32 i = 0; i < NCA_IVFC_LEVEL_COUNT; i++)
{
if (patch->hash_level_patch[i].data) free(patch->hash_level_patch[i].data);
}
memset(patch, 0, sizeof(NcaHierarchicalIntegrityPatch));
}
2021-03-23 14:06:52 +00:00
#ifdef __cplusplus
}
#endif
#endif /* __NCA_H__ */