Skip to content

Espressif: add ESP32-C5 hardware acceleration - #12133

Open
SmallStackApple wants to merge 7 commits into
wolfSSL:masterfrom
SmallStackApple:feature/esp32c5-hw-accel
Open

SmallStackApple wants to merge 7 commits into
wolfSSL:masterfrom
SmallStackApple:feature/esp32c5-hw-accel

Conversation

@SmallStackApple

@SmallStackApple SmallStackApple commented Nov 14, 2026 •

Copy link
Copy Markdown

Description

Adds ESP32-C5 hardware acceleration to the Espressif port:

  • AES-128/256 (ECB/CBC/CTR/OFB/CFB/GCM/XTS/SIV/EAX as exposed by wolfCrypt)
  • SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256
  • RSA/MPI multiply, multiply-modulo and exponentiation
  • Generic ECC point multiplication for SECP192R1, SECP256R1 and SECP384R1
  • Transparent ECDSA verification using the dedicated ECDSA engine
  • Opaque ECDSA signing and public-key export with eFuse or Key Manager keys
    through the ESP-IDF PSA drivers

The C5 uses the ESP-IDF 6.x esp_crypto_* clock helpers; the C6 keeps its
ESP-IDF 5.x register path. SHA-512 family reads the complete 512-bit chaining
state, converts it to native 64-bit words and preserves it across copies.
SHA-224 finalization releases an unfinished engine lock.

Opaque keys fail closed: private-key export, key generation, ECDH and any
software fallback are rejected, and a reused ecc_key has its stale software
scalar destroyed when an opaque key is bound. eFuse provisioning is not part of
the library - wc_esp32_ecdsa_use_efuse_key() only binds an already-provisioned
key and never writes eFuse.

The test example gains optional, default-disabled self-tests for SHA active
copies, eFuse ECDSA and Key Manager ECDSA. The Key Manager test deploys a
throwaway random key without NVS or eFuse writes.

Fixes N/A (new platform support).

Testing

Hardware: ESP32-C5, revision v1.2, ESP-IDF v6.1, COM6.

  • Full wolf_test_task suite passes on the default configuration; exit code 0.
  • With the optional self-tests temporarily enabled:
    • SHA-224/SHA-384/SHA-512/224 active hardware-copy tests: 0
    • eFuse ECDSA sign/verify, copied-key, public-export and private-export
      rejection: 0
    • Key Manager ECDSA sign/verify, public-export and private-export
      rejection: 0
  • Hardware metrics confirm non-zero use of every SHA variant, MPI, AES, ECC
    point multiplication and ECDSA verification.
  • BLOCK_KEY0 was confirmed empty with espefuse.py summary; only a
    throwaway P-256 key was provisioned for the eFuse test.
  • Builds: ESP32-C5 default, ESP32-C6, ESP32-C5 software-only
    (CONFIG_ESP_WOLFSSL_NO_ESP32_CRYPT), and the benchmark, client and server
    examples.
  • Added an ESP-IDF v6.1 ESP32-C5 CI job; component dependencies keep IDF 4.4
    working through version gating.

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

A contributor agreement request will be sent to support@wolfssl.com referencing
this PR.

Enable the ESP32-C5 SHA, AES and RSA/MPI engines, add SECP192R1/256R1/384R1 point multiplication with transparent ECDSA verification, and add eFuse/Key Manager opaque ECDSA signing with public-key export.

The C5 uses the ESP-IDF 6.x crypto clock helpers while C6 retains its 5.x register path. Opaque keys never expose private material: private export, key generation, ECDH and software fallback are rejected.

SHA-512 family reads the full 512-bit chaining state and converts it to native 64-bit words, and SHA copies capture the complete state so hardware contexts can continue in software. SHA-224 finalization releases an unfinished engine lock.
Add the ESP32-C5 target to the ESP-IDF example components, user_settings templates and the platform documentation. The test example ships C5 sdkconfig defaults that enable the opaque ECDSA PSA drivers and a software-only variant used to validate the SW fallback.

Add an IDF v6.1 ESP32-C5 CI job. Component dependencies now include esp_security and mbedtls where available and use version-gated esp_driver_uart and esp_driver_gptimer components, keeping IDF 4.4 support intact.
Add optional, default-disabled self-tests for the ESP32-C5 SHA copy path, an eFuse ECDSA key and a Key Manager key. The eFuse test only binds an already-provisioned throwaway key and never writes eFuse; the Key Manager test deploys a random key without NVS or eFuse writes.

