Async hardware cryptographic function support #829

Open
crabel99 wants to merge 12 commits from crabel99/async-hardware-support-c35df962 into development
crabel99 commented 2026-07-03 19:56:36 -05:00 (Migrated from github.com)

Description

This PR adds generic async hardware dispatch support for selected PSA crypto
operations. The goal is to let platforms with interrupt-driven crypto hardware
start an operation, return an in-progress status to the caller, and complete the
operation later without blocking the TLS or PSA caller.

The implementation adds generic async hardware state tracking and dispatch
surface for ECDSA, ECDH, and RSA signature operations. The supported async
operation families include P-256, P-384, P-521, RSA-PSS, and RSA-PKCS1 signing
and verification paths where the platform provider supports them.

The implementation is intentionally hardware-agnostic. Public/internal hook
names use generic PSA and Mbed TLS naming such as PSA_ASYNC_HARDWARE_*,
MBEDTLS_ASYNC_HARDWARE_*, psa_async_hardware_*, and
mbedtls_async_hardware_*. No SAMD/SAME-specific symbols are required by the
upstream TF-PSA-Crypto or Mbed TLS code.

What changed

In TF-PSA-Crypto, this adds async hardware dispatch support below the PSA and PK
layers:

  • core/psa_crypto.c: async hardware dispatch hooks for PSA operations.
  • include/psa/crypto_struct.h: async hardware operation state storage.
  • extras/pk.c: PK-layer RSA/ECDSA signing and verification integration while
    preserving existing MBEDTLS_PK_RSA and hash_len == 0 behavior.
  • extras/pk_wrap.c: async-capable PK wrapper routing.
  • tests/suites/test_suite_psa_crypto.*: mock/provider coverage for the new
    async dispatch behavior.

In Mbed TLS, the matching TLS integration routes TLS 1.2 and TLS 1.3 handshake
and record-protection operations through the generic async hardware boundary:

  • TLS 1.2 ECDHE/ECDSA/RSA signing and verification.
  • TLS 1.3 key exchange and signature paths.
  • TLS 1.2 and TLS 1.3 AEAD record protection for supported AES-GCM and AES-CCM
    TLS record shapes.
  • Compatibility fixes for upstream TLS/PK behavior, including SHA-512
    CertificateVerify sizing and existing PK signing hash-length semantics.

The platform-specific provider is intentionally outside this repo. If a provider
cannot accept a hardware-required operation, the async path fails closed instead
of silently falling back to synchronous software.

Hardware and validation

This was developed with SAMD/SAME hardware crypto peripherals as the first
provider implementation, including async TRNG, AES, ECDH/ECDSA, and RSA support.
The downstream integration was tested with native TLS/PSA coverage and hardware
end-to-end TLS validation on SAME54 Xplained Pro and SAMD51 hardware.

Validation run:

  • TF-PSA-Crypto upstream CMake build: passed.
  • TF-PSA-Crypto upstream CTest: 129/129 passed.
  • Mbed TLS upstream CMake build: passed.
  • Mbed TLS upstream CTest: 147/147 passed.
  • Downstream native TLS/PSA tests: 265 passed.
  • Downstream SAME54 embedded Ethernet/TLS/crypto/RTC tests: 80 passed.
  • Downstream SAMD51 embedded RTC/crypto tests: 68 passed.

PR checklist

  • changelog provided
  • framework PR not required
  • TF-PSA-Crypto development PR provided Mbed-TLS/TF-PSA-Crypto#829
  • TF-PSA-Crypto 1.1 PR not required because this is new feature work
    targeting development first.
  • mbedtls development PR provided Mbed-TLS/mbedtls#10807
  • mbedtls 4.1 PR not required because this is new feature work targeting
    development first.
  • mbedtls 3.6 PR not required because this is new feature work and is not
    suitable for LTS backport without maintainer direction.
  • tests provided: upstream TF-PSA-Crypto CTest, upstream Mbed TLS CTest,
    downstream native TLS/PSA tests, and downstream hardware TLS validation.
