From c95808fa2d5fe522463dd1aad420c035cf7a97bd Mon Sep 17 00:00:00 2001 From: Aurora Wright Date: Thu, 13 Apr 2017 02:49:19 +0200 Subject: [PATCH] CTRNAND for LayeredFS and small changes --- injector/patches/romfsredir.s | 6 ++++-- injector/source/patcher.c | 36 ++++++++++++++++++++++---------- source/crypto.c | 39 ++++++++++++++--------------------- source/crypto.h | 1 - source/firm.c | 8 +++---- source/main.c | 4 +--- 6 files changed, 49 insertions(+), 45 deletions(-) diff --git a/injector/patches/romfsredir.s b/injector/patches/romfsredir.s index 0362911..53f7559 100644 --- a/injector/patches/romfsredir.s +++ b/injector/patches/romfsredir.s @@ -34,7 +34,7 @@ _start: bne _mountSd+4 stmfd sp!, {r0-r4, lr} sub sp, sp, #4 - mov r1, #9 + load r1, archive mov r0, sp load r4, fsMountArchive blx r4 @@ -97,10 +97,12 @@ _start: .pool .align 4 - sdmcArchiveName : .dcb "sdmc:", 0 + sdmcArchiveName : .word 0xdead0007 + .dcb ":", 0 .align 4 fsMountArchive : .word 0xdead0005 fsRegisterArchive : .word 0xdead0006 + archive : .word 0xdead0008 sdmcCustomPath : .word 0xdead0004 .close diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 9243c25..f152952 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -40,18 +40,18 @@ static Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, in return IFile_Open(file, archiveId, archivePath, filePath, flags); } -static bool dirCheck(FS_ArchiveID archiveId, const char *path) +static u32 dirCheck(FS_ArchiveID archiveId, const char *path) { - bool ret; + u32 ret; Handle handle; FS_Archive archive; FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path}, archivePath = {PATH_EMPTY, 1, (u8 *)""}; - if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = false; + if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = 1; else { - ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)); + ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)) ? 0 : 2; if(ret) FSDIRLDR_Close(handle); FSLDR_CloseArchive(archive); } @@ -59,19 +59,23 @@ static bool dirCheck(FS_ArchiveID archiveId, const char *path) return ret; } -static u32 openLumaFile(IFile *file, const char *path) +static bool openLumaFile(IFile *file, const char *path) { Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ); - if(R_SUCCEEDED(res)) return ARCHIVE_SDMC; + if(R_SUCCEEDED(res)) return false; //Returned if SD is not mounted - return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)) ? ARCHIVE_NAND_RW : 0; + return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)); } -static bool checkLumaDir(const char *path) +static u32 checkLumaDir(const char *path) { - return dirCheck(ARCHIVE_SDMC, path); + u32 res = dirCheck(ARCHIVE_SDMC, path); + + if(!res) return ARCHIVE_SDMC; + + return res == 1 && !dirCheck(ARCHIVE_NAND_RW, path) ? ARCHIVE_NAND_RW : 0; } static inline void loadCFWInfo(void) @@ -513,7 +517,11 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size) char path[] = "/luma/titles/0000000000000000/romfs"; progIdToStr(path + 28, progId); - if(!checkLumaDir(path)) return true; + u32 archive = checkLumaDir(path); + + if(!archive) return true; + + const char *mount = archive == ARCHIVE_SDMC ? "sdmc:" : "nand:"; u32 fsMountArchive = 0xFFFFFFFF, fsRegisterArchive = 0xFFFFFFFF, @@ -546,7 +554,7 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size) payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4); break; case 0xdead0004: - memcpy(payload32 + i, "sdmc:", 5); + memcpy(payload32 + i, mount, 5); memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path)); break; case 0xdead0005: @@ -555,6 +563,12 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size) case 0xdead0006: payload32[i] = 0x100000 + fsRegisterArchive; break; + case 0xdead0007: + memcpy(payload32 + i, mount, 4); + break; + case 0xdead0008: + payload32[i] = archive; + break; } } diff --git a/source/crypto.c b/source/crypto.c index 8e86483..22a224d 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -322,8 +322,6 @@ static void sha(void *res, const void *src, u32 size, u32 mode) void twlConsoleInfoInit(void) { - if(CFG_SYSPROT9 & 2) return; //sorry, the lennies are currently missing - u64 twlConsoleId = CFG_UNITINFO != 0 ? OTP_DEVCONSOLEID : (0x80000000ULL | (*(vu64 *)0x01FFB808 ^ 0x8C267B7B358A6AFULL)); CFG_TWLUNITINFO = CFG_UNITINFO; OTP_TWLCONSOLEID = twlConsoleId; @@ -482,28 +480,6 @@ bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize) return decryptExeFs(cxi); } -void setN3DS96Keys(void) -{ - //Set 0x11 keyslot - __attribute__((aligned(4))) const u8 key2s[2][AES_BLOCK_SIZE] = { - {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0}, - {0xFF, 0x77, 0xA0, 0x9A, 0x99, 0x81, 0xE9, 0x48, 0xEC, 0x51, 0xC9, 0x32, 0x5D, 0x14, 0xEC, 0x25} - }; - - aes_setkey(0x11, key2s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); - - __attribute__((aligned(4))) u8 keyData[AES_BLOCK_SIZE] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}, - decKey[sizeof(keyData)]; - - //Set keys 0x19..0x1F keyXs - aes_use_keyslot(0x11); - for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++) - { - aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0); - aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); - } -} - void kernel9Loader(Arm9Bin *arm9Section) { //Determine the kernel9loader version @@ -561,6 +537,21 @@ void kernel9Loader(Arm9Bin *arm9Section) if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary."); } + + //Set >=9.6 KeyXs + if(k9lVersion == 2) + { + __attribute__((aligned(4))) u8 keyData[AES_BLOCK_SIZE] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}, + decKey[sizeof(keyData)]; + + //Set keys 0x19..0x1F keyXs + aes_use_keyslot(0x11); + for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++) + { + aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0); + aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); + } + } } void computePinHash(u8 *outbuf, const u8 *inbuf) diff --git a/source/crypto.h b/source/crypto.h index ef9fc56..bbd5366 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -114,7 +114,6 @@ int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); void set6x7xKeys(void); bool decryptExeFs(Cxi *cxi); bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); -void setN3DS96Keys(void); void kernel9Loader(Arm9Bin *arm9Section); void computePinHash(u8 *outbuf, const u8 *inbuf); void backupAndRestoreShaHash(bool isRestore); diff --git a/source/firm.c b/source/firm.c index 66bcee0..70f8e58 100755 --- a/source/firm.c +++ b/source/firm.c @@ -117,6 +117,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo u8 *arm9Section = (u8 *)firm + firm->section[2].offset, *arm11Section1 = (u8 *)firm + firm->section[1].offset; + //On sighax cold boot, initialize TWL keys + if(!(CFG_SYSPROT9 & 2)) twlConsoleInfoInit(); + if(ISN3DS) { //Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader @@ -173,11 +176,8 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo } //11.3 FIRM patches - if(firmVersion >= (ISN3DS ? 0x2D : 0x5C)) - { - //Stub svc 0x59 + if(firmVersion >= (ISN3DS ? 0x2D : 0x5C)) //Stub svc 0x59 ret += stubSvcRestrictGpuDma(arm11Section1, arm11SvcTable, baseK11VA); - } ret += implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space, isSafeMode); diff --git a/source/main.c b/source/main.c index 5ee5aa4..2694b09 100644 --- a/source/main.c +++ b/source/main.c @@ -98,12 +98,10 @@ void main(void) //Save old options and begin saving the new boot configuration configTemp = (configData.config & 0xFFFFFF00) | ((u32)ISA9LH << 6); - twlConsoleInfoInit(); - setN3DS96Keys(); - //If it's a MCU reboot, try to force boot options if(ISA9LH && CFG_BOOTENV && needConfig != CREATE_CONFIGURATION) { + //Always force a SysNAND boot when quitting AGB_FIRM if(CFG_BOOTENV == 7) {