Document the three test options in the Espressif port README.
Copilot AI balanced review requested due to automatic review settings November 14, 2026 01:08
@wolfSSL-Bot

Copy link
Copy Markdown

Can one of the admins verify this patch?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved dependency guards break supported ESP-IDF 5.0–5.2 builds, while configuration issues cause additional compile failures and leave hardware cryptography enabled in software-only mode.

6 open issues
What changed in this PR

Adds ESP32-C5 hardware acceleration to wolfSSL’s Espressif port, including opaque ECDSA keys backed by eFuse or Key Manager.

Changes:

  • Adds C5 acceleration for AES, SHA, RSA/MPI, ECC multiplication and ECDSA verification.
  • Integrates opaque-key handling and updates SHA state copying and lock cleanup.
  • Updates example configurations, build dependencies, documentation and CI, with optional hardware self-tests.
File Description
wolfssl/​wolfcrypt/​settings.h Adds C5 feature selection and RSA timeout settings.
wolfssl/​wolfcrypt/​port/​Espressif/​esp32-ecdsa.h Declares opaque ECDSA key APIs.
wolfssl/​wolfcrypt/​port/​Espressif/​esp32-ecc.h Declares ECC acceleration interfaces.
wolfssl/​wolfcrypt/​port/​Espressif/​esp32-crypt.h Enables C5 hardware features and SHA types.
wolfssl/​wolfcrypt/​include.am Includes new port headers in distribution.
wolfssl/​wolfcrypt/​ecc.h Adds opaque-key context storage.
wolfcrypt/​src/​sha512.c Integrates C5 SHA-512 variants and copying.
wolfcrypt/​src/​sha256.c Adds C5 handling and SHA-224 lock cleanup.
wolfcrypt/​src/​sha.c Adds C5 byte-order and software-only handling.
wolfcrypt/​src/​port/​Espressif/​README.md Documents C5 capabilities and optional tests.
wolfcrypt/​src/​port/​Espressif/​esp32_util.c Adds C5 diagnostics and ECC metrics.
wolfcrypt/​src/​port/​Espressif/​esp32_sha.c Implements C5 SHA processing and state preservation.
wolfcrypt/​src/​port/​Espressif/​esp32_mp.c Adds C5 MPI support and clock control.
wolfcrypt/​src/​port/​Espressif/​esp32_ecdsa.c Implements opaque-key binding, copying and signing.
wolfcrypt/​src/​port/​Espressif/​esp32_ecc.c Implements hardware multiplication and verification.
wolfcrypt/​src/​port/​Espressif/​esp32_aes.c Adds C5 AES register and clock handling.
wolfcrypt/​src/​include.am Distributes new ECC/ECDSA sources.
wolfcrypt/​src/​ecc.c Integrates acceleration and opaque-key restrictions.
wolfcrypt/​benchmark/​benchmark.c Adds C5 benchmark timing support.
src/​pk_ec.c Preserves opaque bindings during key copying.
IDE/​Espressif/​README.md Lists C5 support.
IDE/​Espressif/​ESP-IDF/​user_settings.h Adds C5 acceleration options.
IDE/​Espressif/​ESP-IDF/​README.md Documents IDF version and opaque-key dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​sdkconfig.sw Adds a software-only configuration overlay.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​sdkconfig.defaults.esp32c5 Sets C5 stack and ECDSA defaults.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​main/​main.c Adds optional SHA-copy and opaque-key self-tests.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​main/​CMakeLists.txt Updates test application dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​components/​wolfssl/​include/​user_settings.h Adds C5 options and self-test switches.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​components/​wolfssl/​CMakeLists.txt Updates dependencies and source exclusions.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test_idf/​main/​main.c Updates RISC-V CPU-frequency reporting.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_server/​main/​CMakeLists.txt Updates server application dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_server/​components/​wolfssl/​include/​user_settings.h Adds server C5 acceleration options.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_server/​components/​wolfssl/​CMakeLists.txt Updates dependencies and source exclusions.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_client/​main/​CMakeLists.txt Updates client application dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_client/​components/​wolfssl/​include/​user_settings.h Adds client C5 acceleration options.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_client/​components/​wolfssl/​CMakeLists.txt Updates dependencies and source exclusions.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_benchmark/​main/​CMakeLists.txt Updates benchmark application dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_benchmark/​components/​wolfssl/​include/​user_settings.h Adds benchmark C5 acceleration options.
IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_benchmark/​components/​wolfssl/​CMakeLists.txt Updates dependencies and source exclusions.
IDE/​Espressif/​ESP-IDF/​examples/​template/​main/​CMakeLists.txt Updates template application dependencies.
IDE/​Espressif/​ESP-IDF/​examples/​template/​components/​wolfssl/​include/​user_settings.h Adds template C5 acceleration options.
IDE/​Espressif/​ESP-IDF/​examples/​template/​components/​wolfssl/​CMakeLists.txt Updates dependencies and source exclusions.
IDE/​Espressif/​ESP-IDF/​compileAllExamples.sh Supports explicit target selection.
examples/​configs/​user_settings_platformio.h Adds C5 configuration options.
examples/​configs/​user_settings_espressif.h Adds C5 configuration options.
examples/​configs/​user_settings_arduino.h Adds C5 configuration options.
ChangeLog.md Records C5 acceleration support.
.wolfssl_known_macro_extras Registers the C5 target macro.
.github/​workflows/​docker-Espressif.yml Adds an IDF 6.1 C5 example-build job.

