diff --git a/lib/libnx/include/nx/xci.h b/lib/libnx/include/nx/xci.h new file mode 100644 index 0000000..47d3c1e --- /dev/null +++ b/lib/libnx/include/nx/xci.h @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include + +namespace nx +{ + namespace xci + { + const std::string kXciSig = "HEAD"; + static const uint32_t kHeaderEncOffset = 0x90; + static const uint32_t kHeaderEncSize = 0x70; + static const uint32_t kPageSize = 0x200; + static const uint32_t kCardKeyAreaPageCount = 8; + static const uint32_t kCardHeaderPageCount = 1; + static const uint32_t kReservedAreaPageCount = 55; + static const uint32_t kCertAreaStartPageAddress = kCardHeaderPageCount + kReservedAreaPageCount + kCardKeyAreaPageCount; + static const uint32_t kCertAreaPageCount = 64; + static const uint32_t kNormalAreaStartPageAddress = kReservedAreaPageCount + kCertAreaPageCount + kCardHeaderPageCount + kCardKeyAreaPageCount; + + + enum RomSize + { + ROM_SIZE_1GB = 0xFA, + ROM_SIZE_2GB = 0xF8, + ROM_SIZE_4GB = 0xF0, + ROM_SIZE_8GB = 0xE0, + ROM_SIZE_16GB = 0xE1, + ROM_SIZE_32GB = 0xE2 + }; + + enum HeaderFlags + { + FLAG_AUTOBOOT, + FLAG_HISTORY_ERASE, + FLAG_REPAIR_TOOL + }; + + enum FwVersionIndex + { + FWVER_MINOR, + FWVER_MAJOR + }; + + enum CardClockRate + { + CLOCK_RATE_25 = 10551312, + CLOCK_RATE_50 = 10551313, + }; + } + +#pragma pack(push,1) + struct sXciHeader + { + char signature[4]; + le_uint32_t rom_area_start_page; + le_uint32_t backup_area_start_page; + byte_t key_flag; + byte_t rom_size; + byte_t card_header_version; + byte_t flags; + le_uint64_t package_id; + le_uint32_t valid_data_end_page; + byte_t reserved_01[4]; + byte_t encryption_iv[16]; + le_uint64_t partition_fs_header_address; + le_uint64_t partition_fs_header_size; + byte_t partition_fs_header_hash[0x20]; + byte_t initial_data_hash[0x20]; + le_uint32_t sel_sec; + le_uint32_t sel_t1_key; + le_uint32_t sel_key; + le_uint32_t lim_area; + // START ENCRYPTION + le_uint32_t fw_version[2]; + le_uint32_t acc_ctrl_1; + le_uint32_t wait_1_time_read; + le_uint32_t wait_2_time_read; + le_uint32_t wait_1_time_write; + le_uint32_t wait_2_time_write; + le_uint32_t fw_mode; + le_uint32_t upp_version; + byte_t reserved_03[0x4]; + byte_t upp_hash[8]; + le_uint64_t upp_id; + byte_t reserved_04[0x38]; + // END ENCRYPTION + }; + + struct sInitialData + { + byte_t key_source[16]; // { package_id[8], zeros[8]} + byte_t title_key_enc[16]; + byte_t ccm_mac[16]; + byte_t ccm_nonce[12]; + }; // sizeof() = 512 (1 page) + + struct sKeyDataArea + { + sInitialData initial_data; // AES128-CCM encrypted {titlekey[16]} + byte_t encrypted_00[0x200*6]; // AES128-CTR encrypted {titlekey[16]} + byte_t encrypted_00_aesctr_data[0x100]; // RSA2048-OAEP-SHA256 encrypted AES-CTR data used for encrypted_00 {key[16],iv[16]} + byte_t reserved_01[0x100]; + }; // sizeof() = 512*8 (8 pages) +#pragma pack(pop) +}