From cb06cf83ff8a426e327c66e51cc65cec69ea240b Mon Sep 17 00:00:00 2001 From: Aurora Date: Fri, 4 Mar 2016 23:43:22 +0100 Subject: [PATCH] Added flag to use a pre-patched FIRM (skips all decrypting and patching) Original patch by @Fix94 --- reboot/rebootCode.s | 2 +- source/crypto.c | 47 +++++++++++++++++++----------------- source/crypto.h | 3 ++- source/firm.c | 59 ++++++++++++++++++++++++++++++++------------- 4 files changed, 70 insertions(+), 41 deletions(-) diff --git a/reboot/rebootCode.s b/reboot/rebootCode.s index b4175e0..06409e7 100644 --- a/reboot/rebootCode.s +++ b/reboot/rebootCode.s @@ -99,7 +99,7 @@ Memcpy: BX LR FileName: - .dcw "sdmc:/rei/patched_firmware.bin" + .dcw "sdmc:/rei/patched_firmware_sys.bin" .word 0x0 .pool diff --git a/source/crypto.c b/source/crypto.c index 8a9c254..fc898d7 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -7,6 +7,11 @@ #include "fatfs/sdmmc/sdmmc.h" #include "fatfs/ff.h" +//Nand key#2 (0x12C10) +u8 key2[0x10] = { + 0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0 +}; + /**************************************************************** * Crypto Libs ****************************************************************/ @@ -375,48 +380,46 @@ void nandFirm0(u8 *outbuf, const u32 size, u8 console){ aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); } -//Emulates the Arm9loader process -void arm9loader(void *armHdr, u8 mode){ - //Nand key#2 (0x12C10) - u8 key2[0x10] = { - 0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0 - }; +//Decrypts the N3DS arm9bin +void decArm9Bin(void *armHdr, u8 mode){ //Firm keys u8 keyX[0x10]; u8 keyY[0x10]; u8 CTR[0x10]; u32 slot = mode ? 0x16 : 0x15; - + //Setup keys needed for arm9bin decryption - memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10); - memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10); - u32 size = atoi((void *)((uintptr_t)armHdr+0x30)); + memcpy((u8*)keyY, (void *)(armHdr+0x10), 0x10); + memcpy((u8*)CTR, (void *)(armHdr+0x20), 0x10); + u32 size = atoi((void *)(armHdr+0x30)); if(mode){ //Set 0x11 to key2 for the arm9bin and misc keys aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(0x11); - aes((u8*)keyX, (void *)((uintptr_t)armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0); + aes((u8*)keyX, (void *)(armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0); aes_setkey(slot, (u8*)keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); } aes_setkey(slot, (u8*)keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setiv((u8*)CTR, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(slot); - + //Decrypt arm9bin aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); +} - if(mode){ - //Set keys 0x19..0x1F keyXs - u8* decKey = (void *)((uintptr_t)armHdr+0x89824); - aes_use_keyslot(0x11); - for(slot = 0x19; slot < 0x20; slot++) { - aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); - aes(decKey, (void *)((uintptr_t)armHdr+0x89814), 1, NULL, AES_ECB_DECRYPT_MODE, 0); - aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - *(u8 *)((void *)((uintptr_t)armHdr+0x89814+0xF)) += 1; - } +//Sets the N3DS 9.6 KeyXs +void setKeyXs(void *armHdr){ + + //Set keys 0x19..0x1F keyXs + u8* decKey = (void *)(armHdr+0x89824); + aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_use_keyslot(0x11); + for(u32 slot = 0x19; slot < 0x20; slot++){ + aes(decKey, (void *)(armHdr+0x89814), 1, NULL, AES_ECB_DECRYPT_MODE, 0); + aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); + *(u8*)(armHdr+0x89814+0xF) += 1; } } \ No newline at end of file diff --git a/source/crypto.h b/source/crypto.h index cdbaf19..2297872 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -132,6 +132,7 @@ int rsa_verify(const void* data, u32 size, const void* sig, u32 mode); //NAND/FIRM stuff void nandFirm0(u8 *outbuf, const u32 size, u8 console); -void arm9loader(void *armHdr, u8 mode); +void decArm9Bin(void *armHdr, u8 mode); +void setKeyXs(void *armHdr); #endif /*__CRYPTO_H*/ diff --git a/source/firm.c b/source/firm.c index 07062b8..ad43a23 100755 --- a/source/firm.c +++ b/source/firm.c @@ -17,9 +17,12 @@ firmSectionHeader *section; u32 firmSize = 0; u8 mode = 1, console = 1, + emuNAND = 0, a9lhSetup = 0, - updatedSys = 0; + updatedSys = 0, + usePatchedFirm = 0; u16 pressed; +char *firmPathPatched = NULL; void setupCFW(void){ @@ -39,13 +42,28 @@ void setupCFW(void){ /* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo is not pressed, boot 9.0 FIRM */ if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0; + + /* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected + or R is pressed on a > 9.2 SysNAND, boot emuNAND */ + if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) || + (!updatedSys && mode && !(pressed & BUTTON_R1))) emuNAND = 1; + + if(mode) firmPathPatched = emuNAND ? "/rei/patched_firmware_emu.bin" : + "/rei/patched_firmware_sys.bin"; + + //Skip decrypting and patching FIRM + if(fileExists("/rei/usepatchedfw")){ + //Only needed with this flag + if(!mode) firmPathPatched = "/rei/patched_firmware90.bin"; + if (fileExists(firmPathPatched)) usePatchedFirm = 1; + } } //Load firm into FCRAM u8 loadFirm(void){ - //If not using an A9LH setup, load 9.0 FIRM from NAND - if(!a9lhSetup && !mode){ + //If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND + if(!usePatchedFirm && !a9lhSetup && !mode){ //Read FIRM from NAND and write to FCRAM firmSize = console ? 0xF2000 : 0xE9000; nandFirm0((u8*)firmLocation, firmSize, console); @@ -54,12 +72,11 @@ u8 loadFirm(void){ } //Load FIRM from SD else{ - char firmPath[] = "/rei/firmware.bin"; - char firmPath2[] = "/rei/firmware90.bin"; - char *pathPtr = mode ? firmPath : firmPath2; - firmSize = fileSize(pathPtr); + char *path = usePatchedFirm ? firmPathPatched : + (mode ? "/rei/firmware.bin" : "/rei/firmware90.bin"); + firmSize = fileSize(path); if (!firmSize) return 1; - fileRead((u8*)firmLocation, pathPtr, firmSize); + fileRead((u8*)firmLocation, path, firmSize); } section = firmLocation->section; @@ -67,7 +84,8 @@ u8 loadFirm(void){ //Check that the loaded FIRM matches the console if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) return 1; - if(console) arm9loader((u8*)firmLocation + section[2].offset, mode); + if(console && !usePatchedFirm) + decArm9Bin((u8*)firmLocation + section[2].offset, mode); return 0; } @@ -124,11 +142,9 @@ u8 loadEmu(void){ //Patches u8 patchFirm(void){ + if(usePatchedFirm) return 0; - /* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected - or R is pressed on a > 9.2 SysNAND, boot emuNAND */ - if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) || - (!updatedSys && mode && !(pressed & BUTTON_R1))){ + if(emuNAND){ if (loadEmu()) return 1; } else if (a9lhSetup){ @@ -152,13 +168,13 @@ u8 patchFirm(void){ *arm9 = 0x801B01C; } - //Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax if(mode){ + //Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax u32 rebootOffset = 0, fOpenOffset = 0; //Read reboot code from SD - char path[] = "/rei/reboot/reboot.bin"; + char *path = "/rei/reboot/reboot.bin"; u32 size = fileSize(path); if (!size) return 1; getReboot(firmLocation, firmSize, &rebootOffset); @@ -169,15 +185,24 @@ u8 patchFirm(void){ getfOpen(firmLocation, firmSize, &fOpenOffset); *pos_fopen = fOpenOffset; - //Write patched FIRM to SD - if(fileWrite((u8*)firmLocation, "/rei/patched_firmware.bin", firmSize) != 0) return 1; + //Patch path for emuNAND-patched FIRM + if(emuNAND){ + u32 *pos_path = memsearch((u32*)rebootOffset, L"sys", size, 6); + memcpy((u8*)pos_path, L"emu", 6); + } } + //Write patched FIRM to SD if needed + if(firmPathPatched) + if(fileWrite((u8*)firmLocation, firmPathPatched, firmSize) != 0) return 1; + return 0; } void launchFirm(void){ + if(console && mode) setKeyXs((u8*)firmLocation + section[2].offset); + //Copy firm partitions to respective memory locations memcpy(section[0].address, (u8*)firmLocation + section[0].offset, section[0].size); memcpy(section[1].address, (u8*)firmLocation + section[1].offset, section[1].size);