diff --git a/bdk/utils/util.c b/bdk/utils/util.c index 146c404..1fae04e 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -102,6 +102,27 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) base[ops[i].off] = ops[i].val; } +u16 crc16_calc(const u8 *buf, u32 len) +{ + const u8 *p, *q; + u16 crc = 0x55aa; + + static u16 table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400 + }; + + q = buf + len; + for (p = buf; p < q; p++) + { + u8 oct = *p; + crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 0) & 0xf]; + crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 4) & 0xf]; + } + + return crc; +} + u32 crc32_calc(u32 crc, const u8 *buf, u32 len) { const u8 *p, *q; diff --git a/bdk/utils/util.h b/bdk/utils/util.h index d3d391f..972a906 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -83,6 +83,7 @@ u8 bit_count(u32 val); u32 bit_count_mask(u8 bits); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); +u16 crc16_calc(const u8 *buf, u32 len); u32 crc32_calc(u32 crc, const u8 *buf, u32 len); u32 get_tmr_us(); diff --git a/source/keys/keys.c b/source/keys/keys.c index ae165aa..4caa658 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -461,8 +461,23 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit return false; } - // settings sysmodule manually zeroes this out below cal version 9 - u32 keypair_generation = cal0->version <= 8 ? 0 : cal0->ext_ecc_rsa2048_eticket_key_ver; + u32 keypair_generation = 0; + const void *eticket_device_key = NULL; + const void *eticket_iv = NULL; + + if (cal0->ext_ecc_rsa2048_eticket_key_crc == crc16_calc(cal0->ext_ecc_rsa2048_eticket_key_iv, 0x24E)) { + eticket_device_key = cal0->ext_ecc_rsa2048_eticket_key; + eticket_iv = cal0->ext_ecc_rsa2048_eticket_key_iv; + + // settings sysmodule manually zeroes this out below cal version 9 + keypair_generation = cal0->version <= 8 ? 0 : cal0->ext_ecc_rsa2048_eticket_key_ver; + } else if (cal0->rsa2048_eticket_key_crc == crc16_calc(cal0->rsa2048_eticket_key_iv, 0x22E)) { + eticket_device_key = cal0->rsa2048_eticket_key; + eticket_iv = cal0->rsa2048_eticket_key_iv; + } else { + EPRINTF("Crc16 error reading device key."); + return false; + } if (keypair_generation) { keypair_generation--; @@ -478,7 +493,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit } se_aes_key_set(6, keys->temp_key, sizeof(keys->temp_key)); - se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), cal0->ext_ecc_rsa2048_eticket_key, sizeof(cal0->ext_ecc_rsa2048_eticket_key), cal0->ext_ecc_rsa2048_eticket_key_iv); + se_aes_crypt_ctr(6, &rsa_keypair, sizeof(rsa_keypair), eticket_device_key, sizeof(rsa_keypair), eticket_iv); // Check public exponent is 65537 big endian if (_read_be_u32(rsa_keypair.public_exponent, 0) != 65537) { diff --git a/source/keys/keys.h b/source/keys/keys.h index 97a9309..676fddb 100644 --- a/source/keys/keys.h +++ b/source/keys/keys.h @@ -67,9 +67,7 @@ typedef struct { u8 private_exponent[RSA_2048_KEY_SIZE]; u8 modulus[RSA_2048_KEY_SIZE]; u8 public_exponent[4]; - u8 reserved[0x14]; - u64 device_id; - u8 gmac[0x10]; + u8 reserved[0xC]; } rsa_keypair_t; typedef struct { diff --git a/source/storage/nx_emmc_bis.h b/source/storage/nx_emmc_bis.h index 4eb5d82..59b766e 100644 --- a/source/storage/nx_emmc_bis.h +++ b/source/storage/nx_emmc_bis.h @@ -124,8 +124,10 @@ typedef struct _nx_emmc_cal0_t u8 crc16_pad20[0x10]; u8 gc_cert[0x400]; u8 gc_cert_sha256[0x20]; - u8 rsa2048_eticket_key[0x220]; - u8 crc16_pad21[0x10]; + u8 rsa2048_eticket_key_iv[0x10]; + u8 rsa2048_eticket_key[0x210]; + u8 crc16_pad21[0xE]; + u16 rsa2048_eticket_key_crc; u8 rsa2048_eticket_cert[0x240]; u8 crc16_pad22[0x10]; @@ -166,7 +168,8 @@ typedef struct _nx_emmc_cal0_t u8 ext_ecc_rsa2048_eticket_key_iv[0x10]; u8 ext_ecc_rsa2048_eticket_key[0x230]; u32 ext_ecc_rsa2048_eticket_key_ver; - u8 crc16_pad38[0xC]; + u8 crc16_pad38[0xA]; + u16 ext_ecc_rsa2048_eticket_key_crc; u8 ext_ssl_key[0x130]; u8 crc16_pad39[0x10]; u8 ext_gc_key[0x130];