From c3415cf25e5c3379ce4a97dc20f74fecf514cfba Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 1 Jun 2020 02:19:40 -0700 Subject: [PATCH] pk11: add proper support for newer (and mariko) package1 --- aes.c | 4 +- extkeys.c | 18 +++- packages.c | 259 ++++++++++++++++++++++++++++++++++++++++++++--------- packages.h | 141 ++++++++++++++++++++++++++--- pki.c | 7 +- settings.h | 3 + 6 files changed, 371 insertions(+), 61 deletions(-) diff --git a/aes.c b/aes.c index ffd6421..e2e420f 100644 --- a/aes.c +++ b/aes.c @@ -70,7 +70,7 @@ void aes_encrypt(aes_ctx_t *ctx, void *dst, const void *src, size_t l) { mbedtls_cipher_reset(&ctx->cipher_enc); /* XTS doesn't need per-block updating */ - if (mbedtls_cipher_get_cipher_mode(&ctx->cipher_enc) == MBEDTLS_MODE_XTS) + if (mbedtls_cipher_get_cipher_mode(&ctx->cipher_enc) == MBEDTLS_MODE_XTS || mbedtls_cipher_get_cipher_mode(&ctx->cipher_enc) == MBEDTLS_MODE_CBC) mbedtls_cipher_update(&ctx->cipher_enc, (const unsigned char * )src, l, (unsigned char *)dst, &out_len); else { @@ -110,7 +110,7 @@ void aes_decrypt(aes_ctx_t *ctx, void *dst, const void *src, size_t l) mbedtls_cipher_reset(&ctx->cipher_dec); /* XTS doesn't need per-block updating */ - if (mbedtls_cipher_get_cipher_mode(&ctx->cipher_dec) == MBEDTLS_MODE_XTS) + if (mbedtls_cipher_get_cipher_mode(&ctx->cipher_dec) == MBEDTLS_MODE_XTS || mbedtls_cipher_get_cipher_mode(&ctx->cipher_enc) == MBEDTLS_MODE_CBC) mbedtls_cipher_update(&ctx->cipher_dec, (const unsigned char * )src, l, (unsigned char *)dst, &out_len); else { diff --git a/extkeys.c b/extkeys.c index ca4bed7..0d227fe 100644 --- a/extkeys.c +++ b/extkeys.c @@ -284,7 +284,13 @@ void extkeys_initialize_settings(hactool_settings_t *settings, FILE *f) { } else if (strcmp(key, "tsec_key") == 0) { parse_hex_key(keyset->tsec_key, value, sizeof(keyset->tsec_key)); matched_key = 1; - } else if (strcmp(key, "tsec_root_kek") == 0) { + } else if (strcmp(key, "mariko_kek") == 0) { + parse_hex_key(keyset->mariko_kek, value, sizeof(keyset->mariko_kek)); + matched_key = 1; + } else if (strcmp(key, "mariko_bek") == 0) { + parse_hex_key(keyset->mariko_bek, value, sizeof(keyset->mariko_bek)); + matched_key = 1; + } else if (strcmp(key, "tsec_root_kek") == 0) { parse_hex_key(keyset->tsec_root_kek, value, sizeof(keyset->tsec_root_kek)); matched_key = 1; } else if (strcmp(key, "package1_mac_kek") == 0) { @@ -365,6 +371,16 @@ void extkeys_initialize_settings(hactool_settings_t *settings, FILE *f) { break; } } + + for (unsigned int i = 0; i < 0xC && !matched_key; i++) { + snprintf(test_name, sizeof(test_name), "mariko_aes_class_key_%02"PRIx32, i); + if (strcmp(key, test_name) == 0) { + parse_hex_key(keyset->mariko_aes_class_keys[i], value, sizeof(keyset->mariko_aes_class_keys[i])); + matched_key = 1; + break; + } + } + for (unsigned int i = 0; i < 0x20 && !matched_key; i++) { snprintf(test_name, sizeof(test_name), "master_kek_%02"PRIx32, i); if (strcmp(key, test_name) == 0) { diff --git a/packages.c b/packages.c index f7d051e..d75a023 100644 --- a/packages.c +++ b/packages.c @@ -5,6 +5,26 @@ #include "rsa.h" #include "sha.h" +static int pk11_is_mariko(pk11_ctx_t *ctx) { + fseeko64(ctx->file, 0, SEEK_SET); + if (fread(&ctx->mariko_oem_header, 1, sizeof(ctx->mariko_oem_header), ctx->file) != sizeof(ctx->mariko_oem_header)) { + fprintf(stderr, "Failed to read PK11 OEM Header!\n"); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < 0x10; i++) { + if (ctx->mariko_oem_header.aes_mac[i] != 0 || ctx->mariko_oem_header._0x160[i] != 0) { + return 0; + } + } + + return 1; +} + +static int pk11_is_legacy(pk11_ctx_t *ctx) { + return ctx->metadata.version < 0x0E || memcmp(ctx->metadata.build_date, "20181107", 8) < 0; +} + void pk11_process(pk11_ctx_t *ctx) { fseeko64(ctx->file, 0, SEEK_SET); if (fread(&ctx->stage1, 1, sizeof(ctx->stage1), ctx->file) != sizeof(ctx->stage1)) { @@ -12,50 +32,147 @@ void pk11_process(pk11_ctx_t *ctx) { exit(EXIT_FAILURE); } - /* Check if PK11 was built in 2016. */ - /* This is a heuristic to detect an older layout for the PK11 binary. */ - if (ctx->stage1.build_date[0] == '2' && ctx->stage1.build_date[1] == '0' && ctx->stage1.build_date[2] == '1' && ctx->stage1.build_date[3] == '6') { - ctx->is_pilot = 1; + // Detect mariko + ctx->is_mariko = pk11_is_mariko(ctx); + + if (ctx->is_mariko) { + fseeko64(ctx->file, sizeof(ctx->mariko_oem_header), SEEK_SET); + + if (ctx->mariko_oem_header.bl_size < sizeof(ctx->metadata)) { + fprintf(stderr, "PK11 seems corrupt!\n"); + exit(EXIT_FAILURE); + } + + ctx->mariko_bl = calloc(1, ctx->mariko_oem_header.bl_size); + if (fread(ctx->mariko_bl, 1, ctx->mariko_oem_header.bl_size, ctx->file) != ctx->mariko_oem_header.bl_size) { + fprintf(stderr, "Failed to read Mariko PK11!\n"); + exit(EXIT_FAILURE); + } + + memcpy(&ctx->metadata, ctx->mariko_bl, sizeof(ctx->metadata)); + + uint32_t enc_size = ctx->mariko_oem_header.bl_size - sizeof(ctx->metadata); + if (enc_size > 0) { + aes_ctx_t *crypt_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.mariko_bek, 0x10, AES_MODE_CBC); + + aes_setiv(crypt_ctx, ctx->mariko_bl + 0x10, 0x10); + aes_decrypt(crypt_ctx, ctx->mariko_bl + 0x20, ctx->mariko_bl + 0x20, enc_size); + + free_aes_ctx(crypt_ctx); + + if (memcmp(&ctx->metadata, ctx->mariko_bl + 0x20, sizeof(ctx->metadata)) != 0) { + fprintf(stderr, "Failed to decrypt Mariko PK11! Is correct key present?\n"); + exit(EXIT_FAILURE); + } + } } else { - ctx->is_pilot = 0; + fseeko64(ctx->file, 0, SEEK_SET); + + if (fread(&ctx->metadata, 1, sizeof(ctx->metadata), ctx->file) != sizeof(ctx->metadata)) { + fprintf(stderr, "Failed to read PK11 Metadata!\n"); + exit(EXIT_FAILURE); + } } - ctx->pk11 = malloc(ctx->stage1.pk11_size); + ctx->is_modern = !pk11_is_legacy(ctx); + + if (ctx->is_mariko) { + if (ctx->is_modern) { + memcpy(&ctx->stage1.modern, ctx->mariko_bl + 0x20, sizeof(ctx->stage1.modern)); + ctx->pk11_size = ctx->stage1.modern.pk11_size; + } else { + memcpy(&ctx->stage1.legacy, ctx->mariko_bl + 0x20, sizeof(ctx->stage1.legacy)); + ctx->pk11_size = ctx->stage1.legacy.pk11_size; + } + } else { + if (ctx->is_modern) { + if (fread(&ctx->stage1.modern, 1, sizeof(ctx->stage1.modern), ctx->file) != sizeof(ctx->stage1.modern)) { + fprintf(stderr, "Failed to read PK11 Stage1!\n"); + exit(EXIT_FAILURE); + } + ctx->pk11_size = ctx->stage1.modern.pk11_size; + } else { + if (fread(&ctx->stage1.legacy, 1, sizeof(ctx->stage1.legacy), ctx->file) != sizeof(ctx->stage1.legacy)) { + fprintf(stderr, "Failed to read PK11 Stage1!\n"); + exit(EXIT_FAILURE); + } + ctx->pk11_size = ctx->stage1.legacy.pk11_size; + } + } + + ctx->pk11 = malloc(ctx->pk11_size); if (ctx->pk11 == NULL) { fprintf(stderr, "Failed to allocate PK11!\n"); exit(EXIT_FAILURE); } - if (fread(ctx->pk11, 1, ctx->stage1.pk11_size, ctx->file) != ctx->stage1.pk11_size) { - fprintf(stderr, "Failed to read PK11!\n"); - exit(EXIT_FAILURE); - } - - aes_ctx_t *crypt_ctx = NULL; - pk11_t dec_header; - for (unsigned int i = 0; i < 0x20; i++) { - ctx->key_rev = i; - crypt_ctx = new_aes_ctx(&ctx->tool_ctx->settings.keyset.package1_keys[i], 0x10, AES_MODE_CTR); - aes_setiv(crypt_ctx, ctx->stage1.ctr, 0x10); - aes_decrypt(crypt_ctx, &dec_header, ctx->pk11, sizeof(dec_header)); - if (dec_header.magic == MAGIC_PK11) { - break; + if (ctx->is_mariko) { + if (ctx->is_modern) { + memcpy(ctx->pk11, ctx->mariko_bl + 0x20 + sizeof(ctx->stage1.modern), ctx->pk11_size); + } else { + memcpy(ctx->pk11, ctx->mariko_bl + 0x20 + sizeof(ctx->stage1.legacy), ctx->pk11_size); + } + + } else { + if (fread(ctx->pk11, 1, ctx->pk11_size, ctx->file) != ctx->pk11_size) { + fprintf(stderr, "Failed to read PK11!\n"); + exit(EXIT_FAILURE); + } + + if (ctx->is_modern) { + if (fread(&ctx->pk11_mac, 1, sizeof(ctx->pk11_mac), ctx->file) != sizeof(ctx->pk11_mac)) { + fprintf(stderr, "Failed to read PK11 MAC!\n"); + exit(EXIT_FAILURE); + } } - free_aes_ctx(crypt_ctx); - crypt_ctx = NULL; } - if (crypt_ctx == NULL) { + int decrypted = 0; + if (ctx->is_mariko) { + decrypted = ctx->pk11->magic == MAGIC_PK11; + } else { + pk11_t dec_header; + aes_ctx_t *crypt_ctx = NULL; + if (ctx->is_modern) { + for (unsigned int i = 6; i < 0x20 && !decrypted; i++) { + ctx->key_rev = i; + crypt_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.package1_keys[i], 0x10, AES_MODE_CBC); + aes_setiv(crypt_ctx, ctx->stage1.modern.iv, 0x10); + aes_decrypt(crypt_ctx, &dec_header, ctx->pk11, sizeof(dec_header)); + if (dec_header.magic == MAGIC_PK11) { + aes_setiv(crypt_ctx, ctx->stage1.modern.iv, 0x10); + aes_decrypt(crypt_ctx, ctx->pk11, ctx->pk11, ctx->pk11_size); + decrypted = 1; + } + free_aes_ctx(crypt_ctx); + crypt_ctx = NULL; + } + } else { + for (unsigned int i = 0; i < 6 && !decrypted; i++) { + ctx->key_rev = i; + crypt_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.package1_keys[i], 0x10, AES_MODE_CTR); + aes_setiv(crypt_ctx, ctx->stage1.legacy.ctr, 0x10); + aes_decrypt(crypt_ctx, &dec_header, ctx->pk11, sizeof(dec_header)); + if (dec_header.magic == MAGIC_PK11) { + aes_setiv(crypt_ctx, ctx->stage1.legacy.ctr, 0x10); + aes_decrypt(crypt_ctx, ctx->pk11, ctx->pk11, ctx->pk11_size); + decrypted = 1; + } + free_aes_ctx(crypt_ctx); + crypt_ctx = NULL; + } + } + } + + if (!decrypted) { fprintf(stderr, "Failed to decrypt PK11! Is correct key present?\n"); exit(EXIT_FAILURE); } - aes_setiv(crypt_ctx, ctx->stage1.ctr, 0x10); - aes_decrypt(crypt_ctx, ctx->pk11, ctx->pk11, ctx->stage1.pk11_size); - uint64_t pk11_size = 0x20 + ctx->pk11->warmboot_size + ctx->pk11->nx_bootloader_size + ctx->pk11->secmon_size; + uint64_t pk11_size = 0x20 + pk11_get_warmboot_bin_size(ctx) + pk11_get_nx_bootloader_size(ctx) + pk11_get_secmon_size(ctx); pk11_size = align64(pk11_size, 0x10); - if (pk11_size != ctx->stage1.pk11_size) { + if (pk11_size != ctx->pk11_size) { fprintf(stderr, "PK11 seems corrupt!\n"); exit(EXIT_FAILURE); } @@ -71,13 +188,20 @@ void pk11_process(pk11_ctx_t *ctx) { void pk11_print(pk11_ctx_t *ctx) { printf("PK11:\n"); - printf(" Build Date: %s\n", ctx->stage1.build_date); - memdump(stdout, " Build Hash: ", ctx->stage1.build_hash, 0x10); + { + char build_date[sizeof(ctx->metadata.build_date) + 1] = {0}; + memcpy(build_date, ctx->metadata.build_date, sizeof(ctx->metadata.build_date)); + printf(" Build Date: %s\n", build_date); + } + memdump(stdout, " Package1ldr Hash: ", &ctx->metadata.ldr_hash, sizeof(uint32_t)); + memdump(stdout, " Secure Monitor Hash: ", &ctx->metadata.sm_hash, sizeof(uint32_t)); + memdump(stdout, " NX Bootloader Hash: ", &ctx->metadata.bl_hash, sizeof(uint32_t)); + printf(" Version: %02"PRIx32"\n", ctx->metadata.version); printf(" Key Revision: %02"PRIx32" (%s)\n", ctx->key_rev, get_key_revision_summary((uint8_t)ctx->key_rev)); - printf(" PK11 Size: %08"PRIx32"\n", ctx->stage1.pk11_size); - printf(" Warmboot.bin Size: %08"PRIx32"\n", ctx->pk11->warmboot_size); - printf(" NX_Bootloader.bin Size %08"PRIx32"\n", ctx->pk11->nx_bootloader_size); - printf(" Secure_Monitor.bin Size: %08"PRIx32"\n", ctx->pk11->secmon_size); + printf(" PK11 Size: %08"PRIx32"\n", ctx->pk11_size); + printf(" Warmboot.bin Size: %08"PRIx32"\n", pk11_get_warmboot_bin_size(ctx)); + printf(" NX_Bootloader.bin Size %08"PRIx32"\n", pk11_get_nx_bootloader_size(ctx)); + printf(" Secure_Monitor.bin Size: %08"PRIx32"\n", pk11_get_secmon_size(ctx)); printf("\n"); } @@ -95,27 +219,74 @@ void pk11_save(pk11_ctx_t *ctx) { /* Save Decrypted.bin */ printf("Saving decrypted binary to %s/Decrypted.bin\n", dirpath->char_path); - char *decrypted_bin = malloc(sizeof(ctx->stage1) + ctx->stage1.pk11_size); - if (decrypted_bin == NULL) { - fprintf(stderr, "Failed to allocate buffer!\n"); - exit(EXIT_FAILURE); + if (ctx->is_mariko) { + char *decrypted_bin = malloc(sizeof(ctx->mariko_oem_header) + ctx->mariko_oem_header.bl_size); + if (decrypted_bin == NULL) { + fprintf(stderr, "Failed to allocate buffer!\n"); + exit(EXIT_FAILURE); + } + memcpy(decrypted_bin, &ctx->mariko_oem_header, sizeof(ctx->mariko_oem_header)); + memcpy(decrypted_bin + sizeof(ctx->mariko_oem_header), ctx->mariko_bl, ctx->mariko_oem_header.bl_size); + save_buffer_to_directory_file(decrypted_bin, sizeof(ctx->stage1) + ctx->pk11_size, dirpath, "Decrypted.bin"); + free(decrypted_bin); + } else { + char *decrypted_bin = malloc(sizeof(ctx->stage1) + ctx->pk11_size); + if (decrypted_bin == NULL) { + fprintf(stderr, "Failed to allocate buffer!\n"); + exit(EXIT_FAILURE); + } + memcpy(decrypted_bin, &ctx->stage1, sizeof(ctx->stage1)); + memcpy(decrypted_bin + sizeof(ctx->stage1), ctx->pk11, ctx->pk11_size); + save_buffer_to_directory_file(decrypted_bin, sizeof(ctx->stage1) + ctx->pk11_size, dirpath, "Decrypted.bin"); + free(decrypted_bin); + } + + /* Save Mariko_OEM_Bootloader.bin */ + if (ctx->is_mariko) { + printf("Saving Mariko_OEM_Bootloader.bin to %s/Mariko_OEM_Bootloader.bin...\n", dirpath->char_path); + save_buffer_to_directory_file(ctx->mariko_bl, ctx->mariko_oem_header.bl_size, dirpath, "Mariko_OEM_Bootloader.bin"); } - memcpy(decrypted_bin, &ctx->stage1, sizeof(ctx->stage1)); - memcpy(decrypted_bin + sizeof(ctx->stage1), ctx->pk11, ctx->stage1.pk11_size); - save_buffer_to_directory_file(decrypted_bin, sizeof(ctx->stage1) + ctx->stage1.pk11_size, dirpath, "Decrypted.bin"); - free(decrypted_bin); /* Save Warmboot.bin */ printf("Saving Warmboot.bin to %s/Warmboot.bin...\n", dirpath->char_path); - save_buffer_to_directory_file(pk11_get_warmboot_bin(ctx), ctx->pk11->warmboot_size, dirpath, "Warmboot.bin"); + save_buffer_to_directory_file(pk11_get_warmboot_bin(ctx), pk11_get_warmboot_bin_size(ctx), dirpath, "Warmboot.bin"); + + if (ctx->is_mariko) { + + uint32_t wb_size = pk11_get_warmboot_bin_size(ctx); + + unsigned char *wb_dec = malloc(wb_size); + if (wb_dec == NULL) { + fprintf(stderr, "Failed to allocate mariko warmboot binary!\n"); + exit(EXIT_FAILURE); + } + + memcpy(wb_dec, pk11_get_warmboot_bin(ctx), wb_size); + + if (wb_size > 0x330) { + aes_ctx_t *crypt_ctx = new_aes_ctx(ctx->tool_ctx->settings.keyset.mariko_bek, 0x10, AES_MODE_CBC); + + unsigned char iv[0x10] = {0}; + aes_setiv(crypt_ctx, iv, 0x10); + + aes_decrypt(crypt_ctx, wb_dec + 0x330, wb_dec + 0x330, wb_size - 0x330); + + free_aes_ctx(crypt_ctx); + } + + printf("Saving Warmboot_Decrypted.bin to %s/Warmboot_Decrypted.bin...\n", dirpath->char_path); + save_buffer_to_directory_file(wb_dec, wb_size, dirpath, "Warmboot_Decrypted.bin"); + + free(wb_dec); + } /* Save NX_Bootloader.bin */ printf("Saving NX_Bootloader.bin to %s/NX_Bootloader.bin...\n", dirpath->char_path); - save_buffer_to_directory_file(pk11_get_nx_bootloader(ctx), ctx->pk11->nx_bootloader_size, dirpath, "NX_Bootloader.bin"); + save_buffer_to_directory_file(pk11_get_nx_bootloader(ctx), pk11_get_nx_bootloader_size(ctx), dirpath, "NX_Bootloader.bin"); /* Save Secure_Monitor.bin */ printf("Saving Secure_Monitor.bin to %s/Secure_Monitor.bin...\n", dirpath->char_path); - save_buffer_to_directory_file(pk11_get_secmon(ctx), ctx->pk11->secmon_size, dirpath, "Secure_Monitor.bin"); + save_buffer_to_directory_file(pk11_get_secmon(ctx), pk11_get_secmon_size(ctx), dirpath, "Secure_Monitor.bin"); } } diff --git a/packages.h b/packages.h index a9259cb..985b2a0 100644 --- a/packages.h +++ b/packages.h @@ -11,46 +11,161 @@ #define MAGIC_KRNLLDR_STRCT_END 0xD51C403E typedef struct { - unsigned char build_hash[0x10]; - unsigned char build_date[0x10]; + unsigned char aes_mac[0x10]; + unsigned char rsa_sig[0x100]; + unsigned char salt[0x20]; + unsigned char hash[0x20]; + uint32_t bl_version; + uint32_t bl_size; + uint32_t bl_load_addr; + uint32_t bl_entrypoint; + unsigned char _0x160[0x10]; +} pk11_mariko_oem_header_t; + +typedef struct { + uint32_t ldr_hash; + uint32_t sm_hash; + uint32_t bl_hash; + uint32_t _0xC; + char build_date[0xE]; + unsigned char _0x1E; + unsigned char version; +} pk11_metadata_t; + +typedef struct { unsigned char stage1[0x3FC0]; uint32_t pk11_size; - unsigned char _0x3FE4[0xC]; + unsigned char _0x3FC4[0xC]; unsigned char ctr[0x10]; +} pk11_legacy_stage1_t; + +typedef struct { + unsigned char stage1[0x6FC0]; + uint32_t pk11_size; + unsigned char _0x6FC4[0xC]; + unsigned char iv[0x10]; +} pk11_modern_stage1_t; + +typedef union { + pk11_legacy_stage1_t legacy; + pk11_modern_stage1_t modern; } pk11_stage1_t; typedef struct { uint32_t magic; - uint32_t warmboot_size; - uint32_t _0x8; + uint32_t wb_size; + uint32_t wb_ep; uint32_t _0xC; - uint32_t nx_bootloader_size; - uint32_t _0x14; - uint32_t secmon_size; - uint32_t _0x1C; + uint32_t bl_size; + uint32_t bl_ep; + uint32_t sm_size; + uint32_t sm_ep; unsigned char data[]; } pk11_t; typedef struct { FILE *file; hactool_ctx_t *tool_ctx; - int is_pilot; + int is_modern; + int is_mariko; unsigned int key_rev; + pk11_mariko_oem_header_t mariko_oem_header; + pk11_metadata_t metadata; pk11_stage1_t stage1; + uint32_t pk11_size; + uint8_t *mariko_bl; pk11_t *pk11; + unsigned char pk11_mac[0x10]; } pk11_ctx_t; +typedef enum { + PK11_SECTION_BL, + PK11_SECTION_SM, + PK11_SECTION_WB, +} pk11_section_id_t; + +static inline int pk11_get_section_idx(pk11_ctx_t *ctx, pk11_section_id_t section_id) { + if (ctx->metadata.version >= 0x07) { + switch (section_id) { + case PK11_SECTION_BL: return 0; + case PK11_SECTION_SM: return 1; + case PK11_SECTION_WB: return 2; + } + } else if (ctx->metadata.version >= 0x02) { + switch (section_id) { + case PK11_SECTION_BL: return 1; + case PK11_SECTION_SM: return 2; + case PK11_SECTION_WB: return 0; + } + } else { + switch (section_id) { + case PK11_SECTION_BL: return 1; + case PK11_SECTION_SM: return 0; + case PK11_SECTION_WB: return 2; + } + } + + return 0; +} + +static inline pk11_section_id_t pk11_get_section_id(pk11_ctx_t *ctx, int id) { + if (pk11_get_section_idx(ctx, PK11_SECTION_BL) == id) { + return PK11_SECTION_BL; + } else if (pk11_get_section_idx(ctx, PK11_SECTION_SM) == id) { + return PK11_SECTION_SM; + } else { + return PK11_SECTION_WB; + } +} + +static inline uint32_t pk11_get_section_size(pk11_ctx_t *ctx, pk11_section_id_t section_id) { + switch (section_id) { + case PK11_SECTION_BL: return ctx->pk11->bl_size; + case PK11_SECTION_SM: return ctx->pk11->sm_size; + case PK11_SECTION_WB: return ctx->pk11->wb_size; + } + + return 0; +} + +static inline uint32_t pk11_get_section_ofs(pk11_ctx_t *ctx, pk11_section_id_t section_id) { + switch (pk11_get_section_idx(ctx, section_id)) { + case 0: + default: + return 0; + case 1: + return pk11_get_section_size(ctx, pk11_get_section_id(ctx, 0)); + case 2: + return pk11_get_section_size(ctx, pk11_get_section_id(ctx, 0)) + pk11_get_section_size(ctx, pk11_get_section_id(ctx, 1)); + } +} + +static inline unsigned char *pk11_get_section(pk11_ctx_t *ctx, pk11_section_id_t section_id) { + return &ctx->pk11->data[pk11_get_section_ofs(ctx, section_id)]; +} static inline unsigned char *pk11_get_warmboot_bin(pk11_ctx_t *ctx) { - return ctx->is_pilot ? &ctx->pk11->data[ctx->pk11->secmon_size + ctx->pk11->nx_bootloader_size] : &ctx->pk11->data[0]; + return pk11_get_section(ctx, PK11_SECTION_WB); } static inline unsigned char *pk11_get_secmon(pk11_ctx_t *ctx) { - return ctx->is_pilot ? &ctx->pk11->data[0] : &ctx->pk11->data[ctx->pk11->warmboot_size + ctx->pk11->nx_bootloader_size]; + return pk11_get_section(ctx, PK11_SECTION_SM); } static inline unsigned char *pk11_get_nx_bootloader(pk11_ctx_t *ctx) { - return ctx->is_pilot ? &ctx->pk11->data[ctx->pk11->secmon_size] : &ctx->pk11->data[ctx->pk11->warmboot_size]; + return pk11_get_section(ctx, PK11_SECTION_BL); +} + +static inline unsigned int pk11_get_warmboot_bin_size(pk11_ctx_t *ctx) { + return pk11_get_section_size(ctx, PK11_SECTION_WB); +} + +static inline unsigned int pk11_get_secmon_size(pk11_ctx_t *ctx) { + return pk11_get_section_size(ctx, PK11_SECTION_SM); +} + +static inline unsigned int pk11_get_nx_bootloader_size(pk11_ctx_t *ctx) { + return pk11_get_section_size(ctx, PK11_SECTION_BL); } diff --git a/pki.c b/pki.c index 4ac19d3..ae0b506 100644 --- a/pki.c +++ b/pki.c @@ -65,7 +65,6 @@ const unsigned char *pki_get_beta_nca0_label_hash(void) { return beta_nca0_label_hash; } - static const nca_keyset_t nca_keys_retail = { .nca_hdr_fixed_key_moduli = { /* Fixed RSA key used to validate NCA signature 0. */ { @@ -509,6 +508,12 @@ void pki_print_keys(nca_keyset_t *keyset) { PRINT_KEY_WITH_NAME_IDX(keyset->master_kek_sources[i], master_kek_source, i); } printf("\n"); + PRINT_KEY_WITH_NAME(keyset->mariko_kek, mariko_kek); + PRINT_KEY_WITH_NAME(keyset->mariko_bek, mariko_bek); + for (unsigned int i = 0x0; i < 0xC; i++) { + PRINT_KEY_WITH_NAME_IDX(keyset->mariko_aes_class_keys[i], mariko_aes_class_key, i); + } + printf("\n"); for (unsigned int i = 0x0; i < 0x20; i++) { PRINT_KEY_WITH_NAME_IDX(keyset->master_keks[i], master_kek, i); } diff --git a/settings.h b/settings.h index 82440e6..202f89a 100644 --- a/settings.h +++ b/settings.h @@ -22,6 +22,9 @@ typedef struct { unsigned char keyblob_keys[0x20][0x10]; /* Actual keys used to decrypt keyblobs. NOTE: CONSOLE UNIQUE.*/ unsigned char keyblob_mac_keys[0x20][0x10]; /* Keys used to validate keyblobs. NOTE: CONSOLE UNIQUE. */ unsigned char encrypted_keyblobs[0x20][0xB0]; /* Actual encrypted keyblobs (EKS). NOTE: CONSOLE UNIQUE. */ + unsigned char mariko_aes_class_keys[0xC][0x10]; /* AES Class Keys set by mariko bootrom. */ + unsigned char mariko_kek[0x10]; /* Key Encryption Key for mariko. */ + unsigned char mariko_bek[0x10]; /* Boot Encryption Key for mariko. */ unsigned char keyblobs[0x20][0x90]; /* Actual decrypted keyblobs (EKS). */ unsigned char keyblob_key_sources[0x20][0x10]; /* Seeds for keyblob keys. */ unsigned char keyblob_mac_key_source[0x10]; /* Seed for keyblob MAC key derivation. */