Provide a public API to allow configuration of a session ID to be used
Suggested enhancement
Provide a public API to allow configuration of a session ID to be used for the newly negotiated session.
Justification
Certain SSL VPN protocols support both, TLS and DTLS tunnels. They always start by establishing a TLS connection, which is used for authenticating the user, retrieving VPN and network related configuration and receiving configuration for the DTLS tunnel.
Once all of that is done, the TLS connection can be used a VPN tunnel for traffic but since it is based on TCP, that's pretty sub-optimal (tunneling TCP over TCP is a very bad idea). That's why the preferred way is to establish a DTLS tunnel with the configuration you've been told (like what crypto params that DTLS tunnel will use) and quite often this configuration includes a session ID, meaning even though that is a newly negotiated tunnel, not a resumed one, it must use a specific session ID.
In mbedTLS 2.x this could be achieved by setting up a DTLS context and then doing the following:
size_t maxIDLen = sizeof(_tlsContext.session_negotiate->id);
size_t maxCopy = MIN(d.length, maxIDLen);
memset(tlsContext.session_negotiate->id, 0, maxIDLen);
memcpy(tlsContext.session_negotiate->id, d.bytes, maxCopy);
tlsContext.session_negotiate->id_len = maxCopy;
tlsContext.handshake->resume = 1;
Now the session is negotiated with the set ID. It is not really resumed as no other resume parameters have been set. Of course this code relies on private API and undocumented behavior but it worked as desired.
In mbedTLS 3.x this is no longer possible, because all fields are now private. In most cases they can still be accessed by prepending private_ to their name but not in case of the last line, since struct mbedtls_ssl_handshake_params is now entirely private and just forward declared in public headers.
Using mbedtls_ssl_set_session() is not a valid work around, for two reasons:
struct mbedtls_ssl_sessionis private as well, so it's not possible to manually create it from scratch and the byte format is not publicly documented either (it is in a comment within the source code but being private, subject to change at any time)- We cannot resume a full session, we don't have full session information, all we have is a session ID, maybe a preferred cipher, the rest must be negotiated as for any new session.
Please note that this can be implemented in OpenSSL and LibreSSL using only public, non-breaking API, otherwise no clients for those SSL VPN protocols would exist.
This makes sense. Note that what you're doing in 2.28 might happen to work, but it isn't guaranteed. The library chooses the session ID internally and you're just lucky that there's no copy of it anywhere else, or other data based on it, at the time you modify the field.
Mbed TLS 3 will no longer have any feature release: the 3.6 branch is a long-time support branch, and the next feature release will be 4.0. So I'm not sure whether we can provide this feature in 3.6. But if you can find a way to allow specifying a session ID externally that's obviously not disruptive and doesn't increase the code size, we'll consider it for a 3.6.x patch release. Otherwise that will have to wait until 4.x.