## Description This PR adds generic async hardware dispatch support for selected PSA crypto operations. The goal is to let platforms with interrupt-driven crypto hardware start an operation, return an in-progress status to the caller, and complete the operation later without blocking the TLS or PSA caller. The implementation adds generic async hardware state tracking and dispatch surface for ECDSA, ECDH, and RSA signature operations. The supported async operation families include P-256, P-384, P-521, RSA-PSS, and RSA-PKCS1 signing and verification paths where the platform provider supports them. The implementation is intentionally hardware-agnostic. Public/internal hook names use generic PSA and Mbed TLS naming such as `PSA_ASYNC_HARDWARE_*`, `MBEDTLS_ASYNC_HARDWARE_*`, `psa_async_hardware_*`, and `mbedtls_async_hardware_*`. No SAMD/SAME-specific symbols are required by the upstream TF-PSA-Crypto or Mbed TLS code. ## What changed In TF-PSA-Crypto, this adds async hardware dispatch support below the PSA and PK layers: - `core/psa_crypto.c`: async hardware dispatch hooks for PSA operations. - `include/psa/crypto_struct.h`: async hardware operation state storage. - `extras/pk.c`: PK-layer RSA/ECDSA signing and verification integration while preserving existing `MBEDTLS_PK_RSA` and `hash_len == 0` behavior. - `extras/pk_wrap.c`: async-capable PK wrapper routing. - `tests/suites/test_suite_psa_crypto.*`: mock/provider coverage for the new async dispatch behavior. In Mbed TLS, the matching TLS integration routes TLS 1.2 and TLS 1.3 handshake and record-protection operations through the generic async hardware boundary: - TLS 1.2 ECDHE/ECDSA/RSA signing and verification. - TLS 1.3 key exchange and signature paths. - TLS 1.2 and TLS 1.3 AEAD record protection for supported AES-GCM and AES-CCM TLS record shapes. - Compatibility fixes for upstream TLS/PK behavior, including SHA-512 CertificateVerify sizing and existing PK signing hash-length semantics. The platform-specific provider is intentionally outside this repo. If a provider cannot accept a hardware-required operation, the async path fails closed instead of silently falling back to synchronous software. ## Hardware and validation This was developed with SAMD/SAME hardware crypto peripherals as the first provider implementation, including async TRNG, AES, ECDH/ECDSA, and RSA support. The downstream integration was tested with native TLS/PSA coverage and hardware end-to-end TLS validation on SAME54 Xplained Pro and SAMD51 hardware. Validation run: - TF-PSA-Crypto upstream CMake build: passed. - TF-PSA-Crypto upstream CTest: `129/129` passed. - Mbed TLS upstream CMake build: passed. - Mbed TLS upstream CTest: `147/147` passed. - Downstream native TLS/PSA tests: `265` passed. - Downstream SAME54 embedded Ethernet/TLS/crypto/RTC tests: `80` passed. - Downstream SAMD51 embedded RTC/crypto tests: `68` passed. ## PR checklist - [x] **changelog** provided - [x] **framework PR** not required - [x] **TF-PSA-Crypto development PR** provided Mbed-TLS/TF-PSA-Crypto#829 - [ ] **TF-PSA-Crypto 1.1 PR** not required because this is new feature work targeting development first. - [x] **mbedtls development PR** provided Mbed-TLS/mbedtls#10807 - [ ] **mbedtls 4.1 PR** not required because this is new feature work targeting development first. - [ ] **mbedtls 3.6 PR** not required because this is new feature work and is not suitable for LTS backport without maintainer direction. - [x] **tests** provided: upstream TF-PSA-Crypto CTest, upstream Mbed TLS CTest, downstream native TLS/PSA tests, and downstream hardware TLS validation.
gilles-peskine-arm commented 2026-07-05 14:40:15 -05:00 (Migrated from github.com)

Thank you for this contribution. Unfortunately, we currently have very little time for feature develpoment and review, so it will take a while before we can give this the attention it deserves.

This resolves part of https://github.com/Mbed-TLS/mbedtls/issues/7020.

