Add NUS-encrypted FIRM support (thanks to CakesFW)

This commit is contained in:
Aurora 2016-09-18 23:50:44 +02:00
parent 92f3a736a7
commit 4e7ac41a6c
4 changed files with 67 additions and 13 deletions

View File

@ -23,6 +23,7 @@
/* /*
* Crypto libs from http://github.com/b1l1s/ctr * Crypto libs from http://github.com/b1l1s/ctr
* ARM9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 * 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" #include "crypto.h"
@ -367,23 +368,42 @@ void setRSAMod0DerivedKeys(void)
} }
} }
//Decrypt a FIRM ExeFS
void decryptExeFs(u8 *inbuf) void decryptExeFs(u8 *inbuf)
{ {
u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200; u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 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++) for(u32 i = 0; i < 8; i++)
ncchCTR[7 - i] = *(inbuf + 0x108 + i); ncchCTR[7 - i] = *(inbuf + 0x108 + i);
ncchCTR[8] = 2; ncchCTR[8] = 2;
aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); 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_use_keyslot(0x2C);
aes(inbuf - 0x200, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 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 //ARM9Loader replacement
void arm9Loader(u8 *arm9Section) 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_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setiv(arm9BinCTR, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(arm9BinSlot); aes_use_keyslot(arm9BinSlot);
//Decrypt arm9bin //Decrypt arm9bin

View File

@ -23,6 +23,7 @@
/* /*
* Crypto libs from http://github.com/b1l1s/ctr * Crypto libs from http://github.com/b1l1s/ctr
* ARM9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 * 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 #pragma once
@ -108,5 +109,6 @@ void ctrNandInit(void);
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
void setRSAMod0DerivedKeys(void); void setRSAMod0DerivedKeys(void);
void decryptExeFs(u8 *inbuf); void decryptExeFs(u8 *inbuf);
void decryptNusFirm(u8 *inbuf, u8 *outbuf, u32 ncchSize);
void arm9Loader(u8 *arm9Section); void arm9Loader(u8 *arm9Section);
void computePinHash(u8 *out, u8 *in); void computePinHash(u8 *out, u8 *in);

View File

@ -271,11 +271,17 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
{ {
section = firm->section; section = firm->section;
const char *firmwareFiles[4] = { const char *firmwareFiles[] = {
"/luma/firmware.bin", "/luma/firmware.bin",
"/luma/firmware_twl.bin", "/luma/firmware_twl.bin",
"/luma/firmware_agb.bin", "/luma/firmware_agb.bin",
"/luma/firmware_safe.bin" "/luma/firmware_safe.bin"
},
*cetkFiles[] = {
"/luma/cetk",
"/luma/cetk_twl",
"/luma/cetk_agb",
"/luma/cetk_safe"
}; };
//Load FIRM from CTRNAND //Load FIRM from CTRNAND
@ -300,11 +306,26 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
else if(firmVersion < 0x25) loadFromSd = true; else if(firmVersion < 0x25) loadFromSd = true;
} }
//Check that the SD FIRM is right for the console from the ARM9 section address u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000);
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))) 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; 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"); if(loadFromSd) error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot");
decryptExeFs((u8 *)firm); 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 //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD
else if(firmVersion < 0x25) else if(firmVersion < 0x25)
{ {
if(!fileRead(firm, "/luma/firmware.bin", 0x400000) || section[2].address != (u8 *)0x8006800) u32 firmSize = fileRead(firm, "/luma/firmware.bin", 0x400000);
error("An old unsupported FIRM has been detected.\nCopy a valid firmware.bin in /luma to boot");
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");
} }
} }

View File

@ -149,7 +149,7 @@ void loadPayload(u32 pressed)
u32 firmRead(void *dest, u32 firmType) u32 firmRead(void *dest, u32 firmType)
{ {
const char *firmFolders[4][2] = {{ "00000002", "20000002" }, const char *firmFolders[][2] = {{ "00000002", "20000002" },
{ "00000102", "20000102" }, { "00000102", "20000102" },
{ "00000202", "20000202" }, { "00000202", "20000202" },
{ "00000003", "20000003" }}; { "00000003", "20000003" }};