Skip to content

Commit

Permalink
Implement support for 6.2.0+ keygen.
Browse files Browse the repository at this point in the history
  • Loading branch information
SciresM committed Nov 24, 2018
1 parent 3b399f2 commit 0388e1b
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 20 deletions.
1 change: 1 addition & 0 deletions aes.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "aes.h"
#include "types.h"
#include "utils.h"
Expand Down
31 changes: 28 additions & 3 deletions extkeys.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,13 @@ void extkeys_initialize_keyset(nca_keyset_t *keyset, FILE *f) {
} else if (strcmp(key, "sd_card_save_key_source") == 0) {
parse_hex_key(keyset->sd_card_key_sources[0], value, sizeof(keyset->sd_card_key_sources[0]));
matched_key = 1;
} else if (strcmp(key, "master_key_source") == 0) {
} else if (strcmp(key, "save_mac_kek_source") == 0) {
parse_hex_key(keyset->save_mac_kek_source, value, sizeof(keyset->save_mac_kek_source));
matched_key = 1;
} else if (strcmp(key, "save_mac_key_source") == 0) {
parse_hex_key(keyset->save_mac_key_source, value, sizeof(keyset->save_mac_key_source));
matched_key = 1;
} else if (strcmp(key, "master_key_source") == 0) {
parse_hex_key(keyset->master_key_source, value, sizeof(keyset->master_key_source));
matched_key = 1;
} else if (strcmp(key, "keyblob_mac_key_source") == 0) {
Expand All @@ -254,14 +260,17 @@ void extkeys_initialize_keyset(nca_keyset_t *keyset, 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, "beta_nca0_exponent") == 0) {
} else if (strcmp(key, "tsec_root_key") == 0) {
parse_hex_key(keyset->tsec_root_key, value, sizeof(keyset->tsec_root_key));
matched_key = 1;
} else if (strcmp(key, "beta_nca0_exponent") == 0) {
unsigned char exponent[0x100] = {0};
parse_hex_key(exponent, value, sizeof(exponent));
pki_set_beta_nca0_exponent(exponent);
matched_key = 1;
} else {
char test_name[0x100] = {0};
for (unsigned int i = 0; i < 0x20 && !matched_key; i++) {
for (unsigned int i = 0; i < 0x6 && !matched_key; i++) {
snprintf(test_name, sizeof(test_name), "keyblob_key_source_%02"PRIx32, i);
if (strcmp(key, test_name) == 0) {
parse_hex_key(keyset->keyblob_key_sources[i], value, sizeof(keyset->keyblob_key_sources[i]));
Expand Down Expand Up @@ -296,6 +305,22 @@ void extkeys_initialize_keyset(nca_keyset_t *keyset, FILE *f) {
matched_key = 1;
break;
}
}
for (unsigned int i = 0x6; i < 0x20 && !matched_key; i++) {
snprintf(test_name, sizeof(test_name), "master_kek_source_%02"PRIx32, i);
if (strcmp(key, test_name) == 0) {
parse_hex_key(keyset->master_kek_sources[i], value, sizeof(keyset->master_kek_sources[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) {
parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i]));
matched_key = 1;
break;
}

snprintf(test_name, sizeof(test_name), "master_key_%02"PRIx32, i);
if (strcmp(key, test_name) == 0) {
Expand Down
199 changes: 182 additions & 17 deletions pki.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,75 @@ static const nca_keyset_t nca_keys_retail = {
ZEROES_KEY /* Keyblob Key Source 31 (CONSOLE UNIQUE) */
},
ZEROES_KEY, /* Keyblob Mac Key Source */
ZEROES_KEY, /* TSEC Root Key */
{
ZEROES_KEY, /* Master Kek Source 00 */
ZEROES_KEY, /* Master Kek Source 01 */
ZEROES_KEY, /* Master Kek Source 02 */
ZEROES_KEY, /* Master Kek Source 03 */
ZEROES_KEY, /* Master Kek Source 04 */
ZEROES_KEY, /* Master Kek Source 05 */
ZEROES_KEY, /* Master Kek Source 06 */
ZEROES_KEY, /* Master Kek Source 07 */
ZEROES_KEY, /* Master Kek Source 08 */
ZEROES_KEY, /* Master Kek Source 09 */
ZEROES_KEY, /* Master Kek Source 10 */
ZEROES_KEY, /* Master Kek Source 11 */
ZEROES_KEY, /* Master Kek Source 12 */
ZEROES_KEY, /* Master Kek Source 13 */
ZEROES_KEY, /* Master Kek Source 14 */
ZEROES_KEY, /* Master Kek Source 15 */
ZEROES_KEY, /* Master Kek Source 16 */
ZEROES_KEY, /* Master Kek Source 17 */
ZEROES_KEY, /* Master Kek Source 18 */
ZEROES_KEY, /* Master Kek Source 19 */
ZEROES_KEY, /* Master Kek Source 20 */
ZEROES_KEY, /* Master Kek Source 21 */
ZEROES_KEY, /* Master Kek Source 22 */
ZEROES_KEY, /* Master Kek Source 23 */
ZEROES_KEY, /* Master Kek Source 24 */
ZEROES_KEY, /* Master Kek Source 25 */
ZEROES_KEY, /* Master Kek Source 26 */
ZEROES_KEY, /* Master Kek Source 27 */
ZEROES_KEY, /* Master Kek Source 28 */
ZEROES_KEY, /* Master Kek Source 29 */
ZEROES_KEY, /* Master Kek Source 30 */
ZEROES_KEY /* Master Kek Source 31 */
},
{
ZEROES_KEY, /* Master Kek 00 */
ZEROES_KEY, /* Master Kek 01 */
ZEROES_KEY, /* Master Kek 02 */
ZEROES_KEY, /* Master Kek 03 */
ZEROES_KEY, /* Master Kek 04 */
ZEROES_KEY, /* Master Kek 05 */
ZEROES_KEY, /* Master Kek 06 */
ZEROES_KEY, /* Master Kek 07 */
ZEROES_KEY, /* Master Kek 08 */
ZEROES_KEY, /* Master Kek 09 */
ZEROES_KEY, /* Master Kek 10 */
ZEROES_KEY, /* Master Kek 11 */
ZEROES_KEY, /* Master Kek 12 */
ZEROES_KEY, /* Master Kek 13 */
ZEROES_KEY, /* Master Kek 14 */
ZEROES_KEY, /* Master Kek 15 */
ZEROES_KEY, /* Master Kek 16 */
ZEROES_KEY, /* Master Kek 17 */
ZEROES_KEY, /* Master Kek 18 */
ZEROES_KEY, /* Master Kek 19 */
ZEROES_KEY, /* Master Kek 20 */
ZEROES_KEY, /* Master Kek 21 */
ZEROES_KEY, /* Master Kek 22 */
ZEROES_KEY, /* Master Kek 23 */
ZEROES_KEY, /* Master Kek 24 */
ZEROES_KEY, /* Master Kek 25 */
ZEROES_KEY, /* Master Kek 26 */
ZEROES_KEY, /* Master Kek 27 */
ZEROES_KEY, /* Master Kek 28 */
ZEROES_KEY, /* Master Kek 29 */
ZEROES_KEY, /* Master Kek 30 */
ZEROES_KEY /* Master Kek 31 */
},
ZEROES_KEY, /* Master Key Source */
{
ZEROES_KEY, /* Master Key 00 */
Expand Down Expand Up @@ -356,6 +425,8 @@ static const nca_keyset_t nca_keys_retail = {
ZEROES_XTS_KEY, /* SD Card Key Source, for NCAs. */
ZEROES_XTS_KEY, /* SD Card Key Source, for saves. */
},
ZEROES_KEY, /* Save MAC kek Source. */
ZEROES_KEY, /* Save MAC key Source. */
ZEROES_XTS_KEY, /* Encrypted Header Key */
ZEROES_XTS_KEY, /* Header key */
{
Expand Down Expand Up @@ -660,6 +731,75 @@ static const nca_keyset_t nca_keys_dev = {
ZEROES_KEY /* Keyblob Key Source 31 (CONSOLE UNIQUE) */
},
ZEROES_KEY, /* Keyblob Mac Key Source */
ZEROES_KEY, /* TSEC Root Key */
{
ZEROES_KEY, /* Master Kek Source 00 */
ZEROES_KEY, /* Master Kek Source 01 */
ZEROES_KEY, /* Master Kek Source 02 */
ZEROES_KEY, /* Master Kek Source 03 */
ZEROES_KEY, /* Master Kek Source 04 */
ZEROES_KEY, /* Master Kek Source 05 */
ZEROES_KEY, /* Master Kek Source 06 */
ZEROES_KEY, /* Master Kek Source 07 */
ZEROES_KEY, /* Master Kek Source 08 */
ZEROES_KEY, /* Master Kek Source 09 */
ZEROES_KEY, /* Master Kek Source 10 */
ZEROES_KEY, /* Master Kek Source 11 */
ZEROES_KEY, /* Master Kek Source 12 */
ZEROES_KEY, /* Master Kek Source 13 */
ZEROES_KEY, /* Master Kek Source 14 */
ZEROES_KEY, /* Master Kek Source 15 */
ZEROES_KEY, /* Master Kek Source 16 */
ZEROES_KEY, /* Master Kek Source 17 */
ZEROES_KEY, /* Master Kek Source 18 */
ZEROES_KEY, /* Master Kek Source 19 */
ZEROES_KEY, /* Master Kek Source 20 */
ZEROES_KEY, /* Master Kek Source 21 */
ZEROES_KEY, /* Master Kek Source 22 */
ZEROES_KEY, /* Master Kek Source 23 */
ZEROES_KEY, /* Master Kek Source 24 */
ZEROES_KEY, /* Master Kek Source 25 */
ZEROES_KEY, /* Master Kek Source 26 */
ZEROES_KEY, /* Master Kek Source 27 */
ZEROES_KEY, /* Master Kek Source 28 */
ZEROES_KEY, /* Master Kek Source 29 */
ZEROES_KEY, /* Master Kek Source 30 */
ZEROES_KEY /* Master Kek Source 31 */
},
{
ZEROES_KEY, /* Master Kek 00 */
ZEROES_KEY, /* Master Kek 01 */
ZEROES_KEY, /* Master Kek 02 */
ZEROES_KEY, /* Master Kek 03 */
ZEROES_KEY, /* Master Kek 04 */
ZEROES_KEY, /* Master Kek 05 */
ZEROES_KEY, /* Master Kek 06 */
ZEROES_KEY, /* Master Kek 07 */
ZEROES_KEY, /* Master Kek 08 */
ZEROES_KEY, /* Master Kek 09 */
ZEROES_KEY, /* Master Kek 10 */
ZEROES_KEY, /* Master Kek 11 */
ZEROES_KEY, /* Master Kek 12 */
ZEROES_KEY, /* Master Kek 13 */
ZEROES_KEY, /* Master Kek 14 */
ZEROES_KEY, /* Master Kek 15 */
ZEROES_KEY, /* Master Kek 16 */
ZEROES_KEY, /* Master Kek 17 */
ZEROES_KEY, /* Master Kek 18 */
ZEROES_KEY, /* Master Kek 19 */
ZEROES_KEY, /* Master Kek 20 */
ZEROES_KEY, /* Master Kek 21 */
ZEROES_KEY, /* Master Kek 22 */
ZEROES_KEY, /* Master Kek 23 */
ZEROES_KEY, /* Master Kek 24 */
ZEROES_KEY, /* Master Kek 25 */
ZEROES_KEY, /* Master Kek 26 */
ZEROES_KEY, /* Master Kek 27 */
ZEROES_KEY, /* Master Kek 28 */
ZEROES_KEY, /* Master Kek 29 */
ZEROES_KEY, /* Master Kek 30 */
ZEROES_KEY /* Master Kek 31 */
},
ZEROES_KEY, /* Master Key Source */
{
ZEROES_KEY, /* Master Key 00 */
Expand Down Expand Up @@ -776,6 +916,8 @@ static const nca_keyset_t nca_keys_dev = {
ZEROES_XTS_KEY, /* SD Card Key Source, for NCAs. */
ZEROES_XTS_KEY, /* SD Card Key Source, for saves. */
},
ZEROES_KEY, /* Save MAC kek Source. */
ZEROES_KEY, /* Save MAC key Source. */
ZEROES_XTS_KEY, /* Encrypted Header Key */
ZEROES_XTS_KEY, /* Header key */
{
Expand Down Expand Up @@ -933,7 +1075,7 @@ void pki_derive_keys(nca_keyset_t *keyset) {
memset(zeroes, 0, 0x100);
memset(cmac, 0, 0x10);
/* Derive keys as necessary. */
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
/* Start by deriving keyblob keys. */
if (memcmp(&keyset->secure_boot_key, zeroes, 0x10) == 0) {
continue;
Expand All @@ -957,11 +1099,11 @@ void pki_derive_keys(nca_keyset_t *keyset) {
aes_decrypt(mac_gen_ctx, &keyset->keyblob_mac_keys[i], keyset->keyblob_mac_key_source, 0x10);
free_aes_ctx(mac_gen_ctx);
}
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
/* Then we decrypt keyblobs. */
if (memcmp(&keyset->keyblob_keys[i], zeroes, 0x10) == 0) {
continue;
}
}
if (memcmp(&keyset->keyblob_mac_keys[i], zeroes, 0x10) == 0) {
continue;
}
Expand All @@ -976,29 +1118,41 @@ void pki_derive_keys(nca_keyset_t *keyset) {
aes_ctx_t *keyblob_ctx = new_aes_ctx(&keyset->keyblob_keys[i], 0x10, AES_MODE_CTR);
aes_setiv(keyblob_ctx, &keyset->encrypted_keyblobs[i][0x10], 0x10);
aes_decrypt(keyblob_ctx, &keyset->keyblobs[i], &keyset->encrypted_keyblobs[i][0x20], sizeof(keyset->keyblobs[i]));
/* Set package1 key as relevant. */
if (memcmp(keyset->keyblobs[i] + 0x80, zeroes, 0x10) != 0) {
memcpy(&keyset->package1_keys[i], &keyset->keyblobs[i][0x80], 0x10);
}
/* Set master kek as relevant. */
if (memcmp(keyset->keyblobs[i] + 0x00, zeroes, 0x10) != 0) {
memcpy(&keyset->master_keks[i], &keyset->keyblobs[i][0x00], 0x10);
}
free_aes_ctx(keyblob_ctx);
}
for (unsigned int i = 0; i < 0x20; i++) {
/* We only need 0x70:0x80 in the blob. */
if (memcmp(keyset->keyblobs[i] + 0x70, zeroes, 0x10) == 0) {
for (unsigned int i = 0x6; i < 0x20; i++) {
/* Do new keygen for 6.2.0+. */
if (memcmp(keyset->tsec_root_key, zeroes, 0x10) == 0) {
continue;
}

/* Package1 key is at the end of the keyblob. */
memcpy(&keyset->package1_keys[i], &keyset->keyblobs[i][0x80], 0x10);
if (memcmp(keyset->master_kek_sources[i], zeroes, 0x10) == 0) {
continue;
}

aes_ctx_t *tsec_root_ctx = new_aes_ctx(keyset->tsec_root_key, 0x10, AES_MODE_ECB);
aes_decrypt(tsec_root_ctx, keyset->master_keks[i], keyset->master_kek_sources[i], 0x10);
free_aes_ctx(tsec_root_ctx);
}
for (unsigned int i = 0; i < 0x20; i++) {
/* Then we derive master keys. */
if (memcmp(keyset->master_key_source, zeroes, 0x10) == 0) {
continue;
}
/* We only need the first key in the blob. */
if (memcmp(keyset->keyblobs[i], zeroes, 0x10) == 0) {
/* We need a non-zero master kek. */
if (memcmp(keyset->master_keks[i], zeroes, 0x10) == 0) {
continue;
}

/* Derive Master Keys. */
aes_ctx_t *master_gen_ctx = new_aes_ctx(&keyset->keyblobs[i], 0x10, AES_MODE_ECB);
aes_ctx_t *master_gen_ctx = new_aes_ctx(&keyset->master_keks[i], 0x10, AES_MODE_ECB);
aes_decrypt(master_gen_ctx, &keyset->master_keys[i], keyset->master_key_source, 0x10);
free_aes_ctx(master_gen_ctx);
}
Expand Down Expand Up @@ -1066,28 +1220,37 @@ void pki_print_keys(nca_keyset_t *keyset) {

PRINT_KEY_WITH_NAME(keyset->secure_boot_key, secure_boot_key);
PRINT_KEY_WITH_NAME(keyset->tsec_key, tsec_key);
PRINT_KEY_WITH_NAME(keyset->tsec_root_key, tsec_root_key);
printf("\n");
PRINT_KEY_WITH_NAME(keyset->keyblob_mac_key_source, keyblob_mac_key_source);
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->keyblob_key_sources[i], keyblob_key_source, i);
}
printf("\n");
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->keyblob_keys[i], keyblob_key, i);
}
printf("\n");
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->keyblob_mac_keys[i], keyblob_mac_key, i);
}
printf("\n");
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->encrypted_keyblobs[i], encrypted_keyblob, i);
}
printf("\n");
for (unsigned int i = 0; i < 0x20; i++) {
for (unsigned int i = 0; i < 0x6; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->keyblobs[i], keyblob, i);
}
printf("\n");
for (unsigned int i = 0x6; i < 0x20; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->master_kek_sources[i], master_kek_source, i);
}
printf("\n");
for (unsigned int i = 0x0; i < 0x20; i++) {
PRINT_KEY_WITH_NAME_IDX(keyset->master_keks[i], master_kek, i);
}
printf("\n");
PRINT_KEY_WITH_NAME(keyset->master_key_source, master_key_source);
printf("\n");
for (unsigned int i = 0; i < 0x20; i++) {
Expand Down Expand Up @@ -1118,6 +1281,8 @@ void pki_print_keys(nca_keyset_t *keyset) {
PRINT_KEY_WITH_NAME(keyset->sd_card_kek_source, sd_card_kek_source);
PRINT_KEY_WITH_NAME(keyset->sd_card_key_sources[0], sd_card_save_key_source);
PRINT_KEY_WITH_NAME(keyset->sd_card_key_sources[1], sd_card_nca_key_source);
PRINT_KEY_WITH_NAME(keyset->save_mac_kek_source, save_mac_kek_source);
PRINT_KEY_WITH_NAME(keyset->save_mac_key_source, save_mac_key_source);
printf("\n");
PRINT_KEY_WITH_NAME(keyset->header_key_source, header_key_source);
PRINT_KEY_WITH_NAME(keyset->header_key, header_key);
Expand Down
5 changes: 5 additions & 0 deletions settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ typedef struct {
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. */
unsigned char tsec_root_key[0x10]; /* Seed for master kek decryption, from TSEC firmware on 6.2.0+. */
unsigned char master_kek_sources[0x20][0x10]; /* Seeds for firmware master keks. */
unsigned char master_keks[0x20][0x10]; /* Firmware master keks, stored in keyblob prior to 6.2.0. */
unsigned char master_key_source[0x10]; /* Seed for master key derivation. */
unsigned char master_keys[0x20][0x10]; /* Firmware master keys. */
unsigned char package1_keys[0x20][0x10]; /* Package1 keys. */
Expand All @@ -38,6 +41,8 @@ typedef struct {
unsigned char header_kek_source[0x10]; /* Seed for header kek. */
unsigned char sd_card_kek_source[0x10]; /* Seed for SD card kek. */
unsigned char sd_card_key_sources[2][0x20]; /* Seed for SD card encryption keys. */
unsigned char save_mac_kek_source[0x10]; /* Seed for save kek. */
unsigned char save_mac_key_source[0x10]; /* Seed for save key. */
unsigned char header_key_source[0x20]; /* Seed for NCA header key. */
unsigned char header_key[0x20]; /* NCA header key. */
unsigned char titlekeks[0x20][0x10]; /* Title key encryption keys. */
Expand Down

0 comments on commit 0388e1b

Please sign in to comment.