se: Upgrade SE and allow SHA calc continue

- Allow SHA to calculate sizes > 16MB and refactor sha function
- Name various registers and magic numbers
- Fix various key access bugs

In a later commit this new design will boost verification times significantly and also allow full SHA256 hashes.
This commit is contained in:
CTCaer 2019-12-04 17:18:16 +02:00
parent 29a51124fd
commit 2c1da3a97d
12 changed files with 231 additions and 89 deletions

View file

@ -116,7 +116,8 @@ Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
Open source and free packages used: Open source and free packages used:
- FatFs R0.13a, Copyright (C) 2017, ChaN - FatFs R0.13a, Copyright (C) 2017, ChaN
- bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard - bcl-1.2.0, Copyright (C) 2003-2006, Marcus Geelnard
- Atmosphère (SE sha256, prc id kernel patches), Copyright (C) 2018, Atmosphère-NX - Atmosphère (Exosphere types/panic, prc id kernel patches),
Copyright (C) 2018-2019, Atmosphère-NX
- elfload, Copyright (C) 2014 Owen Shepherd, Copyright (C) 2018 M4xw - elfload, Copyright (C) 2014 Owen Shepherd, Copyright (C) 2018 M4xw
___ ___

View file

@ -114,11 +114,11 @@ static void _se_lock(bool lock_se)
if (lock_se) if (lock_se)
{ {
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
se_key_acc_ctrl(i, 0x15); 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++) for (u32 i = 0; i < 2; i++)
se_rsa_acc_ctrl(i, 1); se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG);
SE(0x4) = 0; // Make this reg secure only. 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_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_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only.
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only. SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
@ -264,8 +264,8 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
} }
else else
{ {
se_key_acc_ctrl(13, 0x15); 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, 0x15); 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. // Set TSEC key.
se_aes_key_set(13, tmp, 0x10); se_aes_key_set(13, tmp, 0x10);
@ -320,7 +320,7 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
} }
// Package2 key. // Package2 key.
se_key_acc_ctrl(8, 0x15); 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); se_aes_unwrap_key(8, 12, package2_keyseed);
} }
@ -660,16 +660,16 @@ int hos_launch(ini_sec_t *cfg)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id. PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id.
else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301) else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
se_key_acc_ctrl(12, 0xFF); se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(13, 0xFF); se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
bootStateDramPkg2 = 2; bootStateDramPkg2 = 2;
bootStatePkg2Continue = 3; bootStatePkg2Continue = 3;
break; break;
case KB_FIRMWARE_VERSION_400: case KB_FIRMWARE_VERSION_400:
case KB_FIRMWARE_VERSION_500: case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600: case KB_FIRMWARE_VERSION_600:
se_key_acc_ctrl(12, 0xFF); se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(15, 0xFF); se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
default: default:
bootStateDramPkg2 = 2; bootStateDramPkg2 = 2;
bootStatePkg2Continue = 4; bootStatePkg2Continue = 4;

View file

@ -1100,8 +1100,8 @@ void about()
" Copyright (c) 2018, ChaN\n\n" " Copyright (c) 2018, ChaN\n\n"
" - bcl-1.2.0,\n" " - bcl-1.2.0,\n"
" Copyright (c) 2003-2006, Marcus Geelnard\n\n" " Copyright (c) 2003-2006, Marcus Geelnard\n\n"
" - Atmosphere (SE sha256, prc id patches),\n" " - Atmosphere (Exo st/types, prc id patches),\n"
" Copyright (c) 2018, Atmosphere-NX\n\n" " Copyright (c) 2018-2019, Atmosphere-NX\n\n"
" - elfload,\n" " - elfload,\n"
" Copyright (c) 2014, Owen Shepherd\n" " Copyright (c) 2014, Owen Shepherd\n"
" Copyright (c) 2018, M4xw\n" " Copyright (c) 2018, M4xw\n"

View file

