Summary
In PSA-client-only builds (MBEDTLS_PSA_CRYPTO_C disabled, e.g. NS-side mbedtls dispatching to a secure PSA service like TF-M), TLS 1.2 ECDHE handshakes fail because the premaster-secret union is sized below PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE.
The local ECP_LIGHT cascade does not run in this configuration, so MBEDTLS_ECP_MAX_BYTES collapses to 1. The _pms_ecdh and _pms_ecdhe_psk members of union mbedtls_ssl_premaster_secret are declared in terms of that macro, so the whole union ends up ~1 byte in builds that have only ECDHE-RSA / ECDHE-ECDSA enabled (no PSK, no ECJPAKE).
ssl_tls12_client.c:2436 passes sizeof(premaster) to psa_raw_key_agreement(); it returns PSA_ERROR_BUFFER_TOO_SMALL, mbedtls maps that to MBEDTLS_ERR_SSL_HW_ACCEL_FAILED and aborts the handshake. No memory corruption, just a deterministic handshake failure that any PSA-client deployment hits.
System information
Mbed TLS version (number or commit id): 6a08a7eb7 (development HEAD) Operating system and version: Zephyr RTOS, any Configuration (if not default, please attach mbedtls_config.h):
- MBEDTLS_PSA_CRYPTO_C disabled
- MBEDTLS_PSA_CRYPTO_CLIENT enabled (PSA dispatched to TF-M)
- MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED and/or MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
- PSK / ECDHE-PSK / ECJPAKE key exchanges disabled
- PSA_WANT_ALG_ECDH + at least one PSA_WANT_ECC_* curve Compiler and options (if you used a pre-built binary, please indicate how you obtained it): arm-zephyr-eabi-gcc, default Zephyr build for an STM32U585-class target (Cortex-M33 with TF-M secure side)
Additional environment information: Reproduces with both TF-M-backed PSA and any other external PSA service that disables MBEDTLS_PSA_CRYPTO_C in the NS-side build.
Expected behavior
TLS 1.2 ECDHE-RSA or ECDHE-ECDSA handshake completes successfully in a PSA-client-only build.
Actual behavior
Handshake aborts at psa_raw_key_agreement() with PSA_ERROR_BUFFER_TOO_SMALL, surfaced as MBEDTLS_ERR_SSL_HW_ACCEL_FAILED. The premaster union is sized to ~1 byte because every member is gated on a feature macro that is either disabled (PSK family, ECJPAKE) or expands to a 1-byte declaration (_pms_ecdh[MBEDTLS_ECP_MAX_BYTES] with MBEDTLS_ECP_MAX_BYTES == 1).
Steps to reproduce
- Build mbedtls with the configuration above (PSA client only, ECDHE key exchanges enabled, PSK / ECDHE-PSK / ECJPAKE disabled).
- Start a TLS 1.2 ECDHE-RSA or ECDHE-ECDSA handshake against any peer that accepts it.
- Observe handshake failure at the key-exchange step with MBEDTLS_ERR_SSL_HW_ACCEL_FAILED.
Additional information
Proposed fix: introduce MBEDTLS_SSL_PMS_ECDH_SIZE defined as max(PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE, MBEDTLS_ECP_MAX_BYTES) and use it for _pms_ecdh and _pms_ecdhe_psk. PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE is always defined and sized by the enabled PSA_WANT_ECC_* curves, so legacy ECP builds keep their existing buffer size and PSA-client builds get a sufficient one. Happy to follow up with a PR.
Summary
In PSA-client-only builds (MBEDTLS_PSA_CRYPTO_C disabled, e.g. NS-side mbedtls dispatching to a secure PSA service like TF-M), TLS 1.2 ECDHE handshakes fail because the premaster-secret union is sized below PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE.
The local ECP_LIGHT cascade does not run in this configuration, so MBEDTLS_ECP_MAX_BYTES collapses to 1. The
_pms_ecdhand_pms_ecdhe_pskmembers ofunion mbedtls_ssl_premaster_secretare declared in terms of that macro, so the whole union ends up ~1 byte in builds that have only ECDHE-RSA / ECDHE-ECDSA enabled (no PSK, no ECJPAKE).ssl_tls12_client.c:2436 passes sizeof(premaster) to psa_raw_key_agreement(); it returns PSA_ERROR_BUFFER_TOO_SMALL, mbedtls maps that to MBEDTLS_ERR_SSL_HW_ACCEL_FAILED and aborts the handshake. No memory corruption, just a deterministic handshake failure that any PSA-client deployment hits.
System information
Mbed TLS version (number or commit id): 6a08a7eb7 (development HEAD) Operating system and version: Zephyr RTOS, any Configuration (if not default, please attach
mbedtls_config.h):Additional environment information: Reproduces with both TF-M-backed PSA and any other external PSA service that disables MBEDTLS_PSA_CRYPTO_C in the NS-side build.
Expected behavior
TLS 1.2 ECDHE-RSA or ECDHE-ECDSA handshake completes successfully in a PSA-client-only build.
Actual behavior
Handshake aborts at psa_raw_key_agreement() with PSA_ERROR_BUFFER_TOO_SMALL, surfaced as MBEDTLS_ERR_SSL_HW_ACCEL_FAILED. The premaster union is sized to ~1 byte because every member is gated on a feature macro that is either disabled (PSK family, ECJPAKE) or expands to a 1-byte declaration (
_pms_ecdh[MBEDTLS_ECP_MAX_BYTES]with MBEDTLS_ECP_MAX_BYTES == 1).Steps to reproduce
Additional information
Proposed fix: introduce MBEDTLS_SSL_PMS_ECDH_SIZE defined as max(PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE, MBEDTLS_ECP_MAX_BYTES) and use it for
_pms_ecdhand_pms_ecdhe_psk. PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE is always defined and sized by the enabled PSA_WANT_ECC_* curves, so legacy ECP builds keep their existing buffer size and PSA-client builds get a sufficient one. Happy to follow up with a PR.