nstool/lib/libnx/include/nx/xci.h

132 lines
3.4 KiB
C
Raw Normal View History

2018-04-21 09:37:30 +00:00
#pragma once
2018-04-07 08:04:45 +00:00
#include <string>
#include <fnd/types.h>
#include <fnd/List.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
2018-04-21 09:37:30 +00:00
#include <crypto/rsa.h>
2018-04-07 08:04:45 +00:00
#include <fnd/ISerialiseableBinary.h>
#include <nx/macro.h>
2018-04-07 08:04:45 +00:00
namespace nx
{
namespace xci
{
static const uint32_t kXciSig = _MAKE_STRUCT_SIGNATURE("HEAD");
2018-04-07 08:04:45 +00:00
static const uint32_t kHeaderEncOffset = 0x90;
static const uint32_t kHeaderEncSize = 0x70;
static const uint32_t kPageSize = 0x200;
2018-04-21 09:37:30 +00:00
static const uint32_t kUppHashLen = 8;
2018-04-07 08:04:45 +00:00
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;
const std::string kUpdatePartitionStr = "update";
const std::string kNormalPartitionStr = "normal";
const std::string kSecurePartitionStr = "secure";
const std::string kLogoPartitionStr = "logo";
2018-04-07 08:04:45 +00:00
2018-04-21 09:37:30 +00:00
enum KekIndex
{
KEK_XCIE,
KEK_XCIR
};
2018-04-07 08:04:45 +00:00
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
{
le_uint32_t signature;
2018-04-07 08:04:45 +00:00
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;
2018-04-21 09:37:30 +00:00
byte_t reserved_00[4];
crypto::aes::sAesIvCtr aescbc_iv;
2018-04-07 08:04:45 +00:00
le_uint64_t partition_fs_header_address;
le_uint64_t partition_fs_header_size;
2018-04-21 09:37:30 +00:00
crypto::sha::sSha256Hash partition_fs_header_hash;
crypto::sha::sSha256Hash initial_data_hash;
2018-04-07 08:04:45 +00:00
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;
2018-04-21 09:37:30 +00:00
byte_t reserved_01[0x4];
byte_t upp_hash[xci::kUppHashLen];
2018-04-07 08:04:45 +00:00
le_uint64_t upp_id;
2018-04-21 09:37:30 +00:00
byte_t reserved_02[0x38];
2018-04-07 08:04:45 +00:00
// END ENCRYPTION
};
2018-04-21 09:37:30 +00:00
struct sXciHeaderPage
{
byte_t signature[crypto::rsa::kRsa2048Size];
sXciHeader header;
}; // sizeof() = 512 (1 page)
2018-04-07 08:04:45 +00:00
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 reserved_00[xci::kPageSize - sizeof(sInitialData)];
byte_t encrypted_00[xci::kPageSize * 6]; // AES128-CTR encrypted {titlekey[16]}
byte_t encrypted_00_aesctr_data[crypto::rsa::kRsa2048Size]; // RSA2048-OAEP-SHA256 encrypted AES-CTR data used for encrypted_00 {key[16],iv[16]}
byte_t reserved_01[xci::kPageSize - crypto::rsa::kRsa2048Size];
2018-04-07 08:04:45 +00:00
}; // sizeof() = 512*8 (8 pages)
2018-04-07 08:04:45 +00:00
#pragma pack(pop)
}