Review effort: Balanced

Comment thread wolfcrypt/src/ecc.c Resolved
Gate the split esp_driver_uart and esp_driver_gptimer components on ESP-IDF 5.3, where they were introduced, and keep the driver component for older 5.x releases.

Include the ECC/ECDSA declarations when either acceleration flag is set, so NO_WOLFSSL_ESP32_CRYPT_ECC builds still see the verification prototype.

Honor CONFIG_ESP_WOLFSSL_NO_ESP32_CRYPT before any C5 target flags are derived, and keep the opaque ECDSA flag disabled for software-only builds. Guard the truncated SHA-512 variants and C5 chaining-state sizes so SHA-1/SHA-256-only and SHA-384/SHA-512-only configurations compile.
@SmallStackApple

Copy link
Copy Markdown
Author

Thanks for the review. All six items are addressed in fccebdd8c8:

  1. esp_driver_gptimer version guard — the split component is now selected only for ESP-IDF >= 5.3 in the template, benchmark, client, server and test component CMakeLists.txt. Older 5.x keeps driver, which still exports the GPTimer API.
  2. esp_driver_uart version guard — main/CMakeLists.txt now uses driver for ESP-IDF 5.0–5.2 and esp_driver_uart from 5.3.
  3. ECC/ECDSA declaration — wolfcrypt/src/ecc.c includes esp32-ecc.h when either WOLFSSL_ESP32_CRYPT_ECC or WOLFSSL_ESP32_CRYPT_ECDSA is defined, so NO_WOLFSSL_ESP32_CRYPT_ECC builds still see esp32_ecdsa_verify_hash().
  4. Truncated SHA-512 variants — the SHA-512/224 and SHA-512/256 digest sizes are gated on WOLFSSL_SHA512 and the corresponding WOLFSSL_NOSHA512_* switch.
  5. C5 reduced configurations — the SHA-224 state size is guarded by !NO_SHA256 and the 512-bit state handling by WOLFSSL_SHA384 || WOLFSSL_SHA512, so SHA-1/SHA-256-only and SHA-384/SHA-512-only builds compile.
  6. Software-only Kconfig ordering — CONFIG_ESP_WOLFSSL_NO_ESP32_CRYPT now defines NO_ESP32_CRYPT before any target flags are derived in esp32-crypt.h, and the opaque ECDSA flag in settings.h also checks the Kconfig switch. The sdkconfig.sw build no longer contains wc_esp32_ecdsa_use_efuse_key or esp32_ecc_mulmod symbols.

Re-validated after the changes:

  • ESP32-C5 v1.2, ESP-IDF v6.1 full suite: exit code 0, no SHA lock warnings.
  • ESP32-C6 and C5 software-only builds pass.
  • C5 default build passes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Initialization-failure cleanup can free an uninitialized context, while SHA-224 cleanup can leave the FreeRTOS SHA mutex locked and force subsequent hashes into software.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Avoid freeing contexts after initialization failure

IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test/​main/​main.c:296

