mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-29 11:41:15 +03:00
Implement 3.0-semantics for mbedtls_ssl_{get,set}_session()
mbedtls_ssl_{get,set}_session() exhibited idempotent behaviour in Mbed TLS 2.x. Multiple calls to those functions are not useful in TLS 1.2, and the idempotent nature is unsuitable for support of TLS 1.3 which introduces the availabilty to offer multiple tickets for resumption, as well as receive multiple tickets. In preparation for TLS 1.3 support, this commit relaxes the semantics of `mbedtls_ssl_{get,set}_session()` by allowing implementations to fail gracefully, and leveraging this freedom by modifying the existing TLS 1.2 implementation to only accept one call to `mbedtls_ssl_{get,set}_session()` per context, and non-fatally failing all subsequent invocations. For TLS 1.3, it will be leveraged by making multiple calls to `mbedtls_ssl_get_session()` issue one ticket a time until no more tickets are available, and by using multiple calls to `mbedtls_ssl_set_session()` to allow the client to offer multiple tickets to the server. Signed-off-by: Hanno Becker <hanno.becker@arm.com>
This commit is contained in:
@ -897,6 +897,8 @@ struct mbedtls_ssl_session
|
|||||||
unsigned char id[32]; /*!< session identifier */
|
unsigned char id[32]; /*!< session identifier */
|
||||||
unsigned char master[48]; /*!< the master secret */
|
unsigned char master[48]; /*!< the master secret */
|
||||||
|
|
||||||
|
unsigned char exported;
|
||||||
|
|
||||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||||
mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
|
mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
|
||||||
@ -2373,18 +2375,49 @@ void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf,
|
|||||||
|
|
||||||
#if defined(MBEDTLS_SSL_CLI_C)
|
#if defined(MBEDTLS_SSL_CLI_C)
|
||||||
/**
|
/**
|
||||||
* \brief Request resumption of session (client-side only)
|
* \brief Load a session for session resumption.
|
||||||
* Session data is copied from presented session structure.
|
|
||||||
*
|
*
|
||||||
* \param ssl SSL context
|
* Sessions loaded through this call will be considered
|
||||||
* \param session session context
|
* for session resumption in the next handshake.
|
||||||
*
|
*
|
||||||
* \return 0 if successful,
|
* \note Even if this call succeeds, it is not guaranteed that
|
||||||
* MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed,
|
* the next handshake will indeed be shortened through the
|
||||||
* MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or
|
* use of session resumption: The server is always free
|
||||||
* arguments are otherwise invalid
|
* to reject any attempt for resumption and fall back to
|
||||||
|
* a full handshake.
|
||||||
|
*
|
||||||
|
* \note The mechanism of session resumption is opaque to this
|
||||||
|
* call: For TLS 1.2, both session ID-based resumption and
|
||||||
|
* ticket-based resumption will be considered. For TLS 1.3,
|
||||||
|
* once implemented, sessions equate to tickets, and loading
|
||||||
|
* one or more sessions via this call will lead to their
|
||||||
|
* corresponding tickets being advertised as resumption PSKs
|
||||||
|
* by the client.
|
||||||
|
*
|
||||||
|
* \note Calling this function multiple times will only be useful
|
||||||
|
* once TLS 1.3 is supported. For TLS 1.2 connections, this
|
||||||
|
* function should be called at most once.
|
||||||
|
*
|
||||||
|
* \param ssl The SSL context representing the connection which should
|
||||||
|
* be attempted to be setup using session resumption. This
|
||||||
|
* must be initialized via mbedtls_ssl_init() and bound to
|
||||||
|
* an SSL configuration via mbedtls_ssl_setup(), but
|
||||||
|
* the handshake must not yet have been started.
|
||||||
|
* \param session The session to be considered for session resumption.
|
||||||
|
* This must be a session previously exported via
|
||||||
|
* mbedtls_ssl_get_session(), and potentially serialized and
|
||||||
|
* deserialized through mbedtls_ssl_session_save() and
|
||||||
|
* mbedtls_ssl_session_load() in the meantime.
|
||||||
|
*
|
||||||
|
* \return \c 0 if successful.
|
||||||
|
* \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session
|
||||||
|
* could not be loaded because of an implementation limitation.
|
||||||
|
* This error is non-fatal, and has no observable effect on
|
||||||
|
* the SSL context or the session that was attempted to be loaded.
|
||||||
|
* \return Another negative error code on other kinds of failure.
|
||||||
*
|
*
|
||||||
* \sa mbedtls_ssl_get_session()
|
* \sa mbedtls_ssl_get_session()
|
||||||
|
* \sa mbedtls_ssl_session_load()
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session );
|
int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session );
|
||||||
#endif /* MBEDTLS_SSL_CLI_C */
|
#endif /* MBEDTLS_SSL_CLI_C */
|
||||||
@ -3677,32 +3710,41 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
|
|||||||
|
|
||||||
#if defined(MBEDTLS_SSL_CLI_C)
|
#if defined(MBEDTLS_SSL_CLI_C)
|
||||||
/**
|
/**
|
||||||
* \brief Save session in order to resume it later (client-side only)
|
* \brief Export a session in order to resume it later.
|
||||||
* Session data is copied to presented session structure.
|
|
||||||
*
|
*
|
||||||
|
* \param ssl The SSL context representing the connection for which to
|
||||||
|
* to export a session structure for later resumption.
|
||||||
|
* \param session The target structure in which to store the exported session.
|
||||||
|
* This must have been initialized with mbedtls_ssl_init_session()
|
||||||
|
* but otherwise be unused.
|
||||||
*
|
*
|
||||||
* \param ssl SSL context
|
* \note The mechanism of session resumption is opaque to this
|
||||||
* \param session session context
|
* call: For TLS 1.2, both session ID-based resumption and
|
||||||
|
* ticket-based resumption will be considered. For TLS 1.3,
|
||||||
|
* once implemented, sessions equate to tickets, and calling
|
||||||
|
* this function multiple times will export the available
|
||||||
|
* tickets one a time until no further tickets are available,
|
||||||
|
* in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will
|
||||||
|
* be returned.
|
||||||
*
|
*
|
||||||
* \return 0 if successful,
|
* \note Calling this function multiple times will only be useful
|
||||||
* MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed,
|
* once TLS 1.3 is supported. For TLS 1.2 connections, this
|
||||||
* MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or
|
* function should be called at most once.
|
||||||
* arguments are otherwise invalid.
|
|
||||||
*
|
*
|
||||||
* \note Only the server certificate is copied, and not the full chain,
|
* \return \c 0 if successful. In this case, \p session can be used for
|
||||||
* so you should not attempt to validate the certificate again
|
* session resumption by passing it to mbedtls_ssl_set_session(),
|
||||||
* by calling \c mbedtls_x509_crt_verify() on it.
|
* and serialized for storage via mbedtls_ssl_session_save().
|
||||||
* Instead, you should use the results from the verification
|
* \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session
|
||||||
* in the original handshake by calling \c mbedtls_ssl_get_verify_result()
|
* is available for export.
|
||||||
* after loading the session again into a new SSL context
|
* This error is a non-fatal, and has no observable effect on
|
||||||
* using \c mbedtls_ssl_set_session().
|
* the SSL context or the destination session.
|
||||||
*
|
* \return Another negative error code on other kinds of failure.
|
||||||
* \note Once the session object is not needed anymore, you should
|
|
||||||
* free it by calling \c mbedtls_ssl_session_free().
|
|
||||||
*
|
*
|
||||||
* \sa mbedtls_ssl_set_session()
|
* \sa mbedtls_ssl_set_session()
|
||||||
|
* \sa mbedtls_ssl_session_save()
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session );
|
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
|
||||||
|
mbedtls_ssl_session *session );
|
||||||
#endif /* MBEDTLS_SSL_CLI_C */
|
#endif /* MBEDTLS_SSL_CLI_C */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3788,6 +3788,9 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session
|
|||||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( ssl->handshake->resume == 1 )
|
||||||
|
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate,
|
if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate,
|
||||||
session ) ) != 0 )
|
session ) ) != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
@ -4789,6 +4792,8 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
|
|||||||
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
|
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
|
||||||
mbedtls_ssl_session *dst )
|
mbedtls_ssl_session *dst )
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if( ssl == NULL ||
|
if( ssl == NULL ||
|
||||||
dst == NULL ||
|
dst == NULL ||
|
||||||
ssl->session == NULL ||
|
ssl->session == NULL ||
|
||||||
@ -4797,7 +4802,27 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
|
|||||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( mbedtls_ssl_session_copy( dst, ssl->session ) );
|
/* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer
|
||||||
|
* idempotent: Each session can only be exported once.
|
||||||
|
*
|
||||||
|
* (This is in preparation for TLS 1.3 support where we will
|
||||||
|
* need the ability to export multiple sessions (aka tickets),
|
||||||
|
* which will be achieved by calling mbedtls_ssl_get_session()
|
||||||
|
* multiple times until it fails.)
|
||||||
|
*
|
||||||
|
* Check whether we have already exported the current session,
|
||||||
|
* and fail if so.
|
||||||
|
*/
|
||||||
|
if( ssl->session->exported == 1 )
|
||||||
|
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
|
||||||
|
|
||||||
|
ret = mbedtls_ssl_session_copy( dst, ssl->session );
|
||||||
|
if( ret != 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
/* Remember that we've exported the session. */
|
||||||
|
ssl->session->exported = 1;
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_SSL_CLI_C */
|
#endif /* MBEDTLS_SSL_CLI_C */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user