From c12b5d586352ea451eb636ead67ce1345a312991 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Fri, 12 Sep 2025 10:54:57 +0200 Subject: [PATCH] Use HAL instead of ROM for SHA HW acceleration (#23902) --- .../bearssl-esp8266/src/hash/_sha_hal_idf5x.c | 754 ++++++++++++++++++ .../bearssl-esp8266/src/hash/_sha_rom_idf5x.c | 393 --------- 2 files changed, 754 insertions(+), 393 deletions(-) create mode 100644 lib/lib_ssl/bearssl-esp8266/src/hash/_sha_hal_idf5x.c delete mode 100644 lib/lib_ssl/bearssl-esp8266/src/hash/_sha_rom_idf5x.c diff --git a/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_hal_idf5x.c b/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_hal_idf5x.c new file mode 100644 index 000000000..1fc124f35 --- /dev/null +++ b/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_hal_idf5x.c @@ -0,0 +1,754 @@ +/* + * _sha_hal_idf5x.c — BearSSL drop‑in with ESP32 HAL SHA acceleration + * + * This file provides hardware-accelerated implementations of BearSSL-compatible + * hash functions (SHA-1, SHA-224, SHA-256, SHA-384, SHA-512) using the ESP-IDF 5.x + * SHA HAL. It replaces the software digest core with direct access to the ESP32's + * SHA engine, preserving BearSSL's context structure and API semantics. + * + * Each hash context uses a minimal layout: + * - val[] holds the midstate as a raw little-endian byte image. + * - buf[] holds the partial block (64 or 128 bytes). + * - count tracks the total input length in bytes. + * + * Endianness is preserved across state() and set_state() calls, allowing seamless + * serialization and restoration of midstate snapshots. All conversions for hardware + * interaction are localized to update() and out(). + * + * This module is designed for drop-in replacement with no changes to BearSSL clients. + * It supports multihash, midstate injection, and digest resumption. + * + * Author: Christian Baars + */ + +#include "t_inner.h" + +#if defined(USE_SHA_ROM) +#if defined(ESP_PLATFORM) && !defined(ESP8266) + +#include + +#include "freertos/FreeRTOS.h" + +#if __has_include("soc/sha_caps.h") +# include "soc/sha_caps.h" +#elif __has_include("soc/soc_caps.h") +# include "soc/soc_caps.h" +#else +# error "No SHA capability header found" +#endif +#if SOC_SHA_SUPPORT_RESUME + +#if __has_include("hal/sha_ll.h") +# include "hal/sha_ll.h" +# define HAVE_SHA_LL 1 +#else +# define HAVE_SHA_LL 0 +#endif + + +#define HAVE_HAL_SHA1 (SOC_SHA_SUPPORT_SHA1) +#define HAVE_HAL_SHA224 (SOC_SHA_SUPPORT_SHA224) +#define HAVE_HAL_SHA256 (SOC_SHA_SUPPORT_SHA256) +#define HAVE_HAL_SHA384 (SOC_SHA_SUPPORT_SHA384) +#define HAVE_HAL_SHA512 (SOC_SHA_SUPPORT_SHA512) + +static portMUX_TYPE s_sha_mux = portMUX_INITIALIZER_UNLOCKED; +#define SHA_ENTER() {portENTER_CRITICAL(&s_sha_mux); int __DECLARE_RCC_ATOMIC_ENV; sha_ll_enable_bus_clock(true); sha_ll_reset_register();} +#define SHA_EXIT() {portEXIT_CRITICAL(&s_sha_mux); int __DECLARE_RCC_ATOMIC_ENV; sha_ll_enable_bus_clock(false);} +#define SHA_WAIT() {while (sha_ll_busy()) { } } + +/* ================================================================ + * SHA-1 (HAL path, no save/restore) - needs char buf[112]; + * ================================================================ */ +#if HAVE_HAL_SHA1 + +static void __attribute__((noinline)) +sha_hal_process_block(void *state_buf, const void *blk, + esp_sha_type type, size_t digest_words, + size_t block_words, bool first) +{ + SHA_ENTER(); + if (!first) { + sha_ll_write_digest(type, state_buf, digest_words); + } + sha_ll_fill_text_block(blk, block_words); + if (first) { + sha_ll_start_block(type); + } else { + sha_ll_continue_block(type); + } + SHA_WAIT(); + sha_ll_read_digest(type, state_buf, digest_words); + SHA_EXIT(); +} + +static const uint8_t S1_IV_BYTES[20] PROGMEM = { + 0x67,0x45,0x23,0x01, 0xEF,0xCD,0xAB,0x89, + 0x98,0xBA,0xDC,0xFE, 0x10,0x32,0x54,0x76, + 0xC3,0xD2,0xE1,0xF0 +}; + +void br_sha1_init(br_sha1_context *cc) +{ + cc->vtable = &br_sha1_vtable; + cc->count = 0; + memset(cc->buf, 0, sizeof cc->buf); + /* Store IV bytes exactly as given (LE words) into cc->val */ + memcpy(cc->val, S1_IV_BYTES, sizeof S1_IV_BYTES); +} + +void br_sha1_update(br_sha1_context *cc, const void *data, size_t len) +{ + const uint8_t *src = data; + size_t used = (size_t)(cc->count & 63U); + + if (!len) return; + cc->count += len; + + if (used) { + size_t take = 64 - used; + if (take > len) take = len; + memcpy(cc->buf + used, src, take); + src += take; + len -= take; + used += take; + if (used == 64) { + sha_hal_process_block(cc->val, cc->buf, SHA1, 5, 16, cc->count == 64); + used = 0; + } + } + while (len >= 64) { + sha_hal_process_block(cc->val, src, SHA1, 5, 16, + (cc->count - len == 0) && !used); + src += 64; + len -= 64; + } + if (len) { + memcpy(cc->buf, src, len); + } +} + +void br_sha1_out(const br_sha1_context *cc, void *out) +{ + br_sha1_context ctx = *cc; + size_t used = (size_t)(ctx.count & 63U); + uint64_t bit_len = (uint64_t)ctx.count << 3; + + ctx.buf[used++] = 0x80; + if (used > 56) { + memset(ctx.buf + used, 0, 64 - used); + sha_hal_process_block(ctx.val, ctx.buf, SHA1, 5, 16, ctx.count <= 64); + used = 0; + } + memset(ctx.buf + used, 0, 56 - used); + br_enc64be(ctx.buf + 56, bit_len); + sha_hal_process_block(ctx.val, ctx.buf, SHA1, 5, 16, ctx.count <= 64); + memcpy(out, ctx.val, 20); +} + +uint64_t br_sha1_state(const br_sha1_context *cc, void *dst) +{ + /* Export raw 20-byte LE midstate image exactly as stored */ + memcpy(dst, cc->val, 20); + return cc->count; +} + +void br_sha1_set_state(br_sha1_context *cc, const void *src, uint64_t count) +{ + if (!(cc->vtable == &br_sha1_vtable)) { + cc->vtable = &br_sha1_vtable; + } + /* Import raw 20-byte LE midstate image exactly as provided */ + memcpy(cc->val, src, 20); + cc->count = count; + memset(cc->buf, 0, sizeof cc->buf); +} + +const br_hash_class br_sha1_vtable PROGMEM = { + sizeof(br_sha1_context), + BR_HASHDESC_ID(br_sha1_ID) + | BR_HASHDESC_OUT(20) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_STATE(32), + (void (*)(const br_hash_class **)) &br_sha1_init, + (void (*)(const br_hash_class **, const void *, size_t)) &br_sha1_update, + (void (*)(const br_hash_class *const *, void *)) &br_sha1_out, + (uint64_t (*)(const br_hash_class *const *, void *)) &br_sha1_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) &br_sha1_set_state +}; + +#endif /* HAVE_HAL_SHA1 */ + +/* ================================================================ + * SHA-224 (HAL path, no save/restore) + * ================================================================ */ +#if HAVE_HAL_SHA224 + +/* SHA-224 IV as 32-bit words (FIPS 180-4) */ +static const uint32_t S224_IV_WORDS[8] = { + 0xc1059ed8U, 0x367cd507U, 0x3070dd17U, 0xf70e5939U, + 0xffc00b31U, 0x68581511U, 0x64f98fa7U, 0xbefa4fa4U +}; + +void br_sha224_init(br_sha224_context *cc) { + cc->vtable = &br_sha224_vtable; + cc->count = 0; + memset(cc->buf, 0, sizeof cc->buf); + /* Internal state is LE; encode IV directly in LE form into cc->val */ + br_range_enc32le(cc->val, S224_IV_WORDS, 8); +} + +/* Reuse SHA-256 out, then truncate to 28 bytes */ +void br_sha224_out(const br_sha224_context *cc, void *out) { + uint8_t full[32]; + br_sha256_out((const br_sha256_context *)cc, full); + memcpy(out, full, 28); +} + +const br_hash_class br_sha224_vtable PROGMEM = { + sizeof(br_sha224_context), + BR_HASHDESC_ID(br_sha224_ID) + | BR_HASHDESC_OUT(28) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_STATE(32), + (void (*)(const br_hash_class **)) &br_sha224_init, + (void (*)(const br_hash_class **, const void *, size_t)) &br_sha224_update, + (void (*)(const br_hash_class *const *, void *)) &br_sha224_out, + (uint64_t (*)(const br_hash_class *const *, void *)) &br_sha224_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) &br_sha224_set_state +}; + +#endif /* HAVE_HAL_SHA224 */ + +/* ================================================================ + * SHA-256 (HAL path, save/restore) + * ================================================================ */ +#if HAVE_HAL_SHA256 && defined(SOC_SHA_SUPPORT_RESUME) + +/* Fixed SHA-256 IV in big-endian bytes (spec-defined) */ +static const uint8_t S256_IV_BYTES[32] PROGMEM = { + 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, + 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, + 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, + 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19 +}; + +/* Maintain the partial block in cc->buf[] (64 bytes) */ +static inline void s256_update_partial(br_sha256_context *cc, + const uint8_t *data_ptr, + size_t data_len, + size_t prev_partial_len) +{ + size_t new_partial_len = (prev_partial_len + data_len) & 63U; + + if (new_partial_len == 0) { + /* Exact block boundary: clear partial buffer */ + memset(cc->buf, 0, sizeof cc->buf); + return; + } + + if (data_len >= new_partial_len) { + /* Tail entirely from current input */ + memcpy(cc->buf, data_ptr + (data_len - new_partial_len), new_partial_len); + } else { + /* Need some bytes from previous partial tail */ + size_t need_prev = new_partial_len - data_len; + if (need_prev && need_prev <= prev_partial_len) { + memmove(cc->buf, cc->buf + (prev_partial_len - need_prev), need_prev); + } else if (need_prev) { + memset(cc->buf, 0, need_prev); + } + memcpy(cc->buf + need_prev, data_ptr, data_len); + } + + if (new_partial_len < sizeof cc->buf) { + memset(cc->buf + new_partial_len, 0, sizeof cc->buf - new_partial_len); + } +} + +void br_sha256_init(br_sha256_context *cc) +{ + cc->vtable = &br_sha256_vtable; + cc->count = 0; + memset(cc->buf, 0, sizeof cc->buf); + /* Keep midstate bytes exactly as IV (BE byte image), as in the original */ + memcpy(cc->val, S256_IV_BYTES, 32); +} + +void br_sha224_update(br_sha224_context *cc, const void *data, size_t len) +{ + if (!len) return; + + /* Embedded mode selection by vtable pointer (no desc, no tags) */ + const int mode = (cc->vtable == &br_sha256_vtable) ? SHA2_256 : SHA2_224; + + const uint8_t *data_ptr = (const uint8_t *)data; + const uint8_t *orig_ptr = data_ptr; + size_t orig_len = len; + + size_t prev_partial_len = (size_t)(cc->count & 63U); + bool starting_from_iv = (cc->count == 0) && (prev_partial_len == 0); + size_t stitch_take = 0; + if (prev_partial_len && len >= (64 - prev_partial_len)) + stitch_take = 64 - prev_partial_len; + + if (stitch_take || len >= 64) { + size_t block_count_in_run = 0; + + SHA_ENTER(); + + /* Complete the partial block (stitch) if needed */ + if (stitch_take) { + uint32_t midstate_words[8]; + /* Original semantics: decode state from LE words before seeding HW */ + br_range_dec32le(midstate_words, 8, cc->val); + sha_ll_load(mode); + sha_ll_write_digest(mode, midstate_words, 8); + + uint8_t first_block[64]; + memcpy(first_block, cc->buf, prev_partial_len); + memcpy(first_block + prev_partial_len, data_ptr, stitch_take); + + sha_ll_fill_text_block(first_block, 16); + sha_ll_continue_block(mode); + SHA_WAIT(); + + data_ptr += stitch_take; + len -= stitch_take; + block_count_in_run = 1; + } + + /* Process full 64-byte blocks */ + if (len >= 64) { + if (starting_from_iv && stitch_take == 0) { + /* Start from IV directly */ + sha_ll_fill_text_block(data_ptr, 16); + sha_ll_start_block(mode); + SHA_WAIT(); + data_ptr += 64; + len -= 64; + block_count_in_run = 1; + } else if (block_count_in_run == 0) { + /* Seed from current midstate once before the run */ + uint32_t midstate_words2[8]; + br_range_dec32le(midstate_words2, 8, cc->val); + sha_ll_load(mode); + sha_ll_write_digest(mode, midstate_words2, 8); + } + +#if defined(CONFIG_IDF_TARGET_ARCH_RISCV) /* RISC-V: enforce 8-block (512B) window with checkpointing */ + while (len >= 64) { + sha_ll_fill_text_block(data_ptr, 16); + sha_ll_continue_block(mode); + SHA_WAIT(); + + data_ptr += 64; + len -= 64; + block_count_in_run++; + + if (block_count_in_run == 8 && len >= 64) { + uint32_t midstate_words3[8]; + sha_ll_load(mode); + sha_ll_read_digest(mode, midstate_words3, 8); + sha_ll_load(mode); + sha_ll_write_digest(mode, midstate_words3, 8); + block_count_in_run = 0; + } + } +#else /* Xtensa: simple per-block processing, no extra checkpointing */ + while (len >= 64) { + sha_ll_fill_text_block(data_ptr, 16); + sha_ll_continue_block(mode); + SHA_WAIT(); + data_ptr += 64; + len -= 64; + } +#endif + } + + /* Commit midstate back; keep the same on-wire format as before: LE words in cc->val */ + { + uint32_t tmp_words[8]; + sha_ll_load(mode); + SHA_WAIT(); + sha_ll_read_digest(mode, tmp_words, 8); + br_range_enc32le(cc->val, tmp_words, 8); + } + SHA_EXIT(); + } + + /* Bookkeeping and partial buffer maintenance */ + cc->count += orig_len; + s256_update_partial((br_sha256_context *)cc, orig_ptr, orig_len, prev_partial_len); +} + +void br_sha256_out(const br_sha256_context *cc, void *out) +{ + uint8_t saved_partial[sizeof cc->buf]; + uint64_t saved_count = cc->count; + uint8_t saved_state[32]; + + memcpy(saved_partial, cc->buf, sizeof cc->buf); + memcpy(saved_state, cc->val, 32); + + uint8_t partial_len = (uint8_t)(saved_count & 63U); + const int mode = (cc->vtable == &br_sha256_vtable) ? SHA2_256 : SHA2_224; + + bool midstate_is_iv = (memcmp(saved_state, S256_IV_BYTES, 32) == 0); + bool no_full_blocks_done = (saved_count < 64); + bool must_start_from_iv = midstate_is_iv && no_full_blocks_done; + + SHA_ENTER(); + + if (!must_start_from_iv) { + uint32_t midstate_words[8]; + /* Original semantics: state stored as LE words in cc->val */ + br_range_dec32le(midstate_words, 8, saved_state); + sha_ll_load(mode); + sha_ll_write_digest(mode, midstate_words, 8); + } + + uint8_t final_blocks[128]; + memcpy(final_blocks, saved_partial, partial_len); + final_blocks[partial_len] = 0x80; + + size_t zero_len = (partial_len < 56) ? (56 - partial_len - 1) + : (120 - partial_len - 1); + if (zero_len) { + memset(final_blocks + partial_len + 1, 0, zero_len); + } + + uint64_t bit_length = saved_count * 8; + size_t len_pos = partial_len + 1 + zero_len; + for (int i = 0; i < 8; i++) { + final_blocks[len_pos + i] = (uint8_t)(bit_length >> (56 - 8 * i)); + } + size_t total_final_len = len_pos + 8; + + if (total_final_len == 64) { + sha_ll_fill_text_block(final_blocks, 16); + if (must_start_from_iv) + sha_ll_start_block(mode); + else + sha_ll_continue_block(mode); + SHA_WAIT(); + } else { + sha_ll_fill_text_block(final_blocks, 16); + if (must_start_from_iv) + sha_ll_start_block(mode); + else + sha_ll_continue_block(mode); + SHA_WAIT(); + sha_ll_fill_text_block(final_blocks + 64, 16); + sha_ll_continue_block(mode); + SHA_WAIT(); + } + + { + uint32_t tmp_words[8]; + sha_ll_load(mode); + sha_ll_read_digest(mode, tmp_words, 8); + SHA_EXIT(); + /* Final digest serialization remains LE as in your original */ + br_range_enc32le(out, tmp_words, 8); + } + + /* Non-destructive out(): restore snapshot */ + memcpy(((br_sha256_context *)cc)->buf, saved_partial, sizeof cc->buf); + ((br_sha256_context *)cc)->count = saved_count; + /* cc->val was never modified in out() */ +} + +uint64_t br_sha224_state(const br_sha256_context *cc, void *dst) +{ + /* Export midstate bytes exactly as stored (LE words image), unchanged */ + memcpy(dst, cc->val, 32); + return cc->count; +} + +void br_sha224_set_state(br_sha256_context *cc, const void *src, uint64_t count) +{ + if( !(cc->vtable == &br_sha256_vtable) && !(cc->vtable == &br_sha224_vtable)){ + cc->vtable = &br_sha256_vtable; /* safety for multihash fresh gen context */ + } + /* Reset partial, set count, and import state bytes exactly as provided */ + memset(cc->buf, 0, sizeof cc->buf); + memcpy(cc->val, src, 32); + cc->count = count; +} + +const br_hash_class br_sha256_vtable PROGMEM = { + sizeof(br_sha256_context), + BR_HASHDESC_ID(br_sha256_ID) + | BR_HASHDESC_OUT(32) + | BR_HASHDESC_STATE(32) + | BR_HASHDESC_LBLEN(6) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE, + (void (*)(const br_hash_class **))&br_sha256_init, + (void (*)(const br_hash_class **, + const void *, size_t))&br_sha256_update, + (void (*)(const br_hash_class *const *, void *))&br_sha256_out, + (uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) + &br_sha256_set_state +}; + +#endif /* HAVE_HAL_SHA256 && SOC_SHA_SUPPORT_RESUME */ + +/* ================================================================ + * SHA-384 (HAL path, no save/restore) + * ================================================================ */ +#if HAVE_HAL_SHA384 + +static const uint64_t S384_IV_WORDS[8] = { + 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL +}; + +void br_sha384_init(br_sha384_context *cc) { + cc->vtable = &br_sha384_vtable; + cc->count = 0; + memset(cc->buf, 0, sizeof cc->buf); + /* Internal state is LE; encode IV directly in LE form into cc->val */ + br_range_enc64le(cc->val, S384_IV_WORDS, 8); +} + +void br_sha384_update(br_sha384_context *cc, const void *data, size_t len) { + if (!len) return; + const uint8_t *src = (const uint8_t *)data; + size_t used = (size_t)(cc->count & 127U); + uint64_t prior_count = cc->count; + cc->count += len; + + if (used) { + size_t take = 128 - used; + if (take > len) take = len; + memcpy(cc->buf + used, src, take); + src += take; + len -= take; + used += take; + if (used == 128) { + uint64_t st_be[8]; + br_range_dec64le(st_be, 8, cc->val); + br_range_enc64be(st_be, st_be, 8); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be, 16); + sha_ll_fill_text_block(cc->buf, 32); + sha_ll_continue_block(SHA2_512); + SHA_WAIT(); + sha_ll_read_digest(SHA2_512, st_be, 16); + SHA_EXIT(); + br_range_dec64be(st_be, 8, st_be); + br_range_enc64le(cc->val, st_be, 8); + prior_count += 128; + used = 0; + } + } + + if (len >= 128) { + uint64_t st_be[8]; + br_range_dec64le(st_be, 8, cc->val); + br_range_enc64be(st_be, st_be, 8); + bool first = (prior_count == 0); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be, 16); + while (len >= 128) { + sha_ll_fill_text_block(src, 32); + if (first) { + sha_ll_start_block(SHA2_512); + first = false; + } else { + sha_ll_continue_block(SHA2_512); + } + SHA_WAIT(); + src += 128; + len -= 128; + } + sha_ll_read_digest(SHA2_512, st_be, 16); + SHA_EXIT(); + br_range_dec64be(st_be, 8, st_be); + br_range_enc64le(cc->val, st_be, 8); + } + + if (len) memcpy(cc->buf, src, len); +} + +void br_sha384_out(const br_sha384_context *cc, void *out) { + br_sha384_context ctx = *cc; + size_t used = (size_t)(ctx.count & 127U); + uint64_t bit_hi = (uint64_t)(ctx.count >> 61); + uint64_t bit_lo = (uint64_t)(ctx.count << 3); + + ctx.buf[used++] = 0x80; + if (used > 112) { + memset(ctx.buf + used, 0, 128 - used); + uint64_t st_be[8]; + br_range_dec64le(st_be, 8, ctx.val); + br_range_enc64be(st_be, st_be, 8); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be, 16); + sha_ll_fill_text_block(ctx.buf, 32); + sha_ll_continue_block(SHA2_512); + SHA_WAIT(); + sha_ll_read_digest(SHA2_512, st_be, 16); + SHA_EXIT(); + br_range_dec64be(st_be, 8, st_be); + br_range_enc64le(ctx.val, st_be, 8); + used = 0; + } + + memset(ctx.buf + used, 0, 112 - used); + br_enc64be(ctx.buf + 112, bit_hi); + br_enc64be(ctx.buf + 120, bit_lo); + + uint64_t st_be2[8]; + br_range_dec64le(st_be2, 8, ctx.val); + br_range_enc64be(st_be2, st_be2, 8); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be2, 16); + sha_ll_fill_text_block(ctx.buf, 32); + sha_ll_continue_block(SHA2_512); + SHA_WAIT(); + sha_ll_read_digest(SHA2_512, st_be2, 16); + SHA_EXIT(); + + br_range_dec64be(st_be2, 8, st_be2); + br_range_enc64be(out, st_be2, 6); +} + +uint64_t br_sha384_state(const br_sha384_context *cc, void *dst) { + /* Export raw 64-byte LE midstate image exactly as stored */ + memcpy(dst, cc->val, 64); + return cc->count; +} + +void br_sha384_set_state(br_sha384_context *cc, const void *src, uint64_t count) { + if (!(cc->vtable == &br_sha384_vtable)) { + cc->vtable = &br_sha384_vtable; + } + /* Import raw 64-byte LE midstate image exactly as provided */ + memcpy(cc->val, src, 64); + cc->count = count; + memset(cc->buf, 0, sizeof cc->buf); +} + +const br_hash_class br_sha384_vtable PROGMEM = { + sizeof(br_sha384_context), + BR_HASHDESC_ID(br_sha384_ID) + | BR_HASHDESC_OUT(48) + | BR_HASHDESC_STATE(64) + | BR_HASHDESC_LBLEN(7) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_MD_PADDING_128, + (void (*)(const br_hash_class **)) &br_sha384_init, + (void (*)(const br_hash_class **, const void *, size_t)) &br_sha384_update, + (void (*)(const br_hash_class *const *, void *)) &br_sha384_out, + (uint64_t (*)(const br_hash_class *const *, void *)) &br_sha384_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) &br_sha384_set_state +}; + +#endif /* HAVE_HAL_SHA384 */ + +/* ================================================================ + * SHA-512 (HAL path, no save/restore) + * Uses SHA-384 update/state/set_state + * ================================================================ */ +#if HAVE_HAL_SHA512 + +static const uint64_t S512_IV_WORDS[8] = { + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +void br_sha512_init(br_sha512_context *cc) { + cc->vtable = &br_sha512_vtable; + cc->count = 0; + memset(cc->buf, 0, sizeof cc->buf); + /* Internal state is LE; encode IV directly in LE form into cc->val */ + br_range_enc64le(cc->val, S512_IV_WORDS, 8); +} + +void br_sha512_out(const br_sha512_context *cc, void *out) { + br_sha512_context ctx = *cc; + size_t used = (size_t)(ctx.count & 127U); + uint64_t bit_hi = (uint64_t)(ctx.count >> 61); + uint64_t bit_lo = (uint64_t)(ctx.count << 3); + + ctx.buf[used++] = 0x80; + if (used > 112) { + memset(ctx.buf + used, 0, 128 - used); + uint64_t st_be[8]; + br_range_dec64le(st_be, 8, ctx.val); + br_range_enc64be(st_be, st_be, 8); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be, 16); + sha_ll_fill_text_block(ctx.buf, 32); + sha_ll_continue_block(SHA2_512); + SHA_WAIT(); + sha_ll_read_digest(SHA2_512, st_be, 16); + SHA_EXIT(); + br_range_dec64be(st_be, 8, st_be); + br_range_enc64le(ctx.val, st_be, 8); + used = 0; + } + + memset(ctx.buf + used, 0, 112 - used); + br_enc64be(ctx.buf + 112, bit_hi); + br_enc64be(ctx.buf + 120, bit_lo); + + uint64_t st_be2[8]; + br_range_dec64le(st_be2, 8, ctx.val); + br_range_enc64be(st_be2, st_be2, 8); + SHA_ENTER(); + sha_ll_load(SHA2_512); + sha_ll_write_digest(SHA2_512, st_be2, 16); + sha_ll_fill_text_block(ctx.buf, 32); + sha_ll_continue_block(SHA2_512); + SHA_WAIT(); + sha_ll_read_digest(SHA2_512, st_be2, 16); + SHA_EXIT(); + + /* Output digest in big‑endian bytes as BearSSL expects */ + br_range_dec64be(st_be2, 8, st_be2); + br_range_enc64be(out, st_be2, 8); +} + +const br_hash_class br_sha512_vtable PROGMEM = { + sizeof(br_sha512_context), + BR_HASHDESC_ID(br_sha512_ID) + | BR_HASHDESC_OUT(64) + | BR_HASHDESC_STATE(64) + | BR_HASHDESC_LBLEN(7) + | BR_HASHDESC_MD_PADDING + | BR_HASHDESC_MD_PADDING_BE + | BR_HASHDESC_MD_PADDING_128, + (void (*)(const br_hash_class **)) &br_sha512_init, + (void (*)(const br_hash_class **, const void *, size_t)) &br_sha384_update, /* reuse SHA-384 update */ + (void (*)(const br_hash_class *const *, void *)) &br_sha512_out, + (uint64_t (*)(const br_hash_class *const *, void *)) &br_sha512_state, + (void (*)(const br_hash_class **, const void *, uint64_t)) &br_sha512_set_state +}; + +#endif /* HAVE_HAL_SHA512 */ + +#else +/* ===== ESP8266 - leave it unchanged ===== */ +#endif // SOC_SHA_SUPPORT_RESUME +#endif // defined(ESP_PLATFORM) && !defined(ESP8266) +#endif //USE_SHA_ROM diff --git a/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_rom_idf5x.c b/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_rom_idf5x.c deleted file mode 100644 index 189e8c25c..000000000 --- a/lib/lib_ssl/bearssl-esp8266/src/hash/_sha_rom_idf5x.c +++ /dev/null @@ -1,393 +0,0 @@ -/* _sha_rom_idf5x.c — BearSSL drop‑in with ESP32 ROM SHA acceleration - * - * ⚠ TEST‑ONLY IMPLEMENTATION — SERIALIZED VIA GLOBAL SPINLOCK ⚠ - * - * Overview: - * --------- - * - Provides BearSSL hash functions backed by the ESP32 ROM SHA engine. - * - Uses a single global ROM SHA_CTX instance. - * - Access is serialized with a global portMUX spinlock. - * - * Concurrency Warning: - * -------------------- - * - This locking only prevents simultaneous entry into the ROM SHA engine. - * - It does NOT make multiple concurrent hash contexts safe. - * - Interleaving operations from different contexts will corrupt state. - * - Only one hash context may be active at any given time. - * - * Platform Notes: - * --------------- - * - ESP32 (ESP_PLATFORM): Uses ROM SHA acceleration as described above. - * - ESP8266 / other targets: This translation unit compiles to nothing; - * stock BearSSL symbols are provided instead. - * - * SHA‑256 Limitation on ESP32: - * ---------------------------- - * - The ESP32 ROM SHA‑256 implementation shares internal state with the - * hardware engine; without pause/resume support, state cannot be saved - * and restored safely. - * - In this “single global context” model, running SHA‑256 concurrently - * or interleaving with other operations will corrupt the ROM state. - * - Therefore, SHA‑256 acceleration is only enabled when - * SOC_SHA_SUPPORT_RESUME is available; otherwise it is unsafe here. - * - When unsupported, SHA‑256 silently falls back to BearSSL’s software - * implementation at build time (callers see no behavioral change). - * - * Supported ROM Algorithms (if present in ROM): - * ---------------------------------------------- - * • SHA‑1 - * • SHA‑224 - * • SHA‑256 (see limitation and fallback above) - * • SHA‑384 - * • SHA‑512 - */ - -#include "t_inner.h" - -#if defined(USE_SHA_ROM) -#if defined(ESP_PLATFORM) && !defined(ESP8266) - -#include -#include -#include - -#include "freertos/FreeRTOS.h" - -#if __has_include("soc/sha_caps.h") -# include "soc/sha_caps.h" -#elif __has_include("soc/soc_caps.h") -# include "soc/soc_caps.h" -#else -# error "No SHA capability header found" -#endif - -#if __has_include("esp_rom_sha.h") -# include "esp_rom_sha.h" -#elif __has_include("rom/sha.h") -# include "rom/sha.h" -#else -# error "No ROM SHA header found" -#endif - -#define HAVE_ROM_SHA1 (SOC_SHA_SUPPORT_SHA1) -#define HAVE_ROM_SHA224 (SOC_SHA_SUPPORT_SHA224) -#define HAVE_ROM_SHA256 (SOC_SHA_SUPPORT_SHA256) -#define HAVE_ROM_SHA384 (SOC_SHA_SUPPORT_SHA384) -#define HAVE_ROM_SHA512 (SOC_SHA_SUPPORT_SHA512) - -#if defined(SOC_SHA_SUPPORT_RESUME) -/* Newer chips: mode passed to init, update has no mode */ -#define ROM_SHA_ENABLE() ets_sha_enable() -#define ROM_SHA_DISABLE() ets_sha_disable() -#define ROM_SHA_INIT_MODE(ctx, mode) ets_sha_init((ctx), (mode)) -#define ROM_SHA_UPDATE_MODE(ctx, mode, d, l, last) \ - ets_sha_update((ctx), (const unsigned char*)(d), (uint32_t)(l), (last)) -#define ROM_SHA_FINISH_MODE(ctx, mode, out) ets_sha_finish((ctx), (unsigned char*)(out)) -#define ROM_SHA_FINALIZE_MODE(ctx, mode, out) \ - do { ROM_SHA_UPDATE_MODE((ctx), mode, NULL, 0, true); ROM_SHA_FINISH_MODE((ctx), mode, (out)); } while (0) - -#else -/* Old ESP32: mode passed to update/finish, init takes only ctx */ -#define ROM_SHA_ENABLE() ets_sha_enable() -#define ROM_SHA_DISABLE() ets_sha_disable() -#define ROM_SHA_INIT_MODE(ctx, mode) ets_sha_init((ctx)) -#define ROM_SHA_UPDATE_MODE(ctx, mode, d, l, last) \ - ets_sha_update((ctx), (mode), (const uint8_t*)(d), (size_t)((l) * 8)) -#define ROM_SHA_FINISH_MODE(ctx, mode, out) ets_sha_finish((ctx), (mode), (uint8_t*)(out)) -#define ROM_SHA_FINALIZE_MODE(ctx, mode, out) \ - do { ROM_SHA_UPDATE_MODE((ctx), mode, NULL, 0, true); ROM_SHA_FINISH_MODE((ctx), mode, (out)); } while (0) -#endif - - -/* One global ROM context; accesses serialized across cores/tasks. */ -static SHA_CTX rom_ctx; -static portMUX_TYPE s_sha_mux = portMUX_INITIALIZER_UNLOCKED; -#define SHA_ENTER() portENTER_CRITICAL(&s_sha_mux) -#define SHA_EXIT() portEXIT_CRITICAL(&s_sha_mux) - -/* ================================================================ - * SHA-1 (ROM path, no save/restore) - * ================================================================ */ -#if HAVE_ROM_SHA1 -void br_sha1_init(br_sha1_context *cc) { - SHA_ENTER(); - cc->vtable = &br_sha1_vtable; - cc->count = 0; - ROM_SHA_ENABLE(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA1); - SHA_EXIT(); -} - -void br_sha1_update(br_sha1_context *cc, const void *data, size_t len) { - if (!len) return; - SHA_ENTER(); - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA1, data, len, false); - cc->count += len; - SHA_EXIT(); -} - -void br_sha1_out(const br_sha1_context *cc, void *out) { - (void)cc; - SHA_ENTER(); - ROM_SHA_FINALIZE_MODE(&rom_ctx, SHA1, out); - ROM_SHA_INIT_MODE(&rom_ctx, SHA1); - SHA_EXIT(); -} - -const br_hash_class br_sha1_vtable PROGMEM = { - sizeof(br_sha1_context), - BR_HASHDESC_ID(br_sha1_ID) - | BR_HASHDESC_OUT(20) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **)) &br_sha1_init, - (void (*)(const br_hash_class **, const void *, size_t)) &br_sha1_update, - (void (*)(const br_hash_class *const *, void *)) &br_sha1_out, - NULL, - NULL -}; -#endif - -/* ================================================================ - * SHA-224 (ROM path, no save/restore) - * ================================================================ */ -/* ================================================================ - * SHA-224 (ROM path, no save/restore) - * ================================================================ */ -#if HAVE_ROM_SHA224 -void br_sha224_init(br_sha224_context *cc) { - SHA_ENTER(); - cc->vtable = &br_sha224_vtable; - cc->count = 0; - ROM_SHA_ENABLE(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_224); - SHA_EXIT(); -} - -void br_sha224_update(br_sha224_context *cc, const void *data, size_t len) { - if (!len) return; - SHA_ENTER(); - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA2_224, data, len, false); - cc->count += len; - SHA_EXIT(); -} - -void br_sha224_out(const br_sha224_context *cc, void *out) { - (void)cc; - uint8_t tmp[32]; - SHA_ENTER(); - ROM_SHA_FINALIZE_MODE(&rom_ctx, SHA2_224, tmp); - memcpy(out, tmp, 28); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_224); - SHA_EXIT(); -} - -const br_hash_class br_sha224_vtable PROGMEM = { - sizeof(br_sha224_context), - BR_HASHDESC_ID(br_sha224_ID) - | BR_HASHDESC_OUT(28) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **)) &br_sha224_init, - (void (*)(const br_hash_class **, const void *, size_t)) &br_sha224_update, - (void (*)(const br_hash_class *const *, void *)) &br_sha224_out, - NULL, - NULL -}; -#endif /* HAVE_ROM_SHA224 */ - - -/* ================================================================ - * SHA-256 with ROM acceleration + per-blob replay save/restore - * ================================================================ */ -#if HAVE_ROM_SHA256 && defined(SOC_SHA_SUPPORT_RESUME) -#undef br_sha256_init -#undef br_sha256_update -#undef br_sha256_out -#undef br_sha256_state -#undef br_sha256_set_state - -#define S256_CAP 64 - -/* Capture buffer for current context */ -static struct { - uint8_t buf[S256_CAP]; - uint8_t len; -} s256_capture; - -void br_sha256_init(br_sha256_context *cc) -{ - SHA_ENTER(); - cc->vtable = &br_sha256_vtable; - cc->count = 0; - s256_capture.len = 0; - ROM_SHA_ENABLE(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_256); - SHA_EXIT(); -} - -void br_sha256_update(br_sha256_context *cc, const void *data, size_t len) -{ - if (!len) return; - const uint8_t *dp = (const uint8_t *)data; - - SHA_ENTER(); - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA2_256, dp, len, false); - cc->count += len; - - if (s256_capture.len < S256_CAP) { - size_t want = S256_CAP - s256_capture.len; - size_t take = (len < want) ? len : want; - memcpy(s256_capture.buf + s256_capture.len, dp, take); - s256_capture.len += (uint8_t)take; - } - SHA_EXIT(); -} - -void br_sha256_out(const br_sha256_context *cc, void *out) -{ - (void)cc; - SHA_ENTER(); - ROM_SHA_FINALIZE_MODE(&rom_ctx, SHA2_256, out); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_256); - SHA_EXIT(); -} - -uint64_t br_sha256_state(const br_sha256_context *cc, void *dst) -{ - /* Store exactly the captured bytes in the blob */ - memset(dst, 0, S256_CAP); - memcpy(dst, s256_capture.buf, s256_capture.len); - return cc->count; -} - -void br_sha256_set_state(br_sha256_context *cc, const void *src, uint64_t count) -{ - const uint8_t *sp = (const uint8_t *)src; - - SHA_ENTER(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_256); - - if (count <= S256_CAP) { - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA2_256, sp, (size_t)count, false); - cc->count = count; - } else { - cc->count = 0; - s256_capture.len = 0; - } - SHA_EXIT(); -} - -const br_hash_class br_sha256_vtable PROGMEM = { - sizeof(br_sha256_context), - BR_HASHDESC_ID(br_sha256_ID) - | BR_HASHDESC_OUT(32) - | BR_HASHDESC_STATE(S256_CAP) /* store full ipad/opad block */ - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **)) &br_sha256_init, - (void (*)(const br_hash_class **, const void *, size_t)) &br_sha256_update, - (void (*)(const br_hash_class *const *, void *)) &br_sha256_out, - (uint64_t (*)(const br_hash_class *const *, void *)) &br_sha256_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) &br_sha256_set_state -}; -#endif /* HAVE_ROM_SHA256 */ - -/* ================================================================ - * SHA-384 (ROM path, no save/restore) - * ================================================================ */ -#if HAVE_ROM_SHA384 -void br_sha384_init(br_sha384_context *cc) { - SHA_ENTER(); - cc->vtable = &br_sha384_vtable; - cc->count = 0; - ROM_SHA_ENABLE(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_384); - SHA_EXIT(); -} - -void br_sha384_update(br_sha384_context *cc, const void *data, size_t len) { - if (!len) return; - SHA_ENTER(); - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA2_384, data, len, false); - cc->count += len; - SHA_EXIT(); -} - -void br_sha384_out(const br_sha384_context *cc, void *out) { - (void)cc; - uint8_t tmp[64]; - SHA_ENTER(); - ROM_SHA_FINALIZE_MODE(&rom_ctx, SHA2_384, tmp); - memcpy(out, tmp, 48); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_384); - SHA_EXIT(); -} - -const br_hash_class br_sha384_vtable PROGMEM = { - sizeof(br_sha384_context), - BR_HASHDESC_ID(br_sha384_ID) - | BR_HASHDESC_OUT(48) - | BR_HASHDESC_LBLEN(7) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **)) &br_sha384_init, - (void (*)(const br_hash_class **, const void *, size_t)) &br_sha384_update, - (void (*)(const br_hash_class *const *, void *)) &br_sha384_out, - NULL, - NULL -}; -#endif - -/* ================================================================ - * SHA-512 (ROM path, no save/restore) - * ================================================================ */ -#if HAVE_ROM_SHA512 -#undef br_sha512_update -void br_sha512_init(br_sha512_context *cc) { - SHA_ENTER(); - cc->vtable = &br_sha512_vtable; - cc->count = 0; - ROM_SHA_ENABLE(); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_512); - SHA_EXIT(); -} - -void br_sha512_update(br_sha512_context *cc, const void *data, size_t len) { - if (!len) return; - SHA_ENTER(); - ROM_SHA_UPDATE_MODE(&rom_ctx, SHA2_512, data, len, false); - cc->count += len; - SHA_EXIT(); -} - -void br_sha512_out(const br_sha512_context *cc, void *out) { - (void)cc; - SHA_ENTER(); - ROM_SHA_FINALIZE_MODE(&rom_ctx, SHA2_512, out); - ROM_SHA_INIT_MODE(&rom_ctx, SHA2_512); - SHA_EXIT(); -} - -const br_hash_class br_sha512_vtable PROGMEM = { - sizeof(br_sha512_context), - BR_HASHDESC_ID(br_sha512_ID) - | BR_HASHDESC_OUT(64) - | BR_HASHDESC_LBLEN(7) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **)) &br_sha512_init, - (void (*)(const br_hash_class **, const void *, size_t)) &br_sha512_update, - (void (*)(const br_hash_class *const *, void *)) &br_sha512_out, - NULL, - NULL -}; -#endif - -#else -/* ===== ESP8266 - leave it unchanged ===== */ -#endif -#endif //USE_SHA_ROM \ No newline at end of file