@ -1,7 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018 CTCaer
* Copyright (c) 2018 Atmosphère-NX
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -66,8 +65,8 @@ static int _se_wait()
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
; ;
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
SE(SE_STATUS_0) & 3 || SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
SE(SE_ERR_STATUS_0) != 0) SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
return 0; return 0;
return 1; return 1;
} }
@ -93,12 +92,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
int res = _se_wait(); int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (src) if (src)
free(ll_src); free(ll_src);
@ -135,17 +134,19 @@ static void _se_aes_ctr_set(void *ctr)
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & 0x7F) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = (((flags >> 4) & 4) | (flags & 3)) ^ 7; SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
if (flags & 0x80) ((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs);
} }
void se_key_acc_ctrl(u32 ks, u32 flags) void se_key_acc_ctrl(u32 ks, u32 flags)
{ {
if (flags & 0x7F) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
if (flags & 0x80) if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks);
} }
@ -280,15 +281,15 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size)
int res; int res;
// Setup config for SHA256, size = BITS(src_size). // Setup config for SHA256, size = BITS(src_size).
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_ENABLE; SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_INIT_HASH;
SE(SE_SHA_MSG_LENGTH_REG_OFFSET) = (u32)(src_size << 3); SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(src_size << 3);
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 1) = 0; SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 2) = 0; SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 3) = 0; SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_REG_OFFSET) = (u32)(src_size << 3); SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(src_size << 3);
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 1) = 0; SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 2) = 0; SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 3) = 0; SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
// Trigger the operation. // Trigger the operation.
res = _se_execute(OP_START, NULL, 0, src, src_size); res = _se_execute(OP_START, NULL, 0, src, src_size);

View file

@ -36,6 +36,8 @@
#define SE_SECURITY_0 0x000 #define SE_SECURITY_0 0x000
#define SE_KEY_SCHED_READ_SHIFT 3 #define SE_KEY_SCHED_READ_SHIFT 3
#define SE_TZRAM_SECURITY_0 0x004
#define SE_CONFIG_REG_OFFSET 0x014 #define SE_CONFIG_REG_OFFSET 0x014
#define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_CONFIG_ENC_ALG_SHIFT 12
#define SE_CONFIG_DEC_ALG_SHIFT 8 #define SE_CONFIG_DEC_ALG_SHIFT 8
@ -211,7 +213,10 @@
#define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT) #define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT)
#define SE_STATUS_0 0x800 #define SE_STATUS_0 0x800
#define SE_STATUS_0_STATE_WAIT_IN 3
#define SE_ERR_STATUS_0 0x804 #define SE_ERR_STATUS_0 0x804
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 #define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
@ -232,11 +237,17 @@
#define SE_SPARE_0_REG_OFFSET 0x80c #define SE_SPARE_0_REG_OFFSET 0x80c
#define SE_SHA_CONFIG_REG_OFFSET 0x200 #define SE_SHA_CONFIG_REG_OFFSET 0x200
#define SHA_DISABLE 0 #define SHA_CONTINUE 0
#define SHA_ENABLE 1 #define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_REG_OFFSET 0x204 #define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
#define SE_SHA_MSG_LEFT_REG_OFFSET 0x214 #define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
#define SE_HASH_RESULT_REG_COUNT 16 #define SE_HASH_RESULT_REG_COUNT 16
#define SE_HASH_RESULT_REG_OFFSET 0x030 #define SE_HASH_RESULT_REG_OFFSET 0x030
@ -261,7 +272,18 @@
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #define TEGRA_SE_RSA2048_DIGEST_SIZE 256
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 #define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 #define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
#define SE_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG (1 << 2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG (1 << 3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG (1 << 4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG (1 << 5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG (1 << 6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_KEY_READ_DISABLE_SHIFT 0 #define SE_KEY_READ_DISABLE_SHIFT 0
#define SE_KEY_UPDATE_DISABLE_SHIFT 1 #define SE_KEY_UPDATE_DISABLE_SHIFT 1
@ -313,7 +335,16 @@
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 #define TEGRA_SE_RSA_KEYSLOT_COUNT 2
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C #define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 #define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG (1 << 2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT (1 << 2)
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
#define SE_RSA_KEYTABLE_ADDR 0x420 #define SE_RSA_KEYTABLE_ADDR 0x420
#define SE_RSA_KEYTABLE_DATA 0x424 #define SE_RSA_KEYTABLE_DATA 0x424

View file

@ -250,8 +250,8 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
return 1; return 1;
} }
se_calc_sha256(hashEm, bufEm, num << 9); se_calc_sha256(hashEm, NULL, bufEm, num << 9, 0, SHA_INIT_HASH, true);
se_calc_sha256(hashSd, bufSd, num << 9); se_calc_sha256(hashSd, NULL, bufSd, num << 9, 0, SHA_INIT_HASH, true);
res = memcmp(hashEm, hashSd, 0x10); res = memcmp(hashEm, hashSd, 0x10);
if (res) if (res)

View file

