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
* 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

View File

@ -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);

View File

@ -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;
}
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(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((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");
}
}

View File

@ -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" }};