remove remaining uses of brute-force ticket.db parsing

This commit is contained in:
aspargas2 2020-06-11 12:22:38 -04:00 committed by d0k3
parent 127008a274
commit 8ffe774f77
3 changed files with 86 additions and 45 deletions

View File

@ -1,9 +1,16 @@
#include "ticketdb.h" #include "ticketdb.h"
#include "disadiff.h" #include "vbdri.h"
#include "support.h" #include "support.h"
#include "aes.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) { u32 CryptTitleKey(TitleKeyEntry* tik, bool encrypt, bool devkit) {
// From https://github.com/profi200/Project_CTR/blob/master/makerom/pki/prod.h#L19 // 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; 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) { u32 FindTicket(Ticket** ticket, u8* title_id, bool force_legit, bool emunand) {
const char* path_db = TICKDB_PATH(emunand); // EmuNAND / SysNAND 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 (!InitImgFS(path_db))
if (ReadDisaDiffIvfcLvl4(path_db, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) {
free(data);
return 1; 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 InitImgFS(NULL);
bool found = false; return 1;
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;
} }
u32 FindTitleKey(Ticket* ticket, u8* title_id) { u32 FindTitleKey(Ticket* ticket, u8* title_id) {

View File

@ -35,7 +35,6 @@ typedef struct {
u32 GetTitleKey(u8* titlekey, Ticket* ticket); 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 FindTicket(Ticket** ticket, u8* title_id, bool force_legit, bool emunand);
u32 FindTitleKey(Ticket* ticket, u8* title_id); u32 FindTitleKey(Ticket* ticket, u8* title_id);
u32 AddTitleKeyToInfo(TitleKeysInfo* tik_info, TitleKeyEntry* tik_entry, bool decrypted_in, bool decrypted_out, bool devkit); u32 AddTitleKeyToInfo(TitleKeysInfo* tik_info, TitleKeyEntry* tik_entry, bool decrypted_in, bool decrypted_out, bool devkit);

View File

@ -2351,24 +2351,46 @@ u32 BuildTitleKeyInfo(const char* path, bool dec, bool dump) {
return 1; return 1;
} }
} else if (filetype & SYS_TICKDB) { } else if (filetype & SYS_TICKDB) {
u8* data = (u8*) malloc(TICKDB_AREA_SIZE); if (!InitImgFS(path_in))
if (!data) return 1; return 1;
DIR dir;
FILINFO fno;
TicketCommon ticket;
char tik_path[64];
// read and decode ticket.db DIFF partition if (fvx_opendir(&dir, "T:/eshop") != FR_OK) {
if (ReadDisaDiffIvfcLvl4(path_in, NULL, TICKDB_AREA_OFFSET, TICKDB_AREA_SIZE, data) != TICKDB_AREA_SIZE) { InitImgFS(NULL);
free(data);
return 1; return 1;
} }
// parse the decoded data for valid tickets while ((fvx_readdir(&dir, &fno) == FR_OK) && *(fno.fname)) {
for (u32 i = 0; i <= TICKDB_AREA_SIZE - 0x400; i += 0x200) { snprintf(tik_path, 64, "T:/eshop/%s", fno.fname);
Ticket* ticket = TicketFromTickDbChunk(data + i, NULL, true); if (fvx_qread(tik_path, &ticket, 0, TICKET_COMMON_SIZE, NULL) != FR_OK)
if (!ticket || (ticket->commonkey_idx >= 2) || !getbe64(ticket->ticket_id)) continue; continue;
if (TIKDB_SIZE(tik_info) + 32 > STD_BUFFER_SIZE) break; // no error message 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) { } else if (filetype & BIN_TIKDB) {
TitleKeysInfo* tik_info_merge = (TitleKeysInfo*) malloc(STD_BUFFER_SIZE); TitleKeysInfo* tik_info_merge = (TitleKeysInfo*) malloc(STD_BUFFER_SIZE);
if (!tik_info_merge) return 1; if (!tik_info_merge) return 1;