diff --git a/source/config/config.c b/source/config/config.c index adcfee4..34b148b 100644 --- a/source/config/config.c +++ b/source/config/config.c @@ -45,7 +45,6 @@ void set_default_configuration() h_cfg.brand = NULL; h_cfg.tagline = NULL; h_cfg.errors = 0; - h_cfg.eks = NULL; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.rcm_patched = true; h_cfg.emummc_force_disable = false; diff --git a/source/config/config.h b/source/config/config.h index 012fea9..0410a7e 100644 --- a/source/config/config.h +++ b/source/config/config.h @@ -17,7 +17,6 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#include "../hos/hos.h" #include "../utils/types.h" typedef struct _hekate_config @@ -39,7 +38,6 @@ typedef struct _hekate_config bool rcm_patched; u32 sbar_time_keeping; u32 errors; - hos_eks_mbr_t *eks; } hekate_config; void set_default_configuration(); diff --git a/source/hos/fss.c b/source/hos/fss.c deleted file mode 100644 index b359880..0000000 --- a/source/hos/fss.c +++ /dev/null @@ -1,247 +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/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; - -static void _update_r2p(const char *path) -{ - char *r2p_path = malloc(256); - u32 path_len = strlen(path); - strcpy(r2p_path, path); - - while(path_len) - { - if ((r2p_path[path_len - 1] == '/') || (r2p_path[path_len - 1] == 0x5C)) - { - r2p_path[path_len] = 0; - strcat(r2p_path, "reboot_payload.bin"); - u8 *r2p_payload = sd_file_read(r2p_path, NULL); - - is_ipl_updated(r2p_payload, r2p_path, h_cfg.updater2p ? true : false); - - free(r2p_payload); - break; - } - path_len--; - } - - free(r2p_path); -} - -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); - - _update_r2p(path); - - 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 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/hos.c b/source/hos/hos.c deleted file mode 100644 index 2ef2d4b..0000000 --- a/source/hos/hos.c +++ /dev/null @@ -1,953 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 st4rk - * Copyright (c) 2018 Ced2911 - * Copyright (c) 2018-2020 CTCaer - * Copyright (c) 2018 balika011 - * - * 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 "hos_config.h" -#include "sept.h" -#include "secmon_exo.h" -#include "../config/config.h" -#include "../gfx/di.h" -#include "../mem/heap.h" -#include "../mem/mc.h" -#include "../mem/minerva.h" -#include "../sec/se.h" -#include "../sec/se_t210.h" -#include "../sec/tsec.h" -#include "../soc/bpmp.h" -#include "../soc/cluster.h" -#include "../soc/fuse.h" -#include "../soc/pmc.h" -#include "../soc/smmu.h" -#include "../soc/t210.h" -#include "../storage/emummc.h" -#include "../storage/nx_emmc.h" -#include "../storage/nx_sd.h" -#include "../storage/sdmmc.h" -#include "../utils/util.h" -#include "../gfx/gfx.h" - -extern hekate_config h_cfg; - -//#define DPRINTF(...) gfx_printf(__VA_ARGS__) -#define DPRINTF(...) - -#define EHPRINTFARGS(text, args...) \ - ({ display_backlight_brightness(h_cfg.backlight, 1000); \ - gfx_con.mute = false; \ - gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC); }) - -#define PKG2_LOAD_ADDR 0xA9800000 - - // Secmon mailbox. -#define SECMON_MB_ADDR 0x40002EF8 -#define SECMON7_MB_ADDR 0x400000F8 -typedef struct _secmon_mailbox_t -{ - // < 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot. - // >= 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot. - u32 in; - // Non-zero: Secmon ready. - u32 out; -} secmon_mailbox_t; - -static const u8 keyblob_keyseeds[][0x10] = { - { 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 - { 0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE }, //4.0.0 - { 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 }, //5.0.0 - { 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } //6.0.0 -}; - -static const u8 cmac_keyseed[0x10] = - { 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 }; - -static const u8 master_keyseed_retail[0x10] = - { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C }; - -static const u8 console_keyseed[0x10] = - { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 }; - -const u8 package2_keyseed[] = - { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; - -static const u8 master_keyseed_4xx_5xx_610[0x10] = - { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; - -static const u8 master_keyseed_620[0x10] = - { 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A }; - -static const u8 console_keyseed_4xx_5xx[0x10] = - { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; - -static void _hos_crit_error(const char *text) -{ - gfx_con.mute = false; - gfx_printf("%k%s%k\n", 0xFFFF0000, text, 0xFFCCCCCC); - - display_backlight_brightness(h_cfg.backlight, 1000); -} - -static void _se_lock(bool lock_se) -{ - if (lock_se) - { - for (u32 i = 0; i < 16; i++) - se_key_acc_ctrl(i, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); - - for (u32 i = 0; i < 2; i++) - se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG); - SE(SE_TZRAM_SECURITY_0) = 0; // Make SE TZRAM secure only. - SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only. - SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only. - SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only. - } - - memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32)); - SB(SB_CSR) = SB_CSR_PIROM_DISABLE; - - // This is useful for documenting the bits in the SE config registers, so we can keep it around. - /*gfx_printf("SE(SE_SECURITY_0) = %08X\n", SE(SE_SECURITY_0)); - gfx_printf("SE(0x4) = %08X\n", SE(0x4)); - gfx_printf("SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET)); - gfx_printf("SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET)); - for(u32 i = 0; i < 16; i++) - gfx_printf("%02X ", SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF); - gfx_putc('\n'); - for(u32 i = 0; i < 2; i++) - gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF); - gfx_putc('\n'); - gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/ -} - -void _pmc_scratch_lock(u32 kb) -{ - switch (kb) - { - case KB_FIRMWARE_VERSION_100_200: - case KB_FIRMWARE_VERSION_300: - case KB_FIRMWARE_VERSION_301: - PMC(APBDEV_PMC_SEC_DISABLE) = 0x7FFFF3; - PMC(APBDEV_PMC_SEC_DISABLE2) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE3) = 0xFFAFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE4) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE6) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE7) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE8) = 0xFFAAFFFF; - break; - default: - PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; - PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; - PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; - PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; - PMC(APBDEV_PMC_SEC_DISABLE7) |= 0x3FFFFF; - PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF; - break; - } -} - -void _sysctr0_reset() -{ - SYSCTR0(SYSCTR0_CNTCR) = 0; - SYSCTR0(SYSCTR0_COUNTERID0) = 0; - SYSCTR0(SYSCTR0_COUNTERID1) = 0; - SYSCTR0(SYSCTR0_COUNTERID2) = 0; - SYSCTR0(SYSCTR0_COUNTERID3) = 0; - SYSCTR0(SYSCTR0_COUNTERID4) = 0; - SYSCTR0(SYSCTR0_COUNTERID5) = 0; - SYSCTR0(SYSCTR0_COUNTERID6) = 0; - SYSCTR0(SYSCTR0_COUNTERID7) = 0; - SYSCTR0(SYSCTR0_COUNTERID8) = 0; - SYSCTR0(SYSCTR0_COUNTERID9) = 0; - SYSCTR0(SYSCTR0_COUNTERID10) = 0; - SYSCTR0(SYSCTR0_COUNTERID11) = 0; -} - -void hos_eks_get() -{ - // Check if EKS already found and parsed. - if (!h_cfg.eks) - { - u8 *mbr = calloc(512 , 1); - - // Read EKS blob. - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - - // Decrypt EKS blob. - hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x10); - se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t)); - - // Check if valid and for this unit. - if (eks->enabled && - eks->magic == HOS_EKS_MAGIC && - eks->magic2 == HOS_EKS_MAGIC && - eks->sbk_low[0] == FUSE(FUSE_PRIVATE_KEY0) && - eks->sbk_low[1] == FUSE(FUSE_PRIVATE_KEY1)) - { - h_cfg.eks = eks; - return; - } - - free(mbr); - } -} - -void hos_eks_save(u32 kb) -{ - if (kb >= KB_FIRMWARE_VERSION_700) - { - // Only 6 Master keys for now. - u8 key_idx = kb - KB_FIRMWARE_VERSION_700; - if (key_idx > 5) - return; - - if (!h_cfg.eks) - h_cfg.eks = calloc(512 , 1); - - // If matching blob doesn't exist, create it. - if (!(h_cfg.eks->enabled & (1 << key_idx))) - { - // Get keys. - u8 *keys = (u8 *)calloc(0x1000, 1); - se_get_aes_keys(keys + 0x800, keys, 0x10); - - // Set magic and personalized info. - h_cfg.eks->magic = HOS_EKS_MAGIC; - h_cfg.eks->magic2 = HOS_EKS_MAGIC; - h_cfg.eks->enabled |= 1 << key_idx; - h_cfg.eks->sbk_low[0] = FUSE(FUSE_PRIVATE_KEY0); - h_cfg.eks->sbk_low[1] = FUSE(FUSE_PRIVATE_KEY1); - - // Copy new keys. - memcpy(h_cfg.eks->keys[key_idx].dkg, keys + 10 * 0x10, 0x10); - memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10); - memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10); - memcpy(h_cfg.eks->keys[key_idx].dkk, keys + 15 * 0x10, 0x10); - - // Encrypt EKS. - u8 *eks = calloc(512 , 1); - memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); - se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t)); - - // Write EKS to SD. - u8 *mbr = calloc(512 , 1); - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t)); - sdmmc_storage_write(&sd_storage, 0, 1, mbr); - - free(eks); - free(mbr); - free(keys); - } - } -} - -void hos_eks_clear(u32 kb) -{ - if (h_cfg.eks && kb >= KB_FIRMWARE_VERSION_700) - { - // Check if Current Master key is enabled. - u8 key_idx = kb - KB_FIRMWARE_VERSION_700; - if (h_cfg.eks->enabled & (1 << key_idx)) - { - // Disable current Master key version. - h_cfg.eks->enabled &= ~(1 << key_idx); - - // Encrypt EKS. - u8 *eks = calloc(512 , 1); - memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); - se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t)); - - // Write EKS to SD. - u8 *mbr = calloc(512 , 1); - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - memcpy(mbr + 0x10, eks, sizeof(hos_eks_mbr_t)); - sdmmc_storage_write(&sd_storage, 0, 1, mbr); - - free(eks); - free(mbr); - } - } -} - -int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt) -{ - u8 tmp[0x20]; - u32 retries = 0; - - if (kb > KB_FIRMWARE_VERSION_MAX) - return 0; - - if (kb <= KB_FIRMWARE_VERSION_600) - tsec_ctxt->size = 0xF00; - else if (kb == KB_FIRMWARE_VERSION_620) - tsec_ctxt->size = 0x2900; - else if (kb == KB_FIRMWARE_VERSION_700) - tsec_ctxt->size = 0x3000; - else - tsec_ctxt->size = 0x3300; - - // Prepare smmu tsec page for 6.2.0. - if (kb == KB_FIRMWARE_VERSION_620) - { - u8 *tsec_paged = (u8 *)page_alloc(3); - memcpy(tsec_paged, (void *)tsec_ctxt->fw, tsec_ctxt->size); - tsec_ctxt->fw = tsec_paged; - } - - // Get TSEC key. - if (kb <= KB_FIRMWARE_VERSION_620) - { - while (tsec_query(tmp, kb, tsec_ctxt) < 0) - { - memset(tmp, 0x00, 0x20); - retries++; - - // We rely on racing conditions, make sure we cover even the unluckiest cases. - if (retries > 15) - { - _hos_crit_error("\nFailed to get TSEC keys. Please try again."); - return 0; - } - } - } - - if (kb >= KB_FIRMWARE_VERSION_700) - { - // Use HOS EKS if it exists. - u8 key_idx = kb - KB_FIRMWARE_VERSION_700; - if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) - { - // Set Device keygen key to slot 10. - se_aes_key_set(10, h_cfg.eks->keys[key_idx].dkg, 0x10); - // Set Master key to slot 12. - se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10); - // Set FW Device key key to slot 13. - se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10); - // Set Device key to slot 15. - se_aes_key_set(15, h_cfg.eks->keys[key_idx].dkk, 0x10); - - // Lock FDK. - se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); - } - - se_aes_key_clear(8); - se_aes_unwrap_key(8, 12, package2_keyseed); - } - else if (kb == KB_FIRMWARE_VERSION_620) - { - // Set TSEC key. - se_aes_key_set(12, tmp, 0x10); - // Set TSEC root key. - se_aes_key_set(13, tmp + 0x10, 0x10); - - if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock) - { - // Package2 key. - se_aes_key_set(8, tmp + 0x10, 0x10); - se_aes_unwrap_key(8, 8, master_keyseed_620); - se_aes_unwrap_key(8, 8, master_keyseed_retail); - se_aes_unwrap_key(8, 8, package2_keyseed); - } - else - { - // Decrypt keyblob and set keyslots - se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp + 0x20); - se_aes_unwrap_key(14, 15, console_keyseed_4xx_5xx); - se_aes_unwrap_key(15, 15, console_keyseed); - - se_aes_unwrap_key(13, 13, master_keyseed_620); - se_aes_unwrap_key(12, 13, master_keyseed_retail); - se_aes_unwrap_key(10, 13, master_keyseed_4xx_5xx_610); - - // Package2 key. - se_aes_unwrap_key(8, 12, package2_keyseed); - - h_cfg.se_keygen_done = 1; - } - } - else - { - se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); - se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); - - // Set TSEC key. - se_aes_key_set(13, tmp, 0x10); - - // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); - se_aes_unwrap_key(15, 14, tmp); - se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); - se_aes_unwrap_key(13, 14, tmp); - - // Clear SBK. - se_aes_key_clear(14); - - //TODO: verify keyblob CMAC. - //se_aes_unwrap_key(11, 13, cmac_keyseed); - //se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0); - //if (!memcmp(keyblob, tmp, 0x10)) - // return 0; - - se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed); - se_aes_unwrap_key(11, 13, cmac_keyseed); - - // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); - se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key. - se_aes_key_set(12, keyblob + 0x20, 0x10); - se_aes_key_set(13, keyblob + 0x20, 0x10); - - se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail); - - switch (kb) - { - case KB_FIRMWARE_VERSION_100_200: - case KB_FIRMWARE_VERSION_300: - case KB_FIRMWARE_VERSION_301: - se_aes_unwrap_key(13, 15, console_keyseed); - se_aes_unwrap_key(12, 12, master_keyseed_retail); - break; - case KB_FIRMWARE_VERSION_400: - se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx); - se_aes_unwrap_key(15, 15, console_keyseed); - se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610); - se_aes_unwrap_key(12, 12, master_keyseed_retail); - break; - case KB_FIRMWARE_VERSION_500: - case KB_FIRMWARE_VERSION_600: - se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); - se_aes_unwrap_key(15, 15, console_keyseed); - se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610); - se_aes_unwrap_key(12, 12, master_keyseed_retail); - break; - } - - // Package2 key. - se_key_acc_ctrl(8, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG); - se_aes_unwrap_key(8, 12, package2_keyseed); - } - - return 1; -} - -static int _read_emmc_pkg1(launch_ctxt_t *ctxt) -{ - sdmmc_storage_t storage; - sdmmc_t sdmmc; - - int res = emummc_storage_init_mmc(&storage, &sdmmc); - - if (res) - { - if (res == 2) - _hos_crit_error("Failed to init eMMC"); - else - _hos_crit_error("Failed to init emuMMC"); - - return 0; - } - - // Read package1. - ctxt->pkg1 = (void *)malloc(0x40000); - emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, ctxt->pkg1); - ctxt->pkg1_id = pkg1_identify(ctxt->pkg1); - if (!ctxt->pkg1_id) - { - _hos_crit_error("Unknown pkg1 version."); - EHPRINTFARGS("%sNot yet supported HOS version!", - (emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "Is emuMMC corrupt?\nOr " : ""); - goto out; - } - gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb); - - // Read the correct keyblob. - ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); - emummc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob); - - res = 1; - -out:; - sdmmc_storage_end(&storage); - return res; -} - -static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt) -{ - u8 *bctBuf = NULL; - sdmmc_storage_t storage; - sdmmc_t sdmmc; - - int res = emummc_storage_init_mmc(&storage, &sdmmc); - - if (res) - { - if (res == 2) - _hos_crit_error("Failed to init eMMC"); - else - _hos_crit_error("Failed to init emuMMC"); - - return NULL; - } - - emummc_storage_set_mmc_partition(&storage, EMMC_GPP); - - // Parse eMMC GPT. - LIST_INIT(gpt); - nx_emmc_gpt_parse(&gpt, &storage); -DPRINTF("Parsed GPT\n"); - // Find package2 partition. - emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); - if (!pkg2_part) - goto out; - - // Read in package2 header and get package2 real size. - //TODO: implement memalign for DMA buffers. - static const u32 BCT_SIZE = 0x4000; - bctBuf = (u8 *)malloc(BCT_SIZE); - nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, 1, bctBuf); - u32 *hdr = (u32 *)(bctBuf + 0x100); - u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3]; -DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size); - - // Read in Boot Config. - memset(bctBuf, 0, BCT_SIZE); - nx_emmc_part_read(&storage, pkg2_part, 0, BCT_SIZE / NX_EMMC_BLOCKSIZE, bctBuf); - - // Read in package2. - u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE); -DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned); - ctxt->pkg2 = malloc(pkg2_size_aligned); - ctxt->pkg2_size = pkg2_size; - nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, - pkg2_size_aligned / NX_EMMC_BLOCKSIZE, ctxt->pkg2); -out:; - nx_emmc_gpt_free(&gpt); - sdmmc_storage_end(&storage); - - return bctBuf; -} - -static void _free_launch_components(launch_ctxt_t *ctxt) -{ - free(ctxt->keyblob); - free(ctxt->pkg1); - free(ctxt->pkg2); - free(ctxt->warmboot); - free(ctxt->secmon); - free(ctxt->kernel); - free(ctxt->kip1_patches); -} - -static bool _get_fs_exfat_compatible(link_t *info) -{ - u32 fs_idx; - u32 fs_ids_cnt; - u32 sha_buf[32 / sizeof(u32)]; - kip1_id_t *kip_ids; - - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) - { - if (strncmp((const char*)ki->kip1->name, "FS", 2)) - continue; - - if (!se_calc_sha256(sha_buf, ki->kip1, ki->size)) - break; - - pkg2_get_ids(&kip_ids, &fs_ids_cnt); - - for (fs_idx = 0; fs_idx < fs_ids_cnt; fs_idx++) - if (!memcmp(sha_buf, kip_ids[fs_idx].hash, 8)) - break; - - // Return false if FAT32 only. - if (fs_ids_cnt <= fs_idx && !(fs_idx & 1)) - return false; - - break; - } - - return true; -} - -int hos_launch(ini_sec_t *cfg) -{ - minerva_change_freq(FREQ_1600); - launch_ctxt_t ctxt; - tsec_ctxt_t tsec_ctxt; - volatile secmon_mailbox_t *secmon_mb; - - memset(&ctxt, 0, sizeof(launch_ctxt_t)); - memset(&tsec_ctxt, 0, sizeof(tsec_ctxt_t)); - list_init(&ctxt.kip1_list); - - ctxt.cfg = cfg; - - if (!gfx_con.mute) - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - gfx_printf("Initializing...\n\n"); - - // Read package1 and the correct keyblob. - if (!_read_emmc_pkg1(&ctxt)) - return 0; - - // Try to parse config if present. - if (ctxt.cfg && !parse_boot_config(&ctxt)) - { - _hos_crit_error("Wrong ini cfg or missing files!"); - return 0; - } - - // Enable emummc patching. - if (emu_cfg.enabled && !h_cfg.emummc_force_disable) - { - if (ctxt.stock) - { - _hos_crit_error("Stock emuMMC is not supported yet!"); - return 0; - } - - ctxt.atmosphere = true; // Set atmosphere patching in case of Stock emuMMC and no fss0. - config_kip1patch(&ctxt, "emummc"); - } - else if (!emu_cfg.enabled && ctxt.emummc_forced) - { - _hos_crit_error("emuMMC is forced but not enabled!"); - return 0; - } - - // Check if fuses lower than 4.0.0 or 9.0.0 and if yes apply NO Gamecard patch. - // Additionally check if running emuMMC and disable GC if v3 fuses are burnt and HOS is <= 8.1.0. - if (!ctxt.stock) - { - u32 fuses = fuse_read_odm(7); - if ((h_cfg.autonogc && - ((!(fuses & ~0xF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2. - (!(fuses & ~0x3FF) && (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_900)))) // LAFW v3. - || ((emu_cfg.enabled && !h_cfg.emummc_force_disable) && - ((fuses & 0x400) && (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_810)))) - config_kip1patch(&ctxt, "nogc"); - } - - gfx_printf("Loaded config, pkg1 and keyblob\n"); - - // Generate keys. - if (!h_cfg.se_keygen_done) - { - tsec_ctxt.fw = (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off; - tsec_ctxt.pkg1 = ctxt.pkg1; - tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off; - tsec_ctxt.secmon_base = ctxt.pkg1_id->secmon_base; - - if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) - { - _hos_crit_error("Failed to run sept"); - return 0; - } - - if (!hos_keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt)) - return 0; - gfx_printf("Generated keys\n"); - if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600) - h_cfg.se_keygen_done = 1; - } - - // Decrypt and unpack package1 if we require parts of it. - if (!ctxt.warmboot || !ctxt.secmon) - { - if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600) - pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1); - - if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && !(emu_cfg.enabled && !h_cfg.emummc_force_disable)) - { - pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1); - gfx_printf("Decrypted & unpacked pkg1\n"); - } - else - { - _hos_crit_error("No mandatory secmon or warmboot provided!"); - return 0; - } - } - - // Replace 'warmboot.bin' if requested. - if (ctxt.warmboot) - memcpy((void *)ctxt.pkg1_id->warmboot_base, ctxt.warmboot, ctxt.warmboot_size); - else - { - if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700) - { - _hos_crit_error("No warmboot provided!"); - return 0; - } - // Else we patch it to allow downgrading. - patch_t *warmboot_patchset = ctxt.pkg1_id->warmboot_patchset; - gfx_printf("%kPatching Warmboot%k\n", 0xFFFFBA00, 0xFFCCCCCC); - for (u32 i = 0; warmboot_patchset[i].off != 0xFFFFFFFF; i++) - *(vu32 *)(ctxt.pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val; - } - // Set warmboot address in PMC if required. - if (ctxt.pkg1_id->set_warmboot) - PMC(APBDEV_PMC_SCRATCH1) = ctxt.pkg1_id->warmboot_base; - - // Replace 'SecureMonitor' if requested. - if (ctxt.secmon) - memcpy((void *)ctxt.pkg1_id->secmon_base, ctxt.secmon, ctxt.secmon_size); - else if (ctxt.pkg1_id->secmon_patchset) - { - // Else we patch it to allow for an unsigned package2 and patched kernel. - patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset; - gfx_printf("%kPatching Secure Monitor%k\n", 0xFFFFBA00, 0xFFCCCCCC); - for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++) - *(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val; - } - - gfx_printf("Loaded warmboot and secmon\n"); - - // Read package2. - u8 *bootConfigBuf = _read_emmc_pkg2(&ctxt); - if (!bootConfigBuf) - return 0; - - gfx_printf("Read pkg2\n"); - - // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2, ctxt.pkg1_id->kb); - if (!pkg2_hdr) - { - _hos_crit_error("Pkg2 decryption failed!"); - if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700) - { - EPRINTF("Is Sept updated?"); - - // Clear EKS slot, in case something went wrong with sept keygen. - hos_eks_clear(ctxt.pkg1_id->kb); - } - return 0; - } - else if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700) - hos_eks_save(ctxt.pkg1_id->kb); // Save EKS slot if it doesn't exist. - - LIST_INIT(kip1_info); - if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2)) - { - _hos_crit_error("INI1 parsing failed!"); - return 0; - } - - gfx_printf("Parsed ini1\n"); - - // Use the kernel included in package2 in case we didn't load one already. - if (!ctxt.kernel) - { - ctxt.kernel = pkg2_hdr->data; - ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL]; - - if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere)) - { - u8 kernel_hash[0x20]; - // Hash only Kernel when it embeds INI1. - if (!ctxt.new_pkg2) - se_calc_sha256(kernel_hash, ctxt.kernel, ctxt.kernel_size); - else - se_calc_sha256(kernel_hash, ctxt.kernel + PKG2_NEWKERN_START, - pkg2_newkern_ini1_start - PKG2_NEWKERN_START); - - ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash); - if (!ctxt.pkg2_kernel_id) - { - _hos_crit_error("Failed to identify kernel!"); - - return 0; - } - - // In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode. - kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset; - if (kernel_patchset != NULL) - { - gfx_printf("%kPatching kernel%k\n", 0xFFFFBA00, 0xFFCCCCCC); - u32 *temp; - for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++) - { - if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS) - || (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.atmosphere && ctxt.secmon)) - || (ctxt.atmosphere && kernel_patchset[i].id == ATM_GEN_PATCH)) - *(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val; - else if (ctxt.atmosphere && kernel_patchset[i].id == ATM_ARR_PATCH) - { - temp = (u32 *)kernel_patchset[i].ptr; - for (u32 j = 0; j < kernel_patchset[i].val; j++) - *(vu32 *)(ctxt.kernel + kernel_patchset[i].off + (j << 2)) = temp[j]; - } - else if (kernel_patchset[i].id < SVC_VERIFY_DS) - *(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val; - } - } - } - } - - // Merge extra KIP1s into loaded ones. - gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC); - LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link) - pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); - - // Check if FS is compatible with exFAT. - if (!ctxt.stock && sd_fs.fs_type == FS_EXFAT && !_get_fs_exfat_compatible(&kip1_info)) - { - _hos_crit_error("SD Card is exFAT and the installed\nFS only supports FAT32!"); - - _free_launch_components(&ctxt); - return 0; - } - - // Patch kip1s in memory if needed. - const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches); - if (unappliedPatch != NULL) - { - EHPRINTFARGS("Failed to apply '%s'!", unappliedPatch); - - _free_launch_components(&ctxt); - return 0; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated! - } - - // Rebuild and encrypt package2. - pkg2_build_encrypt((void *)PKG2_LOAD_ADDR, ctxt.kernel, ctxt.kernel_size, &kip1_info, ctxt.new_pkg2); - - gfx_printf("Rebuilt & loaded pkg2\n"); - - // Unmount SD card. - sd_unmount(); - - gfx_printf("\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC); - - // Clear pkg1/pkg2 keys. - se_aes_key_clear(8); - se_aes_key_clear(11); - - // Finalize per firmware keys. - int bootStateDramPkg2 = 0; - int bootStatePkg2Continue = 0; - - switch (ctxt.pkg1_id->kb) - { - case KB_FIRMWARE_VERSION_100_200: - case KB_FIRMWARE_VERSION_300: - case KB_FIRMWARE_VERSION_301: - if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_300) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id. - else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. - se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG); - se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG); - bootStateDramPkg2 = 2; - bootStatePkg2Continue = 3; - break; - case KB_FIRMWARE_VERSION_400: - case KB_FIRMWARE_VERSION_500: - case KB_FIRMWARE_VERSION_600: - se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG); - se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG); - default: - bootStateDramPkg2 = 2; - bootStatePkg2Continue = 4; - break; - } - - // Clear BCT area for retail units and copy it over if dev unit. - if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_500) - { - memset((void *)0x4003D000, 0, 0x3000); - if ((fuse_read_odm(4) & 3) == 3) - memcpy((void *)0x4003D000, bootConfigBuf, 0x1000); - } - else - { - memset((void *)0x4003F000, 0, 0x1000); - if ((fuse_read_odm(4) & 3) == 3) - memcpy((void *)0x4003F800, bootConfigBuf, 0x800); - } - free(bootConfigBuf); - - // Config Exosphère if booting full Atmosphère. - if (ctxt.atmosphere && ctxt.secmon) - config_exosphere(&ctxt); - - // Finalize MC carveout. - if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_301) - mc_config_carveout(); - - // Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches. - _se_lock(ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600); - - // Reset sysctr0 counters. - if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_620) - _sysctr0_reset(); - - // < 4.0.0 pkg1.1 locks PMC scratches. - //_pmc_scratch_lock(ctxt.pkg1_id->kb); - - // Set secmon mailbox address. - if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700) - secmon_mb = (secmon_mailbox_t *)SECMON7_MB_ADDR; - else - secmon_mb = (secmon_mailbox_t *)SECMON_MB_ADDR; - - // Start from DRAM ready signal and reset outgoing value. - secmon_mb->in = bootStateDramPkg2; - secmon_mb->out = 0; - - // Disable display. This must be executed before secmon to provide support for all fw versions. - display_end(); - - // Clear EMC_SCRATCH0. - EMC(EMC_SCRATCH0) = 0; - - // Flush cache and disable MMU. - bpmp_mmu_disable(); - bpmp_clk_rate_set(BPMP_CLK_NORMAL); - minerva_change_freq(FREQ_1600); - - // emuMMC: Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. - sdmmc_storage_init_wait_sd(); - - // Wait for secmon to get ready. - if (smmu_is_used()) - smmu_exit(); - else - cluster_boot_cpu0(ctxt.pkg1_id->secmon_base); - while (!secmon_mb->out) - ; // A usleep(1) only works when in IRAM or with a trained DRAM. - - // Signal pkg2 ready and continue boot. - secmon_mb->in = bootStatePkg2Continue; - - // Halt ourselves in waitevent state and resume if there's JTAG activity. - while (true) - bpmp_halt(); - - return 0; -} diff --git a/source/hos/hos.h b/source/hos/hos.h deleted file mode 100644 index 6378738..0000000 --- a/source/hos/hos.h +++ /dev/null @@ -1,120 +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 . - */ - -#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) < 424, "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/hos_config.c b/source/hos/hos_config.c deleted file mode 100644 index 4c3d789..0000000 --- a/source/hos/hos_config.c +++ /dev/null @@ -1,309 +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 . - */ - -#include - -#include "hos.h" -#include "hos_config.h" -#include "fss.h" -#include "../libs/fatfs/ff.h" -#include "../mem/heap.h" -#include "../storage/nx_sd.h" -#include "../utils/dirlist.h" - -#include "../gfx/gfx.h" - -//#define DPRINTF(...) gfx_printf(__VA_ARGS__) -#define DPRINTF(...) - -static int _config_warmboot(launch_ctxt_t *ctxt, const char *value) -{ - ctxt->warmboot = sd_file_read(value, &ctxt->warmboot_size); - if (!ctxt->warmboot) - return 0; - - return 1; -} - -static int _config_secmon(launch_ctxt_t *ctxt, const char *value) -{ - ctxt->secmon = sd_file_read(value, &ctxt->secmon_size); - if (!ctxt->secmon) - return 0; - - return 1; -} - -static int _config_kernel(launch_ctxt_t *ctxt, const char *value) -{ - ctxt->kernel = sd_file_read(value, &ctxt->kernel_size); - if (!ctxt->kernel) - return 0; - - return 1; -} - -static int _config_kip1(launch_ctxt_t *ctxt, const char *value) -{ - u32 size; - - if (!memcmp(value + strlen(value) - 1, "*", 1)) - { - char *dir = (char *)malloc(256); - strcpy(dir, value); - - u32 dirlen = 0; - dir[strlen(dir) - 2] = 0; - char *filelist = dirlist(dir, "*.kip*", false); - - strcat(dir, "/"); - dirlen = strlen(dir); - - u32 i = 0; - if (filelist) - { - while (true) - { - if (!filelist[i * 256]) - break; - - strcpy(dir + dirlen, &filelist[i * 256]); - - merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t)); - mkip1->kip1 = sd_file_read(dir, &size); - if (!mkip1->kip1) - { - free(mkip1); - free(dir); - free(filelist); - - return 0; - } - DPRINTF("Loaded kip1 from SD (size %08X)\n", size); - list_append(&ctxt->kip1_list, &mkip1->link); - - i++; - } - } - - free(dir); - free(filelist); - } - else - { - merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t)); - mkip1->kip1 = sd_file_read(value, &size); - if (!mkip1->kip1) - { - free(mkip1); - - return 0; - } - DPRINTF("Loaded kip1 from SD (size %08X)\n", size); - list_append(&ctxt->kip1_list, &mkip1->link); - } - - return 1; -} - -int config_kip1patch(launch_ctxt_t *ctxt, const char *value) -{ - if (value == NULL) - return 0; - - int valueLen = strlen(value); - if (!valueLen) - return 0; - - if (ctxt->kip1_patches == NULL) - { - ctxt->kip1_patches = malloc(valueLen + 1); - memcpy(ctxt->kip1_patches, value, valueLen); - ctxt->kip1_patches[valueLen] = 0; - } - else - { - char *oldAlloc = ctxt->kip1_patches; - int oldSize = strlen(oldAlloc); - ctxt->kip1_patches = malloc(oldSize + 1 + valueLen + 1); - memcpy(ctxt->kip1_patches, oldAlloc, oldSize); - free(oldAlloc); - oldAlloc = NULL; - ctxt->kip1_patches[oldSize++] = ','; - memcpy(&ctxt->kip1_patches[oldSize], value, valueLen); - ctxt->kip1_patches[oldSize + valueLen] = 0; - } - return 1; -} - -static int _config_svcperm(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Disabled SVC verification\n"); - ctxt->svcperm = true; - } - return 1; -} - -static int _config_debugmode(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Enabled Debug mode\n"); - ctxt->debugmode = true; - } - return 1; -} - -static int _config_stock(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Disabled all patching\n"); - ctxt->stock = true; - } - return 1; -} - -static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Forced emuMMC\n"); - ctxt->emummc_forced = true; - } - return 1; -} - -static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Enabled atmosphere patching\n"); - ctxt->atmosphere = true; - } - return 1; -} - -static int _config_dis_exo_user_exceptions(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Disabled exosphere user exception handlers\n"); - ctxt->exo_cfg.no_user_exceptions = true; - } - return 1; -} - -static int _config_exo_user_pmu_access(launch_ctxt_t *ctxt, const char *value) -{ - if (*value == '1') - { - DPRINTF("Enabled user access to PMU\n"); - ctxt->exo_cfg.user_pmu = true; - } - return 1; -} - -static int _config_exo_cal0_blanking(launch_ctxt_t *ctxt, const char *value) -{ - // Override key found. - ctxt->exo_cfg.cal0_blank = calloc(1, 1); - - if (*value == '1') - { - DPRINTF("Enabled prodinfo blanking\n"); - *ctxt->exo_cfg.cal0_blank = true; - } - return 1; -} - -static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value) -{ - // Override key found. - ctxt->exo_cfg.cal0_allow_writes_sys = calloc(1, 1); - - if (*value == '1') - { - DPRINTF("Enabled prodinfo writes\n"); - *ctxt->exo_cfg.cal0_allow_writes_sys = true; - } - - return 1; -} - -static int _config_fss(launch_ctxt_t *ctxt, const char *value) -{ - LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link) - { - if (!strcmp("fss0experimental", kv->key)) - { - ctxt->fss0_enable_experimental = *kv->val == '1'; - break; - } - } - - return parse_fss(ctxt, value, NULL); -} - -typedef struct _cfg_handler_t -{ - const char *key; - int (*handler)(launch_ctxt_t *ctxt, const char *value); -} cfg_handler_t; - -static const cfg_handler_t _config_handlers[] = { - { "warmboot", _config_warmboot }, - { "secmon", _config_secmon }, - { "kernel", _config_kernel }, - { "kip1", _config_kip1 }, - { "kip1patch", config_kip1patch }, - { "fullsvcperm", _config_svcperm }, - { "debugmode", _config_debugmode }, - { "stock", _config_stock }, - { "atmosphere", _config_atmosphere }, - { "fss0", _config_fss }, - { "emummcforce", _config_emummc_forced }, - { "nouserexceptions", _config_dis_exo_user_exceptions }, - { "userpmu", _config_exo_user_pmu_access }, - { "cal0blank", _config_exo_cal0_blanking }, - { "cal0writesys", _config_exo_cal0_writes_enable }, - { NULL, NULL }, -}; - -int parse_boot_config(launch_ctxt_t *ctxt) -{ - LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link) - { - for(u32 i = 0; _config_handlers[i].key; i++) - { - if (!strcmp(_config_handlers[i].key, kv->key)) - { - if (!_config_handlers[i].handler(ctxt, kv->val)) - { - gfx_con.mute = false; - EPRINTFARGS("Error while loading %s:\n%s", kv->key, kv->val); - - return 0; - } - } - } - } - - return 1; -} diff --git a/source/hos/hos_config.h b/source/hos/hos_config.h deleted file mode 100644 index f835302..0000000 --- a/source/hos/hos_config.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * - * 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_CONFIG_H_ -#define _HOS_CONFIG_H_ - -#include "hos.h" - -int parse_boot_config(launch_ctxt_t *ctxt); -int config_kip1patch(launch_ctxt_t *ctxt, const char *value); - -#endif - diff --git a/source/hos/pkg1.c b/source/hos/pkg1.c index 86ed842..b1768f8 100644 --- a/source/hos/pkg1.c +++ b/source/hos/pkg1.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 st4rk - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018 balika011 * * This program is free software; you can redistribute it and/or modify it @@ -20,135 +20,29 @@ #include #include "pkg1.h" -#include "../gfx/gfx.h" -#include "../mem/heap.h" #include "../sec/se.h" -#include "../utils/aarch64_util.h" -#define _NOPv7() 0xE320F000 - -#define SM_100_ADR 0x4002B020 -PATCHSET_DEF(_secmon_1_patchset, - // Patch the relocator to be able to run from SM_100_ADR. - { 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) }, - //Patch package2 decryption and signature/hash checks. - { 0x9F0 + 0xADC, _NOP() }, //Header signature. - { 0x9F0 + 0xB8C, _NOP() }, //Version. - { 0x9F0 + 0xBB0, _NOP() } //Sections SHA2. -); - -PATCHSET_DEF(_secmon_2_patchset, - // Patch package2 decryption and signature/hash checks. - { 0xAC8 + 0xAAC, _NOP() }, //Header signature. - { 0xAC8 + 0xB3C, _NOP() }, //Version. - { 0xAC8 + 0xB58, _NOP() } //Sections SHA2. -); - -PATCHSET_DEF(_secmon_3_patchset, - // Patch package2 decryption and signature/hash checks. - { 0xAC8 + 0xA30, _NOP() }, //Header signature. - { 0xAC8 + 0xAB4, _NOP() }, //package2 structure. - { 0xAC8 + 0xAC0, _NOP() }, //Version. - { 0xAC8 + 0xADC, _NOP() } //Sections SHA2. -); - -PATCHSET_DEF(_secmon_4_patchset, - // Patch package2 decryption and signature/hash checks. - { 0x2300 + 0x5D80, _NOP() }, //package2 structure. - { 0x2300 + 0x5D8C, _NOP() }, //Version. - { 0x2300 + 0x5EFC, _NOP() }, //Header signature. - { 0xAC8 + 0xA2C, _NOP() } //Sections SHA2. -); - -PATCHSET_DEF(_secmon_5_patchset, - // Patch package2 decryption and signature/hash checks. - { 0xDA8 + 0x9D8, _NOP() }, //package2 structure. - { 0xDA8 + 0x9E4, _NOP() }, //Version. - { 0xDA8 + 0xC9C, _NOP() }, //Header signature. - { 0xDA8 + 0x1038, _NOP() } //Sections SHA2. -); - -PATCHSET_DEF(_secmon_6_patchset, - // Patch package2 decryption and signature/hash checks. - { 0xDC8 + 0x820, _NOP() }, //package2 structure. - { 0xDC8 + 0x82C, _NOP() }, //Version. - { 0xDC8 + 0xE90, _NOP() }, //Header signature. - { 0xDC8 + 0x112C, _NOP() } //Sections SHA2. - // Fix sleep mode for debug. - // { 0x1A68 + 0x3854, 0x94000E45 }, //gpio_config_for_uart. - // { 0x1A68 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta. - // { 0x1A68 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate. - // { 0x1A68 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A. - // { 0x1A68 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate. - // { 0x1A68 + 0x3868, 0x94000C8C }, //uart_configure. - // { 0x1A68 + 0x3A6C, _NOP() } // warmboot UARTA cfg. -); - -PATCHSET_DEF(_secmon_620_patchset, - // Patch package2 decryption and signature/hash checks. - { 0xDC8 + 0x604, _NOP() }, //package2 structure. - { 0xDC8 + 0x610, _NOP() }, //Version. - { 0xDC8 + 0xC74, _NOP() }, //Header signature. - { 0xDC8 + 0xF10, _NOP() } //Sections SHA2. - // Fix sleep mode for debug. - // { 0x2AC8 + 0x3854, 0x94000F42 }, //gpio_config_for_uart. - // { 0x2AC8 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta. - // { 0x2AC8 + 0x385C, 0x52A00021 }, //MOV W1, #0x10000 ; baudrate. - // { 0x2AC8 + 0x3860, 0x2A1F03E0 }, //MOV W0, WZR ; uart_port -> A. - // { 0x2AC8 + 0x3864, 0x72984001 }, //MOVK W1, #0xC200 ; baudrate. - // { 0x2AC8 + 0x3868, 0x94000D89 }, //uart_configure. - // { 0x2AC8 + 0x3A6C, _NOP() } // warmboot UARTA cfg. -); - -PATCHSET_DEF(_warmboot_1_patchset, - { 0x4DC, _NOPv7() } // Fuse check. -); - -PATCHSET_DEF(_warmboot_2_patchset, - { 0x4DC, _NOPv7() } // Fuse check. -); - -PATCHSET_DEF(_warmboot_3_patchset, - { 0x4DC, _NOPv7() }, // Fuse check. - { 0x4F0, _NOPv7() } // Segment id check. -); - -PATCHSET_DEF(_warmboot_4_patchset, - { 0x544, _NOPv7() }, // Fuse check. - { 0x558, _NOPv7() } // Segment id check. -); - - -/* - * package1.1 header: - * package1.1 layout: - * 1.0: {sm, ldr, wb} { 2, 1, 0 } - * 2.0: {wb, ldr, sm} { 0, 1, 2 } - * 3.0: {wb, ldr, sm} { 0, 1, 2 } - * 3.1: {wb, ldr, sm} { 0, 1, 2 } - * 4.0: {ldr, sm, wb} { 1, 2, 0 } - * 5.0: {ldr, sm, wb} { 1, 2, 0 } - * 6.0: {ldr, sm, wb} { 1, 2, 0 } - * 6.2: {ldr, sm, wb} { 1, 2, 0 } - * 7.0: {ldr, sm, wb} { 1, 2, 0 } - */ +#define HASH_ORDER_100_100 {2, 3, 4, 0, 5, 6, 1} +#define HASH_ORDER_200_510 {2, 3, 4, 0, 5, 7, 10, 12, 11, 6, 8, 1} +#define HASH_ORDER_600_620 {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 1} +#define HASH_ORDER_700_10x {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 9, 1} static const pkg1_id_t _pkg1_ids[] = { - { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset, _warmboot_1_patchset }, //1.0.0 (Patched relocator) - { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset, _warmboot_2_patchset }, //2.0.0 - 2.3.0 - { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.0 - { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.1 - 3.0.2 - { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset, _warmboot_4_patchset }, //4.0.0 - 4.1.0 - { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_4_patchset }, //5.0.0 - 5.1.0 - { "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_4_patchset }, //6.0.0 - 6.1.0 - { "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_4_patchset }, //6.2.0 - { "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.0 - { "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.1 - { "20190314172056", 7, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.0.0 - 8.0.1 - { "20190531152432", 8, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.1.0 - { "20190809135709", 9, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.0.0 - 9.0.1 - { "20191021113848", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.1.0 - { "20200303104606", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //10.0.0 + { "20161121183008", 0, {0x1b517, 0x125bc2, 1, 16, 6, HASH_ORDER_100_100, 0, 0x449dc} }, //1.0.0 + { "20170210155124", 0, {0x1d226, 0x26fe, 0, 16, 11, HASH_ORDER_200_510, 0x557b, 0x3d41a} }, //2.0.0 - 2.3.0 + { "20170519101410", 1, {0x1ffa6, 0x298b, 0, 16, 11, HASH_ORDER_200_510, 0x552d, 0x3cb81} }, //3.0.0 + { "20170710161758", 2, {0x20026, 0x29ab, 0, 16, 11, HASH_ORDER_200_510, 0x552d, 0x3cb81} }, //3.0.1 - 3.0.2 + { "20170921172629", 3, {0x1c64c, 0x37eb, 0, 16, 11, HASH_ORDER_200_510, 0x5382, 0x3711c} }, //4.0.0 - 4.1.0 + { "20180220163747", 4, {0x1f3b4, 0x465b, 0, 16, 11, HASH_ORDER_200_510, 0x5a63, 0x37901} }, //5.0.0 - 5.1.0 + { "20180802162753", 5, {0x27350, 0x17ff5, 1, 8, 11, HASH_ORDER_600_620, 0x5674, 0x1d5be} }, //6.0.0 - 6.1.0 + { "20181107105733", 6, {0x27350, 0x17ff5, 1, 8, 11, HASH_ORDER_600_620, 0x5674, 0x1d5be} }, //6.2.0 + { "20181218175730", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_10x, 0x5563, 0x1d437} }, //7.0.0 + { "20190208150037", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_10x, 0x5563, 0x1d437} }, //7.0.1 + { "20190314172056", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_10x, 0x5563, 0x1d437} }, //8.0.0 - 8.0.1 + { "20190531152432", 8, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_10x, 0x5563, 0x1d437} }, //8.1.0 + { "20190809135709", 9, {0x2ec10, 0x5573, 0, 1, 12, HASH_ORDER_700_10x, 0x6495, 0x1d807} }, //9.0.0 - 9.0.1 + { "20191021113848", 10,{0x2ec10, 0x5573, 0, 1, 12, HASH_ORDER_700_10x, 0x6495, 0x1d807} }, //9.1.0 + { "20200303104606", 10,{0x30ea0, 0x5e4b, 0, 1, 12, HASH_ORDER_700_10x, 0x663c, 0x1d9a4} }, //10.0.0 { NULL } //End. }; @@ -159,31 +53,3 @@ const pkg1_id_t *pkg1_identify(u8 *pkg1) return &_pkg1_ids[i]; return NULL; } - -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1) -{ - // Decrypt package1. - u8 *pkg11 = pkg1 + id->pkg11_off; - u32 pkg11_size = *(u32 *)pkg11; - se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10); -} - -void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1) -{ - pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20); - - u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size }; - //u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off }; - - u8 *pdata = (u8 *)hdr + sizeof(pk11_hdr_t); - for (u32 i = 0; i < 3; i++) - { - if (id->sec_map[i] == 0 && warmboot_dst) - memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]); - else if (id->sec_map[i] == 1 && ldr_dst) - memcpy(ldr_dst, pdata, sec_size[id->sec_map[i]]); - else if (id->sec_map[i] == 2 && secmon_dst) - memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]); - pdata += sec_size[id->sec_map[i]]; - } -} diff --git a/source/hos/pkg1.h b/source/hos/pkg1.h index 455d746..1d1e4ad 100644 --- a/source/hos/pkg1.h +++ b/source/hos/pkg1.h @@ -19,46 +19,25 @@ #include "../utils/types.h" -typedef struct _patch_t +typedef struct _key_info_t { - u32 off; - u32 val; -} patch_t; - -#define PATCHSET_DEF(name, ...) \ - patch_t name[] = { \ - __VA_ARGS__, \ - { 0xFFFFFFFF, 0xFFFFFFFF } \ - } + u32 start_offset; + u32 hks_offset; + bool hks_offset_is_from_end; + u32 alignment; + u32 hash_max; + u8 hash_order[13]; + u32 es_offset; + u32 ssl_offset; +} key_info_t; typedef struct _pkg1_id_t { const char *id; u32 kb; - u32 tsec_off; - u32 pkg11_off; - u32 sec_map[3]; - u32 secmon_base; - u32 warmboot_base; - bool set_warmboot; - patch_t *secmon_patchset; - patch_t *warmboot_patchset; + key_info_t key_info; } pkg1_id_t; -typedef struct _pk11_hdr_t -{ - u32 magic; - u32 wb_size; - u32 wb_off; - u32 pad; - u32 ldr_size; - u32 ldr_off; - u32 sm_size; - u32 sm_off; -} pk11_hdr_t; - const pkg1_id_t *pkg1_identify(u8 *pkg1); -void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); -void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); #endif diff --git a/source/hos/pkg2.c b/source/hos/pkg2.c index 1512a2e..bc77d1e 100644 --- a/source/hos/pkg2.c +++ b/source/hos/pkg2.c @@ -18,758 +18,18 @@ #include -#include "hos.h" #include "pkg2.h" -#include "pkg2_ini_kippatch.h" - -#include "../config/config.h" -#include "../libs/compr/blz.h" -#include "../libs/fatfs/ff.h" +#include "../utils/aarch64_util.h" #include "../mem/heap.h" #include "../sec/se.h" -#include "../storage/emummc.h" -#include "../storage/nx_sd.h" -#include "../utils/aarch64_util.h" +#include "../libs/compr/blz.h" #include "../gfx/gfx.h" -extern hekate_config h_cfg; -extern const u8 package2_keyseed[]; - -#ifdef KIP1_PATCH_DEBUG - #include "../utils/util.h" - #define DPRINTF(...) gfx_printf(__VA_ARGS__) - #define DEBUG_PRINTING -#else - #define DPRINTF(...) -#endif - -//TODO: Replace hardcoded AArch64 instructions with instruction macros. -//TODO: Reduce hardcoded values without searching kernel for patterns? -// The process ID send/receive kernel patches were taken from Atmosphère's kernel patches. -// They should only be used when running Atmosphère. -#define FREE_CODE_OFF_1ST_100 0x4797C -#define FREE_CODE_OFF_1ST_200 0x6486C -#define FREE_CODE_OFF_1ST_300 0x494A4 -#define FREE_CODE_OFF_1ST_302 0x494BC -#define FREE_CODE_OFF_1ST_400 0x52890 -#define FREE_CODE_OFF_1ST_500 0x5C020 -#define FREE_CODE_OFF_1ST_600 0x5EE00 -#define FREE_CODE_OFF_1ST_700 0x5FEC0 -#define FREE_CODE_OFF_1ST_800 0x607F0 -#define FREE_CODE_OFF_1ST_900 0x65780 -#define FREE_CODE_OFF_1ST_1000 0x67790 - -#define ID_SND_OFF_100 0x23CC0 -#define ID_SND_OFF_200 0x3F134 -#define ID_SND_OFF_300 0x26080 -#define ID_SND_OFF_302 0x26080 -#define ID_SND_OFF_400 0x2AF64 -#define ID_SND_OFF_500 0x2AD34 -#define ID_SND_OFF_600 0x2BB8C -#define ID_SND_OFF_700 0x2D044 -#define ID_SND_OFF_800 0x2F1FC -#define ID_SND_OFF_900 0x329A0 -#define ID_SND_OFF_1000 0x34404 - -#define ID_RCV_OFF_100 0x219F0 -#define ID_RCV_OFF_200 0x3D1A8 -#define ID_RCV_OFF_300 0x240F0 -#define ID_RCV_OFF_302 0x240F0 -#define ID_RCV_OFF_400 0x28F6C -#define ID_RCV_OFF_500 0x28DAC -#define ID_RCV_OFF_600 0x29B6C -#define ID_RCV_OFF_700 0x2B23C -#define ID_RCV_OFF_800 0x2D424 -#define ID_RCV_OFF_900 0x309B4 -#define ID_RCV_OFF_1000 0x322F8 - -static u32 PRC_ID_SND_100[] = -{ - 0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA -}; -#define FREE_CODE_OFF_2ND_100 (FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + sizeof(u32)) -static u32 PRC_ID_RCV_100[] = -{ - 0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA -}; - -static u32 PRC_ID_SND_200[] = -{ - 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA -}; -#define FREE_CODE_OFF_2ND_200 (FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + sizeof(u32)) -static u32 PRC_ID_RCV_200[] = -{ - 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, - 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA -}; - -static u32 PRC_ID_SND_300[] = -{ - 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA -}; -#define FREE_CODE_OFF_2ND_300 (FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + sizeof(u32)) -static u32 PRC_ID_RCV_300[] = -{ - 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, - 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA -}; - -#define FREE_CODE_OFF_2ND_302 (FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300) + sizeof(u32)) - -static u32 PRC_ID_SND_400[] = -{ - 0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, - 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA -}; -#define FREE_CODE_OFF_2ND_400 (FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + sizeof(u32)) -static u32 PRC_ID_RCV_400[] = -{ - 0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F -}; - -static u32 PRC_ID_SND_500[] = -{ - 0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, - 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA -}; -#define FREE_CODE_OFF_2ND_500 (FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + sizeof(u32)) -static u32 PRC_ID_RCV_500[] = -{ - 0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA -}; - -static u32 PRC_ID_SND_600[] = -{ - 0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; -#define FREE_CODE_OFF_2ND_600 (FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600) + sizeof(u32)) -static u32 PRC_ID_RCV_600[] = -{ - 0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; - -static u32 PRC_ID_SND_700[] = -{ - 0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; -#define FREE_CODE_OFF_2ND_700 (FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700) + sizeof(u32)) -static u32 PRC_ID_RCV_700[] = -{ - 0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; - -#define FREE_CODE_OFF_2ND_800 (FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700) + sizeof(u32)) - -static u32 PRC_ID_SND_900[] = -{ - 0xA9BF2FEA, 0xF94037EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; -#define FREE_CODE_OFF_2ND_900 (FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900) + sizeof(u32)) -static u32 PRC_ID_RCV_900[] = -{ - 0xA9BF2FEA, 0xF9404BEB, 0x2A1703EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; - -static u32 PRC_ID_SND_1000[] = -{ - 0xA9BF2FEA, 0xF94063EB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002E8, 0xF9401D08, 0xAA1703E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; -#define FREE_CODE_OFF_2ND_1000 (FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000) + sizeof(u32)) -static u32 PRC_ID_RCV_1000[] = -{ - 0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, - 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0, - 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 -}; - -// Include kernel patches here, so we can utilize pkg1 id -KERNEL_PATCHSET_DEF(_kernel_1_patchset, - { SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x44074, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_100, _B(ID_SND_OFF_100, FREE_CODE_OFF_1ST_100), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_100, sizeof(PRC_ID_SND_100) >> 2, PRC_ID_SND_100}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), ID_SND_OFF_100 + sizeof(u32)), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_100, _B(ID_RCV_OFF_100, FREE_CODE_OFF_2ND_100), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_100, sizeof(PRC_ID_RCV_100) >> 2, PRC_ID_RCV_100}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), ID_RCV_OFF_100 + sizeof(u32)), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_2_patchset, - { SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x6086C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_200, _B(ID_SND_OFF_200, FREE_CODE_OFF_1ST_200), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_200, sizeof(PRC_ID_SND_200) >> 2, PRC_ID_SND_200}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), ID_SND_OFF_200 + sizeof(u32)), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_200, _B(ID_RCV_OFF_200, FREE_CODE_OFF_2ND_200), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_200, sizeof(PRC_ID_RCV_200) >> 2, PRC_ID_RCV_200}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), ID_RCV_OFF_200 + sizeof(u32)), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_3_patchset, - { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x483FC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_300, _B(ID_SND_OFF_300, FREE_CODE_OFF_1ST_300), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_300, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), ID_SND_OFF_300 + sizeof(u32)), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_300, _B(ID_RCV_OFF_300, FREE_CODE_OFF_2ND_300), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_300, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_300 + sizeof(u32)), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_302_patchset, - { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x48414, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_302, _B(ID_SND_OFF_302, FREE_CODE_OFF_1ST_302), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_302, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_300), ID_SND_OFF_302 + sizeof(u32)), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_302, _B(ID_RCV_OFF_302, FREE_CODE_OFF_2ND_302), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_302, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_302 + sizeof(u32)), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_4_patchset, - { SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x4EBFC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_400, _B(ID_SND_OFF_400, FREE_CODE_OFF_1ST_400), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_400, sizeof(PRC_ID_SND_400) >> 2, PRC_ID_SND_400}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), ID_SND_OFF_400 + sizeof(u32) * 2), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_400, _B(ID_RCV_OFF_400, FREE_CODE_OFF_2ND_400), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_400, sizeof(PRC_ID_RCV_400) >> 2, PRC_ID_RCV_400}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), ID_RCV_OFF_400 + sizeof(u32)), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_5_patchset, - { SVC_GENERIC, 0x38C2C, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x54E30, _MOVZW(8, 0x1E00, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_500, _B(ID_SND_OFF_500, FREE_CODE_OFF_1ST_500), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_500, sizeof(PRC_ID_SND_500) >> 2, PRC_ID_SND_500}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), ID_SND_OFF_500 + sizeof(u32) * 2), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_500, _B(ID_RCV_OFF_500, FREE_CODE_OFF_2ND_500), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_500, sizeof(PRC_ID_RCV_500) >> 2, PRC_ID_RCV_500}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), ID_RCV_OFF_500 + sizeof(u32) * 2), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_6_patchset, - { SVC_GENERIC, 0x3A8CC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x47EA0, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x57548, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x57330, _MOVZW(8, 0x1D80, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_600, _B(ID_SND_OFF_600, FREE_CODE_OFF_1ST_600), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_600, sizeof(PRC_ID_SND_600) >> 2, PRC_ID_SND_600}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), ID_SND_OFF_600 + sizeof(u32) * 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_600, _B(ID_RCV_OFF_600, FREE_CODE_OFF_2ND_600), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_600, sizeof(PRC_ID_RCV_600) >> 2, PRC_ID_RCV_600}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), ID_RCV_OFF_600 + sizeof(u32) * 4), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_7_patchset, - { SVC_GENERIC, 0x3C6E0, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x49E5C, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x581B0, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x57F98, _MOVZW(8, 0x1D80, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_700, _B(ID_SND_OFF_700, FREE_CODE_OFF_1ST_700), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_700, sizeof(PRC_ID_SND_700) >> 2, PRC_ID_SND_700}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_1ST_700 + sizeof(PRC_ID_SND_700), ID_SND_OFF_700 + sizeof(u32) * 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_700, _B(ID_RCV_OFF_700, FREE_CODE_OFF_2ND_700), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_700, sizeof(PRC_ID_RCV_700) >> 2, PRC_ID_RCV_700}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_700 + sizeof(PRC_ID_RCV_700), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_2ND_700 + sizeof(PRC_ID_RCV_700), ID_RCV_OFF_700 + sizeof(u32) * 4), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_8_patchset, - { SVC_GENERIC, 0x3FAD0, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x4D15C, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x5BFAC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x5F9A4, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_800, _B(ID_SND_OFF_800, FREE_CODE_OFF_1ST_800), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_800, sizeof(PRC_ID_SND_700) >> 2, PRC_ID_SND_700}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_1ST_800 + sizeof(PRC_ID_SND_700), ID_SND_OFF_800 + sizeof(u32) * 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_800, _B(ID_RCV_OFF_800, FREE_CODE_OFF_2ND_800), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_800, sizeof(PRC_ID_RCV_700) >> 2, PRC_ID_RCV_700}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_800 + sizeof(PRC_ID_RCV_700), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_2ND_800 + sizeof(PRC_ID_RCV_700), ID_RCV_OFF_800 + sizeof(u32) * 4), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_9_patchset, - { SVC_GENERIC, 0x43DFC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x50628, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x609E8, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x6493C, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_900, _B(ID_SND_OFF_900, FREE_CODE_OFF_1ST_900), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_900, sizeof(PRC_ID_SND_900) >> 2, PRC_ID_SND_900}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_1ST_900 + sizeof(PRC_ID_SND_900), ID_SND_OFF_900 + sizeof(u32) * 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_900, _B(ID_RCV_OFF_900, FREE_CODE_OFF_2ND_900), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_900, sizeof(PRC_ID_RCV_900) >> 2, PRC_ID_RCV_900}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_900 + sizeof(PRC_ID_RCV_900), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_2ND_900 + sizeof(PRC_ID_RCV_900), ID_RCV_OFF_900 + sizeof(u32) * 4), NULL} -); - -KERNEL_PATCHSET_DEF(_kernel_10_patchset, - { SVC_GENERIC, 0x45DAC, _NOP(), NULL }, // Allow same process on svcControlCodeMemory. - { SVC_VERIFY_DS, 0x523E4, _NOP(), NULL }, // Disable SVC verifications. - { DEBUG_MODE_EN, 0x62B14, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch. - // Atmosphère kernel patches. - { ATM_SYSM_INCR, 0x66950, _MOVZW(19, 0x1D80, LSL16), NULL }, // System memory pool increase. - { ATM_GEN_PATCH, ID_SND_OFF_1000, _B(ID_SND_OFF_1000, FREE_CODE_OFF_1ST_1000), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_1000, sizeof(PRC_ID_SND_1000) >> 2, PRC_ID_SND_1000}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_1ST_1000 + sizeof(PRC_ID_SND_1000), ID_SND_OFF_1000 + sizeof(u32) * 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_1000, _B(ID_RCV_OFF_1000, FREE_CODE_OFF_2ND_1000), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_1000, sizeof(PRC_ID_RCV_1000) >> 2, PRC_ID_RCV_1000}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), // Branch back and skip 4 instructions. - _B(FREE_CODE_OFF_2ND_1000 + sizeof(PRC_ID_RCV_1000), ID_RCV_OFF_1000 + sizeof(u32) * 4), NULL} -); - -// Kernel sha256 hashes. -static const pkg2_kernel_id_t _pkg2_kernel_ids[] = -{ - { "\xb8\xc5\x0c\x68\x25\xa9\xb9\x5b", _kernel_1_patchset }, //1.0.0 - { "\x64\x0b\x51\xff\x28\x01\xb8\x30", _kernel_2_patchset }, //2.0.0 - 2.3.0 - { "\x50\x84\x23\xac\x6f\xa1\x5d\x3b", _kernel_3_patchset }, //3.0.0 - 3.0.1 - { "\x81\x9d\x08\xbe\xe4\x5e\x1f\xbb", _kernel_302_patchset }, //3.0.2 - { "\xe6\xc0\xb7\xe3\x2f\xf9\x44\x51", _kernel_4_patchset }, //4.0.0 - 4.1.0 - { "\xb2\x38\x61\xa8\xe1\xe2\xe4\xe4", _kernel_5_patchset }, //5.0.0 - 5.1.0 - { "\x85\x97\x40\xf6\xc0\x3e\x3d\x44", _kernel_6_patchset }, //6.0.0 - 6.2.0 - { "\xa2\x5e\x47\x0c\x8e\x6d\x2f\xd7", _kernel_7_patchset }, //7.0.0 - 7.0.1 - { "\xf1\x5e\xc8\x34\xfd\x68\xf0\xf0", _kernel_8_patchset }, //8.0.0 - 8.1.0. Kernel only. - { "\x69\x00\x39\xdf\x21\x56\x70\x6b", _kernel_9_patchset }, //9.0.0 - 9.1.0. Kernel only. - { "\xa2\xe3\xad\x1c\x98\xd8\x7a\x62", _kernel_9_patchset }, //9.2.0. Kernel only. - { "\x21\xc1\xd7\x24\x8e\xcd\xbd\xa8", _kernel_10_patchset }, //10.0.0. Kernel only. -}; - -enum kip_offset_section -{ - KIP_TEXT = 0, - KIP_RODATA = 1, - KIP_DATA = 2, - KIP_BSS = 3, - KIP_UNKSEC1 = 4, - KIP_UNKSEC2 = 5 -}; - -#define KIP_PATCH_SECTION_SHIFT (29) -#define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT) -#define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK) -#define GET_KIP_PATCH_SECTION(x) ((x >> KIP_PATCH_SECTION_SHIFT) & 7) -#define GET_KIP_PATCH_OFFSET(x) (x & KIP_PATCH_OFFSET_MASK) -#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT) - -static kip1_patch_t _fs_emummc[] = -{ - { KPS(KIP_TEXT) | 1, 0, "", "" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_100[] = -{ - { "nogc", NULL }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_40x[] = -{ - { KPS(KIP_TEXT) | 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" }, - { KPS(KIP_TEXT) | 0xAAB44, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_40x[] = -{ - { "nogc", _fs_nogc_40x }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_410[] = -{ - { KPS(KIP_TEXT) | 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" }, - { KPS(KIP_TEXT) | 0xAABA8, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_410[] = -{ - { "nogc", _fs_nogc_410 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_50x[] = -{ - { KPS(KIP_TEXT) | 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { KPS(KIP_TEXT) | 0xD73A0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_50x[] = -{ - { "nogc", _fs_nogc_50x }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_510[] = -{ - { KPS(KIP_TEXT) | 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { KPS(KIP_TEXT) | 0xD7770, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_510[] = -{ - { "nogc", _fs_nogc_510 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_600[] = -{ - { KPS(KIP_TEXT) | 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x1538F4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_600_exfat[] = -{ - { KPS(KIP_TEXT) | 0x138320, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x15EFF4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_600[] = -{ - { "nogc", _fs_nogc_600 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_600_exfat[] = -{ - { "nogc", _fs_nogc_600_exfat }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_700[] = -{ - { KPS(KIP_TEXT) | 0x134160, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x15BF04, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_700_exfat[] = -{ - { KPS(KIP_TEXT) | 0x13F710, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x1674B4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_700[] = -{ - { "nogc", _fs_nogc_700 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_700_exfat[] = -{ - { "nogc", _fs_nogc_700_exfat }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_800[] = -{ - { KPS(KIP_TEXT) | 0x136800, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x15EB94, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_800_exfat[] = -{ - { KPS(KIP_TEXT) | 0x141DB0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x16A144, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_800[] = -{ - { "nogc", _fs_nogc_800 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_800_exfat[] = -{ - { "nogc", _fs_nogc_800_exfat }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_900[] = -{ - { KPS(KIP_TEXT) | 0x129420, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x143268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_900[] = -{ - { "nogc", _fs_nogc_900 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_910[] = -{ - { KPS(KIP_TEXT) | 0x129430, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x143278, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_910[] = -{ - { "nogc", _fs_nogc_910 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -static kip1_patch_t _fs_nogc_1000[] = -{ - { KPS(KIP_TEXT) | 0x13BE90, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, - { KPS(KIP_TEXT) | 0x14DE08, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0, 0, NULL, NULL } -}; - -static kip1_patchset_t _fs_patches_1000[] = -{ - { "nogc", _fs_nogc_1000 }, - { "emummc", _fs_emummc }, - { NULL, NULL } -}; - -// SHA256 hashes. -static kip1_id_t _kip_ids[] = -{ - { "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe", _fs_patches_100 }, // FS 1.0.0 - { "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96", _fs_patches_100 }, // FS 1.0.0 exfat - { "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28", _fs_patches_100 }, // FS 2.0.0 - { "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9", _fs_patches_100 }, // FS 2.0.0 exfat - { "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c", _fs_patches_100 }, // FS 2.1.0 - { "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8", _fs_patches_100 }, // FS 2.1.0 exfat - { "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b", _fs_patches_100 }, // FS 3.0.0 - { "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7", _fs_patches_100 }, // FS 3.0.0 exfat - { "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31", _fs_patches_100 }, // FS 3.0.1 - { "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89", _fs_patches_100 }, // FS 3.0.1 exfat - { "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c", _fs_patches_40x }, // FS 4.0.1 - { "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9", _fs_patches_40x }, // FS 4.0.1 exfat - { "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82", _fs_patches_410 }, // FS 4.1.0 - { "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0", _fs_patches_410 }, // FS 4.1.0 exfat - { "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad", _fs_patches_50x }, // FS 5.0.0 - { "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5", _fs_patches_50x }, // FS 5.0.0 exfat - { "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f", _fs_patches_510 }, // FS 5.1.0 - { "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99", _fs_patches_510 }, // FS 5.1.0 exfat - { "FS", "\x1b\x82\xcb\x22\x18\x67\xcb\x52", _fs_patches_600 }, // FS 6.0.0-4.0 - { "FS", "\x96\x6a\xdd\x3d\x20\xb6\x27\x13", _fs_patches_600_exfat }, // FS 6.0.0-4.0 exfat - { "FS", "\x3a\x57\x4d\x43\x61\x86\x19\x1d", _fs_patches_600 }, // FS 6.0.0-5.0 - { "FS", "\x33\x05\x53\xf6\xb5\xfb\x55\xc4", _fs_patches_600_exfat }, // FS 6.0.0-5.0 exfat - { "FS", "\x2A\xDB\xE9\x7E\x9B\x5F\x41\x77", _fs_patches_700 }, // FS 7.0.0 - { "FS", "\x2C\xCE\x65\x9C\xEC\x53\x6A\x8E", _fs_patches_700_exfat }, // FS 7.0.0 exfat - { "FS", "\xB2\xF5\x17\x6B\x35\x48\x36\x4D", _fs_patches_800 }, // FS 8.0.0 - { "FS", "\xDB\xD9\x41\xC0\xC5\x3C\x52\xCC", _fs_patches_800_exfat }, // FS 8.0.0 exfat - { "FS", "\x6B\x09\xB6\x7B\x29\xC0\x20\x24", _fs_patches_800 }, // FS 8.1.0 - { "FS", "\xB4\xCA\xE1\xF2\x49\x65\xD9\x2E", _fs_patches_800_exfat }, // FS 8.1.0 exfat - { "FS", "\x46\x87\x40\x76\x1E\x19\x3E\xB7", _fs_patches_900 }, // FS 9.0.0 - { "FS", "\x7C\x95\x13\x76\xE5\xC1\x2D\xF8", _fs_patches_900 }, // FS 9.0.0 exfat - { "FS", "\xB5\xE7\xA6\x4C\x6F\x5C\x4F\xE3", _fs_patches_910 }, // FS 9.1.0 - { "FS", "\xF1\x96\xD1\x44\xD0\x44\x45\xB6", _fs_patches_910 }, // FS 9.1.0 exfat - { "FS", "\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", _fs_patches_1000 }, // FS 10.0.0 - { "FS", "\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", _fs_patches_1000 }, // FS 10.0.0 exfat -}; - -static kip1_id_t *_kip_id_sets = _kip_ids; -static u32 _kip_id_sets_cnt = sizeof(_kip_ids) / sizeof(_kip_ids[0]); - -void pkg2_get_ids(kip1_id_t **ids, u32 *entries) -{ - *ids = _kip_id_sets; - *entries = _kip_id_sets_cnt; -} - -static void parse_external_kip_patches() -{ - static bool ext_patches_done = false; - - if (ext_patches_done) - return; - - u32 curr_kip_idx = 0; - char path[64]; - strcpy(path, "bootloader/patches.ini"); - - LIST_INIT(ini_kip_sections); - if (ini_patch_parse(&ini_kip_sections, path)) - { - // Copy ids into a new patchset. - _kip_id_sets = calloc(sizeof(kip1_id_t), 256); // Max 256 kip ids. - memcpy(_kip_id_sets, _kip_ids, sizeof(_kip_ids)); - - // Parse patchsets and glue them together. - LIST_FOREACH_ENTRY(ini_kip_sec_t, ini_psec, &ini_kip_sections, link) - { - kip1_id_t* curr_kip = NULL; - bool found = false; - for (curr_kip_idx = 0; curr_kip_idx < _kip_id_sets_cnt + 1; curr_kip_idx++) - { - curr_kip = &_kip_id_sets[curr_kip_idx]; - - if (!curr_kip->name) - break; - - if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8)) - { - found = true; - break; - } - } - - if (!curr_kip) - continue; - - // If not found, create a new empty entry. - if (!found) - { - curr_kip->name = ini_psec->name; - memcpy(curr_kip->hash, ini_psec->hash, 8); - curr_kip->patchset = calloc(sizeof(kip1_patchset_t), 1); - - _kip_id_sets_cnt++; - } - - kip1_patchset_t *patchsets = (kip1_patchset_t *)calloc(sizeof(kip1_patchset_t), 16); // Max 16 patchsets per kip. - - u32 curr_patchset_idx; - for(curr_patchset_idx = 0; curr_kip->patchset[curr_patchset_idx].name != NULL; curr_patchset_idx++) - { - patchsets[curr_patchset_idx].name = curr_kip->patchset[curr_patchset_idx].name; - patchsets[curr_patchset_idx].patches = curr_kip->patchset[curr_patchset_idx].patches; - } - - curr_kip->patchset = patchsets; - bool first_ext_patch = true; - u32 curr_patch_idx = 0; - - // Parse patches and glue them together to a patchset. - kip1_patch_t *patches = calloc(sizeof(kip1_patch_t), 32); // Max 32 patches per set. - LIST_FOREACH_ENTRY(ini_patchset_t, pt, &ini_psec->pts, link) - { - if (first_ext_patch) - { - first_ext_patch = false; - patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1); - strcpy(patchsets[curr_patchset_idx].name, pt->name); - patchsets[curr_patchset_idx].patches = patches; - } - else - { - // Check if new patchset name is found and create a new set. - if (strcmp(pt->name, patchsets[curr_patchset_idx].name)) - { - curr_patchset_idx++; - curr_patch_idx = 0; - patches = calloc(sizeof(kip1_patch_t), 16); // Max 16 patches per set. - - patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1); - strcpy(patchsets[curr_patchset_idx].name, pt->name); - patchsets[curr_patchset_idx].patches = patches; - } - } - - if (pt->length) - { - patches[curr_patch_idx].offset = pt->offset; - patches[curr_patch_idx].length = pt->length; - - patches[curr_patch_idx].srcData = malloc(pt->length); - patches[curr_patch_idx].dstData = malloc(pt->length); - memcpy(patches[curr_patch_idx].srcData, pt->srcData, pt->length); - memcpy(patches[curr_patch_idx].dstData, pt->dstData, pt->length); - } - else - patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0. - - curr_patch_idx++; - } - curr_patchset_idx++; - patchsets[curr_patchset_idx].name = NULL; - patchsets[curr_patchset_idx].patches = NULL; - } - } - - ext_patches_done = true; -} - -const pkg2_kernel_id_t *pkg2_identify(u8 *hash) -{ - for (u32 i = 0; i < (sizeof(_pkg2_kernel_ids) / sizeof(pkg2_kernel_id_t)); i++) - { - if (!memcmp(hash, _pkg2_kernel_ids[i].hash, sizeof(_pkg2_kernel_ids[0].hash))) - return &_pkg2_kernel_ids[i]; - } - return NULL; -} +/*#include "util.h" +#define DPRINTF(...) gfx_printf(__VA_ARGS__) +#define DEBUG_PRINTING*/ +#define DPRINTF(...) static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) { @@ -806,7 +66,7 @@ void pkg2_get_newkern_info(u8 *kern_data) 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) { @@ -842,45 +102,6 @@ DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size); return true; } -int pkg2_has_kip(link_t *info, u64 tid) -{ - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) - if(ki->kip1->tid == tid) - return 1; - return 0; -} - -void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1) -{ - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) - { - if (ki->kip1->tid == tid) - { - ki->kip1 = kip1; - ki->size = _pkg2_calc_kip1_size(kip1); -DPRINTF("replaced kip %s (new size %08X)\n", kip1->name, ki->size); - return; - } - } -} - -void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1) -{ - 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); -DPRINTF("added kip %s (size %08X)\n", kip1->name, ki->size); - list_append(info, &ki->link); -} - -void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1) -{ - if (pkg2_has_kip(info, kip1->tid)) - pkg2_replace_kip(info, kip1->tid, kip1); - else - pkg2_add_kip(info, kip1); -} - int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp) { u32 compClearMask = ~sectsToDecomp; @@ -922,10 +143,9 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp) 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); + //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_con.mute = false; gfx_printf("%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC); free(newKip); @@ -951,328 +171,9 @@ int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp) return 0; } -static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info_t* ki) +pkg2_hdr_t *pkg2_decrypt(void *data) { - if (!strcmp((const char *)ki->kip1->name, target_name)) - { - u32 size = 0; - u8 *kipm_data = (u8 *)sd_file_read(kipm_path, &size); - if (!kipm_data) - return 1; - - u32 inject_size = size - sizeof(ki->kip1->caps); - u8 *kip_patched_data = (u8 *)malloc(ki->size + inject_size); - - // Copy headers. - memcpy(kip_patched_data, ki->kip1, sizeof(pkg2_kip1_t)); - - pkg2_kip1_t *fs_kip = ki->kip1; - ki->kip1 = (pkg2_kip1_t *)kip_patched_data; - ki->size = ki->size + inject_size; - - // Patch caps. - memcpy(&ki->kip1->caps, kipm_data, sizeof(ki->kip1->caps)); - // Copy our .text data. - memcpy(&ki->kip1->data, kipm_data + sizeof(ki->kip1->caps), inject_size); - - u32 new_offset = 0; - - for (u32 currSectIdx = 0; currSectIdx < KIP1_NUM_SECTIONS - 2; currSectIdx++) - { - if(!currSectIdx) // .text. - { - memcpy(ki->kip1->data + inject_size, fs_kip->data, fs_kip->sections[0].size_comp); - ki->kip1->sections[0].size_decomp += inject_size; - ki->kip1->sections[0].size_comp += inject_size; - } - else // Others. - { - if (currSectIdx < 3) - memcpy(ki->kip1->data + new_offset + inject_size, fs_kip->data + new_offset, fs_kip->sections[currSectIdx].size_comp); - ki->kip1->sections[currSectIdx].offset += inject_size; - } - new_offset += fs_kip->sections[currSectIdx].size_comp; - } - - // Patch PMC capabilities for 1.0.0. - if (!emu_cfg.fs_ver) - { - for (u32 i = 0; i < 0x20; i++) - { - if (ki->kip1->caps[i] == 0xFFFFFFFF) - { - ki->kip1->caps[i] = 0x07000E7F; - break; - } - } - } - - free(kipm_data); - return 0; - } - - return 1; -} - -static bool ext_patches_parsed = false; - -const char* pkg2_patch_kips(link_t *info, char* patchNames) -{ - if (patchNames == NULL || patchNames[0] == 0) - return NULL; - - if (!ext_patches_parsed) - { - parse_external_kip_patches(); - ext_patches_parsed = true; - } - - static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8; - char* patches[MAX_NUM_PATCHES_REQUESTED]; - - u32 numPatches = 1; - patches[0] = patchNames; - { - for (char* p = patchNames; *p != 0; p++) - { - if (*p == ',') - { - *p = 0; - patches[numPatches++] = p + 1; - if (numPatches >= MAX_NUM_PATCHES_REQUESTED) - return "too_many_patches"; - } - else if (*p >= 'A' && *p <= 'Z') - *p += 0x20; - } - } - - u32 patchesApplied = 0; // Bitset over patches. - for (u32 i = 0; i < numPatches; i++) - { - // Eliminate leading spaces. - for (const char* p = patches[i]; *p != 0; p++) - { - if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') - patches[i]++; - else - break; - } - int valueLen = strlen(patches[i]); - if (valueLen == 0) - continue; - - // Eliminate trailing spaces. - for (int chIdx = valueLen - 1; chIdx >= 0; chIdx--) - { - const char* p = patches[i] + chIdx; - if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') - valueLen = chIdx; - else - break; - } - patches[i][valueLen] = 0; - - DPRINTF("Requested patch: '%s'\n", patches[i]); - } - - u32 shaBuf[32 / sizeof(u32)]; - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link) - { - shaBuf[0] = 0; // sha256 for this kip not yet calculated. - for (u32 currKipIdx = 0; currKipIdx < _kip_id_sets_cnt; currKipIdx++) - { - if (strncmp((const char*)ki->kip1->name, _kip_id_sets[currKipIdx].name, sizeof(ki->kip1->name)) != 0) - continue; - - u32 bitsAffected = 0; - kip1_patchset_t* currPatchset = _kip_id_sets[currKipIdx].patchset; - while (currPatchset != NULL && currPatchset->name != NULL) - { - for (u32 i = 0; i < numPatches; i++) - { - if (strcmp(currPatchset->name, patches[i]) != 0) - { - bitsAffected = i + 1; - break; - } - } - currPatchset++; - } - - // Dont bother even hashing this KIP if we dont have any patches enabled for it. - if (bitsAffected == 0) - continue; - - if (shaBuf[0] == 0) - { - if (!se_calc_sha256(shaBuf, ki->kip1, ki->size)) - memset(shaBuf, 0, sizeof(shaBuf)); - } - - if (memcmp(shaBuf, _kip_id_sets[currKipIdx].hash, sizeof(_kip_id_sets[0].hash)) != 0) - continue; - - // Find out which sections are affected by the enabled patches, to know which to decompress. - bitsAffected = 0; - currPatchset = _kip_id_sets[currKipIdx].patchset; - while (currPatchset != NULL && currPatchset->name != NULL) - { - if (currPatchset->patches != NULL) - { - for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++) - { - if (strcmp(currPatchset->name, patches[currEnabIdx])) - continue; - - if (!strcmp(currPatchset->name, "emummc")) - bitsAffected |= 1u << GET_KIP_PATCH_SECTION(currPatchset->patches->offset); - - for (const kip1_patch_t* currPatch=currPatchset->patches; currPatch != NULL && (currPatch->length != 0); currPatch++) - bitsAffected |= 1u << GET_KIP_PATCH_SECTION(currPatch->offset); - } - } - currPatchset++; - } - - // Got patches to apply to this kip, have to decompress it. -#ifdef DEBUG_PRINTING - u32 preDecompTime = get_tmr_us(); -#endif - if (pkg2_decompress_kip(ki, bitsAffected)) - return (const char*)ki->kip1->name; // Failed to decompress. - -#ifdef DEBUG_PRINTING - u32 postDecompTime = get_tmr_us(); - if (!se_calc_sha256(shaBuf, ki->kip1, ki->size)) - memset(shaBuf, 0, sizeof(shaBuf)); - - DPRINTF("%dms %s KIP1 size %d hash %08X\n", (postDecompTime-preDecompTime) / 1000, ki->kip1->name, (int)ki->size, __builtin_bswap32(shaBuf[0])); -#endif - - currPatchset = _kip_id_sets[currKipIdx].patchset; - bool emummc_patch_selected = false; - while (currPatchset != NULL && currPatchset->name != NULL) - { - for (u32 currEnabIdx = 0; currEnabIdx < numPatches; currEnabIdx++) - { - if (strcmp(currPatchset->name, patches[currEnabIdx])) - continue; - - u32 appliedMask = 1u << currEnabIdx; - - if (!strcmp(currPatchset->name, "emummc")) - { - emummc_patch_selected = true; - patchesApplied |= appliedMask; - - break; - } - - if (currPatchset->patches == NULL) - { - gfx_printf("Patch '%s' not necessary for %s KIP1\n", currPatchset->name, (const char*)ki->kip1->name); - patchesApplied |= appliedMask; - - break; - } - - unsigned char* kipSectData = ki->kip1->data; - for (u32 currSectIdx = 0; currSectIdx < KIP1_NUM_SECTIONS; currSectIdx++) - { - if (bitsAffected & (1u << currSectIdx)) - { - gfx_printf("Applying patch '%s' on %s KIP1 sect %d\n", currPatchset->name, (const char*)ki->kip1->name, currSectIdx); - for (const kip1_patch_t* currPatch = currPatchset->patches; currPatch != NULL && currPatch->srcData != 0; currPatch++) - { - if (GET_KIP_PATCH_SECTION(currPatch->offset) != currSectIdx) - continue; - - if (!currPatch->length) - { - gfx_con.mute = false; - gfx_printf("%kPatch is empty!%k\n", 0xFFFF0000, 0xFFCCCCCC); - return currPatchset->name; // MUST stop here as it's not probably intended. - } - - u32 currOffset = GET_KIP_PATCH_OFFSET(currPatch->offset); - // If source is does not match and is not already patched, throw an error. - if ((memcmp(&kipSectData[currOffset], currPatch->srcData, currPatch->length) != 0) && - (memcmp(&kipSectData[currOffset], currPatch->dstData, currPatch->length) != 0)) - { - gfx_con.mute = false; - gfx_printf("%kPatch data mismatch at 0x%x!%k\n", 0xFFFF0000, currOffset, 0xFFCCCCCC); - return currPatchset->name; // MUST stop here as kip is likely corrupt. - } - else - { - DPRINTF("Patching %d bytes at offset 0x%x\n", currPatch->length, currOffset); - memcpy(&kipSectData[currOffset], currPatch->dstData, currPatch->length); - } - } - } - kipSectData += ki->kip1->sections[currSectIdx].size_comp; - } - - patchesApplied |= appliedMask; - break; - } - currPatchset++; - } - if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", 2)) - { - emummc_patch_selected = false; - emu_cfg.fs_ver = currKipIdx; - if (currKipIdx) - emu_cfg.fs_ver--; - if (currKipIdx > 17) - emu_cfg.fs_ver -= 2; - - gfx_printf("Injecting emuMMC. FS ver: %d\n", emu_cfg.fs_ver); - if (_kipm_inject("/bootloader/sys/emummc.kipm", "FS", ki)) - return "emummc"; - } - } - } - - for (u32 i = 0; i < numPatches; i++) - { - if ((patchesApplied & (1u << i)) == 0) - return patches[i]; - } - - return NULL; -} - -static const u8 mkey_keyseed_8xx[][0x10] = -{ - // Master key 8 encrypted with 9. (8.1.0 with 9.0.0) - { 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 }, - // Master key 9 encrypted with 10. (9.0.0 with 9.1.0) - { 0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A } -}; - -static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed) -{ - // Decrypt older encrypted mkey. - se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10); - // Set and unwrap pkg2 key. - se_aes_key_clear(9); - se_aes_key_set(9, mkey, 0x10); - se_aes_unwrap_key(9, 9, package2_keyseed); - - // Decrypt header. - se_aes_crypt_ctr(9, tmp_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); - - // Return if header is valid. - return (tmp_test->magic == PKG2_MAGIC); -} - -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) -{ - pkg2_hdr_t mkey_test; u8 *pdata = (u8 *)data; - u8 keyslot = 8; // Skip signature. pdata += 0x100; @@ -1282,60 +183,8 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb) // Skip header. pdata += sizeof(pkg2_hdr_t); - //! Check if we need to decrypt with newer mkeys. Valid for sept for 8.1.0 and up. - se_aes_crypt_ctr(8, &mkey_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); - - if (mkey_test.magic == PKG2_MAGIC) - goto key_found; - - // Decrypt older pkg2 via new mkeys. - if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX)) - { - u8 tmp_mkey[0x10]; - u8 decr_slot = 12; // Sept mkey. - u8 mkey_seeds_cnt = sizeof(mkey_keyseed_8xx) / 0x10; - u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1. - u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb); - - while (mkey_seeds_cnt) - { - // Decrypt and validate mkey. - int res = _pkg2_key_unwrap_validate(&mkey_test, hdr, decr_slot, - tmp_mkey, mkey_keyseed_8xx[mkey_seeds_idx - 1]); - - if (res) - { - keyslot = 9; - goto key_found; - } - else - { - // Set current mkey in order to decrypt a lower mkey. - mkey_seeds_idx--; - se_aes_key_clear(9); - se_aes_key_set(9, tmp_mkey, 0x10); - - decr_slot = 9; // Temp key. - - // Check if we tried last key for that pkg2 version. - // And start with a lower mkey in case sept is older. - if (mkey_seeds_idx == mkey_seeds_min_idx) - { - mkey_seeds_cnt--; - mkey_seeds_idx = mkey_seeds_cnt; - decr_slot = 12; // Sept mkey. - } - - // Out of keys. pkg2 is latest or process failed. - if (!mkey_seeds_cnt) - se_aes_key_clear(9); - } - } - } - -key_found: // Decrypt header. - se_aes_crypt_ctr(keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); + 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) @@ -1347,94 +196,11 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); if (!hdr->sec_size[i]) continue; - se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]); + 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]; } - if (keyslot != 8) - se_aes_key_clear(9); - return hdr; } - -static u32 _pkg2_ini1_build(u8 *pdst, pkg2_hdr_t *hdr, link_t *kips_info, bool new_pkg2) -{ - u32 ini1_size = sizeof(pkg2_ini1_t); - pkg2_ini1_t *ini1 = (pkg2_ini1_t *)pdst; - memset(ini1, 0, sizeof(pkg2_ini1_t)); - ini1->magic = INI1_MAGIC; - pdst += sizeof(pkg2_ini1_t); - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips_info, link) - { -DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->size); - memcpy(pdst, ki->kip1, ki->size); - pdst += ki->size; - ini1_size += ki->size; - ini1->num_procs++; - } - ini1_size = ALIGN(ini1_size, 4); - ini1->size = ini1_size; - if (!new_pkg2) - { - hdr->sec_size[PKG2_SEC_INI1] = ini1_size; - hdr->sec_off[PKG2_SEC_INI1] = 0x14080000; - se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]); - } - else - { - hdr->sec_size[PKG2_SEC_INI1] = 0; - hdr->sec_off[PKG2_SEC_INI1] = 0; - } - - return ini1_size; -} - -void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2) -{ - u8 *pdst = (u8 *)dst; - - // Signature. - memset(pdst, 0, 0x100); - pdst += 0x100; - - // Header. - pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdst; - memset(hdr, 0, sizeof(pkg2_hdr_t)); - pdst += sizeof(pkg2_hdr_t); - hdr->magic = PKG2_MAGIC; - if (!new_pkg2) - hdr->base = 0x10000000; - else - hdr->base = 0x60000; -DPRINTF("kernel @ %08X (%08X)\n", (u32)kernel, kernel_size); - - // Kernel. - memcpy(pdst, kernel, kernel_size); - if (!new_pkg2) - hdr->sec_off[PKG2_SEC_KERNEL] = 0x10000000; - else - { - // Set new INI1 offset to kernel. - *(u32 *)(pdst + pkg2_newkern_ini1_val) = kernel_size; - kernel_size += _pkg2_ini1_build(pdst + kernel_size, hdr, kips_info, new_pkg2); - hdr->sec_off[PKG2_SEC_KERNEL] = 0x60000; - } - hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size; - se_aes_crypt_ctr(8, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]); - pdst += kernel_size; -DPRINTF("kernel encrypted\n"); - - // INI1. - u32 ini1_size = 0; - if (!new_pkg2) - ini1_size = _pkg2_ini1_build(pdst, hdr, kips_info, new_pkg2); -DPRINTF("INI1 encrypted\n"); - - //Encrypt header. - *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; - se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); - memset(hdr->ctr, 0 , 0x10); - *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; -} diff --git a/source/hos/pkg2.h b/source/hos/pkg2.h index 891ab5d..ba6a8a0 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, @@ -26,41 +26,12 @@ #define PKG2_SEC_KERNEL 0 #define PKG2_SEC_INI1 1 -#define INI1_MAGIC 0x31494E49 #define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset. -#define PKG2_NEWKERN_START 0x800 u32 pkg2_newkern_ini1_val; u32 pkg2_newkern_ini1_start; u32 pkg2_newkern_ini1_end; -typedef struct _kernel_patch_t -{ - u32 id; - u32 off; - u32 val; - u32 *ptr; -} kernel_patch_t; - -#define KERNEL_PATCHSET_DEF(name, ...) \ - kernel_patch_t name[] = { \ - __VA_ARGS__, \ - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32 *)0xFFFFFFFF} \ - } - -enum -{ - // Always applied. - SVC_GENERIC = 0, - // Generic instruction patches. - SVC_VERIFY_DS = 0x10, - DEBUG_MODE_EN = 0x11, - ATM_GEN_PATCH = 0x12, - ATM_SYSM_INCR = ATM_GEN_PATCH, - // >4 bytes patches. Value is a pointer of a u32 array. - ATM_ARR_PATCH = 0x13, -}; - typedef struct _pkg2_hdr_t { u8 ctr[0x10]; @@ -116,44 +87,8 @@ 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; - -typedef struct _kip1_patch_t -{ - u32 offset; // section+offset of patch to apply. - u32 length; // In bytes, 0 means last patch. - char* srcData; // That must match. - char* dstData; // That it gets replaced by. -} kip1_patch_t; - -typedef struct _kip1_patchset_t -{ - char* name; // NULL means end. - kip1_patch_t* patches; // NULL means not necessary. -} kip1_patchset_t; - -typedef struct _kip1_id_t -{ - const char* name; - u8 hash[8]; - kip1_patchset_t* patchset; -} kip1_id_t; - -void pkg2_get_newkern_info(u8 *kern_data); bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); -int pkg2_has_kip(link_t *info, u64 tid); -void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1); -void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1); -void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1); -void pkg2_get_ids(kip1_id_t **ids, u32 *entries); -const char* pkg2_patch_kips(link_t *info, char* patchNames); - -const pkg2_kernel_id_t *pkg2_identify(u8 *hash); -pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb); -void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2); +int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp); +pkg2_hdr_t *pkg2_decrypt(void *data); #endif diff --git a/source/hos/pkg2_ini_kippatch.c b/source/hos/pkg2_ini_kippatch.c deleted file mode 100644 index fba2635..0000000 --- a/source/hos/pkg2_ini_kippatch.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include "pkg2_ini_kippatch.h" -#include "../libs/fatfs/ff.h" -#include "../mem/heap.h" - -#define KPS(x) ((u32)(x) << 29) - -static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len) -{ - char ch = *ptr; - u32 ascii_len = byte_len * 2; - if (!result) - result = malloc(byte_len); - u8 *dst = result; - - while (ch == ' ' || ch == '\t') - ch = *(++ptr); - - bool shift = true; - while (ascii_len) - { - u8 tmp = 0; - if (ch >= '0' && ch <= '9') - tmp = (ch - '0'); - else if (ch >= 'A' && ch <= 'F') - tmp = (ch - 'A' + 10); - else if (ch >= 'a' && ch <= 'f') - tmp = (ch - 'a' + 10); - - if (shift) - *dst = (tmp << 4) & 0xF0; - else - { - *dst |= (tmp & 0x0F); - dst++; - } - - ascii_len--; - ch = *(++ptr); - shift = !shift; - } - - return result; -} - -static char *_strdup(char *str) -{ - if (!str) - return NULL; - if (str[0] == ' ' && (strlen(str) > 1)) - str++; - char *res = (char *)malloc(strlen(str) + 1); - strcpy(res, str); - if (res[strlen(res) - 1] == ' ' && (strlen(res) > 1)) - res[strlen(res) - 1] = 0; - - return res; -} - -static u32 _find_patch_section_name(char *lbuf, u32 lblen, char schar) -{ - u32 i; - for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n' && lbuf[i] != '\r'; i++) - ; - lbuf[i] = 0; - - return i; -} - -static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec, char *name) -{ - if (ksec) - list_append(dst, &ksec->link); - - ksec = (ini_kip_sec_t *)calloc(sizeof(ini_kip_sec_t), 1); - u32 i = _find_patch_section_name(name, strlen(name), ':') + 1; - ksec->name = _strdup(name); - - // Get hash section. - _htoa(ksec->hash, &name[i], 8); - - return ksec; -} - -int ini_patch_parse(link_t *dst, char *ini_path) -{ - u32 lblen; - char lbuf[512]; - FIL fp; - ini_kip_sec_t *ksec = NULL; - - // Open ini. - if (f_open(&fp, ini_path, FA_READ) != FR_OK) - return 0; - - do - { - // Fetch one line. - lbuf[0] = 0; - f_gets(lbuf, 512, &fp); - lblen = strlen(lbuf); - - // Remove trailing newline. Depends on 'FF_USE_STRFUNC 2' that removes \r. - if (lblen && lbuf[lblen - 1] == '\n') - lbuf[lblen - 1] = 0; - - if (lblen > 2 && lbuf[0] == '[') // Create new section. - { - _find_patch_section_name(lbuf, lblen, ']'); - - ksec = _ini_create_kip_section(dst, ksec, &lbuf[1]); - list_init(&ksec->pts); - } - else if (ksec && lbuf[0] == '.') //Extract key/value. - { - u32 tmp = 0; - u32 i = _find_patch_section_name(lbuf, lblen, '='); - - ini_patchset_t *pt = (ini_patchset_t *)calloc(sizeof(ini_patchset_t), 1); - - pt->name = _strdup(&lbuf[1]); - - u8 kip_sidx = lbuf[i + 1] - '0'; - - if (kip_sidx < 6) - { - pt->offset = KPS(kip_sidx); - tmp = _find_patch_section_name(&lbuf[i + 3], lblen, ':'); - pt->offset |= strtol(&lbuf[i + 3], NULL, 16); - - i += tmp + 4; - - tmp = _find_patch_section_name(&lbuf[i], lblen, ':'); - pt->length = strtol(&lbuf[i], NULL, 16); - - i += tmp + 1; - - tmp = _find_patch_section_name(&lbuf[i], lblen, ','); - pt->srcData = _htoa(NULL, &lbuf[i], pt->length); - i += tmp + 1; - pt->dstData = _htoa(NULL, &lbuf[i], pt->length); - } - - list_append(&ksec->pts, &pt->link); - } - } while (!f_eof(&fp)); - - f_close(&fp); - - if (ksec) - list_append(dst, &ksec->link); - - return 1; -} diff --git a/source/hos/pkg2_ini_kippatch.h b/source/hos/pkg2_ini_kippatch.h deleted file mode 100644 index f459c3c..0000000 --- a/source/hos/pkg2_ini_kippatch.h +++ /dev/null @@ -1,43 +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 _INIPATCH_H_ -#define _INIPATCH_H_ - -#include "../utils/types.h" -#include "../utils/list.h" - -typedef struct _ini_patchset_t -{ - char *name; - u32 offset; // section + offset of patch to apply. - u32 length; // In bytes, 0 means last patch. - u8 *srcData; // That must match. - u8 *dstData; // Gets replaced with. - link_t link; -} ini_patchset_t; - -typedef struct _ini_kip_sec_t -{ - char *name; - u8 hash[8]; - link_t pts; - link_t link; -} ini_kip_sec_t; - -int ini_patch_parse(link_t *dst, char *ini_path); - -#endif diff --git a/source/hos/secmon_exo.c b/source/hos/secmon_exo.c deleted file mode 100644 index 60e062b..0000000 --- a/source/hos/secmon_exo.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2018-2020 CTCaer - * Copyright (c) 2019 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 . - */ - -#include -#include - -#include "hos.h" -#include "../config/config.h" -#include "../gfx/di.h" -#include "../gfx/gfx.h" -#include "../libs/fatfs/ff.h" -#include "../mem/heap.h" -#include "../soc/fuse.h" -#include "../storage/emummc.h" -#include "../storage/nx_sd.h" -#include "../storage/sdmmc.h" -#include "../utils/btn.h" -#include "../utils/util.h" -#include "../utils/types.h" - -extern hekate_config h_cfg; - -enum emuMMC_Type -{ - emuMMC_None = 0, - emuMMC_Partition, - emuMMC_File, - emuMMC_MAX -}; - -/* "EFS0" */ -#define EMUMMC_MAGIC 0x30534645 -#define EMUMMC_FILE_PATH_MAX 0x80 - -typedef struct -{ - u32 magic; - u32 type; - u32 id; - u32 fs_ver; -} emummc_base_config_t; - -typedef struct -{ - u64 start_sector; -} emummc_partition_config_t; - -typedef struct -{ - char path[EMUMMC_FILE_PATH_MAX]; -} emummc_file_config_t; - -typedef struct -{ - emummc_base_config_t base_cfg; - union - { - emummc_partition_config_t partition_cfg; - emummc_file_config_t file_cfg; - }; - char nintendo_path[EMUMMC_FILE_PATH_MAX]; -} exo_emummc_config_t; - -typedef struct _exo_cfg_t -{ - u32 magic; - u32 fwno; - u32 flags; - u32 reserved[5]; - exo_emummc_config_t emummc_cfg; -} exo_cfg_t; - -typedef struct _atm_meta_t -{ - u32 magic; - u32 fwno; -} wb_cfg_t; - -// Atmosphère reboot-to-fatal-error. -typedef struct _atm_fatal_error_ctx -{ - u32 magic; - u32 error_desc; - u64 title_id; - union - { - u64 gprs[32]; - struct - { - u64 _gprs[29]; - u64 fp; - u64 lr; - u64 sp; - }; - }; - u64 pc; - u64 module_base; - u32 pstate; - u32 afsr0; - u32 afsr1; - u32 esr; - u64 far; - u64 report_identifier; // Normally just system tick. - u64 stack_trace_size; - u64 stack_dump_size; - u64 stack_trace[0x20]; - u8 stack_dump[0x100]; - u8 tls[0x100]; -} atm_fatal_error_ctx; - -#define ATM_FATAL_ERR_CTX_ADDR 0x4003E000 -#define ATM_FATAL_MAGIC 0x30454641 // AFE0 - -#define ATM_WB_HEADER_OFF 0x244 -#define ATM_WB_MAGIC 0x30544257 - -// Exosphère mailbox defines. -#define EXO_CFG_ADDR 0x8000F000 -#define EXO_MAGIC_VAL 0x304F5845 -#define EXO_FLAG_DBG_PRIV (1 << 1) -#define EXO_FLAG_DBG_USER (1 << 2) -#define EXO_FLAG_NO_USER_EXC (1 << 3) -#define EXO_FLAG_USER_PMU (1 << 4) -#define EXO_FLAG_CAL0_BLANKING (1 << 5) -#define EXO_FLAG_CAL0_WRITES_SYS (1 << 6) - -void config_exosphere(launch_ctxt_t *ctxt) -{ - u32 exoFwNo = 0; - u32 exoFlags = 0; - u32 kb = ctxt->pkg1_id->kb; - bool user_debug = false; - bool cal0_blanking = false; - bool cal0_allow_writes_sys = false; - - memset((exo_cfg_t *)EXO_CFG_ADDR, 0, sizeof(exo_cfg_t)); - - volatile exo_cfg_t *exo_cfg = (exo_cfg_t *)EXO_CFG_ADDR; - - switch (kb) - { - case KB_FIRMWARE_VERSION_100_200: - if (!strcmp(ctxt->pkg1_id->id, "20161121183008")) - exoFwNo = 1; - else - exoFwNo = 2; - break; - case KB_FIRMWARE_VERSION_300: - exoFwNo = 3; - break; - default: - exoFwNo = kb + 1; - if (!strcmp(ctxt->pkg1_id->id, "20190314172056") || (kb >= KB_FIRMWARE_VERSION_810)) - exoFwNo++; // ATM_TARGET_FW_800/810/900/910. - if (!strcmp(ctxt->pkg1_id->id, "20200303104606")) - exoFwNo++; // ATM_TARGET_FW_1000. - break; - } - - if (!ctxt->stock) - { - // Parse exosphere.ini. - LIST_INIT(ini_sections); - if (ini_parse(&ini_sections, "exosphere.ini", false)) - { - LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) - { - // Only parse exosphere section. - if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere")) - continue; - - LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) - { - if (!strcmp("debugmode_user", kv->key)) - user_debug = atoi(kv->val); - else if (emu_cfg.enabled && !h_cfg.emummc_force_disable) - { - if (!strcmp("blank_prodinfo_emummc", kv->key)) - cal0_blanking = atoi(kv->val); - } - else - { - if (!strcmp("blank_prodinfo_sysmmc", kv->key)) - cal0_blanking = atoi(kv->val); - else if (!strcmp("allow_writing_to_cal_sysmmc", kv->key)) - cal0_allow_writes_sys = atoi(kv->val); - } - } - break; - } - } - } - - // To avoid problems, make private debug mode always on if not semi-stock. - if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable)) - exoFlags |= EXO_FLAG_DBG_PRIV; - - // Enable user debug. - if (user_debug) - exoFlags |= EXO_FLAG_DBG_USER; - - // Disable proper failure handling. - if (ctxt->exo_cfg.no_user_exceptions) - exoFlags |= EXO_FLAG_NO_USER_EXC; - - // Enable user access to PMU. - if (ctxt->exo_cfg.user_pmu) - exoFlags |= EXO_FLAG_USER_PMU; - - // Check if exo ini value is overridden and enable prodinfo blanking. - if ((ctxt->exo_cfg.cal0_blank && *ctxt->exo_cfg.cal0_blank) - || (!ctxt->exo_cfg.cal0_blank && cal0_blanking)) - exoFlags |= EXO_FLAG_CAL0_BLANKING; - - // Check if exo ini value is overridden and allow prodinfo writes. - if ((ctxt->exo_cfg.cal0_allow_writes_sys && *ctxt->exo_cfg.cal0_allow_writes_sys) - || (!ctxt->exo_cfg.cal0_allow_writes_sys && cal0_allow_writes_sys)) - exoFlags |= EXO_FLAG_CAL0_WRITES_SYS; - - // Set mailbox values. - exo_cfg->magic = EXO_MAGIC_VAL; - exo_cfg->fwno = exoFwNo; - exo_cfg->flags = exoFlags; - - // If warmboot is lp0fw, add in RSA modulus. - volatile wb_cfg_t *wb_cfg = (wb_cfg_t *)(ctxt->pkg1_id->warmboot_base + ATM_WB_HEADER_OFF); - - if (wb_cfg->magic == ATM_WB_MAGIC) - { - wb_cfg->fwno = exoFwNo; - - sdmmc_storage_t storage; - sdmmc_t sdmmc; - - // Set warmboot binary rsa modulus. - u8 *rsa_mod = (u8 *)malloc(512); - - sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400); - sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - sdmmc_storage_read(&storage, 1, 1, rsa_mod); - sdmmc_storage_end(&storage); - - // Patch AutoRCM out. - if ((fuse_read_odm(4) & 3) != 3) - rsa_mod[0x10] = 0xF7; - else - rsa_mod[0x10] = 0x37; - - memcpy((void *)(ctxt->pkg1_id->warmboot_base + 0x10), rsa_mod + 0x10, 0x100); - } - - if (emu_cfg.enabled && !h_cfg.emummc_force_disable) - { - exo_cfg->emummc_cfg.base_cfg.magic = EMUMMC_MAGIC; - exo_cfg->emummc_cfg.base_cfg.type = emu_cfg.sector ? emuMMC_Partition : emuMMC_File; - exo_cfg->emummc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver; - exo_cfg->emummc_cfg.base_cfg.id = emu_cfg.id; - - if (emu_cfg.sector) - exo_cfg->emummc_cfg.partition_cfg.start_sector = emu_cfg.sector; - else - strcpy((char *)exo_cfg->emummc_cfg.file_cfg.path, emu_cfg.path); - - if (emu_cfg.nintendo_path && !ctxt->stock) - strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, emu_cfg.nintendo_path); - else if (ctxt->stock) - strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, "Nintendo"); - else - exo_cfg->emummc_cfg.nintendo_path[0] = 0; - } -} - -static const char *get_error_desc(u32 error_desc) -{ - switch (error_desc) - { - case 0x100: - return "Instruction Abort"; - case 0x101: - return "Data Abort"; - case 0x102: - return "PC Misalignment"; - case 0x103: - return "SP Misalignment"; - case 0x104: - return "Trap"; - case 0x106: - return "SError"; - case 0x301: - return "Bad SVC"; - case 0xFFE: - return "std::abort()"; - default: - return "Unknown"; - } -} - -void secmon_exo_check_panic() -{ - volatile atm_fatal_error_ctx *rpt = (atm_fatal_error_ctx *)ATM_FATAL_ERR_CTX_ADDR; - - // Mask magic to maintain compatibility with any AFE version, thanks to additive struct members. - if ((rpt->magic & 0xF0FFFFFF) != ATM_FATAL_MAGIC) - return; - - gfx_clear_grey(0x1B); - gfx_con_setpos(0, 0); - - WPRINTF("Panic occurred while running Atmosphere.\n\n"); - WPRINTFARGS("Title ID: %08X%08X", (u32)((u64)rpt->title_id >> 32), (u32)rpt->title_id); - WPRINTFARGS("Error Desc: %s (0x%x)\n", get_error_desc(rpt->error_desc), rpt->error_desc); - - // Save context to the SD card. - char filepath[0x40]; - f_mkdir("atmosphere/fatal_errors"); - strcpy(filepath, "/atmosphere/fatal_errors/report_"); - itoa((u32)((u64)rpt->report_identifier >> 32), filepath + strlen(filepath), 16); - itoa((u32)(rpt->report_identifier), filepath + strlen(filepath), 16); - strcat(filepath, ".bin"); - - sd_save_to_file((void *)rpt, sizeof(atm_fatal_error_ctx), filepath); - - gfx_con.fntsz = 8; - WPRINTFARGS("Report saved to %s\n", filepath); - - // Change magic to invalid, to prevent double-display of error/bootlooping. - rpt->magic = 0x0; - - gfx_con.fntsz = 16; - gfx_printf("\n\nPress POWER to continue.\n"); - - display_backlight_brightness(100, 1000); - msleep(1000); - - u32 btn = btn_wait(); - while (!(btn & BTN_POWER)) - btn = btn_wait(); - - display_backlight_brightness(0, 1000); - gfx_con_setpos(0, 0); -} diff --git a/source/hos/secmon_exo.h b/source/hos/secmon_exo.h deleted file mode 100644 index 2ff0ee3..0000000 --- a/source/hos/secmon_exo.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2018-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 _SECMON_EXO_H_ -#define _SECMON_EXO_H_ - -#include "../utils/types.h" - -void config_exosphere(launch_ctxt_t *ctxt); -void secmon_exo_check_panic(); - -#endif diff --git a/source/hos/sept.c b/source/hos/sept.c index d2b726c..1858533 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -16,27 +16,20 @@ #include -#include "hos.h" -#include "fss.h" #include "sept.h" -#include "../config/config.h" #include "../gfx/di.h" -#include "../ianos/ianos.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/emummc.h" #include "../storage/nx_emmc.h" -#include "../storage/nx_sd.h" #include "../storage/sdmmc.h" #include "../utils/btn.h" #include "../utils/types.h" #include "../gfx/gfx.h" -#define RELOC_META_OFF 0x7C #define PATCHED_RELOC_SZ 0x94 #define WB_RST_ADDR 0x40010ED0 @@ -57,178 +50,75 @@ u8 warmboot_reboot[] = { #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 hekate_config h_cfg; -extern const volatile ipl_ver_meta_t ipl_ver; - -extern bool is_ipl_updated(void *buf); +extern void sd_unmount(); extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size); -void check_sept(ini_sec_t *cfg_sec) -{ - hos_eks_get(); - - // Check if non-hekate payload is used for sept and restore it. - if (h_cfg.sept_run) - { - if (!f_stat("sept/payload.bak", NULL)) - { - f_unlink("sept/payload.bin"); - f_rename("sept/payload.bak", "sept/payload.bin"); - } - - return; - } - - u8 *pkg1 = (u8 *)calloc(1, 0x40000); - - sdmmc_storage_t storage; - sdmmc_t sdmmc; - int res = emummc_storage_init_mmc(&storage, &sdmmc); - if (res) - { - if (res == 2) - EPRINTF("Failed to init eMMC"); - else - EPRINTF("Failed to init emuMMC"); - - goto out_free; - } - - emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); - - // Read package1. - emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1); - const pkg1_id_t *pkg1_id = pkg1_identify(pkg1); - if (!pkg1_id) - { - gfx_con.fntsz = 16; - EPRINTF("Unknown pkg1 version."); - goto out_free; - } - - if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) - { - u8 key_idx = pkg1_id->kb - KB_FIRMWARE_VERSION_700; - if (h_cfg.eks && (h_cfg.eks->enabled & (1 << key_idx))) - { - h_cfg.sept_run = true; - EMC(EMC_SCRATCH0) |= EMC_SEPT_RUN; - goto out_free; - } - - sdmmc_storage_end(&storage); - reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec); - } - -out_free: - free(pkg1); - sdmmc_storage_end(&storage); -} - -int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec) +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. - u32 tsec_fw_size = 0x3000; - if (kb > KB_FIRMWARE_VERSION_700) - tsec_fw_size = 0x3300; memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot)); - memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_fw_size); - *(vu32 *)SEPT_TCSZ_ADDR = tsec_fw_size; + memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size); + *(vu32 *)SEPT_TCSZ_ADDR = tsec_size; - if (cfg_sec) + // 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)) { - fss0_sept_t sept_ctxt; - sept_ctxt.kb = kb; - sept_ctxt.cfg_sec = cfg_sec; - sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR; - sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR; - - fss0_sept_used = load_sept_from_ffs0(&sept_ctxt); - } - - if (!fss0_sept_used) - { - // Copy sept-primary. - if (f_open(&fp, "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); + goto error; + } + f_close(&fp); - // Copy sept-secondary. - if (kb < KB_FIRMWARE_VERSION_810) - { - if (f_open(&fp, "sept/sept-secondary_00.enc", FA_READ)) - if (f_open(&fp, "sept/sept-secondary.enc", FA_READ)) // Try the deprecated version. - goto error; - } - else - { - if (f_open(&fp, "sept/sept-secondary_01.enc", FA_READ)) + // 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; - } - - if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL)) - { - f_close(&fp); + } + else + { + if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ)) goto error; - } - f_close(&fp); } - b_cfg.boot_cfg |= (BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_SEPT_RUN); - - bool update_sept_payload = true; - if (!f_open(&fp, "sept/payload.bin", FA_READ | FA_WRITE)) + if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL)) { - ipl_ver_meta_t tmp_ver; - f_lseek(&fp, PATCHED_RELOC_SZ + sizeof(boot_cfg_t)); - f_read(&fp, &tmp_ver, sizeof(ipl_ver_meta_t), NULL); - - if (tmp_ver.magic == ipl_ver.magic) - { - if (tmp_ver.version == ipl_ver.version) - { - // 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)); - f_lseek(&fp, PATCHED_RELOC_SZ); - f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL); - update_sept_payload = false; - } - - f_close(&fp); - } - else - { - f_close(&fp); - f_rename("sept/payload.bin", "sept/payload.bak"); // Backup foreign payload. - } - } - - if (update_sept_payload) - { - volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); - f_mkdir("sept"); - f_open(&fp, "sept/payload.bin", FA_WRITE | FA_CREATE_ALWAYS); - f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, 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(); + gfx_printf("\n%kPress Power or Vol +/-\n to Reboot to Sept...", colors[(color_idx++) % 6]); u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE); @@ -248,8 +138,8 @@ int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec) (*sept)(); error: - gfx_con.mute = false; - EPRINTF("Failed to run sept\n"); + EPRINTF("\nSept files not found in sd:/sept!\nPlace appropriate files and try again."); + display_backlight_brightness(100, 1000); btn_wait(); diff --git a/source/hos/sept.h b/source/hos/sept.h index 8cfc8af..01bd845 100644 --- a/source/hos/sept.h +++ b/source/hos/sept.h @@ -19,7 +19,6 @@ #include "../utils/types.h" -void check_sept(ini_sec_t *cfg_sec); -int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec); +int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb); #endif diff --git a/source/sec/se.c b/source/sec/se.c index 57c0958..6eb4700 100644 --- a/source/sec/se.c +++ b/source/sec/se.c @@ -1,6 +1,8 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * 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, @@ -31,6 +33,9 @@ typedef struct _se_ll_t vu32 size; } se_ll_t; +static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; +static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT]; + static void _gf256_mul_x(void *block) { u8 *pdata = (u8 *)block; @@ -47,6 +52,22 @@ static void _gf256_mul_x(void *block) pdata[0xF] ^= 0x87; } +static void _gf256_mul_x_le(void *block) +{ + u8 *pdata = (u8 *)block; + u32 carry = 0; + + for (u32 i = 0; i < 0x10; i++) + { + u8 b = pdata[i]; + pdata[i] = (b << 1) | carry; + carry = b >> 7; + } + + if (carry) + pdata[0x0] ^= 0x87; +} + static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size) { ll->num = 0; @@ -73,17 +94,15 @@ 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 = NULL, *ll_src = NULL; + se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0; if (dst) { - ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t)); _se_ll_init(ll_dst, (u32)dst, dst_size); } if (src) { - ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); _se_ll_init(ll_src, (u32)src, src_size); } @@ -99,11 +118,6 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); - if (src) - free(ll_src); - if (dst) - free(ll_dst); - return res; } @@ -142,6 +156,66 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags) SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); } +// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot +void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size) +{ + u32 *data = (u32 *)mod; + for (u32 i = 0; i < mod_size / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]); + } + + data = (u32 *)exp; + for (u32 i = 0; i < exp_size / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]); + } + + _se_rsa_mod_sizes[ks] = mod_size; + _se_rsa_exp_sizes[ks] = exp_size; +} + +// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot +void se_rsa_key_clear(u32 ks) +{ + for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA) = 0; + } + for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA) = 0; + } +} + +// se_rsa_exp_mod() was derived from Atmosphère's se_synchronous_exp_mod and se_get_exp_mod_output +int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) +{ + int res; + u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE]; + + for (u32 i = 0; i < src_size; i++) + stack_buf[i] = *((u8 *)src + src_size - i - 1); + + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); + SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks); + SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1; + SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2; + + res = _se_execute(OP_START, NULL, 0, stack_buf, src_size); + + // Copy output hash. + u32 *dst32 = (u32 *)dst; + for (u32 i = 0; i < dst_size / 4; i++) + dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2))); + + return res; +} + void se_key_acc_ctrl(u32 ks, u32 flags) { if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) @@ -150,7 +224,7 @@ void se_key_acc_ctrl(u32 ks, u32 flags) SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); } -void se_aes_key_set(u32 ks, void *key, u32 size) +void se_aes_key_set(u32 ks, const void *key, u32 size) { u32 *data = (u32 *)key; for (u32 i = 0; i < size / 4; i++) @@ -160,6 +234,16 @@ void se_aes_key_set(u32 ks, void *key, u32 size) } } +void se_aes_key_read(u32 ks, void *key, u32 size) +{ + u32 *data = (u32 *)key; + for (u32 i = 0; i < size / 4; i++) + { + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; + data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); + } +} + void se_aes_key_clear(u32 ks) { for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++) @@ -169,6 +253,15 @@ void se_aes_key_clear(u32 ks) } } +void se_aes_key_iv_clear(u32 ks) +{ + for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++) + { + SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i; + SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; + } +} + int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) { SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB); @@ -195,24 +288,6 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, return _se_execute(OP_START, dst, dst_size, src, src_size); } -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_PREVAHB) | - SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); - } - 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(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; - return _se_execute(OP_START, dst, dst_size, src, src_size); -} - int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) { return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10); @@ -223,7 +298,8 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s SE(SE_SPARE_0_REG_OFFSET) = 1; 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_CORE_SEL(CORE_ENCRYPT) | - SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1); + SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1) | + SE_CRYPTO_VCTRAM_SEL(VCTRAM_AHB); _se_aes_ctr_set(ctr); u32 src_size_aligned = src_size & 0xFFFFFFF0; @@ -244,7 +320,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s return 1; } -int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize) +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); @@ -269,7 +345,7 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *sr goto out; for (u32 j = 0; j < 0x10; j++) pdst[j] = pdst[j] ^ tweak[j]; - _gf256_mul_x(tweak); + _gf256_mul_x_le(tweak); psrc += 0x10; pdst += 0x10; } @@ -281,7 +357,7 @@ out:; return res; } -int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs) +int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs) { u8 *pdst = (u8 *)dst; u8 *psrc = (u8 *)src; @@ -293,6 +369,58 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u return 1; } +// se_aes_cmac() was derived from Atmosphère's se_compute_aes_cmac +int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) +{ + int res = 0; + u8 *key = (u8 *)calloc(0x10, 1); + u8 *last_block = (u8 *)calloc(0x10, 1); + + // generate derived key + if (!se_aes_crypt_block_ecb(ks, 1, key, key)) + goto out; + _gf256_mul_x(key); + if (src_size & 0xF) + _gf256_mul_x(key); + + SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG); + SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) | + SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) | + SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); + se_aes_key_iv_clear(ks); + + u32 num_blocks = (src_size + 0xf) >> 4; + 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) { + memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf); + last_block[src_size & 0xf] = 0x80; + } else if (src_size >= 0x10) { + memcpy(last_block, src + src_size - 0x10, 0x10); + } + + for (u32 i = 0; i < 0x10; i++) + last_block[i] ^= key[i]; + + SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; + res = _se_execute(OP_START, NULL, 0, last_block, 0x10); + + u32 *dst32 = (u32 *)dst; + for (u32 i = 0; i < (dst_size >> 2); i++) + dst32[i] = SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)); + +out:; + free(key); + free(last_block); + return res; +} + +// se_calc_sha256() was derived from Atmosphère's se_calculate_sha256. int se_calc_sha256(void *dst, const void *src, u32 src_size) { int res; @@ -319,76 +447,45 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size) return res; } -int se_gen_prng128(void *dst) -{ - // Setup config for X931 PRNG. - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); +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); + u8 *opad = (u8 *)malloc(0x60); - SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL); - //SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = - // SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE); - SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1; - - SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1; - - // Trigger the operation. - return _se_execute(OP_START, dst, 16, NULL, 0); -} - -void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) -{ - u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); - - // Set Secure Random Key. - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); - SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); - SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_START, NULL, 0, NULL, 0); - - // Save AES keys. - SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - - for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++) + if (key_size > 0x40) { - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | - (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); - - SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); - memcpy(keys + i * keysize, aligned_buf, 0x10); - - if (keysize > 0x10) - { - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) | - (i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); - - SE(SE_CRYPTO_LAST_BLOCK) = 0; - _se_execute(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); - memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); - } + if (!se_calc_sha256(secret, key, key_size)) + goto out; + memset(secret + 0x20, 0, 0x20); + } + else + { + memcpy(secret, key, key_size); + memset(secret + key_size, 0, 0x40 - key_size); } - // Save SRK to PMC secure scratches. - SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); - SE(0x80) = 0; // SE_CRYPTO_LAST_BLOCK - _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0); + u32 *secret32 = (u32 *)secret; + u32 *ipad32 = (u32 *)ipad; + u32 *opad32 = (u32 *)opad; + for (u32 i = 0; i < 0x10; i++) + { + ipad32[i] = secret32[i] ^ 0x36363636; + opad32[i] = secret32[i] ^ 0x5C5C5C5C; + } - // End context save. - SE(SE_CONFIG_REG_OFFSET) = 0; - _se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0); + memcpy(ipad + 0x40, src, src_size); + if (!se_calc_sha256(dst, ipad, 0x40 + src_size)) + goto out; + memcpy(opad + 0x40, dst, 0x20); + if (!se_calc_sha256(dst, opad, 0x60)) + goto out; - // Get SRK. - u32 srk[4]; - srk[0] = PMC(0xC0); - srk[1] = PMC(0xC4); - srk[2] = PMC(0x224); - srk[3] = PMC(0x228); + res = 1; - // Decrypt context. - se_aes_key_clear(3); - se_aes_key_set(3, srk, 0x10); - se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); - se_aes_key_clear(3); +out:; + free(secret); + free(ipad); + free(opad); + return res; } diff --git a/source/sec/se.h b/source/sec/se.h index 7d12207..0d517c7 100644 --- a/source/sec/se.h +++ b/source/sec/se.h @@ -20,15 +20,21 @@ #include "../utils/types.h" void se_rsa_acc_ctrl(u32 rs, u32 flags); +void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size); +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_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); -void se_aes_key_set(u32 ks, void *key, u32 size); +void se_aes_key_set(u32 ks, const void *key, u32 size); +void se_aes_key_read(u32 ks, void *key, u32 size); void se_aes_key_clear(u32 ks); 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_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); int se_calc_sha256(void *dst, const void *src, u32 src_size); -int se_gen_prng128(void *dst); +int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); #endif diff --git a/source/sec/tsec.c b/source/sec/tsec.c index 7c9f1e6..5a1f85e 100644 --- a/source/sec/tsec.c +++ b/source/sec/tsec.c @@ -29,7 +29,6 @@ #include "../mem/heap.h" #include "../mem/mc.h" #include "../utils/util.h" -#include "../hos/hos.h" // #include "../gfx/gfx.h" diff --git a/source/tegraexplorer/emmc/emmc.c b/source/tegraexplorer/emmc/emmc.c index 2fb3bd0..afea163 100644 --- a/source/tegraexplorer/emmc/emmc.c +++ b/source/tegraexplorer/emmc/emmc.c @@ -217,6 +217,7 @@ int dump_biskeys(){ //sdmmc_storage_set_mmc_partition(&storage, 0); //nx_emmc_gpt_parse(&sys_gpt, &storage); + se_aes_key_set(8, bis_key[2] + 0x00, 0x10); se_aes_key_set(9, bis_key[2] + 0x10, 0x10);