I cannot do a design review at the moment. But please note a few points about the design. We would want to make asynchronous dispatch algorithm-agnostic: e.g. no separate code for RSA and ECDSA, but dispatch to a driver which can be configured for one or more algorithms. The asynchronous interface needs to be exposed through psa_xxx API functions that take a key ID as argument, and pk*.c should not call anything other than these functions (direct access from pk/x509/ssl to legacy low-level functions is deprecated and we're slowly getting rid of that).

Whatever API we end up with, it needs to be the official PSA API for this feature, so a design discussion needs to happen as part of the PSA API design. We don't mind experimenting on a draft API, but until the PSA API is finalized, the feature would remain experimental and subject to change.

Thank you for this contribution. Unfortunately, we currently have very little time for feature develpoment and review, so it will take a while before we can give this the attention it deserves. This resolves part of https://github.com/Mbed-TLS/mbedtls/issues/7020. I cannot do a design review at the moment. But please note a few points about the design. We would want to make asynchronous dispatch algorithm-agnostic: e.g. no separate code for RSA and ECDSA, but dispatch to a driver which can be configured for one or more algorithms. The asynchronous interface needs to be exposed through `psa_xxx` API functions that take a key ID as argument, and `pk*.c` should not call anything other than these functions (direct access from pk/x509/ssl to legacy low-level functions is deprecated and we're slowly getting rid of that). Whatever API we end up with, it needs to be the official PSA API for this feature, so a design discussion needs to happen [as part of the PSA API design](https://github.com/GlobalPlatform/psa-api/issues/52). We don't mind experimenting on a draft API, but until the PSA API is finalized, the feature would remain experimental and subject to change.
crabel99 commented 2026-07-08 16:20:55 -05:00 (Migrated from github.com)

@gilles-peskine-arm I think I may have a direction that addresses part of this.

I have been working on a no-OS asynchronous execution model for Cortex-M systems using PendSV as the deferred-dispatch mechanism. The current implementation targets Microchip SAMD5x/E5x devices. Each hardware block has its own async execution context, for example SERCOM, GMAC, PUKCC, AES, ICM, TRNG, RTC, etc. Interrupt and DMA completion feed into a PendSV-scheduled continuation path, so foreground code does not need to block while long-running peripheral work completes.

The relevant piece here is the crypto integration. The design uses a common PSA-facing async provider surface, tentatively:

mbedtls_psa_async_crypto_provider_t

That layer receives algorithm-agnostic PSA-style requests: operation kind, key identity/type, algorithm, input/output buffers, nonce/IV, associated data, tag buffers, curve metadata, etc. It does not expose RSA-specific or ECDSA-specific hardware calls to TLS, X.509, or PK code.

The provider can be compiled in one of several modes:

  • crypto disabled
  • hardware-only for supported operations
  • software-only
  • hybrid, where hardware is used when available and software fills supported gaps

Below that, the hardware-facing contract is tentatively:

mbedtls_psa_hardware_crypto_provider_t

Each platform implements that contract locally. For SAMD5x/E5x, the local implementation binds the common provider request surface to the chip hardware: PUKCC for RSA/ECC, AES for block and AEAD primitives, ICM for hash/HMAC, and TRNG for random generation.

The important point is that the TLS/PSA-facing dispatch stays algorithm-agnostic. A TLS, X.509, or PK caller should submit a PSA/provider request using the same common operation structure regardless of whether the selected backend is hardware, software, or hybrid. The provider policy decides whether that request is handled by hardware or by TF-PSA/mbedTLS software. The chip-specific hardware binding remains below that boundary.

I validated this on a SAME54P20 using the same embedded test harness compiled in hardware and software modes. The goal was to verify that the same provider-facing API could exercise both paths by changing compile-time mode guards, without changing the consumer/test request surface.

Software / hardware greater than 1.0x means the hardware path is faster.

Algorithm Size/Meaning Hardware cycles/op Software cycles/op Software / hardware
SHA-256 16 8470 14665 1.7x
SHA-256 64 9065 20722 2.3x
SHA-256 256 9032 39660 4.4x
SHA-256 1024 10096 115432 11.4x
SHA-256 4096 14780 418223 28.3x
HMAC-SHA256 16 16043 59634 3.7x
HMAC-SHA256 64 16519 66765 4.0x
HMAC-SHA256 256 16597 89563 5.4x
HMAC-SHA256 1024 17679 180663 10.2x
HMAC-SHA256 4096 22346 545003 24.4x
AES-CBC 16 11481 21973 1.9x
AES-CBC 64 14371 27478 1.9x
AES-CBC 256 16131 49396 3.1x
AES-CBC 1024 21982 137149 6.2x
AES-CBC 4096 45962 487941 10.6x
AES-CTR 16 12096 22166 1.8x
AES-CTR 64 15044 27766 1.8x
AES-CTR 256 16504 50230 3.0x
AES-CTR 1024 22312 139964 6.3x
AES-CTR 4096 46286 498824 10.8x
AES-GCM encrypt AAD16 16 16724 48260 2.9x
AES-GCM encrypt AAD16 64 19710 60683 3.1x
AES-GCM encrypt AAD16 256 21718 110230 5.1x
AES-GCM encrypt AAD16 1024 27533 308332 11.2x
AES-GCM encrypt AAD16 4096 51496 1100521 21.4x
AES-GCM decrypt AAD16 16 18188 48596 2.7x
AES-GCM decrypt AAD16 64 24430 61034 2.5x
AES-GCM decrypt AAD16 256 49551 110698 2.2x
AES-GCM decrypt AAD16 1024 149242 309104 2.1x
AES-GCM decrypt AAD16 4096 547735 1102635 2.0x
AES-CCM encrypt AAD16 16 18972 41400 2.2x
AES-CCM encrypt AAD16 64 26465 51739 2.0x
AES-CCM encrypt AAD16 256 29314 93144 3.2x
AES-CCM encrypt AAD16 1024 41009 258640 6.3x
AES-CCM encrypt AAD16 4096 88962 920479 10.3x
AES-CCM decrypt AAD16 16 21148 41909 2.0x
AES-CCM decrypt AAD16 64 35491 52606 1.5x
AES-CCM decrypt AAD16 256 60170 95420 1.6x
AES-CCM decrypt AAD16 1024 168107 266564 1.6x
AES-CCM decrypt AAD16 4096 619283 951063 1.5x
RSA raw exponentiation 2048-bit modulus 372472 unavailable unavailable
RSA CRT 192-bit test vector 104561 unavailable unavailable
EC public key P-256 108113 11644790 107.7x
ECDH P-256 2697836 32607295 12.1x
ECDSA sign P-256 2760608 14287025 5.2x
ECDSA verify P-256 5477387 49471414 9.0x

In this model, the common API surface is the PSA-provider request, not the hardware peripheral API. Consumers such as TLS, X.509, PK, or PSA wrappers submit one algorithm-agnostic request shape containing the operation kind, PSA algorithm, key metadata, buffers, and operation parameters. mbedtls_psa_async_crypto_provider_t applies policy and dispatches that request either to TF-PSA/mbedTLS software or to mbedtls_psa_hardware_crypto_provider_t. The hardware provider then translates the same request into chip-local peripherals. This keeps TLS and PK code from needing direct RSA, ECDSA, AES, or hash hardware hooks.

@gilles-peskine-arm I think I may have a direction that addresses part of this. I have been working on a no-OS asynchronous execution model for Cortex-M systems using PendSV as the deferred-dispatch mechanism. The current implementation targets Microchip SAMD5x/E5x devices. Each hardware block has its own async execution context, for example SERCOM, GMAC, PUKCC, AES, ICM, TRNG, RTC, etc. Interrupt and DMA completion feed into a PendSV-scheduled continuation path, so foreground code does not need to block while long-running peripheral work completes. The relevant piece here is the crypto integration. The design uses a common PSA-facing async provider surface, tentatively: `mbedtls_psa_async_crypto_provider_t` That layer receives algorithm-agnostic PSA-style requests: operation kind, key identity/type, algorithm, input/output buffers, nonce/IV, associated data, tag buffers, curve metadata, etc. It does not expose RSA-specific or ECDSA-specific hardware calls to TLS, X.509, or PK code. The provider can be compiled in one of several modes: - crypto disabled - hardware-only for supported operations - software-only - hybrid, where hardware is used when available and software fills supported gaps Below that, the hardware-facing contract is tentatively: `mbedtls_psa_hardware_crypto_provider_t` Each platform implements that contract locally. For SAMD5x/E5x, the local implementation binds the common provider request surface to the chip hardware: PUKCC for RSA/ECC, AES for block and AEAD primitives, ICM for hash/HMAC, and TRNG for random generation. The important point is that the TLS/PSA-facing dispatch stays algorithm-agnostic. A TLS, X.509, or PK caller should submit a PSA/provider request using the same common operation structure regardless of whether the selected backend is hardware, software, or hybrid. The provider policy decides whether that request is handled by hardware or by TF-PSA/mbedTLS software. The chip-specific hardware binding remains below that boundary. I validated this on a SAME54P20 using the same embedded test harness compiled in hardware and software modes. The goal was to verify that the same provider-facing API could exercise both paths by changing compile-time mode guards, without changing the consumer/test request surface. `Software / hardware` greater than `1.0x` means the hardware path is faster. | Algorithm | Size/Meaning | Hardware cycles/op | Software cycles/op | Software / hardware | | --- | --- | ---: | ---: | ---: | | SHA-256 | 16 | 8470 | 14665 | 1.7x | | SHA-256 | 64 | 9065 | 20722 | 2.3x | | SHA-256 | 256 | 9032 | 39660 | 4.4x | | SHA-256 | 1024 | 10096 | 115432 | 11.4x | | SHA-256 | 4096 | 14780 | 418223 | 28.3x | | HMAC-SHA256 | 16 | 16043 | 59634 | 3.7x | | HMAC-SHA256 | 64 | 16519 | 66765 | 4.0x | | HMAC-SHA256 | 256 | 16597 | 89563 | 5.4x | | HMAC-SHA256 | 1024 | 17679 | 180663 | 10.2x | | HMAC-SHA256 | 4096 | 22346 | 545003 | 24.4x | | AES-CBC | 16 | 11481 | 21973 | 1.9x | | AES-CBC | 64 | 14371 | 27478 | 1.9x | | AES-CBC | 256 | 16131 | 49396 | 3.1x | | AES-CBC | 1024 | 21982 | 137149 | 6.2x | | AES-CBC | 4096 | 45962 | 487941 | 10.6x | | AES-CTR | 16 | 12096 | 22166 | 1.8x | | AES-CTR | 64 | 15044 | 27766 | 1.8x | | AES-CTR | 256 | 16504 | 50230 | 3.0x | | AES-CTR | 1024 | 22312 | 139964 | 6.3x | | AES-CTR | 4096 | 46286 | 498824 | 10.8x | | AES-GCM encrypt AAD16 | 16 | 16724 | 48260 | 2.9x | | AES-GCM encrypt AAD16 | 64 | 19710 | 60683 | 3.1x | | AES-GCM encrypt AAD16 | 256 | 21718 | 110230 | 5.1x | | AES-GCM encrypt AAD16 | 1024 | 27533 | 308332 | 11.2x | | AES-GCM encrypt AAD16 | 4096 | 51496 | 1100521 | 21.4x | | AES-GCM decrypt AAD16 | 16 | 18188 | 48596 | 2.7x | | AES-GCM decrypt AAD16 | 64 | 24430 | 61034 | 2.5x | | AES-GCM decrypt AAD16 | 256 | 49551 | 110698 | 2.2x | | AES-GCM decrypt AAD16 | 1024 | 149242 | 309104 | 2.1x | | AES-GCM decrypt AAD16 | 4096 | 547735 | 1102635 | 2.0x | | AES-CCM encrypt AAD16 | 16 | 18972 | 41400 | 2.2x | | AES-CCM encrypt AAD16 | 64 | 26465 | 51739 | 2.0x | | AES-CCM encrypt AAD16 | 256 | 29314 | 93144 | 3.2x | | AES-CCM encrypt AAD16 | 1024 | 41009 | 258640 | 6.3x | | AES-CCM encrypt AAD16 | 4096 | 88962 | 920479 | 10.3x | | AES-CCM decrypt AAD16 | 16 | 21148 | 41909 | 2.0x | | AES-CCM decrypt AAD16 | 64 | 35491 | 52606 | 1.5x | | AES-CCM decrypt AAD16 | 256 | 60170 | 95420 | 1.6x | | AES-CCM decrypt AAD16 | 1024 | 168107 | 266564 | 1.6x | | AES-CCM decrypt AAD16 | 4096 | 619283 | 951063 | 1.5x | | RSA raw exponentiation | 2048-bit modulus | 372472 | unavailable | unavailable | | RSA CRT | 192-bit test vector | 104561 | unavailable | unavailable | | EC public key | P-256 | 108113 | 11644790 | 107.7x | | ECDH | P-256 | 2697836 | 32607295 | 12.1x | | ECDSA sign | P-256 | 2760608 | 14287025 | 5.2x | | ECDSA verify | P-256 | 5477387 | 49471414 | 9.0x | In this model, the common API surface is the PSA-provider request, not the hardware peripheral API. Consumers such as TLS, X.509, PK, or PSA wrappers submit one algorithm-agnostic request shape containing the operation kind, PSA algorithm, key metadata, buffers, and operation parameters. `mbedtls_psa_async_crypto_provider_t` applies policy and dispatches that request either to TF-PSA/mbedTLS software or to `mbedtls_psa_hardware_crypto_provider_t`. The hardware provider then translates the same request into chip-local peripherals. This keeps TLS and PK code from needing direct RSA, ECDSA, AES, or hash hardware hooks.
This pull request is broken due to missing fork information.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 'crabel99/async-hardware-support-c35df962:crabel99/async-hardware-support-c35df962'
git switch 'crabel99/async-hardware-support-c35df962'

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch 'development'
git merge --no-ff 'crabel99/async-hardware-support-c35df962'
git switch 'crabel99/async-hardware-support-c35df962'
git rebase 'development'
git switch 'development'
git merge --ff-only 'crabel99/async-hardware-support-c35df962'
git switch 'crabel99/async-hardware-support-c35df962'
git rebase 'development'
git switch 'development'
git merge --no-ff 'crabel99/async-hardware-support-c35df962'
git switch 'development'
git merge --squash 'crabel99/async-hardware-support-c35df962'
git switch 'development'
git merge --ff-only 'crabel99/async-hardware-support-c35df962'
git switch 'development'
git merge 'crabel99/async-hardware-support-c35df962'
git push origin 'development'
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-Mbed-TLS/TF-PSA-Crypto!829
No description provided.