Merge lockpickrcm changes

This commit is contained in:
Such Meme, Many Skill 2020-05-19 18:20:19 +02:00
parent a8e86c2de3
commit fc69dc36ee
20 changed files with 633 additions and 104 deletions

View File

@ -8,7 +8,7 @@ include $(DEVKITARM)/base_rules
################################################################################
IPL_LOAD_ADDR := 0x40008000
IPL_LOAD_ADDR := 0x40003000
LPVERSION_MAJOR := 3
LPVERSION_MINOR := 0
LPVERSION_BUGFX := 2

View File

@ -1,9 +1,9 @@
/*
* Common Gfx Header
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018 M4xw
*
* Copyright (C) 2018 CTCaer
* Copyright (C) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.

View File

@ -1,6 +1,6 @@
/*
* Common Module Header
* Copyright (c) 2018 M4xw
* Copyright (C) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@ -19,8 +19,8 @@
//#define IPL_STACK_TOP 0x4003FF00
/* --- BIT/BCT: 0x40000000 - 0x40003000 --- */
/* --- IPL: 0x40008000 - 0x40028000 --- */
#define IPL_LOAD_ADDR 0x40008000
/* --- IPL: 0x40003000 - 0x40028000 --- */
#define IPL_LOAD_ADDR 0x40003000
#define IPL_SZ_MAX 0x20000 // 128KB.
//#define IRAM_LIB_ADDR 0x4002B000
#define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init.

220
source/hos/fss.c Normal file
View File

