From 97d196cdbf991dad5ce2c88dd271922ffe380521 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Wed, 13 Jul 2016 23:58:14 -0400 Subject: [PATCH] General cleanup, misc fixes, etc * Fixed a boatload of warnings. * Initialize 0x3D Common Y #1/0x05 KeyY from FIRM0/FIRM1 * This means that CETKs can be used during boot. * Additionally, I can read NAND for future use. Thanks to the good people on #Cakey for helping get this working. @d0k3, @gemarcano and @dark-samus all gave advice. Some of this is roughly based on @Wolfvak's code. --- external/bits/Makefile | 5 +- external/libctr9_io | 1 + host/error-decoder.c | 53 +++++++++ source/firm/firm.c | 238 +++++++++++++++++------------------------ source/interp.c | 54 ++++++---- source/main.c | 2 + source/misc/sha256.c | 217 ------------------------------------- source/misc/sha256.h | 192 --------------------------------- source/patch/emunand.c | 20 ++-- source/patch/module.c | 6 +- source/patch/reboot.c | 14 +-- source/patch/svc.c | 4 +- source/std/abort.h | 2 +- source/std/draw.h | 2 +- 14 files changed, 215 insertions(+), 595 deletions(-) create mode 160000 external/libctr9_io create mode 100644 host/error-decoder.c delete mode 100644 source/misc/sha256.c delete mode 100644 source/misc/sha256.h diff --git a/external/bits/Makefile b/external/bits/Makefile index 22c4087..a7e39f1 100644 --- a/external/bits/Makefile +++ b/external/bits/Makefile @@ -1,6 +1,9 @@ PATH := $(PATH):$(DEVKITARM)/bin -all: backdoor.bin stub.bin emunand.bin reboot_hook.bin reboot_code.bin chain.bin +SOURCES=$(wildcard *.s) +OBJECTS=$(patsubst %.s, %.bin, $(SOURCES)) + +all: $(OBJECTS) %.o: %.s arm-none-eabi-as -o $@ $< diff --git a/external/libctr9_io b/external/libctr9_io new file mode 160000 index 0000000..0e8bb5d --- /dev/null +++ b/external/libctr9_io @@ -0,0 +1 @@ +Subproject commit 0e8bb5d3c55b3cab5eb704da1c25e4321423039d diff --git a/host/error-decoder.c b/host/error-decoder.c new file mode 100644 index 0000000..b8da732 --- /dev/null +++ b/host/error-decoder.c @@ -0,0 +1,53 @@ +#include +#include +#include + +const static char* get_desc(unsigned int index) { + const static char *strs[] = { + "Not found", + "Exists already", + "Out of space", + "Invalidated archive", + "Unacceptable", + "Verification Failure", + "Not supported", + "Unknown", + "Success," + }; + + if (index == 0) + return strs[8]; + + if (index >= 100 && index < 180) + return strs[0]; + else if (index >= 180 && index < 200) + return strs[1]; + else if (index >= 200 && index < 220) + return strs[2]; + else if (index >= 220 && index < 230) + return strs[3]; + else if (index >= 230 && index < 340) + return strs[4]; + else if (index >= 390 && index < 400) + return strs[5]; + else if (index >= 760 && index < 780) + return strs[6]; + return strs[7]; +} + + + +int main(int c, char** v) { + unsigned int error, desc, module, summary, level; + sscanf(v[1], "%08x", &error); + printf("Code: %08x\n", error); + + desc = error & 0b1111111111; + module = (error >> 10) & 0b11111111; + summary = (error >> 21) & 0b111111; + level = (error >> 27) & 0b11111; + + printf("Desc: %s (%u)\n", get_desc(desc), desc); + + return 0; +} diff --git a/source/firm/firm.c b/source/firm/firm.c index b9e4998..8be9226 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -4,7 +4,6 @@ #include #include "../common.h" -#include "../misc/sha256.h" #include "../fatfs/sdmmc.h" firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC; @@ -29,105 +28,87 @@ static int update_96_keys = 0; static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8; -void -slot0x11key96_init() -{ - // 9.6 crypto may need us to get the key from somewhere else. - // Unless the console already has the key initialized, that is. - uint8_t key[AES_BLOCK_SIZE]; - if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0 || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0) { - // Read key successfully. - aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); - - // Tell boot_firm it needs to regenerate the keys. - update_96_keys = 1; - } - // If we can't read the key, we assume it's not needed, and the firmware is - // the right version. - // Otherwise, we make sure the error message for decrypting arm9bin mentions - // this. -} - // Fwd decl int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version); -// The following two functions are loosely based on code from @Wolfvak's KGB CFW. -void extract_firms() { - // 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB) - uint32_t firm0_offset = 0x0B530000, // FIRM1 (AKA Safe Mode FIRM) - firm1_offset = 0x0B530000, // FIRM1 (AKA Safe Mode FIRM) +#define SECTOR_SIZE 0x200 + +// 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB) +void dump_firm(firm_h** buffer, uint8_t index) { + if (*buffer != NULL) return; + + uint32_t firm_offset = 0x0B130000 + (index % 2) * 0x400000, firm_size = 0x00100000; // 1MB, because - firm0 = (firm_h*)static_allocate(firm_size); - firm1 = (firm_h*)static_allocate(firm_size); + buffer[0] = static_allocate(firm_size); - uint8_t ctr[0x10] = {0}, - cid[0x10] = {0}, - sha[0x20] = {0}; + uint8_t ctr[0x10], + cid[0x10], + sha_t[0x20]; - if (sdmmc_nand_readsectors(firm0_offset / 0x200, firm_size / 0x200, (uint8_t*)firm0)) { - abort("Failed to read FIRM1 off NAND!\n"); - } + firm_h* firm = buffer[0]; - if (sdmmc_nand_readsectors(firm1_offset / 0x200, firm_size / 0x200, (uint8_t*)firm1)) { - abort("Failed to read FIRM1 off NAND!\n"); - } + if (sdmmc_nand_readsectors(firm_offset / SECTOR_SIZE, firm_size / SECTOR_SIZE, (uint8_t*)firm)) + abort("Failed to read NAND!\n"); + + fprintf(stderr, "Read FIRM%u off NAND.\n", index); - // Common. sdmmc_get_cid(1, (uint32_t*)cid); - Sha256Data(cid, 0x10, sha); - memcpy(ctr, sha, 0x10); + sha(sha_t, cid, 0x10, SHA_256_MODE); + memcpy(ctr, sha_t, 0x10); + aes_advctr(ctr, firm_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); - // FIRM0 - aes_advctr(ctr, firm0_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(0x06); - aes_setiv(ctr, AES_INPUT_BE | AES_INPUT_NORMAL); - aes((uint8_t*)firm0, (uint8_t*)firm0, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_setiv(ctr, AES_INPUT_BE|AES_INPUT_NORMAL); + aes((uint8_t*)firm, (uint8_t*)firm, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); - // FIXME: First off, don't hardcode the section index. Second, the version. - if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm0 + firm0->section[2].offset), firm0->section[2].size, 0x10)) { - abort("Failed to decrypt FIRM0 arm9loader.\n"); - } + fprintf(stderr, "AES decrypted FIRM%u.\n", index); - // We don't check magic on FIRM0 since it's like, you know, fucked up. Deliberately. + if (memcmp((char*) & firm->magic, "FIRM", 4)) + abort("Decryption failed on FIRM.\n"); - // Common. - sdmmc_get_cid(1, (uint32_t*)cid); - Sha256Data(cid, 0x10, sha); - memcpy(ctr, sha, 0x10); + fprintf(stderr, "Magic is intact on FIRM%u.\n", index); - // FIRM1 - aes_advctr(ctr, firm1_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_use_keyslot(0x06); - aes_setiv(ctr, AES_INPUT_BE | AES_INPUT_NORMAL); - aes((uint8_t*)firm1, (uint8_t*)firm1, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + uint8_t detver = 0; - if (memcmp(& firm1->magic, "FIRM", 4)) { - abort("FIRM1 magic is missing!\n"); - } + if(index == 1) + detver = 0x10; - // FIXME: First off, don't hardcode the section index. Second, the version. - if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm1 + firm1->section[2].offset), firm1->section[2].size, 0x10)) { - abort("Failed to decrypt FIRM1 arm9loader.\n"); + if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm + firm->section[2].offset), NATIVE_FIRM_TITLEID, detver)) { + abort("\rFailed to decrypt FIRM%u arm9loader.\n", index); } - fprintf(stderr, "\rExtracted FIRM off NAND.\n"); - // FIXME - "\r": Workaround because decrypt_arm9bin wasn't intended to be used outside of normal FIRM decryption. - // Causes output when we don't want that here. + fprintf(stderr, "\rDecrypted FIRM%u arm9loader.\n", index); +} + +void +slot0x11key96_init() +{ + // 9.6 crypto may need us to get the key from somewhere else. + // Unless the console already has the key initialized, that is. + uint8_t key[AES_BLOCK_SIZE]; + if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0 || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0) { + // Read key successfully. + aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); + + // Tell boot_firm it needs to regenerate the keys. + update_96_keys = 1; + } } uint8_t* key_search(uint8_t* mem, uint32_t size, uint8_t* sha256, uint8_t byte) { uint8_t hash[0x20] = {0}; - // Search ARM9 for NAND key. - for(; size > 0; size -= 4) { + // Search ARM9 for key. + for(uint32_t j = 0; j < size; j ++) { // Is candidate? - if (mem[size] == byte) { + if (mem[j] == byte) { // Yes. Check hash. - Sha256Data(&mem[size], 16, hash); + sha(hash, &mem[j], 0x10, SHA_256_MODE); - if(memcmp(sha256, hash, 0x20)) - return &mem[size]; + if(!memcmp(sha256, hash, 0x20)) { + return &mem[j]; + } } } @@ -135,46 +116,75 @@ uint8_t* key_search(uint8_t* mem, uint32_t size, uint8_t* sha256, uint8_t byte) } void extract_slot0x05keyY() { - if (firm0 == NULL || firm1 == NULL) - extract_firms(); + if (firm1 == NULL) + dump_firm(&firm1, 1); uint8_t sha256[] = {0x98, 0x24, 0x27, 0x14, 0x22, 0xB0, 0x6B, 0xF2, 0x10, 0x96, 0x9C, 0x36, 0x42, 0x53, 0x7C, 0x86, 0x62, 0x22, 0x5C, 0xFD, 0x6F, 0xAE, 0x9B, 0x0A, 0x85, 0xA5, 0xCE, 0x21, 0xAA, 0xB6, 0xC8, 0x4D}; uint8_t* key_loc = (uint8_t*)firm1 + firm1->section[2].offset; - uint32_t search_size = firm1->section[2].size - 16; + uint32_t search_size = firm1->section[2].size; - uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xDD); + uint8_t mem[16] __attribute__((aligned(4))) = {0}; + + uint8_t* key_data = key_search(key_loc, search_size, sha256, 0x4D); if (!key_data) abort("0x05 KeyY not found!\n"); - fprintf(stderr, "0x05 KeyY at %x in FIRM1\n", (uint32_t)key_data - (uint32_t)key_loc); + fprintf(stderr, "0x05 KeyY at %lx in FIRM1\n", (uint32_t)key_data - (uint32_t)key_loc); + + memcpy(mem, key_data, 16); + aes_setkey(0x05, mem, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); } void extract_slot0x3DkeyY() { - if (firm0 == NULL || firm1 == NULL) - extract_firms(); + if (firm0 == NULL) + dump_firm(&firm0, 0); - uint8_t sha256[] = {0x0a, 0x1c, 0x7b, 0x55, 0x86, 0x05, 0x89, 0xb0, 0xed, 0xd8, 0x87, 0x4b, 0x50, 0x55, 0xe3, 0x47, - 0x16, 0xa2, 0xcd, 0xe2, 0x5b, 0xad, 0x12, 0x48, 0xbb, 0xbb, 0xee, 0xd1, 0xb3, 0x40, 0xb1, 0xb8}; + uint8_t sha256[] = {0x21, 0x12, 0xf4, 0x50, 0x78, 0x6d, 0xce, 0x64, 0x39, 0xfd, 0xb8, 0x71, 0x14, 0x74, 0x41, 0xf4, + 0x69, 0xb6, 0xc4, 0x70, 0xa4, 0xb1, 0x5f, 0x7d, 0xfd, 0xe8, 0xcc, 0xe4, 0xc4, 0x62, 0x82, 0x5b}; uint8_t* key_loc = (uint8_t*)firm0 + firm0->section[2].offset; - uint32_t search_size = firm0->section[2].size - 16; + uint32_t search_size = firm0->section[2].size; - uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xD0); + uint8_t mem[16] __attribute__((aligned(4))) = {0}; + + uint8_t* key_data = key_search(key_loc, search_size, sha256, 0x0C); if (!key_data) - abort("0x3D KeyY not found!\n"); + abort("0x3D KeyY #1 not found!\n"); + + fprintf(stderr, "0x3D KeyY #1 at %lx in FIRM0\n", (uint32_t)key_data - (uint32_t)key_loc); + + memcpy(mem, key_data, 16); - fprintf(stderr, "0x3D KeyY at %x in FIRM0\n", (uint32_t)key_data - (uint32_t)key_loc); + aes_setkey(0x3D, mem, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); +} + +void* find_section_key() { + // The key will be dword-aligned (I think? Verify this. May need new NFIRM to check assumption. Go, Nintendo!) + + // The hash of the key. Can't give the key itself out, obviously. + uint8_t sha256[] = {0xb9, 0x4d, 0xb1, 0xb1, 0xc3, 0xe0, 0x11, 0x08, 0x9c, 0x19, 0x46, 0x06, 0x4a, 0xbc, 0x40, 0x2a, + 0x7c, 0x66, 0xf4, 0x4a, 0x74, 0x6f, 0x71, 0x50, 0x32, 0xfd, 0xff, 0x03, 0x74, 0xd7, 0x45, 0x2c}; + uint8_t* key_loc = (uint8_t*)firm_loc + firm_loc->section[2].offset; + uint32_t search_size = firm_loc->section[2].size; + + uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xDD); + + if (!key_data) + abort("FIRM Section key not found!\n"); + + fprintf(stderr, "FIRM Section key at %lx in FIRM\n", (uint32_t)key_data - (uint32_t)key_loc); + + return key_data; } int decrypt_cetk_key(void *key, const void *cetk) { - static int common_key_y_init = 0; uint8_t iv[AES_BLOCK_SIZE] = { 0 }; uint32_t sigtype = __builtin_bswap32(*(uint32_t *)cetk); @@ -186,27 +196,6 @@ decrypt_cetk_key(void *key, const void *cetk) if (ticket->ticketCommonKeyYIndex != 1) return 1; - if (!common_key_y_init) { - uint8_t common_key_y[AES_BLOCK_SIZE] = { 0 }; - uint8_t *p9_base = (uint8_t *)0x08028000; - uint8_t *i; - for (i = p9_base + 0x70000 - AES_BLOCK_SIZE; i >= p9_base; i--) { - if (i[0] == 0xD0 && i[4] == 0x9C && i[8] == 0x32 && i[12] == 0x23) { - // At i, there's 7 keys with 4 bytes padding between them. - // We only need the 2nd. - memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y)); - fprintf(stderr, "y"); - break; - } - } - - if (i < p9_base) - return 1; - - aes_setkey(0x3D, common_key_y, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - common_key_y_init = 1; - } - aes_use_keyslot(0x3D); memcpy(iv, ticket->titleID, sizeof(ticket->titleID)); @@ -264,8 +253,6 @@ decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version) { uint8_t slot = 0x15; - fprintf(BOTTOM_SCREEN, "9"); - if (firm_title == NATIVE_FIRM_TITLEID && version > 0x0F) { uint8_t decrypted_keyx[AES_BLOCK_SIZE]; @@ -288,10 +275,11 @@ decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version) if (firm_title == NATIVE_FIRM_TITLEID) return *(uint32_t *)arm9bin != ARM9BIN_MAGIC; + else if (firm_title == AGB_FIRM_TITLEID || firm_title == TWL_FIRM_TITLEID) return *(uint32_t *)arm9bin != LGY_ARM9BIN_MAGIC; - else - return 0; + + return 1; } int @@ -426,34 +414,6 @@ void __attribute__((naked)) arm11_preboot_halt() extern void wait(); -void* find_section_key() { - // The key will be dword-aligned (I think? Verify this. May need new NFIRM to check assumption. Go, Nintendo!) - uint8_t* key_loc = (uint8_t*)firm_loc + firm_loc->section[2].offset - 16; - uint32_t search_size = firm_loc->section[2].size - 16; - - key_loc = (uint8_t*)((uint32_t)key_loc & 0xFFFFFFF8); // Align to 4bytes. - - // The hash of the key. Can't give the key itself out, obviously. - uint32_t sha256boot[32] = {0xb9, 0x4d, 0xb1, 0xb1, 0xc3, 0xe0, 0x11, 0x08, - 0x9c, 0x19, 0x46, 0x06, 0x4a, 0xbc, 0x40, 0x2a, - 0x7c, 0x66, 0xf4, 0x4a, 0x74, 0x6f, 0x71, 0x50, - 0x32, 0xfd, 0xff, 0x03, 0x74, 0xd7, 0x45, 0x2c}; - uint8_t sha256check[32] = {0}; - - for(; search_size > 0; search_size -= 4) { - // Is candidate? - if (key_loc[search_size] == 0xDD) { - // Yes. Check hash. - Sha256Data(&key_loc[search_size], 16, sha256check); - if(memcmp(sha256boot, sha256check, 32)) { - fprintf(stderr, "Key at %x\n", (uint32_t)(&key_loc[search_size]) - (uint32_t)key_loc); - return &key_loc[search_size]; - } - } - } - return NULL; -} - void boot_firm() { diff --git a/source/interp.c b/source/interp.c index 991a4c1..35423e4 100644 --- a/source/interp.c +++ b/source/interp.c @@ -64,7 +64,7 @@ struct mode { uint8_t *memory; - size_t size; + uint32_t size; }; struct mode modes[21]; int init_bytecode = 0; @@ -155,18 +155,18 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si memset(stack, 0, stack_size); // Clear stack. - _UNUSED size_t top = stack_size - 1; + _UNUSED uint32_t top = stack_size - 1; #ifdef LOADER - size_t set_mode = 18; + uint32_t set_mode = 18; #else - size_t set_mode = 3; + uint32_t set_mode = 3; #endif struct mode *current_mode = &modes[set_mode]; - size_t offset = 0, new_offset = 0; + uint32_t offset = 0, new_offset = 0; - size_t i; + uint32_t i; int eq = 0, gt = 0, lt = 0, found = 0; // Flags. @@ -185,7 +185,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifdef LOADER log("rel\n"); #else - fprintf(stderr, "rel %u\n", *(code+1)); + fprintf(stderr, "rel %hhu\n", code[1]); #endif } code++; @@ -198,7 +198,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifdef LOADER log("find\n"); #else - fprintf(stderr, "find %u ...\n", code[1]); + fprintf(stderr, "find %hhu ...\n", code[1]); #endif } found = 0; @@ -215,7 +215,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifdef LOADER log("back\n"); #else - fprintf(stderr, "back %u\n", *(code+1)); + fprintf(stderr, "back %hhu\n", code[1]); #endif } offset -= code[1]; @@ -226,7 +226,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifdef LOADER log("fwd\n"); #else - fprintf(stderr, "fwd %u\n", *(code+1)); + fprintf(stderr, "fwd %u\n", code[1]); #endif } offset += code[1]; @@ -449,7 +449,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifdef LOADER log("seek\n"); #else - fprintf(stderr, "seek %u\n", offset); + fprintf(stderr, "seek %lu\n", offset); #endif } code += 4; @@ -527,14 +527,21 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si #ifndef LOADER // Panic; not proper opcode. fprintf(stderr, "Invalid opcode. State:\n" - " Relative: %u\n" - " Actual: %x:%u\n" - " Memory: %x\n" - " Actual: %x\n" - " Code Loc: %x\n" - " Actual: %x\n" - " Opcode: %u\n", - set_mode, current_mode->memory, current_mode->size, offset, current_mode->memory + offset, code - bytecode, code, *code); + " Relative: %lu\n" + " Actual: %lx:%lu\n" + " Memory: %lx\n" + " Actual: %lx\n" + " Code Loc: %lx\n" + " Actual: %lx\n" + " Opcode: %hhu\n", + (uint32_t)set_mode, + (uint32_t)current_mode->memory, + (uint32_t)current_mode->size, + (uint32_t)offset, + (uint32_t)(current_mode->memory + offset), + (uint32_t)(code - bytecode), + (uint32_t)code, + *code); #endif abort("Halting startup.\n"); break; @@ -542,14 +549,17 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si if (offset > current_mode->size) { // Went out of bounds. Error. #ifndef LOADER - fprintf(stderr, " -> %x", offset); + fprintf(stderr, " -> %lx", offset); #endif abort("seeked out of bounds\n"); } #ifndef LOADER if (debug) { - fprintf(stderr, "l:%u g:%u e:%u f:%u m:%u o:0x%x\nc:0x%x m:0x%x n:%x\n", lt, gt, eq, found, set_mode, offset, code - bytecode, current_mode->memory + offset, code); + fprintf(stderr, "l:%d g:%d e:%d f:%d m:%lu o:0x%lx\nc:0x%lx m:0x%lx n:%lx\n", + lt, gt, eq, found, + set_mode, + (uint32_t)offset, (uint32_t)(code - bytecode), (uint32_t)(current_mode->memory + offset), (uint32_t)code); wait(); } #endif @@ -641,7 +651,7 @@ execb(char *filename, int build_cache) // File wasn't found. The user didn't enable anything. return 0; } - size_t len = fsize(f); + uint32_t len = fsize(f); fread((uint8_t *)FCRAM_PATCH_LOC, 1, len, f); fclose(f); diff --git a/source/main.c b/source/main.c index d2b3420..55e998a 100644 --- a/source/main.c +++ b/source/main.c @@ -42,6 +42,8 @@ main(int argc, char** argv) load_config(); // Load configuration. + config.options[OPTION_SAVE_LOGS] = 1; + extract_slot0x05keyY(); extract_slot0x3DkeyY(); diff --git a/source/misc/sha256.c b/source/misc/sha256.c deleted file mode 100644 index 1788553..0000000 --- a/source/misc/sha256.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Crypto/Sha256.c -- SHA-256 Hash function -2008-11-06 : Igor Pavlov : Public domain -This code is based on public domain code from Wei Dai's Crypto++ library. */ - -#include "sha256.h" - -#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) - - -/* define it for speed optimization */ -/* #define _SHA256_UNROLL */ -/* #define _SHA256_UNROLL2 */ - -void Sha256_Init(CSha256 *p) -{ - p->state[0] = 0x6a09e667; - p->state[1] = 0xbb67ae85; - p->state[2] = 0x3c6ef372; - p->state[3] = 0xa54ff53a; - p->state[4] = 0x510e527f; - p->state[5] = 0x9b05688c; - p->state[6] = 0x1f83d9ab; - p->state[7] = 0x5be0cd19; - p->count = 0; -} - -#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) -#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) -#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) -#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) - -#define blk0(i) (W[i] = data[i]) -#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) - -#define Ch(x,y,z) (z^(x&(y^z))) -#define Maj(x,y,z) ((x&y)|(z&(x|y))) - -#define a(i) T[(0-(i))&7] -#define b(i) T[(1-(i))&7] -#define c(i) T[(2-(i))&7] -#define d(i) T[(3-(i))&7] -#define e(i) T[(4-(i))&7] -#define f(i) T[(5-(i))&7] -#define g(i) T[(6-(i))&7] -#define h(i) T[(7-(i))&7] - - -#ifdef _SHA256_UNROLL2 - -#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\ - d += h; h += S0(a) + Maj(a, b, c) - -#define RX_8(i) \ - R(a,b,c,d,e,f,g,h, i); \ - R(h,a,b,c,d,e,f,g, i+1); \ - R(g,h,a,b,c,d,e,f, i+2); \ - R(f,g,h,a,b,c,d,e, i+3); \ - R(e,f,g,h,a,b,c,d, i+4); \ - R(d,e,f,g,h,a,b,c, i+5); \ - R(c,d,e,f,g,h,a,b, i+6); \ - R(b,c,d,e,f,g,h,a, i+7) - -#else - -#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ - d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) - -#ifdef _SHA256_UNROLL - -#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); - -#endif - -#endif - -const UInt32 K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -static void Sha256_Transform(UInt32 *state, const UInt32 *data) -{ - UInt32 W[16]; - unsigned j; - #ifdef _SHA256_UNROLL2 - UInt32 a,b,c,d,e,f,g,h; - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - #else - UInt32 T[8]; - for (j = 0; j < 8; j++) - T[j] = state[j]; - #endif - - for (j = 0; j < 64; j += 16) - { - #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) - RX_8(0); RX_8(8); - #else - unsigned i; - for (i = 0; i < 16; i++) { R(i); } - #endif - } - - #ifdef _SHA256_UNROLL2 - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; - #else - for (j = 0; j < 8; j++) - state[j] += T[j]; - #endif - - /* Wipe variables */ - /* memset(W, 0, sizeof(W)); */ - /* memset(T, 0, sizeof(T)); */ -} - -#undef S0 -#undef S1 -#undef s0 -#undef s1 - -static void Sha256_WriteByteBlock(CSha256 *p) -{ - UInt32 data32[16]; - unsigned i; - for (i = 0; i < 16; i++) - data32[i] = - ((UInt32)(p->buffer[i * 4 ]) << 24) + - ((UInt32)(p->buffer[i * 4 + 1]) << 16) + - ((UInt32)(p->buffer[i * 4 + 2]) << 8) + - ((UInt32)(p->buffer[i * 4 + 3])); - Sha256_Transform(p->state, data32); -} - -void Sha256_Update(CSha256 *p, const Byte *data, size_t size) -{ - UInt32 curBufferPos = (UInt32)p->count & 0x3F; - while (size > 0) - { - p->buffer[curBufferPos++] = *data++; - p->count++; - size--; - if (curBufferPos == 64) - { - curBufferPos = 0; - Sha256_WriteByteBlock(p); - } - } -} - -void Sha256_Final(CSha256 *p, Byte *digest) -{ - UInt64 lenInBits = (p->count << 3); - UInt32 curBufferPos = (UInt32)p->count & 0x3F; - unsigned i; - p->buffer[curBufferPos++] = 0x80; - while (curBufferPos != (64 - 8)) - { - curBufferPos &= 0x3F; - if (curBufferPos == 0) - Sha256_WriteByteBlock(p); - p->buffer[curBufferPos++] = 0; - } - for (i = 0; i < 8; i++) - { - p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56); - lenInBits <<= 8; - } - Sha256_WriteByteBlock(p); - - for (i = 0; i < 8; i++) - { - *digest++ = (Byte)((p->state[i] >> 24) & 0xFF); - *digest++ = (Byte)((p->state[i] >> 16) & 0xFF); - *digest++ = (Byte)((p->state[i] >> 8) & 0xFF); - *digest++ = (Byte)((p->state[i]) & 0xFF); - } - Sha256_Init(p); -} - -unsigned char *Sha256Data (const unsigned char *data, unsigned int len, unsigned char *buf) { - CSha256 ctx; - - Sha256_Init(&ctx); - Sha256_Update(&ctx,data,len); - Sha256_Final(&ctx, buf); - - return buf; -} diff --git a/source/misc/sha256.h b/source/misc/sha256.h deleted file mode 100644 index f929931..0000000 --- a/source/misc/sha256.h +++ /dev/null @@ -1,192 +0,0 @@ -/* Crypto/Sha256.h -- SHA-256 Hash function -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __CRYPTO_SHA256_H -#define __CRYPTO_SHA256_H - -#include -#include - -/* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ - -#define SZ_OK 0 -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -typedef int WRes; - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -typedef long long int Int64; -typedef unsigned long long int UInt64; - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#define MY_CDECL -#define MY_STD_CALL -#define MY_FAST_CALL - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define SHA256_DIGEST_SIZE 32 - -typedef struct -{ - UInt32 state[8]; - UInt64 count; - Byte buffer[64]; -} CSha256; - -void Sha256_Init(CSha256 *p); -void Sha256_Update(CSha256 *p, const Byte *data, size_t size); -void Sha256_Final(CSha256 *p, Byte *digest); -unsigned char *Sha256Data (const unsigned char *data, unsigned int len, unsigned char *buf); - -#endif diff --git a/source/patch/emunand.c b/source/patch/emunand.c index 20237a0..60c0215 100644 --- a/source/patch/emunand.c +++ b/source/patch/emunand.c @@ -49,7 +49,7 @@ verify_emunand(uint32_t index, uint32_t *off, uint32_t *head) *off = offset + 1; *head = offset + 1; - fprintf(stderr, "emunand: found NCSD magic for %u\n", index); + fprintf(stderr, "emunand: found NCSD magic for %lu\n", index); fprintf(stderr, "emunand: layout is normal\n"); } // Check for GW EmuNAND on SD @@ -57,7 +57,7 @@ verify_emunand(uint32_t index, uint32_t *off, uint32_t *head) *off = offset; *head = offset + nandSize; - fprintf(stderr, "emunand: found NCSD magic for %u\n", index); + fprintf(stderr, "emunand: found NCSD magic for %lu\n", index); fprintf(stderr, "emunand: layout is gateway\n"); } else { abort("emunand: selected NAND image is not valid.\n"); @@ -73,8 +73,8 @@ getEmuCode(uint8_t *pos, uint32_t size) uint8_t *ret = memfind(pos + 0x13500, size - 0x13500, pattern, 6) + 0x455; if (ret) { - fprintf(stderr, "emunand: free space @ %x\n", ret); - fprintf(stderr, "emunand: size is %u bytes\n", (uint8_t *)ret - pos); + fprintf(stderr, "emunand: free space @ %lx\n", (uint32_t)ret); + fprintf(stderr, "emunand: size is %lu bytes\n", (uint32_t) (ret - pos)); } return ret; @@ -89,7 +89,7 @@ getSDMMC(uint8_t *pos, uint32_t size) uint32_t ret = *(uint32_t *)(off + 9) + *(uint32_t *)(off + 0xD); - fprintf(stderr, "emunand: SDMMC code @ %x\n", ret); + fprintf(stderr, "emunand: SDMMC code @ %lx\n", ret); return ret; } @@ -116,8 +116,8 @@ patchNANDRW(uint8_t *pos, uint32_t size, uint32_t branchOffset) writeOffset[1] = nandRedir[1]; ((uint32_t *)writeOffset)[1] = branchOffset; - fprintf(stderr, "emunand: write @ %x\n", writeOffset); - fprintf(stderr, "emunand: read @ %x\n", readOffset); + fprintf(stderr, "emunand: write @ %lx\n", (uint32_t)writeOffset); + fprintf(stderr, "emunand: read @ %lx\n", (uint32_t)readOffset); } static void @@ -134,7 +134,7 @@ patchMPU(uint8_t *pos, uint32_t size) off[6] = mpuPatch[1]; off[9] = mpuPatch[2]; - fprintf(stderr, "emunand: mpu @ %x\n", off); + fprintf(stderr, "emunand: mpu @ %lx\n", (uint32_t)off); } void @@ -174,8 +174,8 @@ patch_emunand(uint32_t index) verify_emunand(index, pos_offset, pos_head); - fprintf(stderr, "emunand: nand is on sector %u\n", *pos_offset); - fprintf(stderr, "emunand: head is on sector %u\n", *pos_head); + fprintf(stderr, "emunand: nand is on sector %lu\n", *pos_offset); + fprintf(stderr, "emunand: head is on sector %lu\n", *pos_head); // Add emuNAND hooks patchNANDRW(process9Offset, process9Size, branchOffset); diff --git a/source/patch/module.c b/source/patch/module.c index c99b189..08f3e96 100644 --- a/source/patch/module.c +++ b/source/patch/module.c @@ -52,13 +52,13 @@ PATCH(modules) } } - fprintf(stderr, "module: Grow %d units\n", need_units); + fprintf(stderr, "module: Grow %lu units\n", need_units); } // Move the remaining modules closer else if (module->contentSize < sysmodule->contentSize) { // NOTE - This doesn't change the sysmodule section size; it isn't needed to do so. - fprintf(stderr, "Module: Shrink %d units\n", sysmodule->contentSize - module->contentSize); + fprintf(stderr, "Module: Shrink %lu units\n", sysmodule->contentSize - module->contentSize); int remaining_size = sysmodule_section->size - (((uint32_t)sysmodule + sysmodule->contentSize * 0x200) - ((uint32_t)firm_loc + sysmodule_section->offset)); // Sysmodule section size - (End location of this sysmodule - @@ -67,7 +67,7 @@ PATCH(modules) // Move end of section to be adjacent } - fprintf(stderr, "Module: Injecting %llu\n", module->programID); + fprintf(stderr, "Module: Injecting module\n"); // Copy the module into the firm memcpy(sysmodule, module, module->contentSize * 0x200); } diff --git a/source/patch/reboot.c b/source/patch/reboot.c index 95a5bfe..f07cc99 100644 --- a/source/patch/reboot.c +++ b/source/patch/reboot.c @@ -31,18 +31,18 @@ patch_reboot() uint8_t *process9Offset = getProcess9((uint8_t *)firm_loc + firm_loc->section[2].offset + 0x15000, firm_loc->section[2].size - 0x15000, &process9Size, &process9MemAddr); - fprintf(stderr, "reboot: proc9 mem @ %x\n", process9MemAddr); + fprintf(stderr, "reboot: proc9 mem @ %lx\n", (uint32_t)process9MemAddr); wait(); uint8_t *off = memfind(process9Offset, process9Size, pattern, 4) - 0x10; - fprintf(stderr, "reboot: firmlaunch @ %x\n", off); + fprintf(stderr, "reboot: firmlaunch @ %lx\n", (uint32_t)off); // Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1 uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - process9Offset + process9MemAddr); - fprintf(stderr, "reboot: fopen @ %x\n", fOpenOffset); + fprintf(stderr, "reboot: fopen @ %lx\n", fOpenOffset); wait(); @@ -69,9 +69,9 @@ patch_reboot() if (!pos_native && !pos_twl && !pos_agb) abort("reboot: missing string placeholder?\n"); - fprintf(stderr, "reboot: NATF @ %x\n", pos_native); - fprintf(stderr, "reboot: TWLF @ %x\n", pos_twl); - fprintf(stderr, "reboot: AGBF @ %x\n", pos_agb); + fprintf(stderr, "reboot: NATF @ %lx\n", (uint32_t)pos_native); + fprintf(stderr, "reboot: TWLF @ %lx\n", (uint32_t)pos_twl); + fprintf(stderr, "reboot: AGBF @ %lx\n", (uint32_t)pos_agb); uint8_t *mem = (uint8_t *)0x01FF8000; // 0x8000 space that will be resident. This is AXI WRAM. We have about 0x3700 bytes here. // According to 3dbrew, this space's props from userland: @@ -107,7 +107,7 @@ patch_reboot() uint32_t *pos_rebc = (uint32_t *)memfind(off, size, "rebc", 4); *pos_rebc = (uint32_t)mem; - fprintf(stderr, "reboot: rebc @ %x\n", pos_rebc); + fprintf(stderr, "reboot: rebc @ %lx\n", (uint32_t)pos_rebc); f = fopen(PATH_REBOOT_CODE, "r"); if (!f) diff --git a/source/patch/svc.c b/source/patch/svc.c index 9c4b900..dfb6e1f 100644 --- a/source/patch/svc.c +++ b/source/patch/svc.c @@ -33,8 +33,8 @@ PATCH(services) FILE *data = fopen(PATH_BACKDOOR, "r"); uint32_t size = fsize(data); - fprintf(stderr, "Svc: backdoor is %d bytes\n", size); - fprintf(stderr, "Svc: Read code to %x\n", (uint32_t)svc_tab_open); + fprintf(stderr, "Svc: backdoor is %lu bytes\n", size); + fprintf(stderr, "Svc: Read code to %lx\n", (uint32_t)svc_tab_open); fread(svc_tab_open, 1, size, data); diff --git a/source/std/abort.h b/source/std/abort.h index b909193..397ff20 100644 --- a/source/std/abort.h +++ b/source/std/abort.h @@ -1,6 +1,6 @@ #ifndef __ABORT_H #define __ABORT_H -void abort(const char* x, ...); +void abort(const char* x, ...) __attribute__ ((format (printf, 1, 2))); #endif diff --git a/source/std/draw.h b/source/std/draw.h index 61fdbfe..fb2b451 100644 --- a/source/std/draw.h +++ b/source/std/draw.h @@ -80,7 +80,7 @@ void clear_disp(uint8_t *screen); // Formats are also supported (but are subject to replacement) // %p - unsigned char, changes color of text (will be replaced with ANSI codes // eventually) -void fprintf(void *channel, const char *format, ...); +void fprintf(void *channel, const char *format, ...) __attribute__ ((format (printf, 2, 3))); void vfprintf(void *channel, const char *format, va_list ap); -- 2.39.5