Skip to content

Commit

Permalink
add support for 9.x NCA fixed-key, use loop instead of recursion to p…
Browse files Browse the repository at this point in the history
…arse romfs
  • Loading branch information
SciresM committed Mar 18, 2020
1 parent eef1139 commit 575845f
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 120 deletions.
128 changes: 76 additions & 52 deletions nca.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,12 @@ void nca_process(nca_ctx_t *ctx) {
return;
}

if (rsa2048_pss_verify(&ctx->header.magic, 0x200, ctx->header.fixed_key_sig, ctx->tool_ctx->settings.keyset.nca_hdr_fixed_key_modulus)) {
ctx->fixed_sig_validity = VALIDITY_VALID;
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])) {
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 {
ctx->fixed_sig_validity = VALIDITY_INVALID;
}
Expand Down Expand Up @@ -815,6 +819,16 @@ void nca_print(nca_ctx_t *ctx) {
printf("\nNCA:\n");
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->fixed_sig_validity == VALIDITY_VALID) {
memdump(stdout, "Fixed-Key Signature (GOOD): ", &ctx->header.fixed_key_sig, 0x100);
Expand Down Expand Up @@ -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) {
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));
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_any_file = 0;

int found_file = 1;
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);
}

/* 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);
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 {
printf("rom:%s\n", cur_path->char_path);
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;
}
} else {
found_file = 0;
}

free(cur_path);
found_any_file |= found_file;

if (entry->sibling != ROMFS_ENTRY_EMPTY) {
return found_file | nca_visit_romfs_file(ctx, entry->sibling, dir_path);
}
file_offset = entry->sibling;
} while (file_offset != ROMFS_ENTRY_EMPTY);

free(cur_path);

return found_file;
return found_any_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_any_file = 0;

int found_file = 1;
do {
romfs_fentry_t *entry = romfs_get_fentry(ctx->nca0_romfs_ctx.files, file_offset);

/* If we're extracting... */
uint64_t phys_offset = ctx->nca0_romfs_ctx.romfs_offset + ctx->nca0_romfs_ctx.header.data_offset + entry->offset;
filepath_copy(cur_path, dir_path);
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}

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);
}
int found_file = 1;

free(cur_path);
/* If we're extracting... */
uint64_t phys_offset = ctx->nca0_romfs_ctx.romfs_offset + ctx->nca0_romfs_ctx.header.data_offset + entry->offset;

if (entry->sibling != ROMFS_ENTRY_EMPTY) {
return found_file | nca_visit_nca0_romfs_file(ctx, entry->sibling, dir_path);
}
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);
}

found_any_file |= found_file;

file_offset = entry->sibling;
} while (file_offset != ROMFS_ENTRY_EMPTY);

free(cur_path);

return found_file;
return found_any_file;
}

static int nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {
Expand Down
3 changes: 2 additions & 1 deletion nca.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ typedef struct {
};
};
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). */
nca_section_entry_t section_entries[4]; /* Section entry metadata. */
uint8_t section_hashes[4][0x20]; /* SHA-256 hashes for each section header. */
Expand Down
31 changes: 16 additions & 15 deletions nca0_romfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,32 @@

/* NCA0 RomFS functions... */
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));
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);
}
while (file_offset != ROMFS_ENTRY_EMPTY) {
romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset);

/* 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);
}
filepath_copy(cur_path, dir_path);
if (entry->name_size) {
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
}

free(cur_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);
}

if (entry->sibling != ROMFS_ENTRY_EMPTY) {
nca0_romfs_visit_file(ctx, entry->sibling, dir_path);
file_offset = entry->sibling;
}

free(cur_path);
}

static void nca0_romfs_visit_dir(nca0_romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {
Expand Down
Loading

0 comments on commit 575845f

Please sign in to comment.