add support for 9.x NCA fixed-key, use loop instead of recursion to parse romfs

This commit is contained in:
Michael Scire 2020-03-18 11:05:17 -07:00
parent eef1139b82
commit 575845f5e7
7 changed files with 199 additions and 130 deletions

148
nca.c
View file

@ -410,8 +410,12 @@ void nca_process(nca_ctx_t *ctx) {
return; return;
} }
if (rsa2048_pss_verify(&ctx->header.magic, 0x200, ctx->header.fixed_key_sig, ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_modulus)) { if (ctx->header.fixed_key_generation < sizeof(ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_moduli) / sizeof(ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_moduli[0])) {
ctx->fixed_sig_validity = VALIDITY_VALID; if (rsa2048_pss_verify(&ctx->header.magic, 0x200, ctx->header.fixed_key_sig, ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_moduli[ctx->header.fixed_key_generation])) {
ctx->fixed_sig_validity = VALIDITY_VALID;
} else {
ctx->fixed_sig_validity = VALIDITY_INVALID;
}
} else { } else {
ctx->fixed_sig_validity = VALIDITY_INVALID; ctx->fixed_sig_validity = VALIDITY_INVALID;
} }
@ -815,6 +819,16 @@ void nca_print(nca_ctx_t *ctx) {
printf("\nNCA:\n"); printf("\nNCA:\n");
print_magic("Magic: ", ctx->header.magic); print_magic("Magic: ", ctx->header.magic);
if (ctx->tool_ctx->action & ACTION_VERIFY) {
if (ctx->header.fixed_key_generation < sizeof(ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_moduli) / sizeof(ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_moduli[0])) {
printf("Fixed-Key Index (GOOD): 0x%"PRIX8"\n", ctx->header.fixed_key_generation);
} else {
printf("Fixed-Key Index (FAIL): 0x%"PRIX8"\n", ctx->header.fixed_key_generation);
}
} else {
printf("Fixed-Key Index: 0x%"PRIX8"\n", ctx->header.fixed_key_generation);
}
if (ctx->tool_ctx->action & ACTION_VERIFY && ctx->fixed_sig_validity != VALIDITY_UNCHECKED) { if (ctx->tool_ctx->action & ACTION_VERIFY && ctx->fixed_sig_validity != VALIDITY_UNCHECKED) {
if (ctx->fixed_sig_validity == VALIDITY_VALID) { if (ctx->fixed_sig_validity == VALIDITY_VALID) {
memdump(stdout, "Fixed-Key Signature (GOOD): ", &ctx->header.fixed_key_sig, 0x100); memdump(stdout, "Fixed-Key Signature (GOOD): ", &ctx->header.fixed_key_sig, 0x100);
@ -1517,84 +1531,94 @@ static int nca_is_romfs_file_updated(nca_section_ctx_t *ctx, uint64_t file_offse
} }
static int nca_visit_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) { static int nca_visit_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
romfs_fentry_t *entry;
if (ctx->type == ROMFS) {
entry = romfs_get_fentry(ctx->romfs_ctx.files, file_offset);
} else {
entry = romfs_get_fentry(ctx->bktr_ctx.files, file_offset);
}
filepath_t *cur_path = calloc(1, sizeof(filepath_t)); filepath_t *cur_path = calloc(1, sizeof(filepath_t));
if (cur_path == NULL) { if (cur_path == NULL) {
fprintf(stderr, "Failed to allocate filepath!\n"); fprintf(stderr, "Failed to allocate filepath!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
filepath_copy(cur_path, dir_path); int found_any_file = 0;
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name); do {
romfs_fentry_t *entry;
if (ctx->type == ROMFS) {
entry = romfs_get_fentry(ctx->romfs_ctx.files, file_offset);
} else {
entry = romfs_get_fentry(ctx->bktr_ctx.files, file_offset);
}
filepath_copy(cur_path, dir_path);
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}
int found_file = 1;
/* If we're extracting... */
uint64_t phys_offset;
if (ctx->type == ROMFS) {
phys_offset = ctx->romfs_ctx.romfs_offset + ctx->romfs_ctx.header.data_offset + entry->offset;
} else {
phys_offset = ctx->bktr_ctx.romfs_offset + ctx->bktr_ctx.header.data_offset + entry->offset;
}
if ((ctx->tool_ctx->action & ACTION_ONLYUPDATEDROMFS) == 0 || nca_is_romfs_file_updated(ctx, phys_offset, entry->size)) {
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
printf("Saving %s...\n", cur_path->char_path);
nca_save_section_file(ctx, phys_offset, entry->size, cur_path);
} else {
printf("rom:%s\n", cur_path->char_path);
}
} else {
found_file = 0;
}
found_any_file |= found_file;
file_offset = entry->sibling;
} while (file_offset != ROMFS_ENTRY_EMPTY);
free(cur_path);
return found_any_file;
}
static int nca_visit_nca0_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
filepath_t *cur_path = calloc(1, sizeof(filepath_t));
if (cur_path == NULL) {
fprintf(stderr, "Failed to allocate filepath!\n");
exit(EXIT_FAILURE);
} }
int found_file = 1; int found_any_file = 0;
do {
romfs_fentry_t *entry = romfs_get_fentry(ctx->nca0_romfs_ctx.files, file_offset);
filepath_copy(cur_path, dir_path);
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}
int found_file = 1;
/* If we're extracting... */
uint64_t phys_offset = ctx->nca0_romfs_ctx.romfs_offset + ctx->nca0_romfs_ctx.header.data_offset + entry->offset;
/* If we're extracting... */
uint64_t phys_offset;
if (ctx->type == ROMFS) {
phys_offset = ctx->romfs_ctx.romfs_offset + ctx->romfs_ctx.header.data_offset + entry->offset;
} else {
phys_offset = ctx->bktr_ctx.romfs_offset + ctx->bktr_ctx.header.data_offset + entry->offset;
}
if ((ctx->tool_ctx->action & ACTION_ONLYUPDATEDROMFS) == 0 || nca_is_romfs_file_updated(ctx, phys_offset, entry->size)) {
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) { if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
printf("Saving %s...\n", cur_path->char_path); printf("Saving %s...\n", cur_path->char_path);
nca_save_section_file(ctx, phys_offset, entry->size, cur_path); nca_save_section_file(ctx, phys_offset, entry->size, cur_path);
} else { } else {
printf("rom:%s\n", cur_path->char_path); printf("rom:%s\n", cur_path->char_path);
} }
} else {
found_file = 0; found_any_file |= found_file;
}
file_offset = entry->sibling;
} while (file_offset != ROMFS_ENTRY_EMPTY);
free(cur_path); free(cur_path);
if (entry->sibling != ROMFS_ENTRY_EMPTY) { return found_any_file;
return found_file | nca_visit_romfs_file(ctx, entry->sibling, dir_path);
}
return found_file;
}
static int nca_visit_nca0_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
romfs_fentry_t *entry = romfs_get_fentry(ctx->nca0_romfs_ctx.files, file_offset);
filepath_t *cur_path = calloc(1, sizeof(filepath_t));
if (cur_path == NULL) {
fprintf(stderr, "Failed to allocate filepath!\n");
exit(EXIT_FAILURE);
}
filepath_copy(cur_path, dir_path);
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}
int found_file = 1;
/* If we're extracting... */
uint64_t phys_offset = ctx->nca0_romfs_ctx.romfs_offset + ctx->nca0_romfs_ctx.header.data_offset + entry->offset;
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
printf("Saving %s...\n", cur_path->char_path);
nca_save_section_file(ctx, phys_offset, entry->size, cur_path);
} else {
printf("rom:%s\n", cur_path->char_path);
}
free(cur_path);
if (entry->sibling != ROMFS_ENTRY_EMPTY) {
return found_file | nca_visit_nca0_romfs_file(ctx, entry->sibling, dir_path);
}
return found_file;
} }
static int nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) { static int nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {

3
nca.h
View file

@ -109,7 +109,8 @@ typedef struct {
}; };
}; };
uint8_t crypto_type2; /* Which keyblob (field 2) */ uint8_t crypto_type2; /* Which keyblob (field 2) */
uint8_t _0x221[0xF]; /* Padding. */ uint8_t fixed_key_generation;
uint8_t _0x222[0xF]; /* Padding. */
uint8_t rights_id[0x10]; /* Rights ID (for titlekey crypto). */ uint8_t rights_id[0x10]; /* Rights ID (for titlekey crypto). */
nca_section_entry_t section_entries[4]; /* Section entry metadata. */ nca_section_entry_t section_entries[4]; /* Section entry metadata. */
uint8_t section_hashes[4][0x20]; /* SHA-256 hashes for each section header. */ uint8_t section_hashes[4][0x20]; /* SHA-256 hashes for each section header. */

