diff --git a/.gitignore b/.gitignore
index 7592fed..dfb2a80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ research/*
loader/payload_00.h
loader/payload_01.h
tools/bin2c/bin2c
+keygen/tsec_keygen.h
tools/lz/lz77
diff --git a/Makefile b/Makefile
index 94d81f3..1fdc863 100644
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,12 @@ include ./Versions.inc
TARGET := Lockpick_RCM
BUILDDIR := build
OUTPUTDIR := output
-SOURCEDIR = source
+SOURCEDIR := source
BDKDIR := bdk
BDKINC := -I./$(BDKDIR)
+KEYGENDIR := keygen
+KEYGEN := tsec_keygen
+KEYGENH := tsec_keygen.h
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
@@ -100,6 +103,11 @@ $(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
@echo "Lockpick_RCM was built with the following flags:\nCFLAGS: "$(CFLAGS)"\nLDFLAGS: "$(LDFLAGS)
+$(OBJS): | $(KEYGENDIR)
+
+$(KEYGENDIR): $(TOOLS)
+ @cd $(KEYGENDIR) && ../$(TOOLSB2C)/bin2c $(KEYGEN) > $(KEYGENH)
+
$(BUILDDIR)/$(TARGET)/%.o: $(SOURCEDIR)/%.c
@mkdir -p "$(@D)"
@echo Building $@
diff --git a/README.md b/README.md
index fcdd5ef..8c8d4bd 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Usage
* It is highly recommended, but not required, to place Minerva on SD from the latest [Hekate](https://github.com/CTCaer/hekate/releases) for best performance, especially while dumping titlekeys - the file and path is `/bootloader/sys/libsys_minerva.bso`
* Launch Lockpick_RCM.bin using your favorite payload injector or chainloader
* Upon completion, keys will be saved to `/switch/prod.keys` and titlekeys to `/switch/title.keys` on SD
-* If the console has Firmware 7.x or higher, the `/sept/` folder from [Atmosphère](https://github.com/Atmosphere-NX/Atmosphere/releases) or [Kosmos](https://github.com/AtlasNX/Kosmos/releases) release zip must be present on SD or else only keyblob master key derivation is possible (ie. up to `master_key_05` only)
+* This release bundles the Falcon keygen from [Atmosphère-NX](https://github.com/Atmosphere-NX/Atmosphere)
Mariko-Specific Keys
=
diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c
index adf5ac2..c154062 100644
--- a/bdk/sec/tsec.c
+++ b/bdk/sec/tsec.c
@@ -66,8 +66,6 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
int res = 0;
u8 *fwbuf = NULL;
- u32 *pdir, *car, *fuse, *pmc, *flowctrl, *se, *mc, *iram, *evec;
- u32 *pkg11_magic_off;
bpmp_mmu_disable();
bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL);
@@ -125,61 +123,6 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
}
}
- if (kb == KB_TSEC_FW_EMU_COMPAT)
- {
- // Init SMMU translation for TSEC.
- pdir = smmu_init_for_tsec();
- smmu_init(0x4002B000);
- // Enable SMMU
- if (!smmu_is_used())
- smmu_enable();
-
- // Clock reset controller.
- car = page_alloc(1);
- memcpy(car, (void *)CLOCK_BASE, 0x1000);
- car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
- smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
-
- // Fuse driver.
- fuse = page_alloc(1);
- memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, 0x400);
- fuse[0x82C / 4] = 0;
- fuse[0x9E0 / 4] = (1 << (kb + 2)) - 1;
- fuse[0x9E4 / 4] = (1 << (kb + 2)) - 1;
- smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
-
- // Power management controller.
- pmc = page_alloc(1);
- smmu_map(pdir, RTC_BASE, (u32)pmc, 1, _READABLE | _NONSECURE);
-
- // Flow control.
- flowctrl = page_alloc(1);
- smmu_map(pdir, FLOW_CTLR_BASE, (u32)flowctrl, 1, _WRITABLE | _NONSECURE);
-
- // Security engine.
- se = page_alloc(1);
- memcpy(se, (void *)SE_BASE, 0x1000);
- smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
-
- // Memory controller.
- mc = page_alloc(1);
- memcpy(mc, (void *)MC_BASE, 0x1000);
- mc[MC_IRAM_BOM / 4] = 0;
- mc[MC_IRAM_TOM / 4] = 0x80000000;
- smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
-
- // IRAM
- iram = page_alloc(0x30);
- memcpy(iram, tsec_ctxt->pkg1, 0x30000);
- // PKG1.1 magic offset.
- pkg11_magic_off = (u32 *)(iram + (0x7000 / 4));
- smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
-
- // Exception vectors
- evec = page_alloc(1);
- smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
- }
-
//Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0;
@@ -187,91 +130,27 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
TSEC(TSEC_BOOTVEC) = 0;
TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU;
- if (kb == KB_TSEC_FW_EMU_COMPAT)
+ if (!_tsec_dma_wait_idle())
{
- u32 start = get_tmr_us();
- u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
- u32 key[16] = {0};
- u32 kidx = 0;
-
- while (*pkg11_magic_off != PKG11_MAGIC)
+ res = -3;
+ goto out_free;
+ }
+ u32 timeout = get_tmr_ms() + 4000;
+ while (!(TSEC(TSEC_CPUCTL) & TSEC_CPUCTL_KEYGEN_DONE))
+ if (get_tmr_ms() > timeout)
{
- smmu_flush_all();
-
- if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
- {
- k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
- key[kidx++] = k;
- }
-
- // Failsafe.
- if ((u32)get_tmr_us() - start > 125000)
- break;
- }
-
- if (kidx != 8)
- {
- res = -6;
- smmu_deinit_for_tsec();
-
+ res = -4;
goto out_free;
}
-
- // Give some extra time to make sure PKG1.1 is decrypted.
- msleep(50);
-
- memcpy(tsec_keys, &key, 0x20);
- memcpy(tsec_ctxt->pkg1, iram, 0x30000);
-
- smmu_deinit_for_tsec();
-
- // for (int i = 0; i < kidx; i++)
- // gfx_printf("key %08X\n", key[i]);
-
- // gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS));
-
- // u32 errst = MC(MC_ERR_STATUS);
- // gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR));
- // gfx_printf(" type: %02X\n", errst >> 28);
- // gfx_printf(" smmu: %02X\n", (errst >> 25) & 3);
- // gfx_printf(" dir: %s\n", (errst >> 16) & 1 ? "W" : "R");
- // gfx_printf(" cid: %02x\n", errst & 0xFF);
- }
- else
+ if (TSEC(TSEC_STATUS) != 0xB0B0B0B0)
{
- if (!_tsec_dma_wait_idle())
- {
- res = -3;
- goto out_free;
- }
- u32 timeout = get_tmr_ms() + 2000;
- while (!TSEC(TSEC_STATUS))
- if (get_tmr_ms() > timeout)
- {
- res = -4;
- goto out_free;
- }
- if (TSEC(TSEC_STATUS) != 0xB0B0B0B0)
- {
- res = -5;
- goto out_free;
- }
-
- //Fetch result.
- HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
- u32 buf[4];
- buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
- buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB);
- buf[2] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB);
- buf[3] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB);
- SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB) = 0;
- SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB) = 0;
- SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
- SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
-
- memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
+ res = -5;
+ goto out_free;
}
+ //Fetch result.
+ HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
+
out_free:;
free(fwbuf);
@@ -288,3 +167,26 @@ out:;
return res;
}
+
+int tsec_run_fw(tsec_ctxt_t *tsec_ctxt)
+{
+ /* Ensure that the ahb redirect is enabled. */
+ mc_enable_ahb_redirect();
+
+ /* Get bom/tom */
+ u32 bom = MC(MC_IRAM_BOM);
+ u32 tom = MC(MC_IRAM_TOM);
+
+ /* Override the ahb redirect extents. */
+ MC(MC_IRAM_BOM) = 0x40000000;
+ MC(MC_IRAM_TOM) = 0x80000000;
+
+ /* Run the fw. */
+ int res = tsec_query(NULL, 0, tsec_ctxt);
+
+ /* Reset the ahb redirect extents. */
+ MC(MC_IRAM_BOM) = bom;
+ MC(MC_IRAM_TOM) = tom;
+
+ return res;
+}
diff --git a/bdk/sec/tsec.h b/bdk/sec/tsec.h
index 274b6e7..47c9f45 100644
--- a/bdk/sec/tsec.h
+++ b/bdk/sec/tsec.h
@@ -24,7 +24,7 @@
typedef struct _tsec_ctxt_t
{
- void *fw;
+ const void *fw;
u32 size;
void *pkg1;
} tsec_ctxt_t;
@@ -47,5 +47,6 @@ typedef struct _tsec_key_data_t
} tsec_key_data_t;
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
+int tsec_run_fw(tsec_ctxt_t *tsec_ctxt);
#endif
diff --git a/bdk/sec/tsec_t210.h b/bdk/sec/tsec_t210.h
index 889d0d4..9d473cb 100644
--- a/bdk/sec/tsec_t210.h
+++ b/bdk/sec/tsec_t210.h
@@ -37,6 +37,7 @@
#define TSEC_IRQDEST_EXT(val) (((val) & 0xFF) << 8)
#define TSEC_CPUCTL 0x1100
#define TSEC_CPUCTL_STARTCPU BIT(1)
+#define TSEC_CPUCTL_KEYGEN_DONE BIT(4)
#define TSEC_BOOTVEC 0x1104
#define TSEC_DMACTL 0x110C
#define TSEC_DMATRFBASE 0x1110
diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c
index 1da102f..afde017 100644
--- a/bdk/soc/hw_init.c
+++ b/bdk/soc/hw_init.c
@@ -253,9 +253,8 @@ static void _config_se_brom()
// Enable fuse clock.
clock_enable_fuse(true);
- // Skip SBK/SSK if sept was run.
- bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
- if (!sbk_skip)
+ // Skip SBK/SSK if running on patched Erista.
+ if (!(FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF))
{
// Bootrom part we skipped.
u32 sbk[4] = {
diff --git a/bdk/soc/t210.h b/bdk/soc/t210.h
index e48f53a..ac703ef 100644
--- a/bdk/soc/t210.h
+++ b/bdk/soc/t210.h
@@ -281,7 +281,6 @@
/*! Special registers. */
#define EMC_SCRATCH0 0x324
#define EMC_HEKA_UPD BIT(30)
-#define EMC_SEPT_RUN BIT(31)
/*! Flow controller registers. */
#define FLOW_CTLR_HALT_COP_EVENTS 0x4
diff --git a/bdk/utils/types.h b/bdk/utils/types.h
index afa6853..57fb509 100644
--- a/bdk/utils/types.h
+++ b/bdk/utils/types.h
@@ -83,7 +83,6 @@ typedef int bool;
#define BOOT_CFG_FROM_LAUNCH BIT(1)
#define BOOT_CFG_FROM_ID BIT(2)
#define BOOT_CFG_TO_EMUMMC BIT(3)
-#define BOOT_CFG_SEPT_RUN BIT(7)
#define EXTRA_CFG_DUMP_EMUMMC BIT(0)
diff --git a/keygen/tsec_keygen b/keygen/tsec_keygen
new file mode 100644
index 0000000..b27cdaf
Binary files /dev/null and b/keygen/tsec_keygen differ
diff --git a/source/config.c b/source/config.c
index 55bd64e..526eb55 100644
--- a/source/config.c
+++ b/source/config.c
@@ -46,7 +46,6 @@ void set_default_configuration()
h_cfg.bootprotect = 0;
h_cfg.errors = 0;
h_cfg.eks = NULL;
- h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.aes_slots_new = false;
h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
diff --git a/source/config.h b/source/config.h
index 9a69d19..bfb0b3b 100644
--- a/source/config.h
+++ b/source/config.h
@@ -34,7 +34,6 @@ typedef struct _hekate_config
// Global temporary config.
bool t210b01;
bool se_keygen_done;
- bool sept_run;
bool aes_slots_new;
bool emummc_force_disable;
bool rcm_patched;
diff --git a/source/hos/fss.c b/source/hos/fss.c
deleted file mode 100644
index 1521d82..0000000
--- a/source/hos/fss.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Atmosphère Fusée Secondary Storage parser.
- *
- * Copyright (c) 2019-2020 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 .
- */
-
-#include
-
-#include "fss.h"
-#include "hos.h"
-#include "../config.h"
-#include
-#include
-#include "../storage/emummc.h"
-#include
-
-#include
-#define DPRINTF(...)
-
-extern hekate_config h_cfg;
-
-extern bool is_ipl_updated(void *buf, char *path, bool force);
-
-// FSS0 Magic and Meta header offset.
-#define FSS0_MAGIC 0x30535346
-#define FSS0_META_OFFSET 0x4
-#define FSS0_VERSION_0_17_0 0x110000
-
-// FSS0 Content Types.
-#define CNT_TYPE_FSP 0
-#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
-#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
-#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
-#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
-#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
-#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
-#define CNT_TYPE_BMP 7
-#define CNT_TYPE_EMC 8
-#define CNT_TYPE_KLD 9 // Kernel Loader.
-#define CNT_TYPE_KRN 10 // Kernel.
-#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload.
-
-// FSS0 Content Flags.
-#define CNT_FLAG0_EXPERIMENTAL BIT(0)
-
-// FSS0 Meta Header.
-typedef struct _fss_meta_t
-{
- u32 magic;
- u32 size;
- u32 crt0_off;
- u32 cnt_off;
- u32 cnt_count;
- u32 hos_ver;
- u32 version;
- u32 git_rev;
-} fss_meta_t;
-
-// FSS0 Content Header.
-typedef struct _fss_content_t
-{
- u32 offset;
- u32 size;
- u8 type;
- u8 flags0;
- u8 flags1;
- u8 flags2;
- u32 rsvd1;
- char name[0x10];
-} fss_content_t;
-
-int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
-{
- FIL fp;
-
- bool stock = false;
- int sept_used = 0;
-
- // Skip if stock and Exosphere and warmboot are not needed.
- if (!sept_ctxt)
- {
- bool pkg1_old = ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620;
- bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
-
- LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
- {
- if (!strcmp("stock", kv->key))
- if (kv->val[0] == '1')
- stock = true;
- }
-
-#ifdef HOS_MARIKO_STOCK_SECMON
- if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01))
-#else
- if (stock && emummc_disabled && pkg1_old)
-#endif
- return 1;
- }
-
- if (f_open(&fp, path, FA_READ) != FR_OK)
- return 0;
-
- void *fss = malloc(f_size(&fp));
-
- // Read first 1024 bytes of the fss file.
- f_read(&fp, fss, 1024, NULL);
-
- // Get FSS0 Meta header offset.
- u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
- fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
-
- // Check if valid FSS0 and parse it.
- if (fss_meta->magic == FSS0_MAGIC)
- {
- bool mariko_not_supported = false;
- if (h_cfg.t210b01 && (fss_meta->version < FSS0_VERSION_0_17_0))
- {
- gfx_con.mute = false;
- mariko_not_supported = true;
- }
-
- gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
- "Max HOS supported: %d.%d.%d\n"
- "Unpacking and loading components.. ",
- fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
- fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
-
- if (mariko_not_supported)
- {
- EPRINTF("\nMariko not supported on < 0.17.0!");
- goto fail;
- }
-
- if (!sept_ctxt)
- {
- ctxt->atmosphere = true;
- ctxt->fss0_hosver = fss_meta->hos_ver;
- }
-
- // Parse FSS0 contents.
- fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
- void *content;
- for (u32 i = 0; i < fss_meta->cnt_count; i++)
- {
- content = (void *)(fss + curr_fss_cnt[i].offset);
-
- // Check if offset is inside limits.
- if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
- continue;
-
- // If content is experimental and experimental flag is not enabled, skip it.
- if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_experimental)
- continue;
-
- // Parse content.
- if (!sept_ctxt)
- {
- // Prepare content context.
- switch (curr_fss_cnt[i].type)
- {
- case CNT_TYPE_KIP:
- if (stock)
- continue;
- merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
- mkip1->kip1 = content;
- list_append(&ctxt->kip1_list, &mkip1->link);
- DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
- break;
-
- case CNT_TYPE_KRN:
- if (stock)
- continue;
- ctxt->kernel_size = curr_fss_cnt[i].size;
- ctxt->kernel = content;
- break;
-
- case CNT_TYPE_EXO:
- ctxt->secmon_size = curr_fss_cnt[i].size;
- ctxt->secmon = content;
- break;
-
- case CNT_TYPE_EXF:
- ctxt->exofatal_size = curr_fss_cnt[i].size;
- ctxt->exofatal = content;
- break;
-
- case CNT_TYPE_WBT:
- if (h_cfg.t210b01)
- continue;
- ctxt->warmboot_size = curr_fss_cnt[i].size;
- ctxt->warmboot = content;
- break;
-
- default:
- continue;
- }
-
- // Load content to launch context.
- f_lseek(&fp, curr_fss_cnt[i].offset);
- f_read(&fp, content, curr_fss_cnt[i].size, NULL);
- }
- else
- {
- // Load sept content directly to launch context.
- switch (curr_fss_cnt[i].type)
- {
- case CNT_TYPE_SP1:
- f_lseek(&fp, curr_fss_cnt[i].offset);
- f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
- break;
- case CNT_TYPE_SP2:
- if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
- {
- f_lseek(&fp, curr_fss_cnt[i].offset);
- f_read(&fp, sept_ctxt->sept_secondary, curr_fss_cnt[i].size, NULL);
- sept_used = 1;
- goto out;
- }
- break;
- default:
- break;
- }
- }
- }
-
-out:
- gfx_printf("Done!\n");
- f_close(&fp);
-
- return (!sept_ctxt ? 1 : sept_used);
- }
-
-fail:
- f_close(&fp);
- free(fss);
-
- return 0;
-}
-
-int load_sept_from_ffs0(fss0_sept_t *sept_ctxt)
-{
- LIST_FOREACH_ENTRY(ini_kv_t, kv, &sept_ctxt->cfg_sec->kvs, link)
- {
- if (!strcmp("fss0", kv->key))
- return parse_fss(NULL, kv->val, sept_ctxt);
- }
-
- return 0;
-}
diff --git a/source/hos/fss.h b/source/hos/fss.h
deleted file mode 100644
index 3f56d7c..0000000
--- a/source/hos/fss.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2019 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 .
- */
-
-#ifndef _FSS_H_
-#define _FSS_H_
-
-#include "hos.h"
-
-typedef struct _fss0_sept_t
-{
- u32 kb;
- ini_sec_t *cfg_sec;
- void *sept_primary;
- void *sept_secondary;
-
-} fss0_sept_t;
-
-int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt);
-int load_sept_from_ffs0(fss0_sept_t *sept_ctxt);
-
-#endif
diff --git a/source/hos/sept.c b/source/hos/sept.c
deleted file mode 100644
index 873b7ab..0000000
--- a/source/hos/sept.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2019 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 .
- */
-
-#include
-
-#include "hos.h"
-#include "fss.h"
-#include "sept.h"
-#include "../config.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "../storage/nx_emmc.h"
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#define PATCHED_RELOC_SZ 0x94
-
-#define WB_RST_ADDR 0x40010ED0
-#define WB_RST_SIZE 0x30
-
-u8 warmboot_reboot[] = {
- 0x14, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E450
- 0x01, 0x10, 0xB0, 0xE3, // MOVS R1, #1
- 0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
- 0x0C, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E400
- 0x10, 0x10, 0xB0, 0xE3, // MOVS R1, #0x10
- 0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
- 0xFE, 0xFF, 0xFF, 0xEA, // LOOP
- 0x50, 0xE4, 0x00, 0x70, // #0x7000E450
- 0x00, 0xE4, 0x00, 0x70 // #0x7000E400
-};
-
-#define SEPT_PRI_ADDR 0x4003F000
-
-#define SEPT_PK1T_ADDR 0xC0400000
-#define SEPT_PK1T_STACK 0x40008000
-#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4)
-#define SEPT_STG1_ADDR (SEPT_PK1T_ADDR + 0x2E100)
-#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
-#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
-
-extern u32 color_idx;
-extern boot_cfg_t b_cfg;
-extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
-
-int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
-{
- FIL fp;
- bool fss0_sept_used = false;
-
- // Copy warmboot reboot code and TSEC fw.
- memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
- memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size);
- *(vu32 *)SEPT_TCSZ_ADDR = tsec_size;
-
- LIST_INIT(ini_sections);
- if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
- {
- bool found = false;
- LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
- {
- // Only parse non config sections.
- if (ini_sec->type == INI_CHOICE && strcmp(ini_sec->name, "config"))
- {
- LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
- {
- if (!strcmp("fss0", kv->key))
- {
- fss0_sept_t sept_ctxt;
- sept_ctxt.kb = kb;
- sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR;
- sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR;
- fss0_sept_used = parse_fss(NULL, kv->val, &sept_ctxt);
-
- found = true;
- break;
- }
- }
- }
- if (found)
- break;
- }
- }
-
- if (!fss0_sept_used)
- {
- // Copy sept-primary.
- if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
- goto error;
-
- if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
- {
- f_close(&fp);
- goto error;
- }
- f_close(&fp);
-
- // Copy sept-secondary.
- if (kb < KB_FIRMWARE_VERSION_810)
- {
- if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
- if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
- goto error;
- }
- else
- {
- if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
- goto error;
- }
-
- if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
- {
- f_close(&fp);
- goto error;
- }
- f_close(&fp);
- }
-
- // Save auto boot config to sept payload, if any.
- boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
- memcpy(tmp_cfg, &b_cfg, sizeof(boot_cfg_t));
-
- tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
-
- if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE))
- {
- free(tmp_cfg);
- goto error;
- }
-
- f_lseek(&fp, PATCHED_RELOC_SZ);
- f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
-
- f_close(&fp);
-
- sd_unmount();
-
- u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
-
- void (*sept)() = (void *)pk1t_sept;
-
- reloc_patcher(WB_RST_ADDR, pk1t_sept, SEPT_PKG_SZ);
-
- // Patch SDRAM init to perform an SVC immediately after second write.
- PMC(APBDEV_PMC_SCRATCH45) = 0x2E38DFFF;
- PMC(APBDEV_PMC_SCRATCH46) = 0x6001DC28;
- // Set SVC handler to jump to sept-primary in IRAM.
- PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
- PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
-
- hw_reinit_workaround(false, 0);
-
- (*sept)();
-
-error:
- EPRINTF("\nSept files not found in sd:/sept!\nPlace appropriate files and try again.");
- display_backlight_brightness(100, 1000);
-
- btn_wait();
-
- return 0;
-}
\ No newline at end of file
diff --git a/source/hos/sept.h b/source/hos/sept.h
deleted file mode 100644
index 086d50d..0000000
--- a/source/hos/sept.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2019 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 .
- */
-
-#ifndef _SEPT_H_
-#define _SEPT_H_
-
-#include
-
-int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb);
-
-#endif
diff --git a/source/keys/key_sources.inl b/source/keys/key_sources.inl
index 2dd52c2..dab8a4b 100644
--- a/source/keys/key_sources.inl
+++ b/source/keys/key_sources.inl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 shchmue
+ * Copyright (c) 2019-2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -19,7 +19,7 @@ static const u8 null_hash[0x20] __attribute__((aligned(4))) = {
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55};
-static const u8 keyblob_key_source[][0x10] __attribute__((aligned(4))) = {
+static const u8 keyblob_key_sources[][0x10] __attribute__((aligned(4))) = {
{0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, //1.0.0
{0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, //3.0.0
{0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, //3.0.1
@@ -146,7 +146,7 @@ static const u8 aes_key_generation_source[0x10] __attribute__((aligned(4))) = {
// from FS
static const u8 bis_kek_source[0x10] __attribute__((aligned(4))) = {
0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F};
-static const u8 bis_key_source[3][0x20] __attribute__((aligned(4))) = {
+static const u8 bis_key_sources[3][0x20] __attribute__((aligned(4))) = {
{0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48,
0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06},
{0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F,
diff --git a/source/keys/keys.c b/source/keys/keys.c
index 4bc24d7..765ac5a 100644
--- a/source/keys/keys.c
+++ b/source/keys/keys.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 shchmue
+ * Copyright (c) 2019-2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -16,17 +16,17 @@
#include "keys.h"
+#include "../../keygen/tsec_keygen.h"
+
#include "../config.h"
#include
#include
#include "../gfx/tui.h"
#include "../hos/pkg1.h"
#include "../hos/pkg2.h"
-#include "../hos/sept.h"
#include
#include
#include
-#include
#include
#include
#include
@@ -122,108 +122,6 @@ static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
return pkg1;
}
-#define RELOC_META_OFF 0x7C
-
-static bool _handle_sept(void *tsec_fw, u32 tsec_size, u32 kb, void *out_key) {
- sd_mount();
- if (!f_stat("sd:/sept/payload.bak", NULL)) {
- f_unlink("sd:/sept/payload.bin");
- f_rename("sd:/sept/payload.bak", "sd:/sept/payload.bin");
- }
-
- if (!h_cfg.sept_run) {
- // bundle lp0 fw for sept instead of loading it from SD as hekate does
- sdram_lp0_save_params(sdram_get_params_patched());
-
- FIL fp;
- if (f_stat("sd:/sept", NULL)) {
- EPRINTF("On firmware 7.x+ but Sept missing.\nSkipping new key derivation...");
- return true;
- }
- // backup post-reboot payload
- if (!f_stat("sd:/sept/payload.bin", NULL)) {
- if (f_rename("sd:/sept/payload.bin", "sd:/sept/payload.bak")) {
- EPRINTF("Unable to backup payload.bin.");
- return false;
- }
- }
- // write self to payload.bin to run again when sept finishes
- volatile reloc_meta_t *relocator = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
- u32 payload_size = relocator->end - IPL_LOAD_ADDR;
- if (f_open(&fp, "sd:/sept/payload.bin", FA_CREATE_NEW | FA_WRITE)) {
- EPRINTF("Unable to write self to /sept/payload.bin.");
- return false;
- }
- gfx_printf("%kWrite self to /sept/payload.bin...", colors[(color_idx++) % 6]);
- if (f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL)) {
- EPRINTF("Unable to write self to /sept/payload.bin.");
- f_close(&fp);
- return false;
- }
- gfx_printf(" done");
- f_close(&fp);
- gfx_printf("%k\nRebooting to sept...\n\n", colors[(color_idx++) % 6]);
- sdmmc_storage_end(&emmc_storage);
- if (!reboot_to_sept((u8 *)tsec_fw, tsec_size, kb)) {
- return false;
- }
- } else {
- se_aes_key_get(se_key_acc_ctrl_get(12) == 0x6A ? 13 : 12, out_key, AES_128_KEY_SIZE);
- }
-
- return true;
-}
-
-static bool _derive_tsec_keys(tsec_ctxt_t *tsec_ctxt, u32 kb, key_derivation_ctx_t *keys) {
- tsec_ctxt->fw = _find_tsec_fw(tsec_ctxt->pkg1);
- if (!tsec_ctxt->fw) {
- EPRINTF("Unable to locate TSEC firmware.");
- return false;
- }
-
- minerva_periodic_training();
-
- tsec_ctxt->size = _get_tsec_fw_size((tsec_key_data_t *)(tsec_ctxt->fw + TSEC_KEY_DATA_OFFSET));
- if (tsec_ctxt->size > PKG1_MAX_SIZE) {
- EPRINTF("Unexpected TSEC firmware size.");
- return false;
- }
-
- if (kb >= KB_FIRMWARE_VERSION_700) {
- if (!_handle_sept(tsec_ctxt->fw, tsec_ctxt->size, kb, keys->master_key[KB_FIRMWARE_VERSION_MAX])) {
- return false;
- }
- } else if (kb == KB_FIRMWARE_VERSION_620) {
- u8 *tsec_paged = (u8 *)page_alloc(3);
- memcpy(tsec_paged, tsec_ctxt->fw, tsec_ctxt->size);
- tsec_ctxt->fw = tsec_paged;
- }
-
- int res = 0;
- u32 retries = 0;
-
- // mc_disable_ahb_redirect();
-
- while (tsec_query(keys->tsec_keys, kb, tsec_ctxt) < 0) {
- memset(keys->tsec_keys, 0, sizeof(keys->tsec_keys));
- retries++;
- if (retries > 15) {
- res = -1;
- break;
- }
- }
-
- // mc_enable_ahb_redirect();
-
- if (res < 0) {
- EPRINTFARGS("ERROR %x dumping TSEC.\n", res);
- return false;
- }
-
- TPRINTFARGS("%kTSEC key(s)... ", colors[(color_idx++) % 6]);
- return true;
-}
-
static void _derive_master_key_mariko(key_derivation_ctx_t *keys) {
// Relies on the SBK being properly set in slot 14
se_aes_crypt_block_ecb(14, 0, keys->device_key_4x, device_master_key_source_kek_source);
@@ -232,39 +130,41 @@ static void _derive_master_key_mariko(key_derivation_ctx_t *keys) {
se_aes_crypt_block_ecb(8, 0, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source);
}
-static void _derive_master_keys_post_620(u32 pkg1_kb, key_derivation_ctx_t *keys) {
- // on firmware 6.2.0 only, the tsec_root_key is available
- if (pkg1_kb == KB_FIRMWARE_VERSION_620 && _key_exists(keys->tsec_keys + AES_128_KEY_SIZE)) {
- se_aes_key_set(8, keys->tsec_keys + AES_128_KEY_SIZE, AES_128_KEY_SIZE); // mkek6 = unwrap(mkeks6, tsecroot)
- se_aes_crypt_block_ecb(8, 0, keys->master_kek[6], master_kek_sources[0]);
- se_aes_key_set(8, keys->master_kek[6], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mks)
- se_aes_crypt_block_ecb(8, 0, keys->master_key[6], master_key_source);
+static int _run_ams_keygen(key_derivation_ctx_t *keys) {
+ tsec_ctxt_t tsec_ctxt;
+ tsec_ctxt.fw = tsec_keygen;
+ tsec_ctxt.size = sizeof(tsec_keygen);
+ int res = tsec_run_fw(&tsec_ctxt);
+
+ if (res) {
+ EPRINTFARGS("ERROR %d running keygen.\n", res);
}
- if (pkg1_kb >= KB_FIRMWARE_VERSION_620) {
- // derive all lower master keys in case keyblobs are bad
- // handle sept version differences
- for (u32 kb = pkg1_kb == KB_FIRMWARE_VERSION_620 ? KB_FIRMWARE_VERSION_620 : KB_FIRMWARE_VERSION_MAX; kb >= KB_FIRMWARE_VERSION_620; kb--) {
- for (u32 i = kb; i > 0; i--) {
- se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE);
- se_aes_crypt_block_ecb(8, 0, keys->master_key[i - 1], master_key_vectors[i]);
- }
- se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE);
- se_aes_crypt_block_ecb(8, 0, keys->temp_key, master_key_vectors[0]);
- if (!_key_exists(keys->temp_key)) {
- break;
- }
- memcpy(keys->master_key[kb - 1], keys->master_key[kb], AES_128_KEY_SIZE);
- memset(keys->master_key[kb], 0, AES_128_KEY_SIZE);
- }
- if (_key_exists(keys->temp_key)) {
- EPRINTFARGS("Unable to derive master key. kb = %d.", pkg1_kb);
- memset(keys->master_key, 0, sizeof(keys->master_key));
- }
+ return res;
+}
+
+static void _derive_master_keys_from_latest_key(key_derivation_ctx_t *keys) {
+ if (!h_cfg.t210b01) {
+ se_aes_crypt_block_ecb(13, 0, keys->master_kek[KB_FIRMWARE_VERSION_MAX], master_kek_sources[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_620]); // mkek = unwrap(tsec_root, mkeks)
+ se_aes_key_set(8, keys->master_kek[KB_FIRMWARE_VERSION_MAX], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mkeys)
+ se_aes_crypt_block_ecb(8, 0, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source);
+ }
+
+ // Derive all lower master keys
+ for (u32 i = KB_FIRMWARE_VERSION_MAX; i > 0; i--) {
+ se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE);
+ se_aes_crypt_block_ecb(8, 0, keys->master_key[i - 1], master_key_vectors[i]);
+ }
+ se_aes_key_set(8, keys->master_key[0], AES_128_KEY_SIZE);
+ se_aes_crypt_block_ecb(8, 0, keys->temp_key, master_key_vectors[0]);
+
+ if (_key_exists(keys->temp_key)) {
+ EPRINTF("Unable to derive master key.");
+ memset(keys->master_key, 0, sizeof(keys->master_key));
}
}
-static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) {
+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};
@@ -281,15 +181,13 @@ static void _derive_master_keys_from_keyblobs(key_derivation_ctx_t *keys) {
keys->sbk[3] = FUSE(FUSE_PRIVATE_KEY3);
}
- se_aes_key_set(8, keys->tsec_keys, sizeof(keys->tsec_keys) / 2);
-
if (!emummc_storage_read(KEYBLOB_OFFSET / NX_EMMC_BLOCKSIZE, KB_FIRMWARE_VERSION_600 + 1, keyblob_block)) {
EPRINTF("Unable to read keyblobs.");
}
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) {
minerva_periodic_training();
- se_aes_crypt_block_ecb(8, 0, keys->keyblob_key[i], keyblob_key_source[i]); // temp = unwrap(kbks, tsec)
+ se_aes_crypt_block_ecb(12, 0, keys->keyblob_key[i], keyblob_key_sources[i]); // temp = unwrap(kbks, tsec)
se_aes_crypt_block_ecb(14, 0, keys->keyblob_key[i], keys->keyblob_key[i]); // kbk = unwrap(temp, sbk)
se_aes_key_set(7, keys->keyblob_key[i], sizeof(keys->keyblob_key[i]));
se_aes_crypt_block_ecb(7, 0, keys->keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk)
@@ -335,18 +233,18 @@ static void _derive_bis_keys(key_derivation_ctx_t *keys) {
_get_device_key(8, keys->temp_key, key_generation, keys->device_key, keys->device_key_4x, keys->master_key[0]);
se_aes_key_set(8, keys->temp_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(8, 8, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_source[0] + 0x00); // bkey = unwrap(bkeys, kek)
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_source[0] + 0x10);
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x00, bis_key_sources[0] + 0x00); // bkey = unwrap(bkeys, kek)
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[0] + 0x10, bis_key_sources[0] + 0x10);
// kek = generate_kek(bkeks, devkey, aeskek, aeskey)
_generate_kek(8, bis_kek_source, keys->temp_key, aes_kek_generation_source, aes_key_generation_source);
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_source[1] + 0x00); // bkey = unwrap(bkeys, kek)
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_source[1] + 0x10);
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_source[2] + 0x00);
- se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_source[2] + 0x10);
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x00, bis_key_sources[1] + 0x00); // bkey = unwrap(bkeys, kek)
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[1] + 0x10, bis_key_sources[1] + 0x10);
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x00, bis_key_sources[2] + 0x00);
+ se_aes_crypt_block_ecb(8, 0, keys->bis_key[2] + 0x10, bis_key_sources[2] + 0x10);
memcpy(keys->bis_key[3], keys->bis_key[2], 0x20);
}
-static void _derive_misc_keys(key_derivation_ctx_t *keys, u32 *derivable_key_count) {
+static void _derive_misc_keys(key_derivation_ctx_t *keys) {
if (_key_exists(keys->master_key[0])) {
_generate_kek(8, header_kek_source, keys->master_key[0], aes_kek_generation_source, aes_key_generation_source);
se_aes_crypt_block_ecb(8, 0, keys->header_key + 0x00, header_key_source + 0x00);
@@ -359,10 +257,7 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, u32 *derivable_key_cou
se_aes_crypt_block_ecb(8, 0, keys->save_mac_key, save_mac_key_source);
}
- if (_key_exists(keys->master_key[*derivable_key_count])) {
- *derivable_key_count = KB_FIRMWARE_VERSION_MAX + 1;
- }
- for (u32 i = 0; i < *derivable_key_count; i++) {
+ for (u32 i = 0; i < KB_FIRMWARE_VERSION_MAX + 1; i++) {
if (!_key_exists(keys->master_key[i]))
continue;
for (u32 j = 0; j < 3; j++) {
@@ -666,7 +561,9 @@ static bool _derive_emmc_keys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
return false;
}
- if (!_derive_sd_seed(keys)) {
+ if (!sd_mount()) {
+ EPRINTF("Unable to mount SD.");
+ } else if (!_derive_sd_seed(keys)) {
EPRINTF("Unable to get SD seed.");
}
@@ -757,7 +654,7 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
free(text_buffer);
}
-static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, const pkg1_id_t *pkg1_id, u32 start_whole_operation_time, u32 derivable_key_count) {
+static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titlekey_buffer, const pkg1_id_t *pkg1_id, u32 start_whole_operation_time) {
char *text_buffer = NULL;
if (!sd_mount()) {
EPRINTF("Unable to mount SD.");
@@ -771,7 +668,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_source, 0);
+ SAVE_KEY_FAMILY(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);
@@ -789,7 +686,7 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
SAVE_KEY_VAR(key_area_key_system_source, key_area_key_sources[2]);
SAVE_KEY_FAMILY_VAR(keyblob, keys->keyblob, 0);
SAVE_KEY_FAMILY_VAR(keyblob_key, keys->keyblob_key, 0);
- SAVE_KEY_FAMILY(keyblob_key_source, 0);
+ SAVE_KEY_FAMILY(keyblob_key_sources, 0);
SAVE_KEY_FAMILY_VAR(keyblob_mac_key, keys->keyblob_mac_key, 0);
SAVE_KEY(keyblob_mac_key_source);
SAVE_KEY_FAMILY_VAR(master_kek, keys->master_kek, 0);
@@ -823,18 +720,24 @@ static void _save_keys_to_sd(key_derivation_ctx_t *keys, titlekey_buffer_t *titl
SAVE_KEY(ssl_rsa_kek_source_y);
SAVE_KEY_FAMILY_VAR(titlekek, keys->titlekek, 0);
SAVE_KEY(titlekek_source);
- _save_key("tsec_key", keys->tsec_keys, AES_128_KEY_SIZE, text_buffer);
- if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
- _save_key("tsec_root_key", keys->tsec_keys + AES_128_KEY_SIZE, AES_128_KEY_SIZE, text_buffer);
+ SAVE_KEY_VAR(tsec_key, keys->tsec_key);
+
+ const u32 root_key_ver = 2;
+ char root_key_name[21] = "tsec_root_key_00";
+ s_printf(root_key_name + 14, "%02x", root_key_ver);
+ _save_key(root_key_name, keys->tsec_root_key, AES_128_KEY_SIZE, text_buffer);
+
+ s_printf(root_key_name + 14, "dev_%02x", root_key_ver);
+ _save_key(root_key_name, keys->tsec_root_key_dev, AES_128_KEY_SIZE, text_buffer);
end_time = get_tmr_us();
gfx_printf("\n%k Found %d keys.\n\n", colors[(color_idx++) % 6], _key_count);
gfx_printf("%kLockpick totally done in %d us\n\n", colors[(color_idx++) % 6], end_time - start_whole_operation_time);
- gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], derivable_key_count - 1);
+ gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], KB_FIRMWARE_VERSION_MAX);
f_mkdir("sd:/switch");
char keyfile_path[30] = "sd:/switch/prod.keys";
- if (fuse_read_odm(4) & 3)
+ if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
s_printf(&keyfile_path[11], "dev.keys");
FILINFO fno;
@@ -902,28 +805,30 @@ static void _derive_keys() {
if (!pkg1) {
return;
}
-
- u32 derivable_key_count = pkg1_id->kb >= KB_FIRMWARE_VERSION_620 ? pkg1_id->kb + 1 : 6;
- bool res = true;
- key_derivation_ctx_t __attribute__((aligned(4))) keys = {0};
-
- if (!h_cfg.t210b01) {
- tsec_ctxt_t tsec_ctxt;
- tsec_ctxt.pkg1 = pkg1;
- res =_derive_tsec_keys(&tsec_ctxt, pkg1_id->kb, &keys);
- }
free(pkg1);
- if (res == false) {
- return;
- }
+
+ key_derivation_ctx_t __attribute__((aligned(4))) keys = {0};
// Master key derivation
if (h_cfg.t210b01) {
_derive_master_key_mariko(&keys);
- _derive_master_keys_post_620(KB_FIRMWARE_VERSION_MAX, &keys);
+ _derive_master_keys_from_latest_key(&keys);
} else {
- _derive_master_keys_post_620(pkg1_id->kb, &keys);
- _derive_master_keys_from_keyblobs(&keys);
+ int res = _run_ams_keygen(&keys);
+ if (res) {
+ EPRINTF("Unable to run keygen.");
+ return;
+ }
+
+ u8 *aes_keys = (u8 *)calloc(0x1000, 1);
+ se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE);
+ memcpy(&keys.tsec_root_key_dev, aes_keys + 11 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
+ memcpy(&keys.tsec_key, aes_keys + 12 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
+ memcpy(&keys.tsec_root_key, aes_keys + 13 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
+ free(aes_keys);
+
+ _derive_master_keys_from_latest_key(&keys);
+ _derive_keyblob_keys(&keys);
}
TPRINTFARGS("%kMaster keys... ", colors[(color_idx++) % 6]);
@@ -932,7 +837,7 @@ static void _derive_keys() {
TPRINTFARGS("%kBIS keys... ", colors[(color_idx++) % 6]);
- _derive_misc_keys(&keys, &derivable_key_count);
+ _derive_misc_keys(&keys);
titlekey_buffer_t *titlekey_buffer = (titlekey_buffer_t *)TITLEKEY_BUF_ADR;
@@ -943,7 +848,7 @@ static void _derive_keys() {
EPRINTF("Missing needed BIS keys.\nSkipping SD seed and titlekeys.");
}
- _save_keys_to_sd(&keys, titlekey_buffer, pkg1_id, start_whole_operation_time, derivable_key_count);
+ _save_keys_to_sd(&keys, titlekey_buffer, pkg1_id, start_whole_operation_time);
}
void dump_keys() {
diff --git a/source/keys/keys.h b/source/keys/keys.h
index b3018a5..32d7fb6 100644
--- a/source/keys/keys.h
+++ b/source/keys/keys.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 shchmue
+ * Copyright (c) 2019-2021 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -108,7 +108,9 @@ typedef struct {
master_key[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE],
package2_key[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE],
titlekek[KB_FIRMWARE_VERSION_MAX + 1][AES_128_KEY_SIZE],
- tsec_keys[AES_128_KEY_SIZE * 2];
+ tsec_key[AES_128_KEY_SIZE],
+ tsec_root_key[AES_128_KEY_SIZE],
+ tsec_root_key_dev[AES_128_KEY_SIZE];
u32 sbk[4];
keyblob_t keyblob[KB_FIRMWARE_VERSION_600 + 1];
} key_derivation_ctx_t;
@@ -137,9 +139,9 @@ typedef struct {
// save key with different name than variable
#define SAVE_KEY_VAR(name, varname) _save_key(#name, varname, sizeof(varname), text_buffer)
// save key family wrapper
-#define SAVE_KEY_FAMILY(name, start) _save_key_family(#name, name, start, sizeof(name) / sizeof(name[0]), sizeof(name[0]), text_buffer)
+#define SAVE_KEY_FAMILY(name, start) _save_key_family(#name, name, start, ARRAY_SIZE(name), sizeof(*(name)), text_buffer)
// save key family with different name than variable
-#define SAVE_KEY_FAMILY_VAR(name, varname, start) _save_key_family(#name, varname, start, sizeof(varname) / sizeof(varname[0]), sizeof(varname[0]), text_buffer)
+#define SAVE_KEY_FAMILY_VAR(name, varname, start) _save_key_family(#name, varname, start, ARRAY_SIZE(varname), sizeof(*(varname)), text_buffer)
void dump_keys();
diff --git a/source/main.c b/source/main.c
index deee446..1eea1fb 100644
--- a/source/main.c
+++ b/source/main.c
@@ -395,15 +395,6 @@ void ipl_main()
h_cfg.emummc_force_disable = emu_cfg.sector == 0 && !emu_cfg.path;
emu_cfg.enabled = !h_cfg.emummc_force_disable;
- if (b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN)
- {
- if (!(b_cfg.extra_cfg & EXTRA_CFG_DUMP_EMUMMC)) {
- h_cfg.emummc_force_disable = true;
- emu_cfg.enabled = false;
- }
- dump_keys();
- }
-
// Grey out emummc option if not present.
if (h_cfg.emummc_force_disable)
{