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
|
* 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
|
||||||
|
@ -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);
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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" }};
|
||||||
|
Reference in New Issue
Block a user