From 4e7ac41a6c4f93740b75b3b5fada31aeed0be90f Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 18 Sep 2016 23:50:44 +0200 Subject: [PATCH] Add NUS-encrypted FIRM support (thanks to CakesFW) --- source/crypto.c | 27 +++++++++++++++++++++++---- source/crypto.h | 2 ++ source/firm.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- source/fs.c | 2 +- 4 files changed, 67 insertions(+), 13 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index 4ff21a3..bfdc0e9 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -23,6 +23,7 @@ /* * Crypto libs from http://github.com/b1l1s/ctr * ARM9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 +* decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c */ #include "crypto.h" @@ -367,23 +368,42 @@ void setRSAMod0DerivedKeys(void) } } -//Decrypt a FIRM ExeFS void decryptExeFs(u8 *inbuf) { u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200; u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200; - u8 ncchCTR[0x10] = {0}; + u8 __attribute__((aligned(4))) ncchCTR[0x10] = {0}; for(u32 i = 0; i < 8; i++) ncchCTR[7 - i] = *(inbuf + 0x108 + i); ncchCTR[8] = 2; aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_setiv(ncchCTR, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(0x2C); aes(inbuf - 0x200, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); } +void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize) +{ + const u8 keyY0x3D[0x10] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C}; + u8 __attribute__((aligned(4))) cetkIv[0x10] = {0}; + u8 __attribute__((aligned(4))) titleKey[0x10]; + memcpy(titleKey, inbuf + 0x1BF, 0x10); + memcpy(cetkIv, inbuf + 0x1DC, 8); + + aes_setkey(0x3D, keyY0x3D, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_use_keyslot(0x3D); + aes(titleKey, titleKey, 1, cetkIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + + u8 ncchIv[0x10] = {0}; + + aes_setkey(0x16, titleKey, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_use_keyslot(0x16); + aes(outbuf, outbuf, ncchSize / AES_BLOCK_SIZE, ncchIv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + + decryptExeFs(outbuf); +} + //ARM9Loader replacement void arm9Loader(u8 *arm9Section) { @@ -440,7 +460,6 @@ void arm9Loader(u8 *arm9Section) } aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_setiv(arm9BinCTR, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(arm9BinSlot); //Decrypt arm9bin diff --git a/source/crypto.h b/source/crypto.h index ac832e5..1ed87c2 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -23,6 +23,7 @@ /* * Crypto libs from http://github.com/b1l1s/ctr * ARM9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 +* decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c */ #pragma once @@ -108,5 +109,6 @@ void ctrNandInit(void); u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); void setRSAMod0DerivedKeys(void); void decryptExeFs(u8 *inbuf); +void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize); void arm9Loader(u8 *arm9Section); void computePinHash(u8 *out, u8 *in); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 9c30231..9ce78ad 100755 --- a/source/firm.c +++ b/source/firm.c @@ -271,11 +271,17 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) { section = firm->section; - const char *firmwareFiles[4] = { + const char *firmwareFiles[] = { "/luma/firmware.bin", "/luma/firmware_twl.bin", "/luma/firmware_agb.bin", "/luma/firmware_safe.bin" + }, + *cetkFiles[] = { + "/luma/cetk", + "/luma/cetk_twl", + "/luma/cetk_agb", + "/luma/cetk_safe" }; //Load FIRM from CTRNAND @@ -300,11 +306,26 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) else if(firmVersion < 0x25) loadFromSd = true; } - //Check that the SD FIRM is right for the console from the ARM9 section address - if(fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000) && - ((section[3].offset ? section[3].address : section[2].address) == (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))) + u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000); + + if(firmSize > 0) + { + if(memcmp(firm, "FIRM", 4) != 0) + { + u8 cetk[0xA50]; + + if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk))) + decryptNusFirm(cetk, (u8 *)firm, firmSize); + } + + //Check that the SD FIRM is right for the console from the ARM9 section address + if((section[3].offset ? section[3].address : section[2].address) != (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800)) + error("The firmware.bin in /luma is not valid for your\nconsole, or corrupted"); + firmVersion = 0xFFFFFFFF; - else + } + + if(firmVersion != 0xFFFFFFFF) { if(loadFromSd) error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot"); decryptExeFs((u8 *)firm); @@ -336,10 +357,22 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD else if(firmVersion < 0x25) { - if(!fileRead(firm, "/luma/firmware.bin", 0x400000) || section[2].address != (u8 *)0x8006800) - error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot"); + u32 firmSize = fileRead(firm, "/luma/firmware.bin", 0x400000); - firmVersion = 0xFFFFFFFF; + if(firmSize > 0) + { + if(memcmp(firm, "FIRM", 4) != 0) + { + u8 cetk[0xA50]; + + if(fileRead(cetk, "/luma/cetk", sizeof(cetk))) + decryptNusFirm(cetk, (u8 *)firm, firmSize); + } + + if(section[2].address != (u8 *)0x8006800) firmVersion = 0xFFFFFFFF; + } + + if(firmVersion != 0xFFFFFFFF) error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot"); } } diff --git a/source/fs.c b/source/fs.c index 80b9a05..b0ebb96 100644 --- a/source/fs.c +++ b/source/fs.c @@ -149,7 +149,7 @@ void loadPayload(u32 pressed) u32 firmRead(void *dest, u32 firmType) { - const char *firmFolders[4][2] = {{ "00000002", "20000002" }, + const char *firmFolders[][2] = {{ "00000002", "20000002" }, { "00000102", "20000102" }, { "00000202", "20000202" }, { "00000003", "20000003" }};