From 8ffe774f7742263c7eee0289840a63ab778e3bc8 Mon Sep 17 00:00:00 2001 From: aspargas2 Date: Thu, 11 Jun 2020 12:22:38 -0400 Subject: [PATCH] remove remaining uses of brute-force ticket.db parsing --- arm9/source/game/ticketdb.c | 86 ++++++++++++++++++++++-------------- arm9/source/game/ticketdb.h | 1 - arm9/source/utils/gameutil.c | 44 +++++++++++++----- 3 files changed, 86 insertions(+), 45 deletions(-) diff --git a/arm9/source/game/ticketdb.c b/arm9/source/game/ticketdb.c index 0005ce0..e79e70d 100644 --- a/arm9/source/game/ticketdb.c +++ b/arm9/source/game/ticketdb.c @@ -1,9 +1,16 @@ #include "ticketdb.h" -#include "disadiff.h" +#include "vbdri.h" #include "support.h" #include "aes.h" -#include "ff.h" +#include "vff.h" +#include "fsinit.h" +const char* virtual_tickdb_dirs[] = { + "homebrew", + "eshop", + "system", + "unknown", +}; u32 CryptTitleKey(TitleKeyEntry* tik, bool encrypt, bool devkit) { // From https://github.com/profi200/Project_CTR/blob/master/makerom/pki/prod.h#L19 @@ -52,43 +59,56 @@ u32 GetTitleKey(u8* titlekey, Ticket* ticket) { return 0; } -Ticket* TicketFromTickDbChunk(u8* chunk, u8* title_id, bool legit_pls) { - // chunk must be aligned to 0x200 byte in file and at least 0x400 byte big - Ticket* tick = (Ticket*) (void*) (chunk + 0x18); - if ((getle32(chunk + 0x10) == 0) || (getle32(chunk + 0x14) != GetTicketSize(tick))) return NULL; - if (ValidateTicket(tick) != 0) return NULL; // ticket not validated - if (title_id && (memcmp(title_id, tick->title_id, 8) != 0)) return NULL; // title id not matching - if (legit_pls && (ValidateTicketSignature(tick) != 0)) return NULL; // legit check using RSA sig - - return tick; -} - u32 FindTicket(Ticket** ticket, u8* title_id, bool force_legit, bool emunand) { const char* path_db = TICKDB_PATH(emunand); // EmuNAND / SysNAND - u8* data = (u8*) malloc(TICKDB_AREA_SIZE); - if (!data) return 1; - // read and decode ticket.db DIFF partition - if (ReadDisaDiffIvfcLvl4(path_db, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) { - free(data); + if (!InitImgFS(path_db)) return 1; + + char tid_string[17]; + u64 tid = getbe64(title_id); + snprintf(tid_string, 17, "%016llX", tid); + + DIR dir; + FILINFO fno; + char dir_path[12]; + char tik_path[64]; + + for (u32 i = force_legit ? 1 : 0; i < 4; i++) { + snprintf(dir_path, 12, "T:/%s", virtual_tickdb_dirs[i]); + + if (fvx_opendir(&dir, dir_path) != FR_OK) { + InitImgFS(NULL); + return 1; + } + + while ((fvx_readdir(&dir, &fno) == FR_OK) && *(fno.fname)) { + if (strncmp(tid_string, fno.fname, 16) == 0) { + snprintf(tik_path, 64, "%s/%s", dir_path, fno.fname); + + u32 size = fvx_qsize(tik_path); + if (!(*ticket = malloc(size))) { + InitImgFS(NULL); + return 1; + } + + if ((fvx_qread(tik_path, *ticket, 0, size, NULL) != FR_OK) || + (force_legit && (ValidateTicketSignature(*ticket) != 0))) { + free(*ticket); + InitImgFS(NULL); + return 1; + } + + InitImgFS(NULL); + return 0; + } + } + + fvx_closedir(&dir); } - // parse the decoded data for a ticket - bool found = false; - for (u32 i = 0; !found && (i <= TICKDB_AREA_SIZE - 0x400); i += 0x200) { - Ticket* tick = TicketFromTickDbChunk(data + i, title_id, force_legit); - if (!tick) continue; - u32 size = GetTicketSize(tick); - Ticket* newtick = (Ticket*)malloc(size); - if (!newtick) break; - memcpy(newtick, tick, size); - *ticket = newtick; - found = true; - } - - free(data); - return (found) ? 0 : 1; + InitImgFS(NULL); + return 1; } u32 FindTitleKey(Ticket* ticket, u8* title_id) { diff --git a/arm9/source/game/ticketdb.h b/arm9/source/game/ticketdb.h index 2a6d512..4684168 100644 --- a/arm9/source/game/ticketdb.h +++ b/arm9/source/game/ticketdb.h @@ -35,7 +35,6 @@ typedef struct { u32 GetTitleKey(u8* titlekey, Ticket* ticket); -Ticket* TicketFromTickDbChunk(u8* chunk, u8* title_id, bool legit_pls); u32 FindTicket(Ticket** ticket, u8* title_id, bool force_legit, bool emunand); u32 FindTitleKey(Ticket* ticket, u8* title_id); u32 AddTitleKeyToInfo(TitleKeysInfo* tik_info, TitleKeyEntry* tik_entry, bool decrypted_in, bool decrypted_out, bool devkit); diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 0c2a2d8..7aaf04a 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -2351,24 +2351,46 @@ u32 BuildTitleKeyInfo(const char* path, bool dec, bool dump) { return 1; } } else if (filetype & SYS_TICKDB) { - u8* data = (u8*) malloc(TICKDB_AREA_SIZE); - if (!data) return 1; + if (!InitImgFS(path_in)) + return 1; + + DIR dir; + FILINFO fno; + TicketCommon ticket; + char tik_path[64]; - // read and decode ticket.db DIFF partition - if (ReadDisaDiffIvfcLvl4(path_in, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) { - free(data); + if (fvx_opendir(&dir, "T:/eshop") != FR_OK) { + InitImgFS(NULL); return 1; } - // parse the decoded data for valid tickets - for (u32 i = 0; i <= TICKDB_AREA_SIZE - 0x400; i += 0x200) { - Ticket* ticket = TicketFromTickDbChunk(data + i, NULL, true); - if (!ticket || (ticket->commonkey_idx >= 2) || !getbe64(ticket->ticket_id)) continue; + while ((fvx_readdir(&dir, &fno) == FR_OK) && *(fno.fname)) { + snprintf(tik_path, 64, "T:/eshop/%s", fno.fname); + if (fvx_qread(tik_path, &ticket, 0, TICKET_COMMON_SIZE, NULL) != FR_OK) + continue; if (TIKDB_SIZE(tik_info) + 32 > STD_BUFFER_SIZE) break; // no error message - AddTicketToInfo(tik_info, ticket, dec); // ignore result + AddTicketToInfo(tik_info, (Ticket*) &ticket, dec); // ignore result } - free(data); + fvx_closedir(&dir); + + if (fvx_opendir(&dir, "T:/system") != FR_OK) { + InitImgFS(NULL); + return 1; + } + + while ((fvx_readdir(&dir, &fno) == FR_OK) && *(fno.fname)) { + snprintf(tik_path, 64, "T:/system/%s", fno.fname); + if ((fvx_qread(tik_path, &ticket, 0, TICKET_COMMON_SIZE, NULL) != FR_OK) || + (ValidateTicketSignature((Ticket*) &ticket) != 0)) + continue; + if (TIKDB_SIZE(tik_info) + 32 > STD_BUFFER_SIZE) break; // no error message + AddTicketToInfo(tik_info, (Ticket*) &ticket, dec); // ignore result + } + + fvx_closedir(&dir); + + InitImgFS(NULL); } else if (filetype & BIN_TIKDB) { TitleKeysInfo* tik_info_merge = (TitleKeysInfo*) malloc(STD_BUFFER_SIZE); if (!tik_info_merge) return 1;