|
|
|
|
@@ -1,8 +1,6 @@
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2018 naehrwert
|
|
|
|
|
* Copyright (c) 2018 CTCaer
|
|
|
|
|
* Copyright (c) 2018 Atmosphère-NX
|
|
|
|
|
* Copyright (c) 2019 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,
|
|
|
|
|
@@ -33,9 +31,6 @@ 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;
|
|
|
|
|
@@ -52,22 +47,6 @@ 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;
|
|
|
|
|
@@ -94,15 +73,17 @@ 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;
|
|
|
|
|
se_ll_t *ll_dst = NULL, *ll_src = NULL;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -118,6 +99,11 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -156,66 +142,6 @@ 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)
|
|
|
|
|
@@ -224,7 +150,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, const void *key, u32 size)
|
|
|
|
|
void se_aes_key_set(u32 ks, void *key, u32 size)
|
|
|
|
|
{
|
|
|
|
|
u32 *data = (u32 *)key;
|
|
|
|
|
for (u32 i = 0; i < size / 4; i++)
|
|
|
|
|
@@ -234,16 +160,6 @@ void se_aes_key_set(u32 ks, const 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++)
|
|
|
|
|
@@ -253,15 +169,6 @@ 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);
|
|
|
|
|
@@ -288,6 +195,24 @@ 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);
|
|
|
|
|
@@ -298,8 +223,7 @@ 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_VCTRAM_SEL(VCTRAM_AHB);
|
|
|
|
|
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
|
|
|
|
|
_se_aes_ctr_set(ctr);
|
|
|
|
|
|
|
|
|
|
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
|
|
|
|
@@ -320,7 +244,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, const void *src, u32 secsize)
|
|
|
|
|
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
u8 *tweak = (u8 *)malloc(0x10);
|
|
|
|
|
@@ -345,7 +269,7 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const vo
|
|
|
|
|
goto out;
|
|
|
|
|
for (u32 j = 0; j < 0x10; j++)
|
|
|
|
|
pdst[j] = pdst[j] ^ tweak[j];
|
|
|
|
|
_gf256_mul_x_le(tweak);
|
|
|
|
|
_gf256_mul_x(tweak);
|
|
|
|
|
psrc += 0x10;
|
|
|
|
|
pdst += 0x10;
|
|
|
|
|
}
|
|
|
|
|
@@ -357,7 +281,7 @@ out:;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs)
|
|
|
|
|
{
|
|
|
|
|
u8 *pdst = (u8 *)dst;
|
|
|
|
|
u8 *psrc = (u8 *)src;
|
|
|
|
|
@@ -369,58 +293,6 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, const void *
|
|
|
|
|
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;
|
|
|
|
|
@@ -447,45 +319,76 @@ 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 res = 0;
|
|
|
|
|
u8 *secret = (u8 *)malloc(0x40);
|
|
|
|
|
u8 *ipad = (u8 *)malloc(0x40 + src_size);
|
|
|
|
|
u8 *opad = (u8 *)malloc(0x60);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
if (key_size > 0x40)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
res = 1;
|
|
|
|
|
|
|
|
|
|
out:;
|
|
|
|
|
free(secret);
|
|
|
|
|
free(ipad);
|
|
|
|
|
free(opad);
|
|
|
|
|
return res;
|
|
|
|
|
// 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++)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
// End context save.
|
|
|
|
|
SE(SE_CONFIG_REG_OFFSET) = 0;
|
|
|
|
|
_se_execute(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
|
|
|
|
|
|
|
|
|
// Get SRK.
|
|
|
|
|
u32 srk[4];
|
|
|
|
|
srk[0] = PMC(0xC0);
|
|
|
|
|
srk[1] = PMC(0xC4);
|
|
|
|
|
srk[2] = PMC(0x224);
|
|
|
|
|
srk[3] = PMC(0x228);
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
|