Hi Almut,

It's not clear to me what you're validating when. I'll try to suggest methods below but it's possible that I misunderstood.

On 28/07/2025 18:09, Almut Herzog via mbed-tls wrote:

Hi,

 

Prior to the first TLS handshake our application is required to perform input validation of the provided credentials (from file or smart card) for this peer.

One of those checks is to verify that private and public key match.

You can check whether a public key corresponds to a private key by doing a public-key export on both and comparing the results. Public key representations are canonical for all supported key formats. Alternatively, if you have both as pk contexts, you can call mbedtls_pk_check_pair().

 

We used to use mbedtls_pk_sign() with a custom mbedtls_pk_context for that.

But in version 3.X mbedtls_pk_info_t was made private so mbedtls_pk_setup() with a custom mbedtls_pk_info_t whose sign_func would call into our smart card wrapper is no longer possible.

Is there still a way to provide custom callback functions for signing in 3.6.4 somehow? Or any other workaround for early check of a key pair?

Passing a custom pk_info structure was already not officially supported in 2.x (you had to poke into pk_internal.h), but it could work if you knew what you were doing. The situation is the same in 3.x (in the default configuration), except that it's now clearly documented that it's unsupported. Given that 3.6 is a long-time support branch, if you have something working in 3.6, it's very unlikely to break in 3.6.x.

 

Looking at 4.0.0-beta, also pk.h is no longer public.

pk.h is still public. But hacking pk_info is no longer likely to work. We're planning to get rid of it during post-4.0 cleanup.

Will it still be possible to perform early validation of this peer’s credentials prior to a first TLS handshake? How?

While I am at it, it would be good to implement something that is future-proof.

 

What else I have looked at:

As far as I understand, here, you want to be able to use a smartcard to perform the signature. The official way to do this is with a PSA secure element driver (we use “secure element” as a generic term including smartcards, HSM, etc.). Unfortunately the documentation on this is not good; improving that is relatively high on our priority list for 2026. There is a driver tutorial at https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/development/docs/psa-driver-example-and-guide.md, but it's focused on accelerators. Writing a driver requires editing files manually (this is also on our priority list).

For a TLS server that needs to check signatures inside a secure element, there's a different approach, which is to bypass pk altogether. This requires the library to be compiled with MBEDTLS_SSL_ASYNC_PRIVATE, which is disabled by default, but it's an official feature, requiring no weird fiddling. See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/ssl_async/

 

Related:

Early validation of a CRL (whether it was signed by the expected CA) used to be possible with mbedtls_pk_verify_ext().

But to properly set the input parameters requires access to private members of mbedtls_x509_crl in 3.6.4 (maybe an acceptable move?) but in 4.0.0 mbedtls_pk_verify_ext() is no longer public.

How perform explicit/”manual” CRL validation especially given the possibly skipped CRL validation in mbedtls_x509_crt_verify() as per the comment below?

“It is your responsibility to provide up-to-date CRLs for all trusted CAs. If no CRL is provided for the CA that was used t sign the certificate, CRL verification is skipped silently…”

Any future-proof ideas for this?

I'm not very familiar with our CRL checking capabilities, but doing that from pk was never intended to be a thing. I suggest that you check the available callbacks in TLS that let you access the peer certificate. If you don't find what you need, please raise an issue asking for a new callback.

Best regards,

--
Gilles Peskine
Mbed TLS developer

 

Best regards,

/Almut