Properly check for slot0x05 crypto & EmuNAND availability

This commit is contained in:
d0k3 2016-03-22 19:24:21 +01:00
parent 0b735edc49
commit 762dce04cd
6 changed files with 63 additions and 14 deletions

View File

@ -534,7 +534,7 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
"SYSNAND VIRTUAL", "EMUNAND VIRTUAL"
};
static const char* drvnum[] = {
"0", "1", "2", "3", "4", "5", "6", "S", "E"
"0:", "1:", "2:", "3:", "4:", "5:", "6:", "S:", "E:"
};
u32 n_entries = 0;
@ -542,11 +542,10 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
for (u32 pdrv = 0; (pdrv < MAX_FS+2) && (n_entries < MAX_ENTRIES); pdrv++) {
DirEntry* entry = &(contents->entry[n_entries]);
if ((pdrv < MAX_FS) && !fs_mounted[pdrv]) continue;
if ((pdrv == MAX_FS+0) && (!fs_mounted[1])) continue;
if ((pdrv == MAX_FS+1) && (!fs_mounted[4])) continue;
else if ((pdrv >= MAX_FS) && (!CheckVirtualPath(drvnum[pdrv]))) continue;
memset(entry->path, 0x00, 64);
snprintf(entry->path + 0, 4, "%s:", drvnum[pdrv]);
snprintf(entry->path + 4, 32, "[%s:] %s", drvnum[pdrv], drvname[pdrv]);
snprintf(entry->path + 0, 4, drvnum[pdrv]);
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]);
entry->name = entry->path + 4;
entry->size = GetTotalSpace(entry->path);
entry->type = T_ROOT;

View File

@ -2,10 +2,11 @@
#include "draw.h"
#include "hid.h"
#include "fs.h"
#include "platform.h"
#include "nand.h"
#include "virtual.h"
#define VERSION "0.1.9"
#define VERSION "0.2.0"
#define COLOR_TOP_BAR ((GetWritePermissions() == 0) ? COLOR_WHITE : (GetWritePermissions() == 1) ? COLOR_BRIGHTGREEN : (GetWritePermissions() == 2) ? COLOR_BRIGHTYELLOW : COLOR_RED)
#define COLOR_SIDE_BAR COLOR_DARKGREY
@ -151,6 +152,14 @@ u32 GodMode() {
InitNandCrypto();
InitNandFS();
if ((GetUnitPlatform() == PLATFORM_N3DS) && !CheckSlot0x05Crypto()) {
if (!ShowPrompt(true, "Warning: slot0x05 crypto fail\nslot0x05keyY.bin is either corrupt\nor does not exist. Continue?")) {
DeinitNandFS();
DeinitSDCardFS();
return exit_mode;
}
}
GetDirContents(current_dir, "");
clipboard->n_entries = 0;
while (true) { // this is the main loop

View File

@ -8,6 +8,12 @@
#define NAND_BUFFER ((u8*)0x21100000)
#define NAND_BUFFER_SIZE (0x100000) // must be multiple of 0x200
static u8 slot0x05KeyY[0x10] = { 0x00 }; // need to load this from file
static u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY file
0x98, 0x24, 0x27, 0x14, 0x22, 0xB0, 0x6B, 0xF2, 0x10, 0x96, 0x9C, 0x36, 0x42, 0x53, 0x7C, 0x86,
0x62, 0x22, 0x5C, 0xFD, 0x6F, 0xAE, 0x9B, 0x0A, 0x85, 0xA5, 0xCE, 0x21, 0xAA, 0xB6, 0xC8, 0x4D
};
static u8 nand_magic_n3ds[0x60] = { // NCSD NAND header N3DS magic
0x4E, 0x43, 0x53, 0x44, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x04, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00,
@ -73,19 +79,39 @@ bool InitNandCrypto(void)
use_aeskey(0x03);
// part #3: CTRNAND N3DS KEY
if (GetUnitPlatform() == PLATFORM_N3DS) {
u8 CtrNandKeyY[16];
if (FileGetData("0:/slot0x05KeyY.bin", CtrNandKeyY, 16, 0)) {
setup_aeskeyY(0x05, CtrNandKeyY);
if (FileGetData("0:/slot0x05KeyY.bin", slot0x05KeyY, 16, 0)) {
setup_aeskeyY(0x05, slot0x05KeyY);
use_aeskey(0x05);
}
}
return true;
}
bool CheckSlot0x05Crypto(void)
{
// step #1 - check the slot0x05KeyY SHA-256
u8 shasum[32];
sha_init(SHA256_MODE);
sha_update(slot0x05KeyY, 16);
sha_get(shasum);
if (memcmp(shasum, slot0x05KeyY_sha256, 32) == 0)
return true;
// step #2 - check actual CTRNAND magic
const u8 magic[8] = {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20};
const u32 sector = 0x05CAD7;
u8 buffer[0x200];
for (u32 nand = 0; nand < 2; nand++) {
ReadNandSectors(buffer, sector, 1, 0x05, nand);
if (memcmp(buffer, magic, 8) == 0)
return true;
}
// failed if we arrive here
return false;
}
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot)
{
u32 mode = (sector >= (0x0B100000 / 0x200)) ? AES_CNT_CTRNAND_MODE : AES_CNT_TWLNAND_MODE;
@ -184,5 +210,6 @@ bool InitEmuNandBase(void)
return true;
if (GetPartitionOffsetSector("0:") > getMMCDevice(0)->total_size)
emunand_base_sector = 0x000000; // keep unknown EmuNAND as RedNAND only if space is low
return false;
}

View File

@ -8,8 +8,9 @@
#define NAND_TYPE_NO3DS (1<<2)
bool InitNandCrypto(void);
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot);
bool CheckSlot0x05Crypto(void);
void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot);
int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, bool read_emunand);
int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, bool write_emunand);

View File

@ -35,6 +35,16 @@ u32 IsVirtualPath(const char* path) {
return 0;
}
bool CheckVirtualPath(const char* path) {
u32 vp_nand = IsVirtualPath(path);
if (vp_nand == VRT_SYSNAND) {
return true; // this is safe because we re-check for slot0x05 crypto
} else if (vp_nand == VRT_EMUNAND) {
return GetNandSizeSectors(true);
}
return false;
}
bool FindVirtualFile(VirtualFile* vfile, const char* path)
{
char* fname = strchr(path, '/');
@ -68,6 +78,8 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path)
memcpy(vfile, curr_template, sizeof(VirtualFile));
// process special flags
if ((vfile->keyslot == 0x05) && !CheckSlot0x05Crypto())
return false; // keyslot 0x05 not properly set up
if (vfile->flags & VFLAG_NAND_SIZE) {
if (on_emunand && (GetNandSizeSectors(false) != GetNandSizeSectors(true)))
return false; // EmuNAND is too small

View File

@ -22,6 +22,7 @@ typedef struct {
} __attribute__((packed)) VirtualFile;
u32 IsVirtualPath(const char* path);
bool CheckVirtualPath(const char* path);
bool FindVirtualFile(VirtualFile* vfile, const char* path);
int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count);
int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count);