@ -38,7 +38,6 @@
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache. #define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
#define OUT_FILENAME_SZ 128 #define OUT_FILENAME_SZ 128
#define SHA256_SZ 0x20
#define MBR_1ST_PART_TYPE_OFF 0x1C2 #define MBR_1ST_PART_TYPE_OFF 0x1C2

View file

@ -714,8 +714,8 @@ static void _create_tab_about(lv_theme_t * th, lv_obj_t * parent)
" Copyright (c) 2018, ChaN\n\n" " Copyright (c) 2018, ChaN\n\n"
" - bcl-1.2.0,\n" " - bcl-1.2.0,\n"
" Copyright (c) 2003-2006, Marcus Geelnard\n\n" " Copyright (c) 2003-2006, Marcus Geelnard\n\n"
" - Atmosphere (SE sha256, process id patches),\n" " - Atmosphere (Exosphere types/panic, proc id patches),\n"
" Copyright (c) 2018, Atmosphere-NX\n\n" " Copyright (c) 2018-2019, Atmosphere-NX\n\n"
" - elfload,\n" " - elfload,\n"
" Copyright (c) 2014, Owen Shepherd\n" " Copyright (c) 2014, Owen Shepherd\n"
" Copyright (c) 2018, M4xw\n\n" " Copyright (c) 2018, M4xw\n\n"

View file

@ -150,9 +150,6 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
} }
else else
{ {
se_key_acc_ctrl(13, 0x15);
se_key_acc_ctrl(14, 0x15);
// Set TSEC key. // Set TSEC key.
se_aes_key_set(13, tmp, 0x10); se_aes_key_set(13, tmp, 0x10);
@ -206,7 +203,6 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
} }
// Package2 key. // Package2 key.
se_key_acc_ctrl(8, 0x15);
se_aes_unwrap_key(8, 12, package2_keyseed); se_aes_unwrap_key(8, 12, package2_keyseed);
} }

View file

@ -1,7 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018 CTCaer
* Copyright (c) 2018 Atmosphère-NX
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -66,15 +65,17 @@ static int _se_wait()
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET))) while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
; ;
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) || if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
SE(SE_STATUS_0) & 3 || SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
SE(SE_ERR_STATUS_0) != 0) SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
return 0; return 0;
return 1; return 1;
} }
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) se_ll_t *ll_dst, *ll_src;
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
{ {
se_ll_t *ll_dst = NULL, *ll_src = NULL; ll_dst = NULL;
ll_src = NULL;
if (dst) if (dst)
{ {
@ -93,17 +94,42 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op); SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); int res = 1;
if (is_oneshot)
{
res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (src) if (src)
free(ll_src); free(ll_src);
if (dst) if (dst)
free(ll_dst); free(ll_dst);
}
return res;
}
static int _se_execute_finalize()
{
int res = _se_wait();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (ll_src)
{
free(ll_src);
ll_src = NULL;
}
if (ll_dst)
{
free(ll_dst);
ll_dst = NULL;
}
return res; return res;
} }
@ -119,7 +145,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
memcpy(block, src, src_size); memcpy(block, src, src_size);
int res = _se_execute(op, block, 0x10, block, 0x10); int res = _se_execute(op, block, 0x10, block, 0x10, true);
memcpy(dst, block, dst_size); memcpy(dst, block, dst_size);
free(block); free(block);
@ -135,17 +161,19 @@ static void _se_aes_ctr_set(void *ctr)
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & 0x7F) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = (((flags >> 4) & 4) | (flags & 3)) ^ 7; SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
if (flags & 0x80) ((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs); SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs);
} }
void se_key_acc_ctrl(u32 ks, u32 flags) void se_key_acc_ctrl(u32 ks, u32 flags)
{ {
if (flags & 0x7F) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
if (flags & 0x80) if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks); SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~(1 << ks);
} }
@ -175,7 +203,7 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
return _se_execute(OP_START, NULL, 0, input, 0x10); return _se_execute(OP_START, NULL, 0, input, 0x10, true);
} }
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size) int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
@ -191,7 +219,7 @@ int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src,
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute(OP_START, dst, dst_size, src, src_size); return _se_execute(OP_START, dst, dst_size, src, src_size, true);
} }
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src) int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
@ -213,7 +241,7 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
if (src_size_aligned) if (src_size_aligned)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned)) if (!_se_execute(OP_START, dst, dst_size, src, src_size_aligned, true))
return 0; return 0;
} }
@ -274,30 +302,84 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
return 1; return 1;
} }
// se_calc_sha256() was derived from Atmosphère's se_calculate_sha256. int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
int se_calc_sha256(void *dst, const void *src, u32 src_size)
{ {
int res; int res;
// Setup config for SHA256, size = BITS(src_size). u32 *hash32 = (u32 *)hash;
if (src_size > 0xFFFFFF || (u32)hash % 4 || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;
// Setup config for SHA256.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG_OFFSET) = SHA_ENABLE; SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg;
SE(SE_SHA_MSG_LENGTH_REG_OFFSET) = (u32)(src_size << 3);
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 1) = 0; // Set total size to current buffer size if empty.
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 2) = 0; if (!total_size)
SE(SE_SHA_MSG_LENGTH_REG_OFFSET + 4 * 3) = 0; total_size = src_size;
SE(SE_SHA_MSG_LEFT_REG_OFFSET) = (u32)(src_size << 3);
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 1) = 0; // Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 2) = 0; SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_REG_OFFSET + 4 * 3) = 0; SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
// Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
// If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE)
{
if (!msg_left)
return 0;
// Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
// Restore hash reg.
for (u32 i = 0; i < 8; i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
}
// Trigger the operation. // Trigger the operation.
res = _se_execute(OP_START, NULL, 0, src, src_size); res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot)
{
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
}
// Copy output hash. // Copy output hash.
u32 *dst32 = (u32 *)dst;
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
dst32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
}
return res; return res;
} }
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
{
u32 *hash32 = (u32 *)hash;
int res = _se_execute_finalize();
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
}
// Copy output hash.
for (u32 i = 0; i < 8; i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
return res;
}

