Merge lockpickrcm changes
This commit is contained in:
141
source/sec/se.c
141
source/sec/se.c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user