bdk: se: refactor and optimize SHA256

- Simplify config and fix partial hashing
- Add partial function calls
- All partial state is handled internally
- All functions now use the classic naming convention.
This commit is contained in:
CTCaer
2026-01-06 22:59:20 +02:00
parent 607b19067a
commit c9208593af
2 changed files with 58 additions and 53 deletions

View File

@@ -474,15 +474,8 @@ int se_aes_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, vo
return 1; return 1;
} }
static void se_calc_sha256_get_hash(void *hash, u32 *msg_left) static void _se_sha_hash_256_get_hash(void *hash)
{ {
// 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. // Copy output hash.
u32 hash32[SE_SHA_256_SIZE / sizeof(u32)]; u32 hash32[SE_SHA_256_SIZE / sizeof(u32)];
for (u32 i = 0; i < (SE_SHA_256_SIZE / sizeof(u32)); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / sizeof(u32)); i++)
@@ -490,15 +483,8 @@ static void se_calc_sha256_get_hash(void *hash, u32 *msg_left)
memcpy(hash, hash32, SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_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) static int _se_sha_hash_256(void *hash, u64 total_size, const void *src, u32 src_size, 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. // Src size of 0 is not supported, so return null string sha256.
if (!src_size) if (!src_size)
{ {
@@ -510,59 +496,75 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
return 1; 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. // 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_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 to current buffer size if empty. // Set total size: BITS(total_size), up to 2 EB.
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_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29); 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 size left to hash. // Set leftover size: BITS(src_size).
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3); SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(msg_left << 3);
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(msg_left >> 29);
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate. // Set config based on init or partial continuation.
if (sha_cfg == SHA_CONTINUE && msg_left) if (total_size == src_size || !total_size)
{ SE(SE_SHA_CONFIG_REG) = SHA_INIT_HASH;
// Restore message left to process. else
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0]; SE(SE_SHA_CONFIG_REG) = SHA_CONTINUE;
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg. // Trigger the operation. src vs total size decides if it's partial.
memcpy(hash32, hash, SE_SHA_256_SIZE); int res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
}
// Trigger the operation. if (res && is_oneshot)
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot); _se_sha_hash_256_get_hash(hash);
if (is_oneshot)
se_calc_sha256_get_hash(hash, msg_left);
return res; return res;
} }
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size) int se_sha_hash_256_async(void *hash, const void *src, u32 size)
{ {
return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true); return _se_sha_hash_256(hash, size, src, size, false);
} }
int se_calc_sha256_finalize(void *hash, u32 *msg_left) 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 res = _se_execute_finalize(); int res = _se_execute_finalize();
se_calc_sha256_get_hash(hash, msg_left); _se_sha_hash_256_get_hash(hash);
return res; return res;
} }

View File

@@ -42,9 +42,12 @@ int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *ds
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_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_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
/*! Hashing Functions */ /*! Hashing Functions */
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_sha_hash_256_async(void *hash, const void *src, u32 size);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left); 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_hash_cmac(u32 ks, void *hash, const void *src, u32 size);
/*! Random Functions */ /*! Random Functions */
int se_gen_prng128(void *dst); int se_gen_prng128(void *dst);