View file

@ -27,6 +27,7 @@ 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_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_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_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_calc_sha256(void *dst, const void *src, u32 src_size); int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
#endif #endif

View file

@ -36,6 +36,8 @@
#define SE_SECURITY_0 0x000 #define SE_SECURITY_0 0x000
#define SE_KEY_SCHED_READ_SHIFT 3 #define SE_KEY_SCHED_READ_SHIFT 3
#define SE_TZRAM_SECURITY_0 0x004
#define SE_CONFIG_REG_OFFSET 0x014 #define SE_CONFIG_REG_OFFSET 0x014
#define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_CONFIG_ENC_ALG_SHIFT 12
#define SE_CONFIG_DEC_ALG_SHIFT 8 #define SE_CONFIG_DEC_ALG_SHIFT 8
@ -211,7 +213,10 @@
#define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT) #define SE_INT_ERROR(x) (x << SE_INT_ERROR_SHIFT)
#define SE_STATUS_0 0x800 #define SE_STATUS_0 0x800
#define SE_STATUS_0_STATE_WAIT_IN 3
#define SE_ERR_STATUS_0 0x804 #define SE_ERR_STATUS_0 0x804
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330 #define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0 #define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
@ -232,11 +237,17 @@
#define SE_SPARE_0_REG_OFFSET 0x80c #define SE_SPARE_0_REG_OFFSET 0x80c
#define SE_SHA_CONFIG_REG_OFFSET 0x200 #define SE_SHA_CONFIG_REG_OFFSET 0x200
#define SHA_DISABLE 0 #define SHA_CONTINUE 0
#define SHA_ENABLE 1 #define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_REG_OFFSET 0x204 #define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
#define SE_SHA_MSG_LEFT_REG_OFFSET 0x214 #define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
#define SE_HASH_RESULT_REG_COUNT 16 #define SE_HASH_RESULT_REG_COUNT 16
#define SE_HASH_RESULT_REG_OFFSET 0x030 #define SE_HASH_RESULT_REG_OFFSET 0x030
@ -261,7 +272,18 @@
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #define TEGRA_SE_RSA2048_DIGEST_SIZE 256
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280 #define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 #define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
#define SE_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG (1 << 2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG (1 << 3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG (1 << 4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG (1 << 5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG (1 << 6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_KEY_READ_DISABLE_SHIFT 0 #define SE_KEY_READ_DISABLE_SHIFT 0
#define SE_KEY_UPDATE_DISABLE_SHIFT 1 #define SE_KEY_UPDATE_DISABLE_SHIFT 1
@ -313,7 +335,16 @@
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2 #define TEGRA_SE_RSA_KEYSLOT_COUNT 2
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C #define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410 #define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG (1 << 0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG (1 << 1)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG (1 << 2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT (1 << 2)
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
#define SE_RSA_KEYTABLE_ADDR 0x420 #define SE_RSA_KEYTABLE_ADDR 0x420
#define SE_RSA_KEYTABLE_DATA 0x424 #define SE_RSA_KEYTABLE_DATA 0x424