Mbed-TLS / mbedtls

An open source, portable, easy to use, readable and flexible TLS library, and reference implementation of the PSA Cryptography API. Releases are on a varying cadence, typically around 3 - 6 months between releases.
https://www.trustedfirmware.org/projects/mbed-tls/
Other
5.24k stars 2.56k forks source link

Setting up kTLS after marking fields as private #7722

Open lpereira opened 1 year ago

lpereira commented 1 year ago

Hi -- I have a web server that can use mbedTLS to provide HTTPS using kTLS on Linux. With the mbedTLS 3.4.0 update, it doesn't build anymore because the code (link) peeks inside the private context to get the necessary stuff to pass to the kernel.

Some of the stuff that's directly in a mbedtls_ssl_context can be accessed just fine with a MBEDTLS_PRIVATE macro call (albeit without the guarantee that it'll be there in a future update); but some of the stuff that's required, such as stuff inside the transform member (e.g. iv_dec and cipher_ctx_enc), aren't exported.

I understand that peeking inside these structs isn't ideal and this restriction was bound to happen someday; however, there's currently no way to set up kTLS keys without downgrading mbedTLS or using a patched version that exposes the transform struct, both of which aren't ideal and I'd like to very much avoid.

It would be nice if there was some sort of API to set up the keys in a socket given a SSL context, for instance as part of mbedtls_ssl_handshake(), if an option is set, or some other API to perform this step more explicitly. This could be done in a platform-independent way, too, for instance by also supporting FreeBSD. Of course this would need to fail if such thing isn't supported by the operating system.

ronald-cron-arm commented 1 year ago

Did you have a look to mbedtls_ssl_set_export_keys_cb() (see in ssl.h)? Is that what you are looking for or the kind of thing you are looking for?

lpereira commented 1 year ago

Ah, I didn't notice that this existed; should've looked further, thanks!

It's in the vicinity of what I need, yes. It doesn't however export the salt (from transform->iv_dec or iv_enc), IV (32 bits after the salt), AES round key for both encryption and decryption (from obtained by getting the GCM context from transform->cipher_ctx_enc or cipher_ctx_dec and peeking inside). Everything to fill out a struct tls12_crypto_info_aes_gcm128 from <linux/tls.h>, as shown in the link in the issue description.

I would imagine that, since the migration guide mentions that the older callbacks that mbedtls_ssl_set_export_keys_cb() replaced used to export these things, that this kind of information isn't coming back, unfortunately.

ronald-cron-arm commented 1 year ago

In the migration guide I can see:

"Users which require access to the raw keys used to secure application traffic may derive those by hand based on the master secret and the handshake transcript hashes which can be obtained from the raw data on the wire. Such users are also encouraged to reach out to the Mbed TLS team on the mailing list, to let the team know about their use case."

Here we are I would say.

gilles-peskine-arm commented 10 months ago

This is going to be difficult. The information that lwan wants only exists in very specific circumstances, and the way it's stored in memory depends on internal details. Designing a stable API seems challenging.

We can add a function that only works in the cases where it can work and returns an error otherwise. In order to keep working in Mbed TLS 4.0, it would have to cope with a PSA stack, where the key material is not directly accessible. So it would need to save the key material at the time it's generated, or call a callback at that time. I'm not sure without digging further whether the keys and IVs are available at the same time, and that might even depend on the protocol version and the cipher suite and extensions. This is doable in principle, but it's a lot more work than just exposing a few structure fields. And the new API seems extremely specific, it would basically be mbedtls_ssl_give_lwan_what_it_wants. We are very unlikely to have time to design this properly before the 3.x LTS release. So I'm afraid we don't really have a solution without some design changes in lwan.


So, how else could lwan work?

One solution would be to change the TLS stack. You need a TLS stack with limited flexibility in terms of cryptography, where Mbed TLS is moving towards more flexibility.

Another solution would be to hook into the crypto stack rather than the TLS stack. The PSA crypto stack supports drivers, so you could inject your own AES-GCM driver that makes a copy of the key material. You would need to maintain AES-GCM code that lets you copy the internal state midway: extracting the AES round keys and the GCM salt is not a standard interface to those cryptographic primitives. I would even say that the Linux TLS interface is badly designed: it should work from the AES key and GCM nonce, and handle the whole symmetric cryptography operation, instead of cutting at an arbitrary point.

gilles-peskine-arm commented 10 months ago

I'm not closing this issue yet, but we are not going to implement exactly what was originally requested, and we are not going to actively work on a design. However, if you can think of an interface that doesn't break the deliberate abstraction boundaries I explain in my previous message, please propose it (basically, a function and its documentation, including error conditions).

mmollgithub commented 6 days ago

I'm sorry if I'm hijacking this issue but I want to do the exact same thing as lpereira and I stumbled over the following remark:

I would even say that the Linux TLS interface is badly designed: it should work from the AES key and GCM nonce, and handle the whole symmetric cryptography operation, instead of cutting at an arbitrary point.

It was my understanding that kTLS does exactly that and only requires the AES key and GCM IV (split into salt and dynamic IV), and the lwan code seems to collect precisely those values (the key material is collected right after the handshake). In that case, wouldn't it be possible to just use the export_keys callback, derive the key material from the master secret (using the PRF as in e.g. RFC 5246 6.3 (I'm currently only interested in TLS 1.2)) and pass that to ktls? Unfortunately, while the callback passes the PRF type, I'm not given the ciphersuite (which I also need, to know whether ktls supports it at all and to extract the appropriate key material). Is there a safe and recommended way to query the tls context for the ciphersuite within the callback?

gilles-peskine-arm commented 5 days ago

Is there a safe and recommended way to query the tls context for the ciphersuite within the callback?

I'm not sure this is the best way, but I think you can pass the SSL context as the context parameter to the callback, call mbedtls_ssl_get_session and call mbedtls_ssl_session_get_ciphersuite_id. That does seem rather heavyweight though.