From fc69dc36eea0203ebdb374ea964e9a4f29a4d703 Mon Sep 17 00:00:00 2001 From: "Such Meme, Many Skill" Date: Tue, 19 May 2020 18:20:19 +0200 Subject: [PATCH] Merge lockpickrcm changes --- Makefile | 2 +- common/common_gfx.h | 6 +- common/common_module.h | 2 +- common/memory_map.h | 4 +- source/hos/fss.c | 220 ++++++++++++++++++++++++++++ source/hos/fss.h | 34 +++++ source/hos/hos.h | 120 +++++++++++++++ source/hos/pkg2.c | 8 +- source/hos/pkg2.h | 16 +- source/hos/sept.c | 87 ++++++++--- source/libs/fatfs/diskio.c | 25 ++-- source/libs/fatfs/ff.c | 4 +- source/mem/heap.c | 4 +- source/rtc/max77620-rtc.c | 8 +- source/sec/se.c | 141 ++++++++++++++++-- source/sec/se.h | 5 + source/sec/tsec.c | 15 +- source/sec/tsec.h | 2 - source/soc/hw_init.c | 13 +- source/tegraexplorer/fs/fsactions.c | 21 +-- 20 files changed, 633 insertions(+), 104 deletions(-) create mode 100644 source/hos/fss.c create mode 100644 source/hos/fss.h create mode 100644 source/hos/hos.h diff --git a/Makefile b/Makefile index bd2925c..7f4fdc5 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ include $(DEVKITARM)/base_rules ################################################################################ -IPL_LOAD_ADDR := 0x40008000 +IPL_LOAD_ADDR := 0x40003000 LPVERSION_MAJOR := 3 LPVERSION_MINOR := 0 LPVERSION_BUGFX := 2 diff --git a/common/common_gfx.h b/common/common_gfx.h index 6bae186..d2e579f 100644 --- a/common/common_gfx.h +++ b/common/common_gfx.h @@ -1,9 +1,9 @@ /* * Common Gfx Header * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 CTCaer - * Copyright (c) 2018 M4xw - * + * Copyright (C) 2018 CTCaer + * Copyright (C) 2018 M4xw + * * 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. diff --git a/common/common_module.h b/common/common_module.h index 93a1541..1d3fb89 100644 --- a/common/common_module.h +++ b/common/common_module.h @@ -1,6 +1,6 @@ /* * Common Module Header - * Copyright (c) 2018 M4xw + * Copyright (C) 2018 M4xw * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/common/memory_map.h b/common/memory_map.h index 16272c9..a1a41cb 100644 --- a/common/memory_map.h +++ b/common/memory_map.h @@ -19,8 +19,8 @@ //#define IPL_STACK_TOP 0x4003FF00 /* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ -/* --- IPL: 0x40008000 - 0x40028000 --- */ -#define IPL_LOAD_ADDR 0x40008000 +/* --- IPL: 0x40003000 - 0x40028000 --- */ +#define IPL_LOAD_ADDR 0x40003000 #define IPL_SZ_MAX 0x20000 // 128KB. //#define IRAM_LIB_ADDR 0x4002B000 #define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. diff --git a/source/hos/fss.c b/source/hos/fss.c new file mode 100644 index 0000000..a68deeb --- /dev/null +++ b/source/hos/fss.c @@ -0,0 +1,220 @@ +/* + * 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/config.h" +#include "../libs/fatfs/ff.h" +#include "../mem/heap.h" +#include "../storage/emummc.h" +#include "../storage/nx_sd.h" + +#include "../gfx/gfx.h" +#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 + +// 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. + +// FSS0 Content Flags. +#define CNT_FLAG0_EXPERIMENTAL (1 << 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; + + if (!sept_ctxt) + { + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link) + { + if (!strcmp("stock", kv->key)) + if (kv->val[0] == '1') + stock = true; + } + + if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable)) + 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) + { + 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 (!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_enable_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_EXO: + ctxt->secmon_size = curr_fss_cnt[i].size; + ctxt->secmon = content; + break; + case CNT_TYPE_WBT: + 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); + } + + 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 new file mode 100644 index 0000000..3f56d7c --- /dev/null +++ b/source/hos/fss.h @@ -0,0 +1,34 @@ +/* + * 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/hos.h b/source/hos/hos.h new file mode 100644 index 0000000..d2c8712 --- /dev/null +++ b/source/hos/hos.h @@ -0,0 +1,120 @@ +/* + * 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 . + */ + +#ifndef _HOS_H_ +#define _HOS_H_ + +#include "pkg1.h" +#include "pkg2.h" +#include "../utils/types.h" +#include "../config/ini.h" +#include "../sec/tsec.h" + +#include + +#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_MAX KB_FIRMWARE_VERSION_910 + +#define HOS_PKG11_MAGIC 0x31314B50 +#define HOS_EKS_MAGIC 0x30534B45 + +typedef struct _exo_ctxt_t +{ + bool no_user_exceptions; + bool user_pmu; + bool *cal0_blank; + bool *cal0_allow_writes_sys; +} exo_ctxt_t; + +typedef struct _hos_eks_keys_t +{ + u8 dkg[0x10]; + u8 mkk[0x10]; + u8 fdk[0x10]; + u8 dkk[0x10]; +} hos_eks_keys_t; + +typedef struct _hos_eks_mbr_t +{ + u32 magic; + u32 enabled; + u32 sbk_low[2]; + hos_eks_keys_t keys[6]; + u32 magic2; + u32 rsvd2[3]; +} hos_eks_mbr_t; + +static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!"); + +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 *pkg2; + u32 pkg2_size; + bool new_pkg2; + + void *kernel; + u32 kernel_size; + link_t kip1_list; + char* kip1_patches; + + u32 fss0_hosver; + bool svcperm; + bool debugmode; + bool stock; + bool atmosphere; + bool fss0_enable_experimental; + bool emummc_forced; + + exo_ctxt_t exo_cfg; + + 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(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt); + +#endif diff --git a/source/hos/pkg2.c b/source/hos/pkg2.c index 74c59c5..09ebb67 100644 --- a/source/hos/pkg2.c +++ b/source/hos/pkg2.c @@ -26,15 +26,15 @@ #include "../gfx/gfx.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(...) -u32 pkg2_newkern_ini1_val; -u32 pkg2_newkern_ini1_start; -u32 pkg2_newkern_ini1_end; - static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) { u32 size = sizeof(pkg2_kip1_t); diff --git a/source/hos/pkg2.h b/source/hos/pkg2.h index 5e7c3de..96e8fe5 100644 --- a/source/hos/pkg2.h +++ b/source/hos/pkg2.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (C) 2018-2020 CTCaer + * 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, @@ -32,6 +32,14 @@ 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]; @@ -87,6 +95,12 @@ typedef struct _pkg2_kip1_info_t 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); diff --git a/source/hos/sept.c b/source/hos/sept.c index 1858533..84d0181 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -17,15 +17,20 @@ #include #include "sept.h" +#include "../config/ini.h" #include "../gfx/di.h" +#include "../hos/fss.h" +#include "../hos/hos.h" #include "../libs/fatfs/ff.h" #include "../mem/heap.h" #include "../soc/hw_init.h" #include "../soc/pmc.h" #include "../soc/t210.h" #include "../storage/nx_emmc.h" +#include "../storage/nx_sd.h" #include "../storage/sdmmc.h" #include "../utils/btn.h" +#include "../utils/list.h" #include "../utils/types.h" #include "../gfx/gfx.h" @@ -58,48 +63,81 @@ u8 warmboot_reboot[] = { extern u32 color_idx; extern boot_cfg_t b_cfg; -extern void sd_unmount(); 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; - // Copy sept-primary. - if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ)) - goto error; + 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); - if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL)) - { - f_close(&fp); - goto error; + found = true; + break; + } + } + } + if (found) + break; + } } - f_close(&fp); - // Copy sept-secondary. - if (kb < KB_FIRMWARE_VERSION_810) + + if (!fss0_sept_used) { - 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)) + // Copy sept-primary. + if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ)) goto error; - } - if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL)) - { + 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); - goto error; } - f_close(&fp); // Save auto boot config to sept payload, if any. boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t)); @@ -107,7 +145,8 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb) tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN; - if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE)) { + if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE)) + { free(tmp_cfg); goto error; } diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c index 62d8373..9edd52a 100644 --- a/source/libs/fatfs/diskio.c +++ b/source/libs/fatfs/diskio.c @@ -81,8 +81,10 @@ static inline void _gf256_mul_x_le(void *block) { static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) { int res = 0; - u8 *pdst = (u8 *)dst; - u8 *psrc = (u8 *)src; + u8 *temptweak = (u8 *)malloc(0x10); + u32 *pdst = (u32 *)dst; + u32 *psrc = (u32 *)src; + u32 *ptweak = (u32 *)tweak; if (regen_tweak) { for (int i = 0xF; i >= 0; i--) { @@ -96,34 +98,33 @@ static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_twe for (u32 i = 0; i < tweak_exp * 0x20; i++) _gf256_mul_x_le(tweak); - u8 temptweak[0x10]; memcpy(temptweak, tweak, 0x10); //We are assuming a 0x10-aligned sector size in this implementation. for (u32 i = 0; i < secsize / 0x10; i++) { - for (u32 j = 0; j < 0x10; j++) - pdst[j] = psrc[j] ^ tweak[j]; + for (u32 j = 0; j < 4; j++) + pdst[j] = psrc[j] ^ ptweak[j]; _gf256_mul_x_le(tweak); - psrc += 0x10; - pdst += 0x10; + psrc += 4; + pdst += 4; } se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize); - pdst = (u8 *)dst; + pdst = (u32 *)dst; memcpy(tweak, temptweak, 0x10); for (u32 i = 0; i < secsize / 0x10; i++) { - for (u32 j = 0; j < 0x10; j++) - pdst[j] = pdst[j] ^ tweak[j]; + for (u32 j = 0; j < 4; j++) + pdst[j] = pdst[j] ^ ptweak[j]; _gf256_mul_x_le(tweak); - pdst += 0x10; + pdst += 4; } - res = 1; out:; + free(temptweak); return res; } diff --git a/source/libs/fatfs/ff.c b/source/libs/fatfs/ff.c index 2464273..736568f 100644 --- a/source/libs/fatfs/ff.c +++ b/source/libs/fatfs/ff.c @@ -42,8 +42,8 @@ #include "../../storage/sdmmc.h" extern sdmmc_storage_t sd_storage; -#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); -//#define EFSPRINTF(...) +//#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); +#define EFSPRINTF(...) /*-------------------------------------------------------------------------- diff --git a/source/mem/heap.c b/source/mem/heap.c index 4ed7230..7c0e202 100644 --- a/source/mem/heap.c +++ b/source/mem/heap.c @@ -136,7 +136,7 @@ void *malloc(u32 size) void *calloc(u32 num, u32 size) { void *res = (void *)_heap_alloc(&_heap, num * size); - memset(res, 0, num * size); + memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size. return res; } @@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats) count, node->used, (u32)node + sizeof(hnode_t), node->size); count++; - + if (node->next) node = node->next; else diff --git a/source/rtc/max77620-rtc.c b/source/rtc/max77620-rtc.c index 385c936..d2a780a 100644 --- a/source/rtc/max77620-rtc.c +++ b/source/rtc/max77620-rtc.c @@ -2,7 +2,7 @@ * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * * Copyright (c) 2018-2019 CTCaer - * Copyright (c) 2019 shchmue + * Copyright (c) 2019-2020 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, @@ -35,10 +35,10 @@ void max77620_rtc_get_time(rtc_time_t *time) // Get time. time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F; time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F; - u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG); - time->hour = hour & 0x1F; - if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK)) + time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F; + + if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK) time->hour = (time->hour & 0xF) + 12; // Get day of week. 1: Monday to 7: Sunday. diff --git a/source/sec/se.c b/source/sec/se.c index 6eb4700..484f3c8 100644 --- a/source/sec/se.c +++ b/source/sec/se.c @@ -19,6 +19,7 @@ #include +#include "../../common/memory_map.h" #include "../sec/se.h" #include "../mem/heap.h" #include "../soc/bpmp.h" @@ -94,7 +95,12 @@ static int _se_wait() static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) { - se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0; + static se_ll_t *ll_dst = NULL, *ll_src = NULL; + if (!ll_dst) + { + ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t)); + ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); + } if (dst) { @@ -234,6 +240,16 @@ void se_aes_key_set(u32 ks, const void *key, u32 size) } } +void se_aes_iv_set(u32 ks, const void *iv, u32 size) +{ + u32 *data = (u32 *)iv; + for (u32 i = 0; i < size / 4; i++) + { + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i; + SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; + } +} + void se_aes_key_read(u32 ks, void *key, u32 size) { u32 *data = (u32 *)key; @@ -320,12 +336,90 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s return 1; } +// random calls were derived from Atmosphère's +int se_initialize_rng(u32 ks) +{ + u8 *output_buf = (u8 *)malloc(0x10); + + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); + SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001; + SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); + SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + + int res =_se_execute(OP_START, output_buf, 0x10, NULL, 0); + + free(output_buf); + return res; +} + +int se_generate_random(u32 ks, void *dst, u32 size) +{ + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); + + u32 num_blocks = size >> 4; + u32 aligned_size = num_blocks << 4; + if (num_blocks) + { + SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1; + if (!_se_execute(OP_START, dst, aligned_size, NULL, 0)) + return 0; + } + if (size > aligned_size) + return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0); + return 1; +} + +int se_generate_random_key(u32 ks_dst, u32 ks_src) +{ + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY); + + SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); + if (!_se_execute(OP_START, NULL, 0, NULL, 0)) + return 0; + SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1; + if (!_se_execute(OP_START, NULL, 0, NULL, 0)) + return 0; + + return 1; +} + +int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) +{ + if (enc) + { + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | + SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | + SE_CRYPTO_IV_SEL(IV_ORIGINAL); + } + else + { + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) | + SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | + SE_CRYPTO_IV_SEL(IV_ORIGINAL); + } + SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; + return _se_execute(OP_START, dst, dst_size, src, src_size); +} + int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize) { int res = 0; u8 *tweak = (u8 *)malloc(0x10); - u8 *pdst = (u8 *)dst; - u8 *psrc = (u8 *)src; + u8 *temptweak = (u8 *)malloc(0x10); + u32 *pdst = (u32 *)dst; + u32 *psrc = (u32 *)src; + u32 *ptweak = (u32 *)tweak; //Generate tweak. for (int i = 0xF; i >= 0; i--) @@ -336,23 +430,35 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak)) goto out; + memcpy(temptweak, tweak, 0x10); + //We are assuming a 0x10-aligned sector size in this implementation. for (u32 i = 0; i < secsize / 0x10; i++) { - for (u32 j = 0; j < 0x10; j++) - pdst[j] = psrc[j] ^ tweak[j]; - if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst)) - goto out; - for (u32 j = 0; j < 0x10; j++) - pdst[j] = pdst[j] ^ tweak[j]; + for (u32 j = 0; j < 4; j++) + pdst[j] = psrc[j] ^ ptweak[j]; _gf256_mul_x_le(tweak); - psrc += 0x10; - pdst += 0x10; + psrc += 4; + pdst += 4; + } + + se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize); + + pdst = (u32 *)dst; + + memcpy(tweak, temptweak, 0x10); + for (u32 i = 0; i < secsize / 0x10; i++) + { + for (u32 j = 0; j < 4; j++) + pdst[j] = pdst[j] ^ ptweak[j]; + _gf256_mul_x_le(tweak); + pdst += 4; } res = 1; out:; + free(temptweak); free(tweak); return res; } @@ -390,17 +496,21 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) se_aes_key_iv_clear(ks); u32 num_blocks = (src_size + 0xf) >> 4; - if (num_blocks > 1) { + if (num_blocks > 1) + { SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2; if (!_se_execute(OP_START, NULL, 0, src, src_size)) goto out; SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED); } - if (src_size & 0xf) { + if (src_size & 0xf) + { memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf); last_block[src_size & 0xf] = 0x80; - } else if (src_size >= 0x10) { + } + else if (src_size >= 0x10) + { memcpy(last_block, src + src_size - 0x10, 0x10); } @@ -447,7 +557,8 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size) return res; } -int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) { +int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) +{ int res = 0; u8 *secret = (u8 *)malloc(0x40); u8 *ipad = (u8 *)malloc(0x40 + src_size); diff --git a/source/sec/se.h b/source/sec/se.h index 0d517c7..211c279 100644 --- a/source/sec/se.h +++ b/source/sec/se.h @@ -25,12 +25,17 @@ void se_rsa_key_clear(u32 ks); int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); void se_key_acc_ctrl(u32 ks, u32 flags); void se_aes_key_set(u32 ks, const void *key, u32 size); +void se_aes_iv_set(u32 ks, const void *iv, u32 size); void se_aes_key_read(u32 ks, void *key, u32 size); void se_aes_key_clear(u32 ks); +int se_initialize_rng(u32 ks); +int se_generate_random(u32 ks, void *dst, u32 size); +int se_generate_random_key(u32 ks_dst, u32 ks_src); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input); int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr); +int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size); int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize); int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs); int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); diff --git a/source/sec/tsec.c b/source/sec/tsec.c index 5a1f85e..0a8169e 100644 --- a/source/sec/tsec.c +++ b/source/sec/tsec.c @@ -18,6 +18,7 @@ #include +#include "../hos/hos.h" #include "../sec/tsec.h" #include "../sec/tsec_t210.h" #include "../sec/se_t210.h" @@ -80,7 +81,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) kfuse_wait_ready(); - // Configure Falcon. + //Configure Falcon. TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_IRQMSET) = TSEC_IRQMSET_EXT(0xFF) | @@ -102,7 +103,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) goto out; } - // Load firmware or emulate memio environment for newer TSEC fw. + //Load firmware or emulate memio environment for newer TSEC fw. if (kb == KB_FIRMWARE_VERSION_620) TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8; else @@ -126,7 +127,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) { // Init SMMU translation for TSEC. pdir = smmu_init_for_tsec(); - smmu_init(tsec_ctxt->secmon_base); + smmu_init(0x4002B000); // Enable SMMU if (!smmu_is_used()) smmu_enable(); @@ -169,7 +170,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) iram = page_alloc(0x30); memcpy(iram, tsec_ctxt->pkg1, 0x30000); // PKG1.1 magic offset. - pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4)); + pkg11_magic_off = (u32 *)(iram + (0x7000 / 4)); smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE); // Exception vectors @@ -177,7 +178,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE); } - // Execute firmware. + //Execute firmware. HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA; TSEC(TSEC_STATUS) = 0; TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1. @@ -254,7 +255,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt) goto out_free; } - // Fetch result. + //Fetch result. HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0; u32 buf[4]; buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB); @@ -274,7 +275,7 @@ out_free:; out:; - // Disable clocks. + //Disable clocks. clock_disable_kfuse(); clock_disable_sor1(); clock_disable_sor0(); diff --git a/source/sec/tsec.h b/source/sec/tsec.h index 83b1d1f..5d15fb5 100644 --- a/source/sec/tsec.h +++ b/source/sec/tsec.h @@ -27,8 +27,6 @@ typedef struct _tsec_ctxt_t void *fw; u32 size; void *pkg1; - u32 pkg11_off; - u32 secmon_base; } tsec_ctxt_t; typedef struct _tsec_key_data_t diff --git a/source/soc/hw_init.c b/source/soc/hw_init.c index f5df093..8867ff2 100644 --- a/source/soc/hw_init.c +++ b/source/soc/hw_init.c @@ -26,7 +26,6 @@ #include "pinmux.h" #include "pmc.h" #include "t210.h" -#include "uart.h" #include "../gfx/di.h" #include "../mem/mc.h" #include "../mem/minerva.h" @@ -102,7 +101,7 @@ void _config_gpios() pinmux_config_i2c(I2C_1); pinmux_config_i2c(I2C_5); - pinmux_config_uart(UART_A); + pinmux_config_uart(0); // Configure volume up/down as inputs. gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO); @@ -295,11 +294,6 @@ void config_hw() APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0; _config_gpios(); -#ifdef DEBUG_UART_PORT - clock_enable_uart(DEBUG_UART_PORT); - uart_init(DEBUG_UART_PORT, 115200); -#endif - clock_enable_cl_dvfs(); clock_enable_i2c(I2C_1); @@ -319,6 +313,7 @@ void config_hw() sdram_init(); bpmp_mmu_enable(); + mc_enable_ahb_redirect(); // Clear flags from PMC_SCRATCH0 PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD; @@ -334,7 +329,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic) // Re-enable clocks to Audio Processing Engine as a workaround to hanging. CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock. if (extra_reconfig) { @@ -357,7 +352,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic) if (magic == 0xBAADF00D) { CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22); - sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); + sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0); clock_disable_cl_dvfs(); msleep(200); diff --git a/source/tegraexplorer/fs/fsactions.c b/source/tegraexplorer/fs/fsactions.c index 1edc6c2..d12e13a 100644 --- a/source/tegraexplorer/fs/fsactions.c +++ b/source/tegraexplorer/fs/fsactions.c @@ -15,7 +15,6 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ FIL in, out; FILINFO in_info; u64 sizeRemaining, toCopy; - UINT temp1, temp2; u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL; u32 x, y, i = 11; int res; @@ -56,19 +55,14 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ while (sizeRemaining > 0){ toCopy = MIN(sizeRemaining, BUFSIZE); - if ((res = f_read(&in, buff, toCopy, &temp1))){ + if ((res = f_read(&in, buff, toCopy, NULL))){ gfx_errDisplay("copy", res, 5); - return 1; + break; } - if ((res = f_write(&out, buff, toCopy, &temp2))){ + if ((res = f_write(&out, buff, toCopy, NULL))){ gfx_errDisplay("copy", res, 6); - return 1; - } - - if (temp1 != temp2){ - gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7); - return 1; + break; } sizeRemaining -= toCopy; @@ -100,13 +94,10 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ f_close(&out); free(buff); - if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){ - gfx_errDisplay("copy", res, 8); - return 1; - } + f_chmod(locout, in_info.fattrib, 0x3A); f_stat(locin, &in_info); //somehow stops fatfs from being weird - return 0; + return res; } int fsact_del_recursive(char *path){