View file

@ -5,31 +5,32 @@
/* NCA0 RomFS functions... */ /* NCA0 RomFS functions... */
static void nca0_romfs_visit_file(nca0_romfs_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) { static void nca0_romfs_visit_file(nca0_romfs_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset);
filepath_t *cur_path = calloc(1, sizeof(filepath_t)); filepath_t *cur_path = calloc(1, sizeof(filepath_t));
if (cur_path == NULL) { if (cur_path == NULL) {
fprintf(stderr, "Failed to allocate filepath!\n"); fprintf(stderr, "Failed to allocate filepath!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
filepath_copy(cur_path, dir_path); while (file_offset != ROMFS_ENTRY_EMPTY) {
if (entry->name_size) { romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset);
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}
/* If we're extracting... */ filepath_copy(cur_path, dir_path);
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) { if (entry->name_size) {
printf("Saving %s...\n", cur_path->char_path); filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
save_file_section(ctx->file, ctx->romfs_offset + ctx->header.data_offset + entry->offset, entry->size, cur_path); }
} else {
printf("rom:%s\n", cur_path->char_path); /* If we're extracting... */
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
printf("Saving %s...\n", cur_path->char_path);
save_file_section(ctx->file, ctx->romfs_offset + ctx->header.data_offset + entry->offset, entry->size, cur_path);
} else {
printf("rom:%s\n", cur_path->char_path);
}
file_offset = entry->sibling;
} }
free(cur_path); free(cur_path);
if (entry->sibling != ROMFS_ENTRY_EMPTY) {
nca0_romfs_visit_file(ctx, entry->sibling, dir_path);
}
} }
static void nca0_romfs_visit_dir(nca0_romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) { static void nca0_romfs_visit_dir(nca0_romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {

110
pki.c
View file

@ -67,23 +67,43 @@ const unsigned char *pki_get_beta_nca0_label_hash(void) {
static const nca_keyset_t nca_keys_retail = { static const nca_keyset_t nca_keys_retail = {
.nca_hdr_fixed_key_modulus = { /* Fixed RSA key used to validate NCA signature 0. */ .nca_hdr_fixed_key_moduli = { /* Fixed RSA key used to validate NCA signature 0. */
0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, 0x61, 0x1D, 0x77, 0x2F, {
0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58, 0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, 0x61, 0x1D, 0x77, 0x2F,
0x34, 0xB0, 0x05, 0xA3, 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16, 0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58,
0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, 0xF6, 0x00, 0x07, 0xB2, 0x34, 0xB0, 0x05, 0xA3, 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16,
0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF, 0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, 0xF6, 0x00, 0x07, 0xB2,
0xA7, 0x82, 0xB5, 0xCF, 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67, 0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF,
0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, 0x8A, 0x68, 0xC9, 0x26, 0xA7, 0x82, 0xB5, 0xCF, 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67,
0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C, 0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, 0x8A, 0x68, 0xC9, 0x26,
0xCE, 0x02, 0x6F, 0x16, 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE, 0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C,
0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, 0x43, 0xF3, 0xFC, 0x86, 0xCE, 0x02, 0x6F, 0x16, 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE,
0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35, 0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, 0x43, 0xF3, 0xFC, 0x86,
0xF2, 0xF6, 0x56, 0x56, 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B, 0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35,
0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, 0xFD, 0x13, 0x63, 0x29, 0xF2, 0xF6, 0x56, 0x56, 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B,
0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40, 0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, 0xFD, 0x13, 0x63, 0x29,
0x7E, 0x32, 0x8C, 0x27, 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81, 0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40,
0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, 0x9D, 0xE4, 0xF4, 0x03 0x7E, 0x32, 0x8C, 0x27, 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81,
0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, 0x9D, 0xE4, 0xF4, 0x03,
},
{
0xAD, 0xE3, 0xE1, 0xFA, 0x04, 0x35, 0xE5, 0xB6, 0xDD, 0x49, 0xEA, 0x89, 0x29, 0xB1, 0xFF, 0xB6,
0x43, 0xDF, 0xCA, 0x96, 0xA0, 0x4A, 0x13, 0xDF, 0x43, 0xD9, 0x94, 0x97, 0x96, 0x43, 0x65, 0x48,
0x70, 0x58, 0x33, 0xA2, 0x7D, 0x35, 0x7B, 0x96, 0x74, 0x5E, 0x0B, 0x5C, 0x32, 0x18, 0x14, 0x24,
0xC2, 0x58, 0xB3, 0x6C, 0x22, 0x7A, 0xA1, 0xB7, 0xCB, 0x90, 0xA7, 0xA3, 0xF9, 0x7D, 0x45, 0x16,
0xA5, 0xC8, 0xED, 0x8F, 0xAD, 0x39, 0x5E, 0x9E, 0x4B, 0x51, 0x68, 0x7D, 0xF8, 0x0C, 0x35, 0xC6,
0x3F, 0x91, 0xAE, 0x44, 0xA5, 0x92, 0x30, 0x0D, 0x46, 0xF8, 0x40, 0xFF, 0xD0, 0xFF, 0x06, 0xD2,
0x1C, 0x7F, 0x96, 0x18, 0xDC, 0xB7, 0x1D, 0x66, 0x3E, 0xD1, 0x73, 0xBC, 0x15, 0x8A, 0x2F, 0x94,
0xF3, 0x00, 0xC1, 0x83, 0xF1, 0xCD, 0xD7, 0x81, 0x88, 0xAB, 0xDF, 0x8C, 0xEF, 0x97, 0xDD, 0x1B,
0x17, 0x5F, 0x58, 0xF6, 0x9A, 0xE9, 0xE8, 0xC2, 0x2F, 0x38, 0x15, 0xF5, 0x21, 0x07, 0xF8, 0x37,
0x90, 0x5D, 0x2E, 0x02, 0x40, 0x24, 0x15, 0x0D, 0x25, 0xB7, 0x26, 0x5D, 0x09, 0xCC, 0x4C, 0xF4,
0xF2, 0x1B, 0x94, 0x70, 0x5A, 0x9E, 0xEE, 0xED, 0x77, 0x77, 0xD4, 0x51, 0x99, 0xF5, 0xDC, 0x76,
0x1E, 0xE3, 0x6C, 0x8C, 0xD1, 0x12, 0xD4, 0x57, 0xD1, 0xB6, 0x83, 0xE4, 0xE4, 0xFE, 0xDA, 0xE9,
0xB4, 0x3B, 0x33, 0xE5, 0x37, 0x8A, 0xDF, 0xB5, 0x7F, 0x89, 0xF1, 0x9B, 0x9E, 0xB0, 0x15, 0xB2,
0x3A, 0xFE, 0xEA, 0x61, 0x84, 0x5B, 0x7D, 0x4B, 0x23, 0x12, 0x0B, 0x83, 0x12, 0xF2, 0x22, 0x6B,
0xB9, 0x22, 0x96, 0x4B, 0x26, 0x0B, 0x63, 0x5E, 0x96, 0x57, 0x52, 0xA3, 0x67, 0x64, 0x22, 0xCA,
0xD0, 0x56, 0x3E, 0x74, 0xB5, 0x98, 0x1F, 0x0D, 0xF8, 0xB3, 0x34, 0xE6, 0x98, 0x68, 0x5A, 0xAD,
}
}, },
.acid_fixed_key_moduli = { /* Fixed RSA keys used to validate ACID signatures. */ .acid_fixed_key_moduli = { /* Fixed RSA keys used to validate ACID signatures. */
{ {
@ -102,7 +122,7 @@ static const nca_keyset_t nca_keys_retail = {
0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, 0x69, 0x2B, 0x31, 0x6A, 0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, 0x69, 0x2B, 0x31, 0x6A,
0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA, 0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA,
0x37, 0xEA, 0xE8, 0x1E, 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B, 0x37, 0xEA, 0xE8, 0x1E, 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B,
0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, 0x7D, 0x35, 0x22, 0xFD 0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, 0x7D, 0x35, 0x22, 0xFD,
}, },
{ {
0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, 0x96, 0x5A, 0xBF, 0x90, 0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, 0x96, 0x5A, 0xBF, 0x90,
@ -144,23 +164,43 @@ static const nca_keyset_t nca_keys_retail = {
}; };
static const nca_keyset_t nca_keys_dev = { static const nca_keyset_t nca_keys_dev = {
.nca_hdr_fixed_key_modulus = { /* Fixed RSA key used to validate NCA signature 0. */ .nca_hdr_fixed_key_moduli = { /* Fixed RSA key used to validate NCA signature 0. */
0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, 0xB3, 0x04, 0xA8, 0xA4, {
0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49, 0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, 0xB3, 0x04, 0xA8, 0xA4,
0x85, 0xE5, 0x8A, 0x9B, 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C, 0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49,
0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, 0x0A, 0x50, 0xF2, 0x2B, 0x85, 0xE5, 0x8A, 0x9B, 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C,
0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4, 0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, 0x0A, 0x50, 0xF2, 0x2B,
0x49, 0x2F, 0xCF, 0x03, 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47, 0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4,
0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, 0x0E, 0x17, 0x3F, 0xFE, 0x49, 0x2F, 0xCF, 0x03, 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47,
0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D, 0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, 0x0E, 0x17, 0x3F, 0xFE,
0xA1, 0xD9, 0x66, 0x20, 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E, 0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D,
0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, 0x75, 0x76, 0xBF, 0xB0, 0xA1, 0xD9, 0x66, 0x20, 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E,
0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D, 0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, 0x75, 0x76, 0xBF, 0xB0,
0x7A, 0xA4, 0x21, 0x55, 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E, 0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D,
0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, 0xDE, 0xD8, 0x1B, 0x4B, 0x7A, 0xA4, 0x21, 0x55, 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E,
0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E, 0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, 0xDE, 0xD8, 0x1B, 0x4B,
0xEA, 0x7F, 0x86, 0xF3, 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62, 0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E,
0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, 0x8F, 0xB9, 0x4A, 0xA9 0xEA, 0x7F, 0x86, 0xF3, 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62,
0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, 0x8F, 0xB9, 0x4A, 0xA9,
},
{
0x9A, 0xBC, 0x88, 0xBD, 0x0A, 0xBE, 0xD7, 0x0C, 0x9B, 0x42, 0x75, 0x65, 0x38, 0x5E, 0xD1, 0x01,
0xCD, 0x12, 0xAE, 0xEA, 0xE9, 0x4B, 0xDB, 0xB4, 0x5E, 0x36, 0x10, 0x96, 0xDA, 0x3D, 0x2E, 0x66,
0xD3, 0x99, 0x13, 0x8A, 0xBE, 0x67, 0x41, 0xC8, 0x93, 0xD9, 0x3E, 0x42, 0xCE, 0x34, 0xCE, 0x96,
0xFA, 0x0B, 0x23, 0xCC, 0x2C, 0xDF, 0x07, 0x3F, 0x3B, 0x24, 0x4B, 0x12, 0x67, 0x3A, 0x29, 0x36,
0xA3, 0xAA, 0x06, 0xF0, 0x65, 0xA5, 0x85, 0xBA, 0xFD, 0x12, 0xEC, 0xF1, 0x60, 0x67, 0xF0, 0x8F,
0xD3, 0x5B, 0x01, 0x1B, 0x1E, 0x84, 0xA3, 0x5C, 0x65, 0x36, 0xF9, 0x23, 0x7E, 0xF3, 0x26, 0x38,
0x64, 0x98, 0xBA, 0xE4, 0x19, 0x91, 0x4C, 0x02, 0xCF, 0xC9, 0x6D, 0x86, 0xEC, 0x1D, 0x41, 0x69,
0xDD, 0x56, 0xEA, 0x5C, 0xA3, 0x2A, 0x58, 0xB4, 0x39, 0xCC, 0x40, 0x31, 0xFD, 0xFB, 0x42, 0x74,
0xF8, 0xEC, 0xEA, 0x00, 0xF0, 0xD9, 0x28, 0xEA, 0xFA, 0x2D, 0x00, 0xE1, 0x43, 0x53, 0xC6, 0x32,
0xF4, 0xA2, 0x07, 0xD4, 0x5F, 0xD4, 0xCB, 0xAC, 0xCA, 0xFF, 0xDF, 0x84, 0xD2, 0x86, 0x14, 0x3C,
0xDE, 0x22, 0x75, 0xA5, 0x73, 0xFF, 0x68, 0x07, 0x4A, 0xF9, 0x7C, 0x2C, 0xCC, 0xDE, 0x45, 0xB6,
0x54, 0x82, 0x90, 0x36, 0x1F, 0x2C, 0x51, 0x96, 0xC5, 0x0A, 0x53, 0x5B, 0xF0, 0x8B, 0x4A, 0xAA,
0x3B, 0x68, 0x97, 0x19, 0x17, 0x1F, 0x01, 0xB8, 0xED, 0xB9, 0x9A, 0x5E, 0x08, 0xC5, 0x20, 0x1E,
0x6A, 0x09, 0xF0, 0xE9, 0x73, 0xA3, 0xBE, 0x10, 0x06, 0x02, 0xE9, 0xFB, 0x85, 0xFA, 0x5F, 0x01,
0xAC, 0x60, 0xE0, 0xED, 0x7D, 0xB9, 0x49, 0xA8, 0x9E, 0x98, 0x7D, 0x91, 0x40, 0x05, 0xCF, 0xF9,
0x1A, 0xFC, 0x40, 0x22, 0xA8, 0x96, 0x5B, 0xB0, 0xDC, 0x7A, 0xF5, 0xB7, 0xE9, 0x91, 0x4C, 0x49,
}
}, },
.acid_fixed_key_moduli = { /* Fixed RSA keys used to validate ACID signatures. */ .acid_fixed_key_moduli = { /* Fixed RSA keys used to validate ACID signatures. */
{ {

33
romfs.c
View file

@ -5,31 +5,32 @@
/* RomFS functions... */ /* RomFS functions... */
static void romfs_visit_file(romfs_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) { static void romfs_visit_file(romfs_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset);
filepath_t *cur_path = calloc(1, sizeof(filepath_t)); filepath_t *cur_path = calloc(1, sizeof(filepath_t));
if (cur_path == NULL) { if (cur_path == NULL) {
fprintf(stderr, "Failed to allocate filepath!\n"); fprintf(stderr, "Failed to allocate filepath!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
filepath_copy(cur_path, dir_path); while (file_offset != ROMFS_ENTRY_EMPTY) {
if (entry->name_size) { romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset);
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}
/* If we're extracting... */ filepath_copy(cur_path, dir_path);
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) { if (entry->name_size) {
printf("Saving %s...\n", cur_path->char_path); filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
save_file_section(ctx->file, ctx->romfs_offset + ctx->header.data_offset + entry->offset, entry->size, cur_path); }
} else {
printf("rom:%s\n", cur_path->char_path); /* If we're extracting... */
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
printf("Saving %s...\n", cur_path->char_path);
save_file_section(ctx->file, ctx->romfs_offset + ctx->header.data_offset + entry->offset, entry->size, cur_path);
} else {
printf("rom:%s\n", cur_path->char_path);
}
file_offset = entry->sibling;
} }
free(cur_path); free(cur_path);
if (entry->sibling != ROMFS_ENTRY_EMPTY) {
romfs_visit_file(ctx, entry->sibling, dir_path);
}
} }
static void romfs_visit_dir(romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) { static void romfs_visit_dir(romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {
@ -116,6 +117,8 @@ void romfs_save(romfs_ctx_t *ctx) {
filepath_init(&fakepath); filepath_init(&fakepath);
filepath_set(&fakepath, ""); filepath_set(&fakepath, "");
printf("Visiting romfs\n");
romfs_visit_dir(ctx, 0, &fakepath); romfs_visit_dir(ctx, 0, &fakepath);
} else { } else {
/* Extract to directory. */ /* Extract to directory. */

View file

@ -57,7 +57,7 @@ typedef struct {
unsigned char xci_header_key[0x10]; /* Key for XCI partially encrypted header. */ unsigned char xci_header_key[0x10]; /* Key for XCI partially encrypted header. */
unsigned char save_mac_key[0x10]; /* Key used to sign savedata. */ unsigned char save_mac_key[0x10]; /* Key used to sign savedata. */
unsigned char sd_card_keys[2][0x20]; unsigned char sd_card_keys[2][0x20];
unsigned char nca_hdr_fixed_key_modulus[0x100]; /* NCA header fixed key RSA pubk. */ unsigned char nca_hdr_fixed_key_moduli[2][0x100]; /* NCA header fixed key RSA pubk. */
unsigned char acid_fixed_key_moduli[2][0x100]; /* ACID fixed key RSA pubk. */ unsigned char acid_fixed_key_moduli[2][0x100]; /* ACID fixed key RSA pubk. */
unsigned char package2_fixed_key_modulus[0x100]; /* Package2 Header RSA pubk. */ unsigned char package2_fixed_key_modulus[0x100]; /* Package2 Header RSA pubk. */
} nca_keyset_t; } nca_keyset_t;

View file

@ -1,6 +1,6 @@
#ifndef HACTOOL_VERSION_H #ifndef HACTOOL_VERSION_H
#define HACTOOL_VERSION_H #define HACTOOL_VERSION_H
#define HACTOOL_VERSION "1.3.0" #define HACTOOL_VERSION "1.3.2"
#endif #endif