From: chaoskagami Date: Sun, 10 Jul 2016 04:37:45 +0000 (-0400) Subject: Automate 0x05 KeyY from FIRM1 - not 100% tested (shoutout to @Wolfvak again) X-Git-Tag: v0.2.0~24^2~2^2 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=8ce4d5a60ca46bac10c848ea2d48b48262aa3419;p=corbenik%2Fcorbenik.git Automate 0x05 KeyY from FIRM1 - not 100% tested (shoutout to @Wolfvak again) --- diff --git a/source/firm/crypto.c b/source/firm/crypto.c index 67d8e86..dc7ec5b 100644 --- a/source/firm/crypto.c +++ b/source/firm/crypto.c @@ -374,3 +374,5 @@ rsa_verify(const void *data, uint32_t size, const void *sig, uint32_t mode) return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE), SHA_256_HASH_SIZE) == 0; } + + diff --git a/source/firm/firm.c b/source/firm/firm.c index 78d0b9f..cb63a09 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -5,6 +5,7 @@ #include "../common.h" #include "../misc/sha256.h" +#include "../fatfs/sdmmc.h" firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC; uint32_t firm_size = FCRAM_SPACING; @@ -21,6 +22,9 @@ uint32_t agb_firm_size = FCRAM_SPACING * 2; firm_section_h agb_firm_proc9; exefs_h *agb_firm_p9_exefs; +firm_h* firm0 = NULL; +firm_h* firm1 = NULL; + static int update_96_keys = 0; static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8; @@ -44,6 +48,72 @@ slot0x11key96_init() // 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_firm1() { + // 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB) + uint32_t firm_offset = 0x0B530000, // FIRM1 (AKA Safe Mode FIRM) + firm_size = 0x00100000; // 1MB, because + + firm1 = (firm_h*)static_allocate(firm_size); + + uint8_t ctr[0x10] = {0}, + cid[0x10] = {0}, + sha[0x20] = {0}; + + if (sdmmc_nand_readsectors(firm_offset / 0x200, firm_size / 0x200, (uint8_t*)firm1)) { + abort("Failed to read FIRM1 off NAND!\n"); + } + + sdmmc_get_cid(1, (uint32_t*)cid); + Sha256Data(cid, 0x10, sha); + memcpy(ctr, sha, 0x10); + aes_advctr(ctr, firm_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); + + if (memcmp(& firm1->magic, "FIRM", 4)) { + abort("FIRM1 magic is missing!\n"); + } + + // 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"); + } + + fprintf(stderr, "\rExtracted FIRM1 off NAND.\n"); // FIXME - Workaround because decrypt_arm9bin wasn't intended to be used outside of normal FIRM decryption. +} + +void extract_slot0x05keyY() { + const uint8_t keyY_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 keyhash_tmp[0x20] = {0}; + + uint8_t* key_loc = (uint8_t*)firm1 + firm1->section[2].offset; + uint32_t search_size = firm1->section[2].size - 16; + + // Search ARM9 for NAND key. + for(; search_size > 0; search_size -= 4) { + // Is candidate? + if (key_loc[search_size] == 0x4D) { + // Yes. Check hash. + Sha256Data(&key_loc[search_size], 16, keyhash_tmp); + + if(memcmp(keyY_sha256, keyhash_tmp, 0x20)) { + fprintf(stderr, "0x05 KeyY at %x in FIRM1\n", search_size); + aes_setkey(0x05, &key_loc[search_size], AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); + return; + } + } + } + + abort("0x05 KeyY not found!\n"); +} + int decrypt_cetk_key(void *key, const void *cetk) { @@ -324,7 +394,6 @@ void* find_section_key() { } } } - return NULL; } diff --git a/source/firm/firm.h b/source/firm/firm.h index 9fba7e1..d558e98 100644 --- a/source/firm/firm.h +++ b/source/firm/firm.h @@ -38,6 +38,9 @@ extern exefs_h *agb_firm_p9_exefs; struct firm_signature *get_firm_info(firm_h *firm); void slot0x11key96_init(); +void extract_firm1(); +void extract_slot0x05keyY(); + int load_firms(); void boot_firm(); void boot_cfw(); diff --git a/source/main.c b/source/main.c index 9a5e5c7..183f180 100644 --- a/source/main.c +++ b/source/main.c @@ -42,6 +42,9 @@ main(int argc, char** argv) load_config(); // Load configuration. + extract_firm1(); + extract_slot0x05keyY(); + if (CFG_BOOTENV == 7) { fprintf(stderr, "Rebooted from AGB, disabling EmuNAND.\n"); config.options[OPTION_EMUNAND] = 0;