1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-09 12:11:44 +00:00

tik: recreate forged tickets from scratch if detected

This commit is contained in:
Pablo Curiel 2023-11-26 22:16:39 +01:00
parent b723eb1758
commit 1f7d73e8ac
2 changed files with 36 additions and 12 deletions

View file

@ -33,6 +33,8 @@ extern "C" {
#define SIGNED_TIK_MIN_SIZE sizeof(TikSigHmac160) /* Assuming no ESV1/ESV2 records are available. */ #define SIGNED_TIK_MIN_SIZE sizeof(TikSigHmac160) /* Assuming no ESV1/ESV2 records are available. */
#define SIGNED_TIK_MAX_SIZE 0x400 /* Max ticket entry size in the ES ticket system savedata file. */ #define SIGNED_TIK_MAX_SIZE 0x400 /* Max ticket entry size in the ES ticket system savedata file. */
#define TIK_FORMAT_VERSION 2
#define GENERATE_TIK_STRUCT(sigtype, tiksize) \ #define GENERATE_TIK_STRUCT(sigtype, tiksize) \
typedef struct { \ typedef struct { \
SignatureBlock##sigtype sig_block; \ SignatureBlock##sigtype sig_block; \
@ -72,7 +74,7 @@ typedef enum {
typedef struct { typedef struct {
char issuer[0x40]; char issuer[0x40];
u8 titlekey_block[0x100]; u8 titlekey_block[0x100];
u8 format_version; u8 format_version; ///< Always matches TIK_FORMAT_VERSION.
u8 titlekey_type; ///< TikTitleKeyType. u8 titlekey_type; ///< TikTitleKeyType.
u16 ticket_version; u16 ticket_version;
u8 license_type; ///< TikLicenseType. u8 license_type; ///< TikLicenseType.

View file

@ -386,8 +386,9 @@ static bool tikFixTamperedCommonTicket(Ticket *tik)
TikCommonBlock *tik_common_block = NULL; TikCommonBlock *tik_common_block = NULL;
u32 sig_type = 0; u32 sig_type = 0;
u8 *signature = NULL; bool dev_cert = false;
u64 signature_size = 0, hash_area_size = 0; TikSigRsa2048 *tik_data = NULL;
u64 hash_area_size = 0;
bool success = false; bool success = false;
@ -397,15 +398,23 @@ static bool tikFixTamperedCommonTicket(Ticket *tik)
return false; return false;
} }
/* Get ticket signature and its properties, as well as the ticket hash area size. */ /* Get ticket signature type. Also determine if it's a development ticket. */
sig_type = signatureGetTypeFromSignedBlob(tik->data, false); sig_type = signatureGetTypeFromSignedBlob(tik->data, false);
signature = signatureGetSigFromSignedBlob(tik->data); dev_cert = (strstr(tik_common_block->issuer, TIK_DEV_CERT_ISSUER) != NULL);
signature_size = signatureGetSigSizeByType(sig_type);
/* Return right away if we're not dealing with a common ticket or if the signature type doesn't match RSA-2048 + SHA-256. */
if (tik_common_block->titlekey_type != TikTitleKeyType_Common || sig_type != SignatureType_Rsa2048Sha256)
{
success = true;
goto end;
}
/* Make sure we're dealing with a tampered ticket by verifying its signature. */
tik_data = (TikSigRsa2048*)tik->data;
tik_common_block = &(tik_data->tik_common_block);
hash_area_size = tikGetSignedTicketBlobHashAreaSize(tik->data); hash_area_size = tikGetSignedTicketBlobHashAreaSize(tik->data);
/* Return right away if we're not dealing with a common ticket, if the signature type doesn't match RSA-2048 + SHA-256, or if the signature is valid. */ if (tikVerifyRsa2048Sha256Signature(tik_common_block, hash_area_size, tik_data->sig_block.signature))
if (tik_common_block->titlekey_type != TikTitleKeyType_Common || sig_type != SignatureType_Rsa2048Sha256 || \
tikVerifyRsa2048Sha256Signature(tik_common_block, hash_area_size, signature))
{ {
success = true; success = true;
goto end; goto end;
@ -416,22 +425,35 @@ static bool tikFixTamperedCommonTicket(Ticket *tik)
/* Nintendo didn't start putting the key generation value into the rights ID until HOS 3.0.1. */ /* Nintendo didn't start putting the key generation value into the rights ID until HOS 3.0.1. */
/* Old custom tools used to wipe the key generation field and/or save its value into a different offset. */ /* Old custom tools used to wipe the key generation field and/or save its value into a different offset. */
/* We're gonna take care of that by setting the correct values where they need to go. */ /* We're gonna take care of that by setting the correct values where they need to go. */
memset(signature, 0xFF, signature_size); memset(tik_data->sig_block.signature, 0xFF, sizeof(tik_data->sig_block.signature));
memset(tik_data->sig_block.padding, 0, sizeof(tik_data->sig_block.padding));
memset(tik_common_block->issuer, 0, sizeof(tik_common_block->issuer));
sprintf(tik_common_block->issuer, "Root-CA%08X-%s", dev_cert ? 4 : 3, TIK_COMMON_CERT_NAME);
memset(tik_common_block->titlekey_block + 0x10, 0, sizeof(tik_common_block->titlekey_block) - 0x10);
tik_common_block->format_version = TIK_FORMAT_VERSION;
tik_common_block->titlekey_type = TikTitleKeyType_Common; tik_common_block->titlekey_type = TikTitleKeyType_Common;
tik_common_block->ticket_version = 0;
tik_common_block->license_type = TikLicenseType_Permanent; tik_common_block->license_type = TikLicenseType_Permanent;
tik_common_block->key_generation = tik->key_generation; tik_common_block->key_generation = tik->key_generation;
tik_common_block->property_mask = TikPropertyMask_None; tik_common_block->property_mask = TikPropertyMask_None;
memset(tik_common_block->reserved, 0, sizeof(tik_common_block->reserved));
tik_common_block->ticket_id = 0; tik_common_block->ticket_id = 0;
tik_common_block->device_id = 0; tik_common_block->device_id = 0;
tik_common_block->account_id = 0; tik_common_block->account_id = 0;
tik_common_block->sect_total_size = 0; tik_common_block->sect_total_size = 0;
tik_common_block->sect_hdr_offset = (u32)tik->size; tik_common_block->sect_hdr_offset = (u32)sizeof(TikSigRsa2048);
tik_common_block->sect_hdr_count = 0; tik_common_block->sect_hdr_count = 0;
tik_common_block->sect_hdr_entry_size = 0; tik_common_block->sect_hdr_entry_size = 0;
/* Update ticket size. */
tik->size = sizeof(TikSigRsa2048);
/* Update return value. */ /* Update return value. */
success = true; success = true;
@ -447,8 +469,8 @@ static bool tikVerifyRsa2048Sha256Signature(const TikCommonBlock *tik_common_blo
return false; return false;
} }
const char *cert_name = (strrchr(tik_common_block->issuer, '-') + 1);
Certificate cert = {0}; Certificate cert = {0};
const char *cert_name = (strrchr(tik_common_block->issuer, '-') + 1);
const u8 *modulus = NULL, *public_exponent = NULL; const u8 *modulus = NULL, *public_exponent = NULL;
/* Get certificate for the ticket signature issuer. */ /* Get certificate for the ticket signature issuer. */