Nyx: emuMMC Manage window, Tools UI, and misc updates
- Add gui_emu_tools: emuMMC Manage window with correct positioning (LV_PROTECT_PARENT + re-parent to win) - Tools: single SD button (tap = SD partition manager, 3s hold = eMMC) - Remove emuSD from Nyx UI (tabs, UMS, partition manager); keep bootloader emusd - Shorten Create emuMMC description text by one character - Storage/build/config and dependency updates Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
357
bdk/sec/se.c
357
bdk/sec/se.c
@@ -91,33 +91,28 @@ static int _se_op_wait()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// WAR: Coherency flushing.
|
||||
if (ll_dst_ptr)
|
||||
// T210B01: IRAM/TZRAM/DRAM AHB coherency WAR.
|
||||
if (!tegra_t210 && ll_dst_ptr)
|
||||
{
|
||||
u32 timeout = get_tmr_us() + 1000000;
|
||||
// Ensure data is out from SE.
|
||||
if (tegra_t210)
|
||||
usleep(15); // Worst case scenario.
|
||||
else
|
||||
while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
|
||||
{
|
||||
// T210B01 has a status bit for that.
|
||||
u32 retries = 500000;
|
||||
while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
|
||||
{
|
||||
if (!retries)
|
||||
return 0;
|
||||
usleep(1);
|
||||
retries--;
|
||||
}
|
||||
if (get_tmr_us() > timeout)
|
||||
return 0;
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
// Ensure data is out from AHB.
|
||||
u32 retries = 500000;
|
||||
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
|
||||
if (ll_dst_ptr->addr >= DRAM_START)
|
||||
{
|
||||
if (!retries)
|
||||
return 0;
|
||||
usleep(1);
|
||||
retries--;
|
||||
timeout = get_tmr_us() + 200000;
|
||||
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
|
||||
{
|
||||
if (get_tmr_us() > timeout)
|
||||
return 0;
|
||||
usleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,9 +131,6 @@ static int _se_execute_finalize()
|
||||
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
|
||||
{
|
||||
if (dst_size > SE_LL_MAX_SIZE || src_size > SE_LL_MAX_SIZE)
|
||||
return 0;
|
||||
|
||||
ll_src_ptr = NULL;
|
||||
ll_dst_ptr = NULL;
|
||||
|
||||
@@ -178,41 +170,18 @@ static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src,
|
||||
return _se_execute(op, dst, dst_size, src, src_size, true);
|
||||
}
|
||||
|
||||
static int _se_execute_aes_oneshot(void *dst, const void *src, u32 size)
|
||||
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
// Set optional memory interface.
|
||||
if (dst >= (void *)DRAM_START && src >= (void *)DRAM_START)
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_MEMIF(MEMIF_MCCIF);
|
||||
if (!src || !dst)
|
||||
return 0;
|
||||
|
||||
u32 size_aligned = ALIGN_DOWN(size, SE_AES_BLOCK_SIZE);
|
||||
u32 size_residue = size % SE_AES_BLOCK_SIZE;
|
||||
int res = 1;
|
||||
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
|
||||
// Handle initial aligned message.
|
||||
if (size_aligned)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (size >> 4) - 1;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = 1 - 1;
|
||||
|
||||
res = _se_execute_oneshot(SE_OP_START, dst, size_aligned, src, size_aligned);
|
||||
}
|
||||
|
||||
// Handle leftover partial message.
|
||||
if (res && size_residue)
|
||||
{
|
||||
// Copy message to a block sized buffer in case it's partial.
|
||||
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
memcpy(block, src + size_aligned, size_residue);
|
||||
|
||||
// Use updated IV for CBC and OFB. Ignored on others.
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1;
|
||||
|
||||
res = _se_execute_oneshot(SE_OP_START, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||
|
||||
// Copy result back.
|
||||
memcpy(dst + size_aligned, block, size_residue);
|
||||
}
|
||||
memcpy(block, src, src_size);
|
||||
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||
memcpy(dst, block, dst_size);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -262,14 +231,13 @@ 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_iv_set(u32 ks, const void *iv)
|
||||
{
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / sizeof(u32)];
|
||||
memcpy(data, iv, size);
|
||||
u32 data[SE_AES_IV_SIZE / sizeof(u32)];
|
||||
memcpy(data, iv, SE_AES_IV_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (size / sizeof(u32)); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / sizeof(u32)); i++)
|
||||
{
|
||||
// QUAD UPDATED_IV bit is automatically set by PKT macro.
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||
}
|
||||
@@ -301,14 +269,22 @@ void se_aes_key_clear(u32 ks)
|
||||
|
||||
void se_aes_iv_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / sizeof(u32)); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / sizeof(u32)); i++)
|
||||
{
|
||||
// QUAD UPDATED_IV bit is automatically set by PKT macro.
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_updated_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(UPDATED_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed)
|
||||
{
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_MODE(MODE_KEY128) | SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
|
||||
@@ -319,7 +295,27 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed)
|
||||
return _se_execute_oneshot(SE_OP_START, NULL, 0, seed, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size)
|
||||
int se_aes_crypt_hash(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = 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_HASH(HASH_ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) |
|
||||
SE_CRYPTO_HASH(HASH_ENABLE);
|
||||
}
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
@@ -333,11 +329,11 @@ int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size)
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT) |
|
||||
SE_CRYPTO_XOR_POS(XOR_BYPASS);
|
||||
}
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size)
|
||||
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
@@ -351,21 +347,16 @@ int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size)
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ofb(u32 ks, void *dst, const void *src, u32 size)
|
||||
int se_aes_crypt_block_ecb(u32 ks, int enc, void *dst, const void *src)
|
||||
{
|
||||
SE(SE_SPARE_REG) = SE_INPUT_NONCE_LE;
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AESOUT) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr)
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
{
|
||||
SE(SE_SPARE_REG) = SE_INPUT_NONCE_LE;
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
@@ -375,10 +366,25 @@ int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr)
|
||||
|
||||
_se_aes_counter_set(ctr);
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
||||
u32 src_size_delta = src_size & 0xF;
|
||||
|
||||
if (src_size_aligned)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
|
||||
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src_size - src_size_aligned && src_size_aligned < dst_size)
|
||||
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
|
||||
MIN(src_size_delta, dst_size - src_size_aligned),
|
||||
src + src_size_aligned, src_size_delta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||
{
|
||||
int res = 0;
|
||||
u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)];
|
||||
@@ -392,7 +398,7 @@ int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst
|
||||
tweak[i] = sec & 0xFF;
|
||||
sec >>= 8;
|
||||
}
|
||||
if (!se_aes_crypt_ecb(tweak_ks, ENCRYPT, tweak, tweak, SE_AES_BLOCK_SIZE))
|
||||
if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
|
||||
goto out;
|
||||
|
||||
// We are assuming a 0x10-aligned sector size in this implementation.
|
||||
@@ -400,7 +406,7 @@ int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst
|
||||
{
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = psrc[j] ^ tweak[j];
|
||||
if (!se_aes_crypt_ecb(crypt_ks, enc, pdst, pdst, SE_AES_BLOCK_SIZE))
|
||||
if (!se_aes_crypt_block_ecb(crypt_ks, enc, pdst, pdst))
|
||||
goto out;
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
@@ -415,7 +421,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size)
|
||||
int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size)
|
||||
{
|
||||
u32 *pdst = (u32 *)dst;
|
||||
u32 *psrc = (u32 *)src;
|
||||
@@ -428,7 +434,7 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
|
||||
tweak[i] = sec & 0xFF;
|
||||
sec >>= 8;
|
||||
}
|
||||
if (!se_aes_crypt_ecb(tweak_ks, ENCRYPT, tweak, tweak, SE_AES_BLOCK_SIZE))
|
||||
if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -450,7 +456,7 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
|
||||
pdst += sizeof(u32);
|
||||
}
|
||||
|
||||
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, dst, sec_size))
|
||||
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size))
|
||||
return 0;
|
||||
|
||||
pdst = (u32 *)dst;
|
||||
@@ -467,20 +473,27 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
|
||||
return 1;
|
||||
}
|
||||
|
||||
int se_aes_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs)
|
||||
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs)
|
||||
{
|
||||
u8 *pdst = (u8 *)dst;
|
||||
u8 *psrc = (u8 *)src;
|
||||
|
||||
for (u32 i = 0; i < num_secs; i++)
|
||||
if (!se_aes_crypt_xts_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize))
|
||||
if (!se_aes_xts_crypt_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _se_sha_hash_256_get_hash(void *hash)
|
||||
static void se_calc_sha256_get_hash(void *hash, u32 *msg_left)
|
||||
{
|
||||
// Backup message left.
|
||||
if (msg_left)
|
||||
{
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
u32 hash32[SE_SHA_256_SIZE / sizeof(u32)];
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / sizeof(u32)); i++)
|
||||
@@ -488,8 +501,15 @@ static void _se_sha_hash_256_get_hash(void *hash)
|
||||
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||
}
|
||||
|
||||
static int _se_sha_hash_256(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot)
|
||||
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 res;
|
||||
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||
|
||||
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
||||
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
|
||||
return 0;
|
||||
|
||||
// Src size of 0 is not supported, so return null string sha256.
|
||||
if (!src_size)
|
||||
{
|
||||
@@ -501,123 +521,79 @@ static int _se_sha_hash_256(void *hash, u64 total_size, const void *src, u32 src
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Increase leftover size if not last message. (Engine will always stop at src_size.)
|
||||
u32 msg_left = src_size;
|
||||
if (total_size < src_size)
|
||||
msg_left++;
|
||||
|
||||
// Setup config for SHA256.
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG) = sha_cfg;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = 1 - 1;
|
||||
|
||||
// Set total size: BITS(total_size), up to 2 EB.
|
||||
// Set total size to current buffer size if empty.
|
||||
if (!total_size)
|
||||
total_size = src_size;
|
||||
|
||||
// Set total size: BITS(src_size), up to 2 EB.
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
|
||||
|
||||
// Set leftover size: BITS(src_size).
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(msg_left << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(msg_left >> 29);
|
||||
// Set size left to hash.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
|
||||
|
||||
// Set config based on init or partial continuation.
|
||||
if (total_size == src_size || !total_size)
|
||||
SE(SE_SHA_CONFIG_REG) = SHA_INIT_HASH;
|
||||
else
|
||||
SE(SE_SHA_CONFIG_REG) = SHA_CONTINUE;
|
||||
// If we hash in chunks, copy over the intermediate.
|
||||
if (sha_cfg == SHA_CONTINUE && msg_left)
|
||||
{
|
||||
// Restore message left to process.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
|
||||
|
||||
// Trigger the operation. src vs total size decides if it's partial.
|
||||
int res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
// Restore hash reg.
|
||||
memcpy(hash32, hash, SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
|
||||
}
|
||||
|
||||
if (res && is_oneshot)
|
||||
_se_sha_hash_256_get_hash(hash);
|
||||
// Trigger the operation.
|
||||
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
|
||||
if (is_oneshot)
|
||||
se_calc_sha256_get_hash(hash, msg_left);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_sha_hash_256_async(void *hash, const void *src, u32 size)
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
|
||||
{
|
||||
return _se_sha_hash_256(hash, size, src, size, false);
|
||||
return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true);
|
||||
}
|
||||
|
||||
int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size)
|
||||
{
|
||||
return _se_sha_hash_256(hash, size, src, size, true);
|
||||
}
|
||||
|
||||
int se_sha_hash_256_partial_start(void *hash, const void *src, u32 size, bool is_oneshot)
|
||||
{
|
||||
// Check if aligned SHA256 block size.
|
||||
if (size % SE_SHA2_MIN_BLOCK_SIZE)
|
||||
return 0;
|
||||
|
||||
return _se_sha_hash_256(hash, 0, src, size, is_oneshot);
|
||||
}
|
||||
|
||||
int se_sha_hash_256_partial_update(void *hash, const void *src, u32 size, bool is_oneshot)
|
||||
{
|
||||
// Check if aligned to SHA256 block size.
|
||||
if (size % SE_SHA2_MIN_BLOCK_SIZE)
|
||||
return 0;
|
||||
|
||||
return _se_sha_hash_256(hash, size - 1, src, size, is_oneshot);
|
||||
}
|
||||
|
||||
int se_sha_hash_256_partial_end(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot)
|
||||
{
|
||||
return _se_sha_hash_256(hash, total_size, src, src_size, is_oneshot);
|
||||
}
|
||||
|
||||
int se_sha_hash_256_finalize(void *hash)
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
{
|
||||
int res = _se_execute_finalize();
|
||||
|
||||
_se_sha_hash_256_get_hash(hash);
|
||||
se_calc_sha256_get_hash(hash, msg_left);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_rng_pseudo(void *dst, u32 size)
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// Setup config for SP 800-90 PRNG.
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
|
||||
SE(SE_RNG_SRC_CONFIG_REG) |= SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE); // DRBG. Depends on ENTROPY clock.
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG) = 4096;
|
||||
//SE(SE_RNG_SRC_CONFIG_REG) |= SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE); // DRBG. Depends on ENTROPY clock.
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
|
||||
|
||||
u32 size_aligned = ALIGN_DOWN(size, SE_RNG_BLOCK_SIZE);
|
||||
u32 size_residue = size % SE_RNG_BLOCK_SIZE;
|
||||
int res = 0;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (16 >> 4) - 1;
|
||||
|
||||
// Handle initial aligned message.
|
||||
if (size_aligned)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (size >> 4) - 1;
|
||||
|
||||
res = _se_execute_oneshot(SE_OP_START, dst, size_aligned, NULL, 0);
|
||||
}
|
||||
|
||||
// Handle leftover partial message.
|
||||
if (res && size_residue)
|
||||
{
|
||||
// Copy message to a block sized buffer in case it's partial.
|
||||
u32 block[SE_RNG_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1;
|
||||
|
||||
res = _se_execute_oneshot(SE_OP_START, block, SE_RNG_BLOCK_SIZE, NULL, 0);
|
||||
|
||||
// Copy result back.
|
||||
if (res)
|
||||
memcpy(dst + size_aligned, block, size_residue);
|
||||
}
|
||||
|
||||
return res;
|
||||
// Trigger the operation.
|
||||
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
{
|
||||
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
||||
|
||||
@@ -668,13 +644,16 @@ void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_cbc(3, DECRYPT, keys, keys, SE_AES_KEYSLOT_COUNT * keysize);
|
||||
se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_clear(3);
|
||||
}
|
||||
|
||||
int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size)
|
||||
int se_aes_cmac_128(u32 ks, void *hash, const void *src, u32 size)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
u32 tmp1[SE_KEY_128_SIZE / sizeof(u32)] = {0};
|
||||
u32 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
u8 *subkey = (u8 *)tmp1;
|
||||
@@ -682,54 +661,52 @@ int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size)
|
||||
|
||||
// Generate sub key (CBC with zeroed IV, basically ECB).
|
||||
se_aes_iv_clear(ks);
|
||||
if (!se_aes_crypt_cbc(ks, ENCRYPT, subkey, subkey, SE_KEY_128_SIZE))
|
||||
return 0;
|
||||
se_aes_iv_updated_clear(ks);
|
||||
if (!se_aes_crypt_hash(ks, ENCRYPT, subkey, SE_KEY_128_SIZE, subkey, SE_KEY_128_SIZE))
|
||||
goto out;
|
||||
|
||||
// Generate K1 subkey.
|
||||
_se_ls_1bit(subkey);
|
||||
if (size & 0xF)
|
||||
_se_ls_1bit(subkey); // Convert to K2.
|
||||
|
||||
// Switch to hash register. The rest of the config is already set.
|
||||
SE(SE_CONFIG_REG) |= SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_HASH(HASH_ENABLE);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
|
||||
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_iv_clear(ks);
|
||||
se_aes_iv_updated_clear(ks);
|
||||
|
||||
// Initial blocks.
|
||||
u32 num_blocks = (size + 0xF) >> 4;
|
||||
if (num_blocks > 1)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = num_blocks - 2;
|
||||
|
||||
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, size))
|
||||
return 0;
|
||||
|
||||
// Use updated IV for next OP as a continuation.
|
||||
goto out;
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
|
||||
}
|
||||
|
||||
// Last block.
|
||||
if (size & 0xF)
|
||||
{
|
||||
memcpy(last_block, src + (size & (~0xF)), size & 0xF);
|
||||
memcpy(last_block, src + (size & ~0xF), size & 0xF);
|
||||
last_block[size & 0xF] = 0x80;
|
||||
}
|
||||
else if (size >= SE_AES_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(last_block, src + size - SE_AES_BLOCK_SIZE, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < SE_KEY_128_SIZE; i++)
|
||||
last_block[i] ^= subkey[i];
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = 0;
|
||||
|
||||
int res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, SE_AES_BLOCK_SIZE);
|
||||
res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, SE_AES_BLOCK_SIZE);
|
||||
|
||||
// Copy output hash.
|
||||
if (res)
|
||||
{
|
||||
u32 *hash32 = (u32 *)hash;
|
||||
for (u32 i = 0; i < (SE_AES_CMAC_DIGEST_SIZE / sizeof(u32)); i++)
|
||||
hash32[i] = SE(SE_HASH_RESULT_REG + sizeof(u32) * i);
|
||||
}
|
||||
u32 *hash32 = (u32 *)hash;
|
||||
for (u32 i = 0; i < (SE_AES_CMAC_DIGEST_SIZE / sizeof(u32)); i++)
|
||||
hash32[i] = SE(SE_HASH_RESULT_REG + sizeof(u32) * i);
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
33
bdk/sec/se.h
33
bdk/sec/se.h
@@ -27,29 +27,28 @@ u32 se_key_acc_ctrl_get(u32 ks);
|
||||
|
||||
/*! AES Key Management Functions */
|
||||
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_iv_set(u32 ks, const void *iv);
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
void se_aes_iv_clear(u32 ks);
|
||||
void se_aes_iv_updated_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed);
|
||||
void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize);
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
|
||||
/*! Encryption Functions */
|
||||
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size);
|
||||
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size);
|
||||
int se_aes_crypt_ofb(u32 ks, void *dst, const void *src, u32 size);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr);
|
||||
int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize);
|
||||
int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size);
|
||||
int se_aes_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
|
||||
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_block_ecb(u32 ks, int enc, void *dst, const void *src);
|
||||
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize);
|
||||
int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size);
|
||||
int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
|
||||
/*! Hashing Functions */
|
||||
int se_sha_hash_256_async(void *hash, const void *src, u32 size);
|
||||
int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size);
|
||||
int se_sha_hash_256_partial_start(void *hash, const void *src, u32 size, bool is_oneshot);
|
||||
int se_sha_hash_256_partial_update(void *hash, const void *src, u32 size, bool is_oneshot);
|
||||
int se_sha_hash_256_partial_end(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot);
|
||||
int se_sha_hash_256_finalize(void *hash);
|
||||
int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size);
|
||||
int se_aes_crypt_hash(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
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 *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_aes_cmac_128(u32 ks, void *hash, const void *src, u32 size);
|
||||
/*! Random Functions */
|
||||
int se_rng_pseudo(void *dst, u32 size);
|
||||
int se_gen_prng128(void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user