@ -0,0 +1,220 @@
/*
* Atmosphère Fusée Secondary Storage parser.
*
* Copyright (c) 2019-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "fss.h"
// #include "hos.h"
#include "../config/config.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../storage/emummc.h"
#include "../storage/nx_sd.h"
#include "../gfx/gfx.h"
#define DPRINTF(...)
extern hekate_config h_cfg;
extern bool is_ipl_updated(void *buf, char *path, bool force);
// FSS0 Magic and Meta header offset.
#define FSS0_MAGIC 0x30535346
#define FSS0_META_OFFSET 0x4
// FSS0 Content Types.
#define CNT_TYPE_FSP 0
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
#define CNT_TYPE_BMP 7
#define CNT_TYPE_EMC 8
#define CNT_TYPE_KLD 9 // Kernel Loader.
#define CNT_TYPE_KRN 10 // Kernel.
// FSS0 Content Flags.
#define CNT_FLAG0_EXPERIMENTAL (1 << 0)
// FSS0 Meta Header.
typedef struct _fss_meta_t
{
u32 magic;
u32 size;
u32 crt0_off;
u32 cnt_off;
u32 cnt_count;
u32 hos_ver;
u32 version;
u32 git_rev;
} fss_meta_t;
// FSS0 Content Header.
typedef struct _fss_content_t
{
u32 offset;
u32 size;
u8 type;
u8 flags0;
u8 flags1;
u8 flags2;
u32 rsvd1;
char name[0x10];
} fss_content_t;
int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
{
FIL fp;
bool stock = false;
int sept_used = 0;
if (!sept_ctxt)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
{
if (!strcmp("stock", kv->key))
if (kv->val[0] == '1')
stock = true;
}
if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable))
return 1;
}
if (f_open(&fp, path, FA_READ) != FR_OK)
return 0;
void *fss = malloc(f_size(&fp));
// Read first 1024 bytes of the fss file.
f_read(&fp, fss, 1024, NULL);
// Get FSS0 Meta header offset.
u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
// Check if valid FSS0 and parse it.
if (fss_meta->magic == FSS0_MAGIC)
{
gfx_printf("Found FSS0, Atmosphere %d.%d.%d-%08x\n"
"Max HOS supported: %d.%d.%d\n"
"Unpacking and loading components.. ",
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
if (!sept_ctxt)
{
ctxt->atmosphere = true;
ctxt->fss0_hosver = fss_meta->hos_ver;
}
// Parse FSS0 contents.
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
void *content;
for (u32 i = 0; i < fss_meta->cnt_count; i++)
{
content = (void *)(fss + curr_fss_cnt[i].offset);
// Check if offset is inside limits.
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
continue;
// If content is experimental and experimental flag is not enabled, skip it.
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental)
continue;
// Parse content.
if (!sept_ctxt)
{
// Prepare content context.
switch (curr_fss_cnt[i].type)
{
case CNT_TYPE_KIP:
if (stock)
continue;
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = content;
list_append(&ctxt->kip1_list, &mkip1->link);
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
break;
case CNT_TYPE_EXO:
ctxt->secmon_size = curr_fss_cnt[i].size;
ctxt->secmon = content;
break;
case CNT_TYPE_WBT:
ctxt->warmboot_size = curr_fss_cnt[i].size;
ctxt->warmboot = content;
break;
default:
continue;
}
// Load content to launch context.
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
}
else
{
// Load sept content directly to launch context.
switch (curr_fss_cnt[i].type)
{
case CNT_TYPE_SP1:
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, sept_ctxt->sept_primary, curr_fss_cnt[i].size, NULL);
break;
case CNT_TYPE_SP2:
if (!memcmp(curr_fss_cnt[i].name, (sept_ctxt->kb < KB_FIRMWARE_VERSION_810) ? "septsecondary00" : "septsecondary01", 15))
{
f_lseek(&fp, curr_fss_cnt[i].offset);
f_read(&fp, sept_ctxt->sept_secondary, curr_fss_cnt[i].size, NULL);
sept_used = 1;
goto out;
}
break;
default:
break;
}
}
}
out:
gfx_printf("Done!\n");
f_close(&fp);
return (!sept_ctxt ? 1 : sept_used);
}
f_close(&fp);
free(fss);
return 0;
}
int load_sept_from_ffs0(fss0_sept_t *sept_ctxt)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &sept_ctxt->cfg_sec->kvs, link)
{
if (!strcmp("fss0", kv->key))
return parse_fss(NULL, kv->val, sept_ctxt);
}
return 0;
}

34
source/hos/fss.h Normal file
View File

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

120
source/hos/hos.h Normal file
View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <assert.h>
#define KB_FIRMWARE_VERSION_100_200 0
#define KB_FIRMWARE_VERSION_300 1
#define KB_FIRMWARE_VERSION_301 2
#define KB_FIRMWARE_VERSION_400 3
#define KB_FIRMWARE_VERSION_500 4
#define KB_FIRMWARE_VERSION_600 5
#define KB_FIRMWARE_VERSION_620 6
#define KB_FIRMWARE_VERSION_700 7
#define KB_FIRMWARE_VERSION_810 8
#define KB_FIRMWARE_VERSION_900 9
#define KB_FIRMWARE_VERSION_910 10
#define KB_FIRMWARE_VERSION_MAX KB_FIRMWARE_VERSION_910
#define HOS_PKG11_MAGIC 0x31314B50
#define HOS_EKS_MAGIC 0x30534B45
typedef struct _exo_ctxt_t
{
bool no_user_exceptions;
bool user_pmu;
bool *cal0_blank;
bool *cal0_allow_writes_sys;
} exo_ctxt_t;
typedef struct _hos_eks_keys_t
{
u8 dkg[0x10];
u8 mkk[0x10];
u8 fdk[0x10];
u8 dkk[0x10];
} hos_eks_keys_t;
typedef struct _hos_eks_mbr_t
{
u32 magic;
u32 enabled;
u32 sbk_low[2];
hos_eks_keys_t keys[6];
u32 magic2;
u32 rsvd2[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 416, "HOS EKS storage bigger than MBR!");
typedef struct _launch_ctxt_t
{
void *keyblob;
void *pkg1;
const pkg1_id_t *pkg1_id;
const pkg2_kernel_id_t *pkg2_kernel_id;
void *warmboot;
u32 warmboot_size;
void *secmon;
u32 secmon_size;
void *pkg2;
u32 pkg2_size;
bool new_pkg2;
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
u32 fss0_hosver;
bool svcperm;
bool debugmode;
bool stock;
bool atmosphere;
bool fss0_enable_experimental;
bool emummc_forced;
exo_ctxt_t exo_cfg;
ini_sec_t *cfg;
} launch_ctxt_t;
typedef struct _merge_kip_t
{
void *kip1;
link_t link;
} merge_kip_t;
void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg);
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#endif

View File

@ -26,15 +26,15 @@
#include "../gfx/gfx.h"
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DEBUG_PRINTING*/
#define DPRINTF(...)
u32 pkg2_newkern_ini1_val;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{
u32 size = sizeof(pkg2_kip1_t);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018-2020 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -32,6 +32,14 @@ extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
typedef struct _kernel_patch_t
{
u32 id;
u32 off;
u32 val;
u32 *ptr;
} kernel_patch_t;
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
@ -87,6 +95,12 @@ typedef struct _pkg2_kip1_info_t
link_t link;
} pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u8 hash[8];
kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);

View File

@ -17,15 +17,20 @@
#include <string.h>
#include "sept.h"
#include "../config/ini.h"
#include "../gfx/di.h"
#include "../hos/fss.h"
#include "../hos/hos.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../soc/hw_init.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../storage/nx_emmc.h"
#include "../storage/nx_sd.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h"
#include "../utils/list.h"
#include "../utils/types.h"
#include "../gfx/gfx.h"
@ -58,48 +63,81 @@ u8 warmboot_reboot[] = {
extern u32 color_idx;
extern boot_cfg_t b_cfg;
extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
{
FIL fp;
bool fss0_sept_used = false;
// Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, tsec_size);
*(vu32 *)SEPT_TCSZ_ADDR = tsec_size;
// Copy sept-primary.
if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
LIST_INIT(ini_sections);
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{
bool found = false;
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Only parse non config sections.
if (ini_sec->type == INI_CHOICE && strcmp(ini_sec->name, "config"))
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp("fss0", kv->key))
{
fss0_sept_t sept_ctxt;
sept_ctxt.kb = kb;
sept_ctxt.sept_primary = (void *)SEPT_STG1_ADDR;
sept_ctxt.sept_secondary = (void *)SEPT_STG2_ADDR;
fss0_sept_used = parse_fss(NULL, kv->val, &sept_ctxt);
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
found = true;
break;
}
}
}
if (found)
break;
}
}
f_close(&fp);
// Copy sept-secondary.
if (kb < KB_FIRMWARE_VERSION_810)
if (!fss0_sept_used)
{
if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
goto error;
}
else
{
if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
// Copy sept-primary.
if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
}
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
// Copy sept-secondary.
if (kb < KB_FIRMWARE_VERSION_810)
{
if (f_open(&fp, "sd:/sept/sept-secondary_00.enc", FA_READ))
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ)) // Try the deprecated version.
goto error;
}
else
{
if (f_open(&fp, "sd:/sept/sept-secondary_01.enc", FA_READ))
goto error;
}
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
goto error;
}
f_close(&fp);
// Save auto boot config to sept payload, if any.
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
@ -107,7 +145,8 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE)) {
if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE))
{
free(tmp_cfg);
goto error;
}

View File

@ -81,8 +81,10 @@ static inline void _gf256_mul_x_le(void *block) {
static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 secsize) {
int res = 0;
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
u8 *temptweak = (u8 *)malloc(0x10);
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_tweak) {
for (int i = 0xF; i >= 0; i--) {
@ -96,34 +98,33 @@ static inline int _emmc_xts(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_twe
for (u32 i = 0; i < tweak_exp * 0x20; i++)
_gf256_mul_x_le(tweak);
u8 temptweak[0x10];
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += 4;
pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u8 *)dst;
pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++) {
for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
pdst += 0x10;
pdst += 4;
}
res = 1;
out:;
free(temptweak);
return res;
}

View File

@ -42,8 +42,8 @@
#include "../../storage/sdmmc.h"
extern sdmmc_storage_t sd_storage;
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...)
//#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
#define EFSPRINTF(...)
/*--------------------------------------------------------------------------

View File

@ -136,7 +136,7 @@ void *malloc(u32 size)
void *calloc(u32 num, u32 size)
{
void *res = (void *)_heap_alloc(&_heap, num * size);
memset(res, 0, num * size);
memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size.
return res;
}
@ -164,7 +164,7 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats)
count, node->used, (u32)node + sizeof(hnode_t), node->size);
count++;
if (node->next)
node = node->next;
else

View File

@ -2,7 +2,7 @@
* PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC
*
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2019 shchmue
* Copyright (c) 2019-2020 shchmue
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -35,10 +35,10 @@ void max77620_rtc_get_time(rtc_time_t *time)
// Get time.
time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F;
time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F;
u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG);
time->hour = hour & 0x1F;
if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK))
time->hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG) & 0x1F;
if (!(val & MAX77620_RTC_24H) && time->hour & MAX77620_RTC_HOUR_PM_MASK)
time->hour = (time->hour & 0xF) + 12;
// Get day of week. 1: Monday to 7: Sunday.

View File

@ -19,6 +19,7 @@
#include <string.h>
#include "../../common/memory_map.h"
#include "../sec/se.h"
#include "../mem/heap.h"
#include "../soc/bpmp.h"
@ -94,7 +95,12 @@ static int _se_wait()
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{
se_ll_t *ll_dst = (se_ll_t *)0xECFFFFE0, *ll_src = (se_ll_t *)0xECFFFFF0;
static se_ll_t *ll_dst = NULL, *ll_src = NULL;
if (!ll_dst)
{
ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t));
ll_src = (se_ll_t *)malloc(sizeof(se_ll_t));
}
if (dst)
{
@ -234,6 +240,16 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
}
}
void se_aes_iv_set(u32 ks, const void *iv, u32 size)
{
u32 *data = (u32 *)iv;
for (u32 i = 0; i < size / 4; i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | 8 | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
}
}
void se_aes_key_read(u32 ks, void *key, u32 size)
{
u32 *data = (u32 *)key;
@ -320,12 +336,90 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
return 1;
}
// random calls were derived from Atmosphère's
int se_initialize_rng(u32 ks)
{
u8 *output_buf = (u8 *)malloc(0x10);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_INSTANTION) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 70001;
SE(SE_RNG_SRC_CONFIG_REG_OFFSET) = SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
int res =_se_execute(OP_START, output_buf, 0x10, NULL, 0);
free(output_buf);
return res;
}
int se_generate_random(u32 ks, void *dst, u32 size)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
u32 num_blocks = size >> 4;
u32 aligned_size = num_blocks << 4;
if (num_blocks)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 1;
if (!_se_execute(OP_START, dst, aligned_size, NULL, 0))
return 0;
}
if (size > aligned_size)
return _se_execute_one_block(OP_START, dst + aligned_size, size - aligned_size, NULL, 0);
return 1;
}
int se_generate_random_key(u32 ks_dst, u32 ks_src)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL) | SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY);
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
if (!_se_execute(OP_START, NULL, 0, NULL, 0))
return 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst) | 1;
if (!_se_execute(OP_START, NULL, 0, NULL, 0))
return 0;
return 1;
}
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
SE_CRYPTO_IV_SEL(IV_ORIGINAL);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_AHB) |
SE_CRYPTO_IV_SEL(IV_ORIGINAL);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute(OP_START, dst, dst_size, src, src_size);
}
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize)
{
int res = 0;
u8 *tweak = (u8 *)malloc(0x10);
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
u8 *temptweak = (u8 *)malloc(0x10);
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
//Generate tweak.
for (int i = 0xF; i >= 0; i--)
@ -336,23 +430,35 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
goto out;
memcpy(temptweak, tweak, 0x10);
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++)
{
for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ tweak[j];
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
goto out;
for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += 4;
pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, secsize, dst, secsize);
pdst = (u32 *)dst;
memcpy(tweak, temptweak, 0x10);
for (u32 i = 0; i < secsize / 0x10; i++)
{
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
pdst += 4;
}
res = 1;
out:;
free(temptweak);
free(tweak);
return res;
}
@ -390,17 +496,21 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
se_aes_key_iv_clear(ks);
u32 num_blocks = (src_size + 0xf) >> 4;
if (num_blocks > 1) {
if (num_blocks > 1)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = num_blocks - 2;
if (!_se_execute(OP_START, NULL, 0, src, src_size))
goto out;
SE(SE_CRYPTO_REG_OFFSET) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
}
if (src_size & 0xf) {
if (src_size & 0xf)
{
memcpy(last_block, src + (src_size & ~0xf), src_size & 0xf);
last_block[src_size & 0xf] = 0x80;
} else if (src_size >= 0x10) {
}
else if (src_size >= 0x10)
{
memcpy(last_block, src + src_size - 0x10, 0x10);
}
@ -447,7 +557,8 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
return res;
}
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) {
int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size)
{
int res = 0;
u8 *secret = (u8 *)malloc(0x40);
u8 *ipad = (u8 *)malloc(0x40 + src_size);

View File

@ -25,12 +25,17 @@ void se_rsa_key_clear(u32 ks);
int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags);
void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv, u32 size);
void se_aes_key_read(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks);
int se_initialize_rng(u32 ks);
int se_generate_random(u32 ks, void *dst, u32 size);
int se_generate_random_key(u32 ks_dst, u32 ks_src);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize);
int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *src, u32 secsize, u32 num_secs);
int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);

View File

@ -18,6 +18,7 @@
#include <string.h>
#include "../hos/hos.h"
#include "../sec/tsec.h"
#include "../sec/tsec_t210.h"
#include "../sec/se_t210.h"
@ -80,7 +81,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
kfuse_wait_ready();
// Configure Falcon.
//Configure Falcon.
TSEC(TSEC_DMACTL) = 0;
TSEC(TSEC_IRQMSET) =
TSEC_IRQMSET_EXT(0xFF) |
@ -102,7 +103,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out;
}
// Load firmware or emulate memio environment for newer TSEC fw.
//Load firmware or emulate memio environment for newer TSEC fw.
if (kb == KB_FIRMWARE_VERSION_620)
TSEC(TSEC_DMATRFBASE) = (u32)tsec_ctxt->fw >> 8;
else
@ -126,7 +127,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
// Init SMMU translation for TSEC.
pdir = smmu_init_for_tsec();
smmu_init(tsec_ctxt->secmon_base);
smmu_init(0x4002B000);
// Enable SMMU
if (!smmu_is_used())
smmu_enable();
@ -169,7 +170,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
iram = page_alloc(0x30);
memcpy(iram, tsec_ctxt->pkg1, 0x30000);
// PKG1.1 magic offset.
pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
pkg11_magic_off = (u32 *)(iram + (0x7000 / 4));
smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
// Exception vectors
@ -177,7 +178,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
}
// Execute firmware.
//Execute firmware.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA;
TSEC(TSEC_STATUS) = 0;
TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1.
@ -254,7 +255,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
goto out_free;
}
// Fetch result.
//Fetch result.
HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0;
u32 buf[4];
buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB);
@ -274,7 +275,7 @@ out_free:;
out:;
// Disable clocks.
//Disable clocks.
clock_disable_kfuse();
clock_disable_sor1();
clock_disable_sor0();

View File

@ -27,8 +27,6 @@ typedef struct _tsec_ctxt_t
void *fw;
u32 size;
void *pkg1;
u32 pkg11_off;
u32 secmon_base;
} tsec_ctxt_t;
typedef struct _tsec_key_data_t

View File

@ -26,7 +26,6 @@
#include "pinmux.h"
#include "pmc.h"
#include "t210.h"
#include "uart.h"
#include "../gfx/di.h"
#include "../mem/mc.h"
#include "../mem/minerva.h"
@ -102,7 +101,7 @@ void _config_gpios()
pinmux_config_i2c(I2C_1);
pinmux_config_i2c(I2C_5);
pinmux_config_uart(UART_A);
pinmux_config_uart(0);
// Configure volume up/down as inputs.
gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO);
@ -295,11 +294,6 @@ void config_hw()
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
_config_gpios();
#ifdef DEBUG_UART_PORT
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200);
#endif
clock_enable_cl_dvfs();
clock_enable_i2c(I2C_1);
@ -319,6 +313,7 @@ void config_hw()
sdram_init();
bpmp_mmu_enable();
mc_enable_ahb_redirect();
// Clear flags from PMC_SCRATCH0
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
@ -334,7 +329,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
if (extra_reconfig)
{
@ -357,7 +352,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
if (magic == 0xBAADF00D)
{
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0);
clock_disable_cl_dvfs();
msleep(200);

View File

@ -15,7 +15,6 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
FIL in, out;
FILINFO in_info;
u64 sizeRemaining, toCopy;
UINT temp1, temp2;
u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL;
u32 x, y, i = 11;
int res;
@ -56,19 +55,14 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
while (sizeRemaining > 0){
toCopy = MIN(sizeRemaining, BUFSIZE);
if ((res = f_read(&in, buff, toCopy, &temp1))){
if ((res = f_read(&in, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 5);
return 1;
break;
}
if ((res = f_write(&out, buff, toCopy, &temp2))){
if ((res = f_write(&out, buff, toCopy, NULL))){
gfx_errDisplay("copy", res, 6);
return 1;
}
if (temp1 != temp2){
gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7);
return 1;
break;
}
sizeRemaining -= toCopy;
@ -100,13 +94,10 @@ int fsact_copy(const char *locin, const char *locout, u8 options){
f_close(&out);
free(buff);
if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){
gfx_errDisplay("copy", res, 8);
return 1;
}
f_chmod(locout, in_info.fattrib, 0x3A);
f_stat(locin, &in_info); //somehow stops fatfs from being weird
return 0;
return res;
}
int fsact_del_recursive(char *path){