-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify SSL write API for Mbed TLS 4 #4183
Comments
A similar change should likely be made to |
What is the migration path for existing code? Is the old
I don't understand in what case |
@gilles-peskine-arm Yes, in essence that's the migration path. I'm currently drafting an implementation of the new API, and for the example programs, it comes down to adding an
I'm not sure I got your question right, but |
@gilles-peskine-arm I was a bit inaccurate above: While the pattern is right, the code you gave will not be equivalent to the old semantics of if( previous_write_needs_flush == 0 )
{
write_ret = mbedtls_ssl_write( ssl, buf, size );
if( write_ret < 0 )
return( write_ret );
previous_write_ret = write_ret;
previous_write_needs_flush = 1;
}
flush_ret = mbedtls_ssl_flush( ssl );
if( flush_ret != 0 )
return( flush_ret );
previous_write_needs_flush = 0;
return( previous_write_ret ); |
Until the new API is in place, are you willing to commit to the following API description change? I believe it doesn't require any code changes.
|
`mbedtls_ssl_flush_output` is needed for async in mbedtls. See: Mbed-TLS/mbedtls#4183
`mbedtls_ssl_flush_output` is needed for async in mbedtls. See: Mbed-TLS/mbedtls#4183
`mbedtls_ssl_flush_output` is needed for async in mbedtls. See: Mbed-TLS/mbedtls#4183
I think this issue is very important for the logic I am writing. Could you please assist me for the following scenario?
I would like to "abort" or "give up on" the write and proceed with sending close_notify. |
@dragan-ponos In principle you should be able to call Unfortunately, we're not going to be able to make any changes to the TLS API in Mbed TLS 3.x. Hopefully we'll have the improved API requested here in 4.0. |
@gilles-peskine-arm My code was doing exactly this for some time, but recently, on closer inspection, this came up as a potential issue. What I see in code is that both
It seems to me that the call to |
@dragan-ponos Thanks for the feedback! Indeed on code inspection this looks like a bug in |
Context: The SSL API
mbedtls_ssl_write()
is for writing application data through an established TLS connection. In Mbed TLS 2.X, the semantics of this API is that it always attempts to deliver the application data to the underlying transport immediately, and returning a dedicated non-fatal errorMBEDTLS_ERR_SSL_WANT_WRITE
if that's not possible.Problem: There are two issues arising from this design:
It is not possible to batch multiple calls to
mbedtls_ssl_write()
prior to delivering them to the underlying transport. This is arguably not an issue for TLS because the user could concatenate the data itself before callingmbedtls_ssl_write()
once, but it is a limitation for DTLS, where every invocation ofmbedtls_ssl_write()
shall correspond to exactly one DTLS datagram, multiple of which may be delivered in the same datagram of the underlying transport (such as UDP).More importantly, when calling
mbedtls_ssl_write()
, we have to distinguish the following situations:mbedtls_ssl_write()
is still to be delivered but the underlying transport is not available, returningMBEDTLS_ERR_SSL_WANT_WRITE
. The new data was not prepared queued for sending.MBEDTLS_ERR_SSL_WANT_WRITE
.With the current design, it is impossible to tell those cases apart. The resolution employed by Mbed TLS 2.X is to mandate that if
mbedtls_ssl_write()
fails withMBEDTLS_ERR_SSL_WANT_WRITE
, then the user must retry the call with the exact same parameters untilmbedtls_ssl_write()
succeeds, and only then it may be called again with different data. In fact, the implementation entirely ignores the arguments tombedtls_ssl_write()
if an earlier write is still unfinished, andmbedtls_ssl_write()
is demoted to a plain flush in this case -- see hereIn addition to not allowing batching of datagrams, the above design seems confusing, and we've had issues with it in the past.
Task: Agree on and implement a more suitable writing API.
Concrete proposal:
Split the writing API in two parts:
mbedtls_ssl_write()
which prepares outgoing application data for sending and queues it internally, but does not yet send it.mbedtls_ssl_flush()
, which attempts to deliver all data previously prepared viambedtls_ssl_write()
to the underlying transport.Both calls may fail with
MBEDTLS_ERR_SSL_WANT_WRITE
, but for different reasons:mbedtls_ssl_write()
fails withMBEDTLS_ERR_SSL_WANT_WRITE
, it's because new outgoing data can only be prepared after previously prepared data has been completely or partially flushed, freeing up internal space. In this case, the user knows that its data was not prepared and queued, but there is no obligation to callmbedtls_ssl_write()
again with the same or different parameters - it's up to the user.mbedtls_ssl_flush()
fails withMBEDTLS_ERR_SSL_WANT_WRITE
, then not all data previously prepared viambedtls_ssl_write()
could be delivered to the underlying transport.This approach fixes both issues above: At no point is the user obliged to call
mbedtls_ssl_write()
again with specific parameters, and it's always unambiguous which data has successfully been passed to the TLS stack and only requires flushing, and for which one the user should callmbedtls_ssl_write()
again. Moreover, the design allows for multiple DTLS datagrams to be packed into a single UDP datagram by the messaging implementation, becausembedtls_ssl_write()
is no longer forced to attempt immediate delivery.The text was updated successfully, but these errors were encountered: