Update to hekate bdk 5.6.0

This commit is contained in:
shchmue 2021-08-28 14:10:33 -06:00
parent a89e9b4d7f
commit f2f3c5daf0
43 changed files with 1530 additions and 1533 deletions

View file

@ -38,19 +38,14 @@ void set_default_configuration()
h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0;
h_cfg.bootwait = 3;
h_cfg.se_keygen_done = 0;
h_cfg.backlight = 100;
h_cfg.autohosoff = 0;
h_cfg.autonogc = 1;
h_cfg.updater2p = 0;
h_cfg.bootprotect = 0;
h_cfg.errors = 0;
h_cfg.eks = NULL;
h_cfg.aes_slots_new = false;
h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
h_cfg.emummc_force_disable = false;
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
sd_power_cycle_time_start = 0;
}

View file

@ -17,7 +17,6 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "hos/hos.h"
#include <utils/types.h>
typedef struct _hekate_config
@ -33,13 +32,10 @@ typedef struct _hekate_config
u32 bootprotect;
// Global temporary config.
bool t210b01;
bool se_keygen_done;
bool aes_slots_new;
bool emummc_force_disable;
bool rcm_patched;
bool sbk_set;
u32 errors;
hos_eks_mbr_t *eks;
} hekate_config;
void set_default_configuration();

View file

@ -18,122 +18,18 @@
#ifndef _HOS_H_
#define _HOS_H_
#include "pkg1.h"
#include "pkg2.h"
#include <sec/se_t210.h>
#include <utils/types.h>
#include <utils/ini.h>
#include <sec/tsec.h>
#include <assert.h>
#define KB_FIRMWARE_VERSION_100_200 0
#define KB_FIRMWARE_VERSION_300 1
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_100 0
#define KB_FIRMWARE_VERSION_300 1
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#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
#define HOS_PKG11_MAGIC 0x31314B50
#define HOS_EKS_MAGIC 0x30534B45
// Use official Mariko secmon when in stock.
//#define HOS_MARIKO_STOCK_SECMON
typedef struct _exo_ctxt_t
{
bool fs_is_510;
bool no_user_exceptions;
bool user_pmu;
bool *usb3_force;
bool *cal0_blank;
bool *cal0_allow_writes_sys;
} exo_ctxt_t;
typedef struct _hos_eks_keys_t
{
u8 mkk[SE_KEY_128_SIZE];
u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[SE_KEY_128_SIZE];
u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t
{
u32 magic;
u8 enabled[5];
u8 enabled_bis;
u8 rsvd[2];
u32 lot0;
u8 dkg[SE_KEY_128_SIZE];
u8 dkk[SE_KEY_128_SIZE];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 304, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
const pkg2_kernel_id_t *pkg2_kernel_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *exofatal;
u32 exofatal_size;
void *pkg2;
u32 pkg2_size;
bool new_pkg2;
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
bool svcperm;
bool debugmode;
bool stock;
bool emummc_forced;
char *fss0_main_path;
u32 fss0_hosver;
bool fss0_experimental;
bool atmosphere;
exo_ctxt_t exo_ctx;
ini_sec_t *cfg;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg);
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_1210 //!TODO: Update on mkey changes.
#endif

View file

@ -1,210 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* 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 <string.h>
#include "pkg2.h"
#include <libs/compr/blz.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <utils/aarch64_util.h>
#include <gfx_utils.h>
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/
#define DPRINTF(...)
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{
u32 size = sizeof(pkg2_kip1_t);
for (u32 j = 0; j < KIP1_NUM_SECTIONS; j++)
size += kip1->sections[j].size_comp;
return size;
}
void pkg2_get_newkern_info(u8 *kern_data)
{
u32 pkg2_newkern_ini1_off = 0;
pkg2_newkern_ini1_start = 0;
// Find static OP offset that is close to INI1 offset.
u32 counter_ops = 0x100;
while (counter_ops)
{
if (*(u32 *)(kern_data + 0x100 - counter_ops) == PKG2_NEWKERN_GET_INI1_HEURISTIC)
{
pkg2_newkern_ini1_off = 0x100 - counter_ops + 12; // OP found. Add 12 for the INI1 offset.
break;
}
counter_ops -= 4;
}
// Offset not found?
if (!counter_ops)
return;
u32 info_op = *(u32 *)(kern_data + pkg2_newkern_ini1_off);
pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + pkg2_newkern_ini1_off; // Parse ADR and PC.
pkg2_newkern_ini1_start = *(u32 *)(kern_data + pkg2_newkern_ini1_val);
pkg2_newkern_ini1_end = *(u32 *)(kern_data + pkg2_newkern_ini1_val + 0x8);
}
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2)
{
u8 *ptr;
// Check for new pkg2 type.
if (!pkg2->sec_size[PKG2_SEC_INI1])
{
pkg2_get_newkern_info(pkg2->data);
if (!pkg2_newkern_ini1_start)
return false;
ptr = pkg2->data + pkg2_newkern_ini1_start;
*new_pkg2 = true;
}
else
ptr = pkg2->data + pkg2->sec_size[PKG2_SEC_KERNEL];
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)ptr;
ptr += sizeof(pkg2_ini1_t);
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t));
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
list_append(info, &ki->link);
ptr += ki->size;
DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
}
return true;
}
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
{
u32 compClearMask = ~sectsToDecomp;
if ((ki->kip1->flags & compClearMask) == ki->kip1->flags)
return 0; // Already decompressed, nothing to do.
pkg2_kip1_t hdr;
memcpy(&hdr, ki->kip1, sizeof(hdr));
unsigned int newKipSize = sizeof(hdr);
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
if (sectIdx < 3 && (sectsToDecomp & sectCompBit) && (hdr.flags & sectCompBit))
newKipSize += hdr.sections[sectIdx].size_decomp;
else
newKipSize += hdr.sections[sectIdx].size_comp;
}
pkg2_kip1_t* newKip = malloc(newKipSize);
unsigned char* dstDataPtr = newKip->data;
const unsigned char* srcDataPtr = ki->kip1->data;
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// Easy copy path for uncompressed or ones we dont want to uncompress.
if (sectIdx >= 3 || !(sectsToDecomp & sectCompBit) || !(hdr.flags & sectCompBit))
{
unsigned int dataSize = hdr.sections[sectIdx].size_comp;
if (dataSize == 0)
continue;
memcpy(dstDataPtr, srcDataPtr, dataSize);
srcDataPtr += dataSize;
dstDataPtr += dataSize;
continue;
}
unsigned int compSize = hdr.sections[sectIdx].size_comp;
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
//gfx_printf("Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
{
gfx_printf("%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
free(newKip);
return 1;
}
else
{
DPRINTF("Done! Decompressed size is %d!\n", outputSize);
}
hdr.sections[sectIdx].size_comp = outputSize;
srcDataPtr += compSize;
dstDataPtr += outputSize;
}
hdr.flags &= compClearMask;
memcpy(newKip, &hdr, sizeof(hdr));
newKipSize = dstDataPtr-(unsigned char*)(newKip);
free(ki->kip1);
ki->kip1 = newKip;
ki->size = newKipSize;
return 0;
}
pkg2_hdr_t *pkg2_decrypt(void *data)
{
u8 *pdata = (u8 *)data;
// Skip signature.
pdata += 0x100;
pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdata;
// Skip header.
pdata += sizeof(pkg2_hdr_t);
// Decrypt header.
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump((u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
return NULL;
for (u32 i = 0; i < 4; i++)
{
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}
return hdr;
}

View file

@ -1,109 +0,0 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PKG2_H_
#define _PKG2_H_
#include <utils/types.h>
#include <utils/list.h>
#define PKG2_MAGIC 0x31324B50
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset.
extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
typedef struct _kernel_patch_t
{
u32 id;
u32 off;
u32 val;
u32 *ptr;
} kernel_patch_t;
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
u8 sec_ctr[0x40];
u32 magic;
u32 base;
u32 pad0;
u8 pkg2_ver;
u8 bl_ver;
u16 pad1;
u32 sec_size[4];
u32 sec_off[4];
u8 sec_sha256[0x80];
u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
{
u32 magic;
u32 size;
u32 num_procs;
u32 pad;
} pkg2_ini1_t;
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
u32 size_decomp;
u32 size_comp;
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
u32 magic;
u8 name[12];
u64 tid;
u32 proc_cat;
u8 main_thrd_prio;
u8 def_cpu_core;
u8 res;
u8 flags;
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
u32 caps[0x20];
u8 data[];
} pkg2_kip1_t;
typedef struct _pkg2_kip1_info_t
{
pkg2_kip1_t *kip1;
u32 size;
link_t link;
} pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u8 hash[8];
kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);
#endif

View file

@ -23,7 +23,6 @@
#include <gfx_utils.h>
#include "../gfx/tui.h"
#include "../hos/pkg1.h"
#include "../hos/pkg2.h"
#include <libs/fatfs/ff.h>
#include <libs/nx_savedata/save.h>
#include <mem/heap.h>
@ -79,21 +78,6 @@ static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device
// titlekey functions
static bool _test_key_pair(const void *E, const void *D, const void *N);
static ALWAYS_INLINE u8 *_find_tsec_fw(const u8 *pkg1) {
const u32 tsec_fw_align = 0x100;
const u32 tsec_fw_first_instruction = 0xCF42004D;
for (const u32 *pos = (const u32 *)pkg1; (u8 *)pos < pkg1 + PKG1_MAX_SIZE; pos += tsec_fw_align / sizeof(u32))
if (*pos == tsec_fw_first_instruction)
return (u8 *)pos;
return NULL;
}
static ALWAYS_INLINE u32 _get_tsec_fw_size(tsec_key_data_t *key_data) {
return key_data->blob0_size + sizeof(tsec_key_data_t) + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
}
static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
if (emummc_storage_init_mmc()) {
EPRINTF("Unable to init MMC.");
@ -125,17 +109,18 @@ static u8 *_read_pkg1(const pkg1_id_t **pkg1_id) {
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, 0, keys->device_key_4x, device_master_key_source_kek_source);
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, 0, keys->master_key[KB_FIRMWARE_VERSION_MAX], master_key_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[KB_FIRMWARE_VERSION_MAX], 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);
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);
@ -149,19 +134,19 @@ static void _derive_master_keys_from_latest_key(key_derivation_ctx_t *keys, bool
u32 tsec_root_key_slot = is_dev ? 11 : 13;
// Derive all master keys based on current root key
for (u32 i = KB_FIRMWARE_VERSION_810 - KB_FIRMWARE_VERSION_620; i < ARRAY_SIZE(master_kek_sources); i++) {
se_aes_crypt_block_ecb(tsec_root_key_slot, 0, keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_kek_sources[i]); // mkek = unwrap(tsec_root, mkeks)
se_aes_crypt_block_ecb(tsec_root_key_slot, DECRYPT, keys->master_kek[i + KB_FIRMWARE_VERSION_620], master_kek_sources[i]); // mkek = unwrap(tsec_root, mkeks)
se_aes_key_set(8, keys->master_kek[i + KB_FIRMWARE_VERSION_620], AES_128_KEY_SIZE); // mkey = unwrap(mkek, mkeys)
se_aes_crypt_block_ecb(8, 0, keys->master_key[i + KB_FIRMWARE_VERSION_620], master_key_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[i + KB_FIRMWARE_VERSION_620], 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], is_dev ? master_key_vectors_dev[i] : master_key_vectors[i]);
se_aes_crypt_block_ecb(8, DECRYPT, keys->master_key[i - 1], is_dev ? master_key_vectors_dev[i] : 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, is_dev ? master_key_vectors_dev[0] : master_key_vectors[0]);
se_aes_crypt_block_ecb(8, DECRYPT, keys->temp_key, is_dev ? master_key_vectors_dev[0] : master_key_vectors[0]);
if (_key_exists(keys->temp_key)) {
EPRINTFARGS("Unable to derive master keys for %s.", is_dev ? "dev" : "prod");
@ -174,7 +159,7 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
encrypted_keyblob_t *current_keyblob = (encrypted_keyblob_t *)keyblob_block;
u32 keyblob_mac[AES_128_KEY_SIZE / 4] = {0};
if (h_cfg.sbk_set) {
if (FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF) {
u8 *aes_keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(aes_keys + 0x800, aes_keys, AES_128_KEY_SIZE);
memcpy(keys->sbk, aes_keys + 14 * AES_128_KEY_SIZE, AES_128_KEY_SIZE);
@ -192,13 +177,13 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++, current_keyblob++) {
minerva_periodic_training();
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_crypt_block_ecb(12, DECRYPT, keys->keyblob_key[i], keyblob_key_sources[i]); // temp = unwrap(kbks, tsec)
se_aes_crypt_block_ecb(14, DECRYPT, 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)
se_aes_crypt_block_ecb(7, DECRYPT, keys->keyblob_mac_key[i], keyblob_mac_key_source); // kbm = unwrap(kbms, kbk)
if (i == 0) {
se_aes_crypt_block_ecb(7, 0, keys->device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0)
se_aes_crypt_block_ecb(7, 0, keys->device_key_4x, device_master_key_source_kek_source);
se_aes_crypt_block_ecb(7, DECRYPT, keys->device_key, per_console_key_source); // devkey = unwrap(pcks, kbk0)
se_aes_crypt_block_ecb(7, DECRYPT, keys->device_key_4x, device_master_key_source_kek_source);
}
// verify keyblob is not corrupt
@ -217,7 +202,7 @@ static void _derive_keyblob_keys(key_derivation_ctx_t *keys) {
memcpy(keys->master_kek[i], keys->keyblob[i].master_kek, sizeof(keys->master_kek[i]));
se_aes_key_set(7, keys->master_kek[i], sizeof(keys->master_kek[i]));
if (!_key_exists(keys->master_key[i])) {
se_aes_crypt_block_ecb(7, 0, keys->master_key[i], master_key_source);
se_aes_crypt_block_ecb(7, DECRYPT, keys->master_key[i], master_key_source);
}
}
free(keyblob_block);
@ -238,15 +223,15 @@ static void _derive_bis_keys(key_derivation_ctx_t *keys) {
_generate_specific_aes_key(8, keys, &keys->bis_key[0], &bis_key_sources[0], key_generation);
// 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_ecb(8, 0, keys->bis_key[1], AES_128_KEY_SIZE * 2, bis_key_sources[1], AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
se_aes_crypt_ecb(8, 0, keys->bis_key[2], AES_128_KEY_SIZE * 2, bis_key_sources[2], AES_128_KEY_SIZE * 2);
se_aes_crypt_ecb(8, DECRYPT, keys->bis_key[1], AES_128_KEY_SIZE * 2, bis_key_sources[1], AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
se_aes_crypt_ecb(8, DECRYPT, keys->bis_key[2], AES_128_KEY_SIZE * 2, bis_key_sources[2], AES_128_KEY_SIZE * 2);
memcpy(keys->bis_key[3], keys->bis_key[2], 0x20);
}
static void _derive_non_unique_keys(key_derivation_ctx_t *keys, bool is_dev) {
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_ecb(8, 0, keys->header_key, AES_128_KEY_SIZE * 2, header_key_source, AES_128_KEY_SIZE * 2);
se_aes_crypt_ecb(8, DECRYPT, keys->header_key, AES_128_KEY_SIZE * 2, header_key_source, AES_128_KEY_SIZE * 2);
}
}
@ -254,19 +239,19 @@ static void _derive_misc_keys(key_derivation_ctx_t *keys, bool is_dev) {
if (_key_exists(keys->device_key) || (_key_exists(keys->master_key[0]) && _key_exists(keys->device_key_4x))) {
_get_device_key(8, keys, keys->temp_key, 0);
_generate_kek(8, save_mac_kek_source, keys->temp_key, aes_kek_generation_source, NULL);
se_aes_crypt_block_ecb(8, 0, keys->save_mac_key, save_mac_key_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->save_mac_key, save_mac_key_source);
}
if (_key_exists(keys->master_key[0])) {
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
_generate_kek(8, eticket_rsa_kekek_source, keys->master_key[0], keys->temp_key, NULL);
se_aes_crypt_block_ecb(8, 0, keys->eticket_rsa_kek, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->eticket_rsa_kek, is_dev ? eticket_rsa_kek_source_dev : eticket_rsa_kek_source);
for (u32 i = 0; i < AES_128_KEY_SIZE; i++)
keys->temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
_generate_kek(8, ssl_rsa_kek_source_x, keys->master_key[0], keys->temp_key, NULL);
se_aes_crypt_block_ecb(8, 0, keys->ssl_rsa_kek, ssl_rsa_kek_source_y);
se_aes_crypt_block_ecb(8, DECRYPT, keys->ssl_rsa_kek, ssl_rsa_kek_source_y);
}
}
@ -276,11 +261,11 @@ static void _derive_master_key_per_generation_keys(key_derivation_ctx_t *keys) {
continue;
for (u32 j = 0; j < 3; j++) {
_generate_kek(8, key_area_key_sources[j], keys->master_key[i], aes_kek_generation_source, NULL);
se_aes_crypt_block_ecb(8, 0, keys->key_area_key[j][i], aes_key_generation_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->key_area_key[j][i], aes_key_generation_source);
}
se_aes_key_set(8, keys->master_key[i], AES_128_KEY_SIZE);
se_aes_crypt_block_ecb(8, 0, keys->package2_key[i], package2_key_source);
se_aes_crypt_block_ecb(8, 0, keys->titlekek[i], titlekek_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->package2_key[i], package2_key_source);
se_aes_crypt_block_ecb(8, DECRYPT, keys->titlekek[i], titlekek_source);
}
}
@ -478,7 +463,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
return false;
}
se_aes_xts_crypt(1, 0, 0, 0, titlekey_buffer->read_buffer, titlekey_buffer->read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE);
se_aes_xts_crypt(1, 0, DECRYPT, 0, titlekey_buffer->read_buffer, titlekey_buffer->read_buffer, XTS_CLUSTER_SIZE, NX_EMMC_CALIBRATION_SIZE / XTS_CLUSTER_SIZE);
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)titlekey_buffer->read_buffer;
if (cal0->magic != MAGIC_CAL0) {
@ -496,7 +481,7 @@ static bool _derive_titlekeys(key_derivation_ctx_t *keys, titlekey_buffer_t *tit
u32 temp_device_key[AES_128_KEY_SIZE / 4] = {0};
_get_device_key(7, keys, temp_device_key, keypair_generation);
_generate_kek(7, eticket_rsa_kekek_source, temp_device_key, keys->temp_key, NULL);
se_aes_crypt_block_ecb(7, 0, keys->eticket_rsa_kek_personalized, eticket_rsa_kek_source);
se_aes_crypt_block_ecb(7, DECRYPT, keys->eticket_rsa_kek_personalized, eticket_rsa_kek_source);
memcpy(keys->temp_key, keys->eticket_rsa_kek_personalized, sizeof(keys->temp_key));
} else {
memcpy(keys->temp_key, keys->eticket_rsa_kek, sizeof(keys->temp_key));
@ -594,21 +579,21 @@ static void _save_mariko_partial_keys(u32 start, u32 count, bool append) {
for (u32 ks = start; ks < start + count; ks++) {
// Check if key is as expected
if (ks < ARRAY_SIZE(mariko_key_vectors)) {
se_aes_crypt_block_ecb(ks, 0, &data[0], mariko_key_vectors[ks]);
se_aes_crypt_block_ecb(ks, DECRYPT, &data[0], mariko_key_vectors[ks]);
if (_key_exists(data)) {
continue;
}
}
// Encrypt zeros with complete key
se_aes_crypt_block_ecb(ks, 1, &data[3 * AES_128_KEY_SIZE], zeros);
se_aes_crypt_block_ecb(ks, ENCRYPT, &data[3 * AES_128_KEY_SIZE], zeros);
// We only need to overwrite 3 of the dwords of the key
for (u32 i = 0; i < 3; i++) {
// Overwrite ith dword of key with zeros
se_aes_key_partial_set(ks, i, 0);
// Encrypt zeros with more of the key zeroed out
se_aes_crypt_block_ecb(ks, 1, &data[(2 - i) * AES_128_KEY_SIZE], zeros);
se_aes_crypt_block_ecb(ks, ENCRYPT, &data[(2 - i) * AES_128_KEY_SIZE], zeros);
}
// Skip saving key if two results are the same indicating unsuccessful overwrite or empty slot
@ -785,7 +770,7 @@ static bool _check_keyslot_access() {
u8 test_data[AES_128_KEY_SIZE] = {0};
const u8 test_ciphertext[AES_128_KEY_SIZE] = {0};
se_aes_key_set(8, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(8, 0, test_data, test_ciphertext);
se_aes_crypt_block_ecb(8, DECRYPT, test_data, test_ciphertext);
return memcmp(test_data, "\x7b\x1d\x29\xa1\x6c\xf8\xcc\xab\x84\xf0\xb8\xa5\x98\xe4\x2f\xa6", SE_KEY_128_SIZE) == 0;
}
@ -944,14 +929,14 @@ static void _generate_specific_aes_key(u32 ks, key_derivation_ctx_t *keys, void
_get_device_key(ks, keys, keys->temp_key, key_generation);
se_aes_key_set(ks, keys->temp_key, AES_128_KEY_SIZE);
se_aes_unwrap_key(ks, ks, retail_specific_aes_key_source); // kek = unwrap(rsaks, devkey)
se_aes_crypt_ecb(ks, 0, out_key, AES_128_KEY_SIZE * 2, key_source, AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
se_aes_crypt_ecb(ks, DECRYPT, out_key, AES_128_KEY_SIZE * 2, key_source, AES_128_KEY_SIZE * 2); // bkey = unwrap(bkeys, kek)
} else {
_get_secure_data(keys, out_key);
}
}
static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device_key, u32 revision) {
if (revision == KB_FIRMWARE_VERSION_100_200 && !h_cfg.t210b01) {
if (revision == KB_FIRMWARE_VERSION_100 && !h_cfg.t210b01) {
memcpy(out_device_key, keys->device_key, AES_128_KEY_SIZE);
return;
}
@ -963,11 +948,11 @@ static void _get_device_key(u32 ks, key_derivation_ctx_t *keys, void *out_device
}
u32 temp_key[AES_128_KEY_SIZE / 4] = {0};
se_aes_key_set(ks, keys->device_key_4x, AES_128_KEY_SIZE);
se_aes_crypt_block_ecb(ks, 0, temp_key, device_master_key_source_sources[revision]);
se_aes_crypt_block_ecb(ks, DECRYPT, temp_key, device_master_key_source_sources[revision]);
se_aes_key_set(ks, keys->master_key[0], AES_128_KEY_SIZE);
const void *kek_source = fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD ? device_master_kek_sources[revision] : device_master_kek_sources_dev[revision];
se_aes_unwrap_key(ks, ks, kek_source);
se_aes_crypt_block_ecb(ks, 0, out_device_key, temp_key);
se_aes_crypt_block_ecb(ks, DECRYPT, out_device_key, temp_key);
}
static bool _test_key_pair(const void *public_exponent, const void *private_exponent, const void *modulus) {

View file

@ -23,6 +23,7 @@
#include <display/di.h>
#include <gfx_utils.h>
#include "gfx/tui.h"
#include "hos/pkg1.h"
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <mem/minerva.h>

View file

@ -160,7 +160,7 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool force
}
// Encrypt and write.
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 1, tweak, true, sector_index_in_cluster, cluster, bis_cache->emmc_buffer, buff, count * NX_EMMC_BLOCKSIZE) ||
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, ENCRYPT, tweak, true, sector_index_in_cluster, cluster, bis_cache->emmc_buffer, buff, count * NX_EMMC_BLOCKSIZE) ||
!nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->emmc_buffer)
)
return 1; // R/W error.
@ -227,7 +227,7 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
// Read and decrypt the whole cluster the sector resides in.
if (!nx_emmc_part_read(&emmc_storage, system_part, aligned_sector, SECTORS_PER_CLUSTER, bis_cache->emmc_buffer) ||
!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, cache_tweak, true, 0, cluster, bis_cache->emmc_buffer, bis_cache->emmc_buffer, XTS_CLUSTER_SIZE)
!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, DECRYPT, cache_tweak, true, 0, cluster, bis_cache->emmc_buffer, bis_cache->emmc_buffer, XTS_CLUSTER_SIZE)
)
return 1; // R/W error.
@ -257,7 +257,7 @@ static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
tweak_exp = sector_index_in_cluster;
// Maximum one cluster (1 XTS crypto block 16KB).
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, bis_cache->emmc_buffer, count * NX_EMMC_BLOCKSIZE))
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, DECRYPT, tweak, regen_tweak, tweak_exp, prev_cluster, buff, bis_cache->emmc_buffer, count * NX_EMMC_BLOCKSIZE))
return 1; // R/W error.
prev_sector = sector + count - 1;