mbedtls

mbedtls Application Record Size


I'm using mbedtls to run SSL over TCP. I'm using my own custom I/O functions for the interface between mbedtls and TCP, set using the mbedtls_ssl_set_bio call.

I've noticed that Application records are generated one-to-one with calls to mbedtls_ssl_write. For example, if I write data in 52-byte chunks, the client sends 52-byte records. If I write data in 520-byte chunks, then the client sends 520-byte records. The latter case is preferable; in the former case, a significant amount of bandwidth is lost to TLS headers.

My question is: is it possible to configure mbedtls to "coalesce" multiple small writes into a single record? For example, TCP does this (e.g., if you write data in 52-byte chunks to a TCP connection in quick succession, they do eventually get coalesced into MSS-sized segments). I'm wondering if it's possible to do something similar for TLS.


Solution

  • With TCP, when the write function returns, the data has written to the socket and is out of control of the application. The network stack can still coalesce packets if it wants. Either the sender, or a router, can merge successive TCP packets on a connection if the second packet arrives before the previous one can be sent.

    With TLS, when the mbedtls_ssl_write function returns (or similar function in any TLS stack), the data has been encrypted-and-authenticated into a TLS record and the record has been sent over the socket (or whatever the underlying I/O function does). The TCP stack can still coalesce the TCP packets, but it can't coalesce TLS records because it doesn't have the necessary cryptographic keys.

    If you want to coalesce data on a TLS connection, either you need to buffer it before you pass it to the TLS stack, or the TLS stack needs to buffer it itself. If you want the TLS stack to buffer it, you need an API with at least two functions: one to take some data as input and not try to send it immediately, and another one to say “send the data now!”. The first function would not really do anything except write the data into some temporary buffer, unless the buffer is full in which case it would need to flush it first. And that's something you can do yourself: just memcpy the data to a temporary buffer, and call mbedtls_ssl_write on that temporary buffer when you're ready to send. So there's not really an incentive for a TLS stack to provide this interface.