If the source initializer fails (for example, an allocation failure with WOLFSSL_SMALL_STACK_CACHE), the destination initializer is skipped, but the macro still calls FREE(&dst) unconditionally. Those free routines inspect fields such as W, so this can wipe or free an indeterminate pointer instead of reporting the initialization error. Exit this test iteration on initialization failure, freeing only contexts that initialized successfully.

Medium severity Unlock the SHA mutex when freeing a same-task context

wolfcrypt/​src/​sha256.c:3330

With the default FreeRTOS task-lock monitoring enabled, freeing a SHA-224 context after processing a full block still leaves the SHA mutex held: the helper's same-task branch only logs instead of unlocking. Cleanup clears the owner and discards the context, leaving subsequent hashes to fall back to software. Update esp_sha_release_unfinished_lock() in esp32_sha.c to unlock in the same-task branch while preserving cross-task ownership handling.

6 resolved since last review

Review effort: Balanced

Free only self-test hash contexts whose initialization succeeded, so an allocation failure cannot free an indeterminate destination context.

When ESP_MONITOR_HW_TASK_LOCK is enabled, the owning task now actually releases an unfinished SHA lock instead of only logging, while a different task still leaves the ESP32_SHA_FREED hint for the owner. This prevents subsequent hashes from falling back to software after wc_Sha224Free().
@SmallStackApple

Copy link
Copy Markdown
Author

Both previously missed issues are fixed in 4b6717b4b5:

  1. Self-test cleanup after initialization failure — C5_SHA_COPY_TEST now tracks srcInit/dstInit and only calls FREE() on contexts that initialized successfully. A failed INIT(&src) no longer leads to FREE(&dst) on an indeterminate context.
  2. Same-task SHA unlock — esp_sha_release_unfinished_lock() now calls esp_sha_hw_unlock(ctx) when ctx->task_owner is the current task under ESP_MONITOR_HW_TASK_LOCK; a different task still sets the ESP32_SHA_FREED hint for the owner.

Validation:

  • ESP32-C5 v1.2, ESP-IDF v6.1 with WOLFSSL_ESP32C5_TEST_SHA_COPY enabled: SHA copy self-test returns 0 and the full suite exits 0.
  • The non-SINGLE_THREADED configuration (where the task-owner branch is compiled) builds successfully.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The new logging statement breaks compilation on supported ESP32-C3/ESP-IDF 4.4 configurations, while ECC binding and hardware-dispatch mismatches can use inconsistent curves or reject valid points.

No open issues 🎉

3 previously missed issues

In code that hasn't changed since last review

High severity Use the legacy C3 CPU-frequency macro with ESP-IDF 4.4

IDE/​Espressif/​ESP-IDF/​examples/​wolfssl_test_idf/​main/​main.c:171

On ESP32-C3 with the still-supported ESP-IDF 4.4, the CPU-frequency setting is CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ, not CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ. This newly enabled logging statement therefore fails to compile that target. Please guard the generic macro's availability or retain a legacy-C3 branch, as esp32_util.c already does.

Medium severity Prevent hardware dispatch for curves with mismatched coefficients

wolfcrypt/​src/​port/​Espressif/​esp32_ecc.c:144

Matching only the prime and A selects SECP192R1 hardware for PRIME192V2 and PRIME192V3, which share those values but have different B coefficients (wolfcrypt/src/ecc.c:1157–1207). Their valid points are rejected with IS_POINT_E, so the callers never reach the software fallback; custom curves sharing a supported curve's prime and A have the same problem. Check point membership in the selected hardware curve, or pass the full curve identity into dispatch, and return NOT_COMPILED_IN for unsupported curves.

Medium severity Reject custom or mismatched curves before hardware key binding

wolfcrypt/​src/​port/​Espressif/​esp32_ecdsa.c:156

Both binding APIs call wc_ecc_set_curve(), which preserves existing custom domain parameters when key->idx == ECC_CUSTOM_IDX. Reusing such a key can therefore bind a hardware R1 key while signing and verification/export use different curves. Reject custom or mismatched domain parameters before binding, or explicitly replace them safely.

Review effort: Balanced

Fix C3 legacy CPU frequency handling and IDF 5.3 component guards. Make ECC fall back to software for mismatched curves, reject custom opaque-key bindings, and preserve keys after invalid curve changes. Align SHA lock ownership and reduced configurations, avoid ECDSA/KM lock inversion, and gate C5 acceleration to IDF 6.x. Add optional SHA lock and ECC curve hardware self-tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants