11 Commits

14 changed files with 276 additions and 48 deletions

View File

@ -9,6 +9,7 @@ include $(DEVKITARM)/base_rules
################################################################################
IPL_LOAD_ADDR := 0x40008000
MAGIC = 0x4B434F4C #"LOCK"
include ./Versions.inc
################################################################################
@ -37,8 +38,8 @@ FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
################################################################################
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX)
CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) -DLP_MAGIC=$(MAGIC)
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) -DLP_RESERVED=$(LPVERSION_RSVD)
CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
#CUSTOMDEFINES += -DDEBUG
@ -51,7 +52,7 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
LDRDIR := $(wildcard loader)

View File

@ -1,4 +1,5 @@
# LP Version.
LPVERSION_MAJOR := 1
LPVERSION_MINOR := 9
LPVERSION_BUGFX := 4
LPVERSION_BUGFX := 5
LPVERSION_RSVD := 0

View File

@ -18,6 +18,8 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#include <assert.h>
#define NULL ((void *)0)
#define ALWAYS_INLINE inline __attribute__((always_inline))
@ -105,6 +107,16 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
};
} boot_cfg_t;
static_assert(sizeof(boot_cfg_t) == 0x84, "Boot CFG size is wrong!");
typedef struct __attribute__((__packed__)) _ipl_ver_meta_t
{
u32 magic;
u32 version;
u16 rsvd0;
u16 rsvd1;
} ipl_ver_meta_t;
typedef struct __attribute__((__packed__)) _reloc_meta_t
{
u32 start;

View File

@ -7,7 +7,7 @@ include $(DEVKITARM)/base_rules
################################################################################
LDR_LOAD_ADDR := 0x40007000
IPL_MAGIC := 0x43544349 #"ICTC"
MAGIC := 0x4B434F4C #"LOCK"
include ../Versions.inc
################################################################################
@ -26,8 +26,8 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
################################################################################
CUSTOMDEFINES := -DBL_MAGIC=$(IPL_MAGIC)
CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BLVERSION_RSVD)
CUSTOMDEFINES := -DLP_MAGIC=$(MAGIC)
CUSTOMDEFINES += -DLP_VER_MJ=$(LPVERSION_MAJOR) -DLP_VER_MN=$(LPVERSION_MINOR) -DLP_VER_BF=$(LPVERSION_BUGFX) -DLP_RESERVED=$(LPVERSION_RSVD)
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
WARNINGS := -Wall -Wno-array-bounds -Wno-stringop-overflow

View File

@ -6,6 +6,7 @@ SECTIONS {
.text : {
*(.text._start);
KEEP(*(._boot_cfg));
KEEP(*(._ipl_version));
*(.text*);
}
.data : {

View File

@ -30,6 +30,12 @@
#define IPL_PATCHED_RELOC_SZ 0x94
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = LP_MAGIC,
.version = (LP_VER_MJ + '0') | ((LP_VER_MN + '0') << 8) | ((LP_VER_BF + '0') << 16),
.rsvd0 = 0,
.rsvd1 = 0
};
void loader_main()
{

99
source/frontend/gui.c Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../gfx/gfx.h"
#include <mem/heap.h>
#include <rtc/max77620-rtc.h>
#include <storage/nx_sd.h>
#include <utils/util.h>
#include <string.h>
int save_fb_to_bmp()
{
// Disallow screenshots if less than 2s passed.
static u32 timer = 0;
if (get_tmr_ms() < timer)
return 1;
const u32 file_size = 0x384000 + 0x36;
u8 *bitmap = malloc(file_size);
u32 *fb = malloc(0x384000);
u32 *fb_ptr = gfx_ctxt.fb;
// Reconstruct FB for bottom-top, portrait bmp.
for (int y = 1279; y > -1; y--)
{
for (u32 x = 0; x < 720; x++)
fb[y * 720 + x] = *fb_ptr++;
}
memcpy(bitmap + 0x36, fb, 0x384000);
typedef struct _bmp_t
{
u16 magic;
u32 size;
u32 rsvd;
u32 data_off;
u32 hdr_size;
u32 width;
u32 height;
u16 planes;
u16 pxl_bits;
u32 comp;
u32 img_size;
u32 res_h;
u32 res_v;
u64 rsvd2;
} __attribute__((packed)) bmp_t;
bmp_t *bmp = (bmp_t *)bitmap;
bmp->magic = 0x4D42;
bmp->size = file_size;
bmp->rsvd = 0;
bmp->data_off = 0x36;
bmp->hdr_size = 40;
bmp->width = 720;
bmp->height = 1280;
bmp->planes = 1;
bmp->pxl_bits = 32;
bmp->comp = 0;
bmp->img_size = 0x384000;
bmp->res_h = 2834;
bmp->res_v = 2834;
bmp->rsvd2 = 0;
sd_mount();
f_mkdir("sd:/switch");
char path[0x80] = "sd:/switch/lockpick_rcm.bmp";
// Save screenshot and log.
int res = sd_save_to_file(bitmap, file_size, path);
// sd_unmount();
free(bitmap);
free(fb);
// Set timer to 2s.
timer = get_tmr_ms() + 2000;
return res;
}

17
source/frontend/gui.h Normal file
View File

@ -0,0 +1,17 @@
/*
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
int save_fb_to_bmp();

View File

@ -224,7 +224,7 @@ void gfx_putc(char c)
cbuf++;
}
gfx_con.x += 16;
if (gfx_con.x >= gfx_ctxt.width - 16)
if (gfx_con.x > gfx_ctxt.width - 16)
{
gfx_con.x = 0;
gfx_con.y += 16;
@ -233,7 +233,7 @@ void gfx_putc(char c)
else if (c == '\n')
{
gfx_con.x = 0;
gfx_con.y +=16;
gfx_con.y += 16;
if (gfx_con.y > gfx_ctxt.height - 16)
gfx_con.y = 0;
}
@ -259,7 +259,7 @@ void gfx_putc(char c)
fb += gfx_ctxt.stride - 8;
}
gfx_con.x += 8;
if (gfx_con.x >= gfx_ctxt.width - 8)
if (gfx_con.x > gfx_ctxt.width - 8)
{
gfx_con.x = 0;
gfx_con.y += 8;

View File

@ -32,6 +32,7 @@
#define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_1210 11
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1210 //!TODO: Update on mkey changes.
#define KB_FIRMWARE_VERSION_1300 12
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1300 //!TODO: Update on mkey changes.
#endif

View File

@ -36,6 +36,7 @@ static const u8 master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION
{0x1A, 0xEC, 0x11, 0x82, 0x2B, 0x32, 0x38, 0x7A, 0x2B, 0xED, 0xBA, 0x01, 0x47, 0x7E, 0x3B, 0x67}, //9.0.0
{0x30, 0x3F, 0x02, 0x7E, 0xD8, 0x38, 0xEC, 0xD7, 0x93, 0x25, 0x34, 0xB5, 0x30, 0xEB, 0xCA, 0x7A}, //9.1.0
{0x84, 0x67, 0xB6, 0x7F, 0x13, 0x11, 0xAE, 0xE6, 0x58, 0x9B, 0x19, 0xAF, 0x13, 0x6C, 0x80, 0x7A}, //12.1.0
{0x68, 0x3B, 0xCA, 0x54, 0xB8, 0x6F, 0x92, 0x48, 0xC3, 0x05, 0x76, 0x87, 0x88, 0x70, 0x79, 0x23}, //13.0.0
};
//!TODO: Update on mkey changes.
@ -52,6 +53,7 @@ static const u8 master_key_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] __attribut
{0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80}, /* Master key 08 encrypted with Master key 09. */
{0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A}, /* Master key 09 encrypted with Master key 0A. */
{0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98}, /* Master key 0A encrypted with Master key 0B. */
{0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06}, /* Master key 0B encrypted with Master key 0C. */
};
//!TODO: Update on mkey changes.
@ -68,6 +70,7 @@ static const u8 master_key_vectors_dev[KB_FIRMWARE_VERSION_MAX + 1][0x10] __attr
{0x43, 0x3D, 0xC5, 0x3B, 0xEF, 0x91, 0x02, 0x21, 0x61, 0x54, 0x63, 0x8A, 0x35, 0xE7, 0xCA, 0xEE}, /* Master key 08 encrypted with Master key 09. */
{0x6C, 0x2E, 0xCD, 0xB3, 0x34, 0x61, 0x77, 0xF5, 0xF9, 0xB1, 0xDD, 0x61, 0x98, 0x19, 0x3E, 0xD4}, /* Master key 09 encrypted with Master key 0A. */
{0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C}, /* Master key 0A encrypted with Master key 0B. */
{0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15}, /* Master key 0B encrypted with Master key 0C. */
};
static const u8 mariko_key_vectors[][0x10] __attribute__((aligned(4))) = {
@ -127,6 +130,7 @@ static const u8 mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_
{0x86, 0x69, 0xF0, 0x09, 0x87, 0xC8, 0x05, 0xAE, 0xB5, 0x7B, 0x48, 0x74, 0xDE, 0x62, 0xA6, 0x13}, // 9.0.0.
{0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}, // 9.1.0.
{0xE5, 0x41, 0xAC, 0xEC, 0xD1, 0xA7, 0xD1, 0xAB, 0xED, 0x03, 0x77, 0xF1, 0x27, 0xCA, 0xF8, 0xF1}, // 12.1.0.
{0x52, 0x71, 0x9B, 0xDF, 0xA7, 0x8B, 0x61, 0xD8, 0xD5, 0x85, 0x11, 0xE4, 0x8E, 0x4F, 0x74, 0xC6}, // 13.0.0.
}; //!TODO: Update on mkey changes.
static const u8 mariko_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600 + 1][0x10] __attribute__((aligned(4))) = {
{0x32, 0xC0, 0x97, 0x6B, 0x63, 0x6D, 0x44, 0x64, 0xF2, 0x3A, 0xA5, 0xC0, 0xDE, 0x46, 0xCC, 0xE9}, // 6.0.0.
@ -136,6 +140,7 @@ static const u8 mariko_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMW
{0x82, 0x72, 0x91, 0x65, 0x40, 0x3B, 0x9D, 0x66, 0x60, 0xD0, 0x1B, 0x3D, 0x4D, 0xA5, 0x70, 0xE1}, // 9.0.0.
{0xF9, 0x37, 0xCF, 0x9A, 0xBD, 0x86, 0xBB, 0xA9, 0x9C, 0x9E, 0x03, 0xC4, 0xFC, 0xBC, 0x3B, 0xCE}, // 9.1.0.
{0x75, 0x2D, 0x2E, 0xF3, 0x2F, 0x3F, 0xFE, 0x65, 0xF4, 0xA9, 0x83, 0xB4, 0xED, 0x42, 0x63, 0xBA}, // 12.1.0.
{0x4D, 0x5A, 0xB2, 0xC9, 0xE9, 0xE4, 0x4E, 0xA4, 0xD3, 0xBF, 0x94, 0x12, 0x36, 0x30, 0xD0, 0x7F}, // 13.0.0.
}; //!TODO: Update on mkey changes.
static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = {
@ -148,6 +153,7 @@ static const u8 device_master_key_source_sources[KB_FIRMWARE_VERSION_MAX - KB_FI
{0x4A, 0xC3, 0x4E, 0x14, 0x8B, 0x96, 0x4A, 0xD5, 0xD4, 0x99, 0x73, 0xC4, 0x45, 0xAB, 0x8B, 0x49}, /* 9.0.0 Device Master Key Source Source. */
{0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94}, /* 9.1.0 Device Master Key Source Source. */
{0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6}, /* 12.1.0 Device Master Key Source Source. */
{0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F}, /* 13.0.0 Device Master Key Source Source. */
}; //!TODO: Update on mkey changes.
// from ES
@ -174,6 +180,7 @@ static const u8 device_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_
{0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED}, /* 9.0.0 Device Master Kek Source. */
{0xCE, 0xFE, 0x41, 0x0F, 0x46, 0x9A, 0x30, 0xD6, 0xF2, 0xE9, 0x0C, 0x6B, 0xB7, 0x15, 0x91, 0x36}, /* 9.1.0 Device Master Kek Source. */
{0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3}, /* 12.1.0 Device Master Kek Source. */
{0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8}, /* 13.0.0 Device Master Kek Source. */
}; //!TODO: Update on mkey changes.
static const u8 device_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] __attribute__((aligned(4))) = {
@ -186,6 +193,7 @@ static const u8 device_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMW
{0x61, 0x6A, 0x88, 0x21, 0xA3, 0x52, 0xB0, 0x19, 0x16, 0x25, 0xA4, 0xE3, 0x4C, 0x54, 0x02, 0x0F}, /* 9.0.0 Device Master Kek Source. */
{0x9D, 0xB1, 0xAE, 0xCB, 0xF6, 0xF6, 0xE3, 0xFE, 0xAB, 0x6F, 0xCB, 0xAF, 0x38, 0x03, 0xFC, 0x7B}, /* 9.1.0 Device Master Kek Source. */
{0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB}, /* 12.1.0 Device Master Kek Source. */
{0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F}, /* 13.0.0 Device Master Kek Source. */
}; //!TODO: Update on mkey changes.
// from SPL

View File

@ -20,6 +20,7 @@
#include "../config.h"
#include <display/di.h>
#include "../frontend/gui.h"
#include <gfx_utils.h>
#include "../gfx/tui.h"
#include "../hos/hos.h"
@ -81,9 +82,13 @@ static bool _test_key_pair(const void *E, const void *D, const void *N);
static void _derive_master_key_mariko(key_derivation_ctx_t *keys, bool is_dev) {
// Relies on the SBK being properly set in slot 14
se_aes_crypt_block_ecb(14, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
// Relies on the Mariko KEK being properly set in slot 12
se_aes_unwrap_key(8, 12, is_dev ? &mariko_master_kek_sources_dev[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600] : &mariko_master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_600]);
se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source);
// Derive all master keys based on Mariko KEK
for (u32 i = KB_FIRMWARE_VERSION_600; i < ARRAY_SIZE(mariko_master_kek_sources) + KB_FIRMWARE_VERSION_600; i++) {
// Relies on the Mariko KEK being properly set in slot 12
se_aes_crypt_block_ecb(12, DECRYPT, keys->master_kek[i], is_dev ? &mariko_master_kek_sources_dev[i - KB_FIRMWARE_VERSION_600] : &mariko_master_kek_sources[i - KB_FIRMWARE_VERSION_600]); // mkek = unwrap(mariko_kek, mariko_kek_source)
se_aes_key_set(8, keys->master_kek[i], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mkeys)
se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[i], master_key_source);
}
}
static int _run_ams_keygen(key_derivation_ctx_t *keys) {
@ -91,13 +96,17 @@ static int _run_ams_keygen(key_derivation_ctx_t *keys) {
tsec_ctxt.fw = tsec_keygen;
tsec_ctxt.size = sizeof(tsec_keygen);
tsec_ctxt.type = TSEC_FW_TYPE_NEW;
int res = tsec_query(keys->temp_key, &tsec_ctxt);
if (res) {
EPRINTFARGS("ERROR %d running keygen.\n", res);
u32 retries = 0;
while (tsec_query(keys->temp_key, &tsec_ctxt) < 0) {
retries++;
if (retries > 15) {
EPRINTF("Failed to run keygen.");
return -1;
}
}
return res;
return 0;
}
static void _derive_master_keys_from_latest_key(key_derivation_ctx_t *keys, bool is_dev) {
@ -127,8 +136,8 @@ static void _derive_master_keys_from_latest_key(key_derivation_ctx_t *keys, bool
static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
u8 *keyblob_block = (u8 *)calloc(KB_FIRMWARE_VERSION_600 + 1, NX_EMMC_BLOCKSIZE);
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0};
bool have_keyblobs = true;
if (FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF) {
u8 *aes_keys = (u8 *)calloc(0x1000, 1);
@ -142,10 +151,16 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
keys->sbk[3] = FUSE(FUSE_PRIVATE_KEY3);
}
if (!emummc_storage_read(KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) {
if (!emmc_storage.initialized) {
have_keyblobs = false;
} else if (!emummc_storage_read(KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) {
EPRINTF("Unable to read keyblobs.");
have_keyblobs = false;
} else {
have_keyblobs = true;
}
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) {
minerva_periodic_training();
se_aes_crypt_block_ecb(12, DECRYPT, keys->keyblob_key[i], keyblob_key_sources[i]); // temp = unwrap(kbks, tsec)
@ -157,6 +172,10 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
se_aes_crypt_block_ecb(7, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
}
if (!have_keyblobs) {
continue;
}
// verify keyblob is not corrupt
se_aes_key_set(10, keys->keyblob_mac_key[i], sizeof(keys->keyblob_mac_key[i]));
se_aes_cmac(10, keyblob_mac, sizeof(keyblob_mac), current_keyblob->iv, sizeof(current_keyblob->iv) + sizeof(keyblob_t));
@ -226,7 +245,7 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) {
}
}
static void _derive_master_key_per_generation_keys(key_derivation_ctx_t *keys) {
static void _derive_per_generation_keys(key_derivation_ctx_t *keys) {
for (u32 i = 0; i < KB_FIRMWARE_VERSION_MAX + 1; i++) {
if (!_key_exists(keys->master_key[i]))
continue;
@ -543,7 +562,7 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
}
u32 pos = 0;
u32 zeros[4] = {0};
u32 zeros[AES_128_KEY_SIZE / 4] = {0};
u8 *data = malloc(4 * AES_128_KEY_SIZE);
char *text_buffer = calloc(1, 0x100 * count);
@ -552,6 +571,7 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
if (ks < ARRAY_SIZE(mariko_key_vectors)) {
se_aes_crypt_block_ecb(ks, DECRYPT, &data[0], mariko_key_vectors[ks]);
if (_key_exists(data)) {
EPRINTFARGS("Failed to validate keyslot %d.", ks);
continue;
}
}
@ -569,6 +589,7 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
// Skip saving key if two results are the same indicating unsuccessful overwrite or empty slot
if (memcmp(&data[0], &data[SE_KEY_128_SIZE], AES_128_KEY_SIZE) == 0) {
EPRINTFARGS("Failed to overwrite keyslot %d.", ks);
continue;
}
@ -583,7 +604,7 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
free(data);
if (strlen(text_buffer) == 0) {
EPRINTF("Failed to dump partial keys.");
EPRINTFARGS("Failed to dump partial keys %d-%d.", start, start + count - 1);
return;
}
@ -625,7 +646,7 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
SAVE_KEY(aes_key_generation_source);
SAVE_KEY(bis_kek_source);
SAVE_KEY_FAMILY_VAR(bis_key, keys->bis_key, 0);
SAVE_KEY_FAMILY(bis_key_sources, 0);
SAVE_KEY_FAMILY_VAR(bis_key_source, bis_key_sources, 0);
SAVE_KEY_VAR(device_key, keys->device_key);
SAVE_KEY_VAR(device_key_4x, keys->device_key_4x);
SAVE_KEY_VAR(eticket_rsa_kek, keys->eticket_rsa_kek);
@ -751,10 +772,14 @@ static void _derive_keys() {
f_unlink("sd:/switch/partialaes.keys");
}
minerva_periodic_training();
if (h_cfg.t210b01) {
_save_mariko_partial_keys(0, 12, false);
}
minerva_periodic_training();
if (!_check_keyslot_access()) {
EPRINTF("Unable to set crypto keyslots!\nTry launching payload differently\n or flash Spacecraft-NX if using a modchip.");
return;
@ -764,13 +789,15 @@ static void _derive_keys() {
if (emummc_storage_init_mmc()) {
EPRINTF("Unable to init MMC.");
return;
} else {
TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]);
}
TPRINTFARGS("%kMMC init... ", colors[(color_idx++) % 6]);
if (!emummc_storage_set_mmc_partition(EMMC_BOOT0)) {
minerva_periodic_training();
if (emmc_storage.initialized && !emummc_storage_set_mmc_partition(EMMC_BOOT0)) {
EPRINTF("Unable to set partition.");
return;
emummc_storage_end();
}
bool is_dev = fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV;
@ -781,11 +808,11 @@ static void _derive_keys() {
// Master key derivation
if (h_cfg.t210b01) {
_derive_master_key_mariko(keys, is_dev);
minerva_periodic_training();
_derive_master_keys_from_latest_key(keys, is_dev);
} else {
int res = _run_ams_keygen(keys);
if (res) {
EPRINTF("Unable to run keygen.");
return;
}
@ -797,7 +824,9 @@ static void _derive_keys() {
free(aes_keys);
_derive_master_keys_from_latest_key(&prod_keys, false);
minerva_periodic_training();
_derive_master_keys_from_latest_key(&dev_keys, true);
minerva_periodic_training();
_derive_keyblob_keys(keys);
}
@ -807,17 +836,24 @@ static void _derive_keys() {
TPRINTFARGS("%kBIS keys... ", colors[(color_idx++) % 6]);
minerva_periodic_training();
_derive_misc_keys(keys, is_dev);
minerva_periodic_training();
_derive_non_unique_keys(&prod_keys, is_dev);
minerva_periodic_training();
_derive_non_unique_keys(&dev_keys, is_dev);
_derive_master_key_per_generation_keys(&prod_keys);
_derive_master_key_per_generation_keys(&dev_keys);
minerva_periodic_training();
_derive_per_generation_keys(&prod_keys);
minerva_periodic_training();
_derive_per_generation_keys(&dev_keys);
titlekey_buffer_t *titlekey_buffer = (titlekey_buffer_t *)TITLEKEY_BUF_ADR;
// BIS key for SYSTEM partition
if (_key_exists(keys->bis_key[2])) {
// Requires BIS key for SYSTEM partition
if (!emmc_storage.initialized) {
EPRINTF("eMMC not initialized.\nSkipping SD seed and titlekeys.");
} else if (_key_exists(keys->bis_key[2])) {
_derive_emmc_keys(keys, titlekey_buffer);
} else {
EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys.");
@ -825,12 +861,21 @@ static void _derive_keys() {
end_time = get_tmr_us();
gfx_printf("%kLockpick totally done in %d us\n", colors[(color_idx++) % 6], end_time - start_whole_operation_time);
_save_keys_to_sd(&prod_keys, titlekey_buffer, false);
_key_count = 0;
_save_keys_to_sd(&dev_keys, NULL, true);
if (h_cfg.t210b01) {
// On Mariko, save only relevant key set
_save_keys_to_sd(keys, titlekey_buffer, is_dev);
} else {
// On Erista, save both prod and dev key sets
_save_keys_to_sd(&prod_keys, titlekey_buffer, false);
_key_count = 0;
_save_keys_to_sd(&dev_keys, NULL, true);
}
}
void dump_keys() {
minerva_change_freq(FREQ_1600);
display_backlight_brightness(h_cfg.backlight, 1000);
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
@ -850,9 +895,23 @@ void dump_keys() {
// Ignore whether emummc is enabled.
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
emu_cfg.enabled = !h_cfg.emummc_force_disable;
emummc_storage_end(&emmc_storage);
gfx_printf("\n%kPress a button to return to the menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]);
btn_wait();
if (emmc_storage.initialized) {
emummc_storage_end();
}
minerva_change_freq(FREQ_800);
gfx_printf("\n%kPress VOL+ to save a screenshot\n or another button to return to the menu.\n\n", colors[(color_idx++) % 6]);
u8 btn = btn_wait();
if (btn == BTN_VOL_UP) {
int res = save_fb_to_bmp();
if (!res) {
gfx_printf("%kScreenshot sd:/switch/lockpick_rcm.bmp saved.", colors[(color_idx++) % 6]);
} else {
EPRINTF("Screenshot failed.");
}
gfx_printf("\n%kPress a button to return to the menu.", colors[(color_idx++) % 6]);
btn_wait();
}
gfx_clear_grey(0x1B);
}

View File

@ -6,6 +6,7 @@ SECTIONS {
.text : {
*(.text._start);
KEEP(*(._boot_cfg));
KEEP(*(._ipl_version));
*(.text._irq_setup);
*(.text*);
}

View File

@ -46,6 +46,12 @@
hekate_config h_cfg;
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = LP_MAGIC,
.version = (LP_VER_MJ + '0') | ((LP_VER_MN + '0') << 8) | ((LP_VER_BF + '0') << 16),
.rsvd0 = 0,
.rsvd1 = 0
};
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
@ -276,6 +282,12 @@ out:
btn_wait();
}
void launch_hekate()
{
if (!f_stat("bootloader/update.bin", NULL))
launch_payload("bootloader/update.bin", false);
}
void dump_sysnand()
{
h_cfg.emummc_force_disable = true;
@ -303,10 +315,11 @@ ment_t ment_top[] = {
MDEF_HANDLER("Dump from EmuNAND", dump_emunand, COLOR_ORANGE),
MDEF_CAPTION("---------------", COLOR_YELLOW),
MDEF_HANDLER("Payloads...", launch_tools, COLOR_GREEN),
MDEF_CAPTION("---------------", COLOR_BLUE),
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex, COLOR_VIOLET),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex, COLOR_RED),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex, COLOR_ORANGE),
MDEF_HANDLER("Reboot to Hekate", launch_hekate, COLOR_BLUE),
MDEF_CAPTION("---------------", COLOR_VIOLET),
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex, COLOR_RED),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex, COLOR_ORANGE),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex, COLOR_YELLOW),
MDEF_END()
};
@ -339,7 +352,6 @@ void ipl_main()
// Train DRAM and switch to max frequency.
if (minerva_init()) //!TODO: Add Tegra210B01 support to minerva.
h_cfg.errors |= ERR_LIBSYS_MTC;
minerva_change_freq(FREQ_1600);
display_init();
@ -370,16 +382,26 @@ void ipl_main()
// Grey out reboot to RCM option if on Mariko or patched console.
if (h_cfg.t210b01 || h_cfg.rcm_patched)
{
ment_top[6].type = MENT_CAPTION;
ment_top[6].color = 0xFF555555;
ment_top[6].handler = NULL;
ment_top[7].type = MENT_CAPTION;
ment_top[7].color = 0xFF555555;
ment_top[7].handler = NULL;
}
if (h_cfg.rcm_patched)
{
ment_top[6].data = &STATE_REBOOT_FULL;
ment_top[7].data = &STATE_REBOOT_FULL;
}
// Grey out reboot to Hekate option if no update.bin found.
if (f_stat("bootloader/update.bin", NULL))
{
ment_top[4].type = MENT_CAPTION;
ment_top[4].color = 0xFF555555;
ment_top[4].handler = NULL;
}
minerva_change_freq(FREQ_800);
while (true)
tui_do_menu(&menu_top);