mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-30 22:43:08 +03:00
Merge pull request #4517 from hanno-arm/ticket_api_3_0
Implement 3.0-API for SSL session resumption
This commit is contained in:
23
docs/3.0-migration-guide.d/remove-ssl-get-session_pointer.md
Normal file
23
docs/3.0-migration-guide.d/remove-ssl-get-session_pointer.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Remove the SSL API mbedtls_ssl_get_session_pointer()
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
This affects two classes of users:
|
||||||
|
|
||||||
|
1. Users who manually inspect parts of the current session through
|
||||||
|
direct structure field access.
|
||||||
|
|
||||||
|
2. Users of session resumption who query the current session
|
||||||
|
via `mbedtls_ssl_get_session_pointer()` prior to saving or exporting
|
||||||
|
it via `mbedtls_ssl_session_copy()` or `mbedtls_ssl_session_save()`,
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
Migration paths:
|
||||||
|
|
||||||
|
1. Mbed TLS 3.0 does not offer a migration path for the usecase 1: Like many
|
||||||
|
other Mbed TLS structures, the structure of `mbedtls_ssl_session` is no
|
||||||
|
longer part of the public API in Mbed TLS 3.0, and direct structure field
|
||||||
|
access is no longer supported. Please see the corresponding migration guide.
|
||||||
|
|
||||||
|
2. Users should replace calls to `mbedtls_ssl_get_session_pointer()` by
|
||||||
|
calls to `mbedtls_ssl_get_session()` as demonstrated in the example
|
||||||
|
program `programs/ssl/ssl_client2.c`.
|
30
docs/3.0-migration-guide.d/ssl-ticket-api.md
Normal file
30
docs/3.0-migration-guide.d/ssl-ticket-api.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Modified semantics of mbedtls_ssl_{get,set}_session()
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
This affects users who call `mbedtls_ssl_get_session()` or
|
||||||
|
`mbedtls_ssl_set_session()` multiple times on the same SSL context
|
||||||
|
representing an established TLS 1.2 connection.
|
||||||
|
Those users will now observe the second call to fail with
|
||||||
|
`MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE`.
|
||||||
|
|
||||||
|
Migration path:
|
||||||
|
- Exporting the same TLS 1.2 connection multiple times via
|
||||||
|
`mbedtls_ssl_get_session()` leads to multiple copies of
|
||||||
|
the same session. This use of `mbedtls_ssl_get_session()`
|
||||||
|
is discouraged, and the following should be considered:
|
||||||
|
* If the various session copies are later loaded into
|
||||||
|
fresh SSL contexts via `mbedtls_ssl_set_session()`,
|
||||||
|
export via `mbedtls_ssl_get_session()` only once and
|
||||||
|
load the same session into different contexts via
|
||||||
|
`mbedtls_ssl_set_session()`. Since `mbedtls_ssl_set_session()`
|
||||||
|
makes a copy of the session that's being loaded, this
|
||||||
|
is functionally equivalent.
|
||||||
|
* If the various session copies are later serialized
|
||||||
|
via `mbedtls_ssl_session_save()`, export and serialize
|
||||||
|
the session only once via `mbedtls_ssl_get_session()` and
|
||||||
|
`mbedtls_ssl_session_save()` and make copies of the raw
|
||||||
|
data instead.
|
||||||
|
- Calling `mbedtls_ssl_set_session()` multiple times in Mbed TLS 2.x
|
||||||
|
is not useful since subsequent calls overwrite the effect of previous
|
||||||
|
calls. Applications achieve equivalent functional behaviour by
|
||||||
|
issuing only the very last call to `mbedtls_ssl_set_session()`.
|
@ -933,6 +933,8 @@ struct mbedtls_ssl_session
|
|||||||
unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */
|
unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */
|
||||||
unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */
|
unsigned char MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */
|
mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */
|
||||||
@ -2391,18 +2393,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 This function can handle a variety of mechanisms for session
|
||||||
|
* resumption: 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 */
|
||||||
@ -2451,7 +2484,6 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session,
|
|||||||
* of session cache or session tickets.
|
* of session cache or session tickets.
|
||||||
*
|
*
|
||||||
* \see mbedtls_ssl_session_load()
|
* \see mbedtls_ssl_session_load()
|
||||||
* \see mbedtls_ssl_get_session_pointer()
|
|
||||||
*
|
*
|
||||||
* \param session The session structure to be saved.
|
* \param session The session structure to be saved.
|
||||||
* \param buf The buffer to write the serialized data to. It must be a
|
* \param buf The buffer to write the serialized data to. It must be a
|
||||||
@ -2474,23 +2506,6 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
|
|||||||
size_t buf_len,
|
size_t buf_len,
|
||||||
size_t *olen );
|
size_t *olen );
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Get a pointer to the current session structure, for example
|
|
||||||
* to serialize it.
|
|
||||||
*
|
|
||||||
* \warning Ownership of the session remains with the SSL context, and
|
|
||||||
* the returned pointer is only guaranteed to be valid until
|
|
||||||
* the next API call operating on the same \p ssl context.
|
|
||||||
*
|
|
||||||
* \see mbedtls_ssl_session_save()
|
|
||||||
*
|
|
||||||
* \param ssl The SSL context.
|
|
||||||
*
|
|
||||||
* \return A pointer to the current session if successful.
|
|
||||||
* \return \c NULL if no session is active.
|
|
||||||
*/
|
|
||||||
const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the list of allowed ciphersuites and the preference
|
* \brief Set the list of allowed ciphersuites and the preference
|
||||||
* order. First in the list has the highest preference.
|
* order. First in the list has the highest preference.
|
||||||
@ -3642,32 +3657,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 This function can handle a variety of mechanisms for session
|
||||||
* \param session session context
|
* resumption: 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 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3504,6 +3504,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 );
|
||||||
@ -4465,6 +4468,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 ||
|
||||||
@ -4473,18 +4478,30 @@ 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 */
|
||||||
|
|
||||||
const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl )
|
|
||||||
{
|
|
||||||
if( ssl == NULL )
|
|
||||||
return( NULL );
|
|
||||||
|
|
||||||
return( ssl->session );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define ticket header determining Mbed TLS version
|
* Define ticket header determining Mbed TLS version
|
||||||
* and structure of the ticket.
|
* and structure of the ticket.
|
||||||
|
@ -2163,6 +2163,8 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
if( opt.reco_mode == 1 )
|
if( opt.reco_mode == 1 )
|
||||||
{
|
{
|
||||||
|
mbedtls_ssl_session exported_session;
|
||||||
|
|
||||||
/* free any previously saved data */
|
/* free any previously saved data */
|
||||||
if( session_data != NULL )
|
if( session_data != NULL )
|
||||||
{
|
{
|
||||||
@ -2171,27 +2173,40 @@ int main( int argc, char *argv[] )
|
|||||||
session_data = NULL;
|
session_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_session_init( &exported_session );
|
||||||
|
ret = mbedtls_ssl_get_session( &ssl, &exported_session );
|
||||||
|
if( ret != 0 )
|
||||||
|
{
|
||||||
|
mbedtls_printf(
|
||||||
|
"failed\n ! mbedtls_ssl_get_session() returned -%#02x\n",
|
||||||
|
(unsigned) -ret );
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* get size of the buffer needed */
|
/* get size of the buffer needed */
|
||||||
mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ),
|
mbedtls_ssl_session_save( &exported_session, NULL, 0, &session_data_len );
|
||||||
NULL, 0, &session_data_len );
|
|
||||||
session_data = mbedtls_calloc( 1, session_data_len );
|
session_data = mbedtls_calloc( 1, session_data_len );
|
||||||
if( session_data == NULL )
|
if( session_data == NULL )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! alloc %u bytes for session data\n",
|
mbedtls_printf( " failed\n ! alloc %u bytes for session data\n",
|
||||||
(unsigned) session_data_len );
|
(unsigned) session_data_len );
|
||||||
|
mbedtls_ssl_session_free( &exported_session );
|
||||||
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* actually save session data */
|
/* actually save session data */
|
||||||
if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ),
|
if( ( ret = mbedtls_ssl_session_save( &exported_session,
|
||||||
session_data, session_data_len,
|
session_data, session_data_len,
|
||||||
&session_data_len ) ) != 0 )
|
&session_data_len ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n",
|
mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n",
|
||||||
(unsigned int) -ret );
|
(unsigned int) -ret );
|
||||||
|
mbedtls_ssl_session_free( &exported_session );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_session_free( &exported_session );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user