Add NUS-encrypted FIRM support (thanks to CakesFW)
This commit is contained in:
parent
92f3a736a7
commit
4e7ac41a6c
@ -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
|
||||
|
@ -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);
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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" }};
|
||||
|
Reference in New Issue
Block a user