From 91fa5bade32dfd704101743fc120f6b38d610d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 May 2019 12:28:17 +0200 Subject: [PATCH 1/4] Add new config MBEDTLS_SSL_CONTEXT_SERIALIZATION This is enabled by default as we generally enable things by default unless there's a reason not to (experimental, deprecated, security risk). We need a compile-time option because, even though the functions themselves can be easily garbage-collected by the linker, implementing them will require saving 64 bytes of Client/ServerHello.random values after the handshake, that would otherwise not be needed, and people who don't need this feature shouldn't have to pay the price of increased RAM usage. --- include/mbedtls/config.h | 27 +++++++++++++++++++++++++++ library/version_features.c | 3 +++ programs/ssl/query_config.c | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index e0b5ba41c..53db082cd 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1308,6 +1308,33 @@ */ //#define MBEDTLS_SSL_ASYNC_PRIVATE +/** + * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION + * + * Enable the APIs for serialization of a full SSL context: + * mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * + * This pair of functions allows one side of a connection to serialize the + * context associated with the connection, then free or re-use that context + * while the serialized state is persisted elsewhere, and finally deserialize + * that state to a live context for resuming read/write operations on the + * connection, in a way that's transparent to the peer, since from a protocol + * point of view, the state of the connection is unaffected. + * + * Note: this is distinct from TLS session resumption, which is part of the + * protocol and fully visible by the peer. TLS session resumption enables + * establishing new connections associated to a saved session with shorter, + * lighter handshakes, while context serialization is a local optimisation in + * handling a single, potentially long-lived connection. + * + * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are + * saved after the handshake to allow for more efficient serialization, so if + * you don't need this feature you'll save RAM by disabling it. + * + * Comment to disable the context serialization APIs. + */ +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION + /** * \def MBEDTLS_SSL_DEBUG_ALL * diff --git a/library/version_features.c b/library/version_features.c index fc0b1f8f0..1bfc3d2b1 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -441,6 +441,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) "MBEDTLS_SSL_ASYNC_PRIVATE", #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + "MBEDTLS_SSL_CONTEXT_SERIALIZATION", +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "MBEDTLS_SSL_DEBUG_ALL", #endif /* MBEDTLS_SSL_DEBUG_ALL */ diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index be35a76ce..b630c34b7 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -1218,6 +1218,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + if( strcmp( "MBEDTLS_SSL_CONTEXT_SERIALIZATION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONTEXT_SERIALIZATION ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + #if defined(MBEDTLS_SSL_DEBUG_ALL) if( strcmp( "MBEDTLS_SSL_DEBUG_ALL", config ) == 0 ) { From d87601e3efdf34cc853d2d62df3548b4fcf1e3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 May 2019 13:02:16 +0200 Subject: [PATCH 2/4] Declare and document ssl_context_save()/load() Also introduce stub definitions so that things compile and link. --- include/mbedtls/ssl.h | 88 +++++++++++++++++++++++++++++++++++++++++++ library/ssl_tls.c | 34 +++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 50668072a..4f641022f 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3552,6 +3552,94 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); */ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); +/** + * \brief Save a live connection as serialized data in a buffer. + * This allows to free or re-use the SSL context while still + * picking up the connection later in a way that it entirely + * transparent to the peer. + * + * \see mbedtls_ssl_context_load() + * + * \note This feature is currently only available under certain + * conditions, see the documentation of return value + * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. + * + * \note When the function succeeds, it calls + * mbedtls_ssl_session_reset() on \p ssl which as a result is + * no longer associated with the connection that has been + * serialized. This avoid creating copies of the session + * state. You're then free to either re-use the context + * structure for a different connection, or call + * mbedtls_ssl_session_free() on it. + * + * \param ssl The SSL context to save. On success, it is no longer + * associated with the connection that has been serialized. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handsahke is in + * progress, or there is pending data for reading or sending, + * or the connection does not use DTLS 1.2 with and AEAD + * ciphersuite, or renegotiation is enabled. + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ); +/** + * \brief Load serialized connection data to an SSL context. + * + * \see mbedtls_ssl_context_save() + * + * \warning The same serialized data must never be loaded into more + * that one context. In order to ensure that, after + * successfully loading serialized data to an SSL context, you + * should immediately destroy or invalidate all copies of the + * serialized data that was loaded. Loading the same data in + * more than one context would cause severe security failures + * including but not limited to loss of confidentiality. + * + * \note Before calling this function, the SSL context must be + * prepared either by calling mbedtls_ssl_setup() on it with + * the same ::mbedtls_ssl_config structure that was used in + * the original connection, and not using it with any other + * function between mbedtls_ssl_setup() and this one, or by + * calling mbedtls_ssl_session_reset() on a context that was + * previously prepared as above but used in the meantime. + * + * \note After calling this function sucessfully, you still need to + * configure some connection-specific callback and settings + * before you can use the connection again. Specifically, you + * want to call at least mbedtls_ssl_set_bio() and possibly + * mbedtls_ssl_set_timer_cb(). You might also want to call + * mbedtls_ssl_set_mtu() if new information about the PMTU is + * available - otherwise the saved information will be used. + * + * \param ssl The SSL context structure to be populated. It must have + * been prepared as described in the note above. + * \param buf The buffer holding the serialized connection data. It must + * be a readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ); + /** * \brief Initialize an SSL configuration context * Just makes the context ready for diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ca4ab36f8..f14b9a207 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10213,6 +10213,40 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } +/* + * Serialize a full SSL context + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + /* Unimplemented yet */ + (void) ssl; + + if( buf != NULL ) + memset( buf, 0, buf_len ); + + *olen = 0; + + return( 0 ); +} + +/* + * Deserialize a full SSL context + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* Unimplemented yet */ + (void) ssl; + (void) buf; + (void) len; + + return( 0 ); +} + /* * Free an SSL context */ From cc71c77b5d8930aacbc2d72e0121c827daad9840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 5 Jun 2019 09:47:18 +0200 Subject: [PATCH 3/4] Fix typos, grammar and wording in documentation --- include/mbedtls/config.h | 10 +++++----- include/mbedtls/ssl.h | 30 +++++++++++++++++------------- library/ssl_tls.c | 4 ++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 53db082cd..6bb009819 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1311,20 +1311,20 @@ /** * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION * - * Enable the APIs for serialization of a full SSL context: - * mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * Enable serialization of the TLS context structures, through use of the + * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). * * This pair of functions allows one side of a connection to serialize the * context associated with the connection, then free or re-use that context * while the serialized state is persisted elsewhere, and finally deserialize * that state to a live context for resuming read/write operations on the - * connection, in a way that's transparent to the peer, since from a protocol - * point of view, the state of the connection is unaffected. + * connection. From a protocol perspective, the state of the connection is + * unaffected, in particular this is entirely transparent to the peer. * * Note: this is distinct from TLS session resumption, which is part of the * protocol and fully visible by the peer. TLS session resumption enables * establishing new connections associated to a saved session with shorter, - * lighter handshakes, while context serialization is a local optimisation in + * lighter handshakes, while context serialization is a local optimization in * handling a single, potentially long-lived connection. * * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 4f641022f..536c0a719 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3553,24 +3553,25 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); /** - * \brief Save a live connection as serialized data in a buffer. - * This allows to free or re-use the SSL context while still - * picking up the connection later in a way that it entirely - * transparent to the peer. + * \brief Save an active connection as serialized data in a buffer. + * This allows the freeing or re-using of the SSL context + * while still picking up the connection later in a way that + * it entirely transparent to the peer. * * \see mbedtls_ssl_context_load() * * \note This feature is currently only available under certain - * conditions, see the documentation of return value + * conditions, see the documentation of the return value * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. * - * \note When the function succeeds, it calls + * \note When this function succeeds, it calls * mbedtls_ssl_session_reset() on \p ssl which as a result is * no longer associated with the connection that has been - * serialized. This avoid creating copies of the session + * serialized. This avoids creating copies of the session * state. You're then free to either re-use the context * structure for a different connection, or call - * mbedtls_ssl_session_free() on it. + * mbedtls_ssl_session_free() on it. See the documentation of + * mbedtls_ssl_session_reset() for more details. * * \param ssl The SSL context to save. On success, it is no longer * associated with the connection that has been serialized. @@ -3588,7 +3589,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. - * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handsahke is in + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with and AEAD * ciphersuite, or renegotiation is enabled. @@ -3618,10 +3619,13 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * calling mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. * - * \note After calling this function sucessfully, you still need to - * configure some connection-specific callback and settings - * before you can use the connection again. Specifically, you - * want to call at least mbedtls_ssl_set_bio() and possibly + * \note Before or after calling this function successfully, you + * also need to configure some connection-specific callback + * and settings before you can use the connection again + * (unless they were already set before calling + * mbedtls_ssl_session_reset() and the values are suitable for + * the present connection). Specifically, you want to call + * at least mbedtls_ssl_set_bio() and possibly * mbedtls_ssl_set_timer_cb(). You might also want to call * mbedtls_ssl_set_mtu() if new information about the PMTU is * available - otherwise the saved information will be used. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f14b9a207..6a0f0a75d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10221,7 +10221,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, size_t buf_len, size_t *olen ) { - /* Unimplemented yet */ + /* Unimplemented */ (void) ssl; if( buf != NULL ) @@ -10239,7 +10239,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - /* Unimplemented yet */ + /* Unimplemented */ (void) ssl; (void) buf; (void) len; From 7667afd4fc6269fe79389ba65827dc75f4324e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 11 Jun 2019 11:25:10 +0200 Subject: [PATCH 4/4] Clarify documentation of mbedtls_ssl_context_load() --- include/mbedtls/ssl.h | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 536c0a719..1044b5a05 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3612,23 +3612,42 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * including but not limited to loss of confidentiality. * * \note Before calling this function, the SSL context must be - * prepared either by calling mbedtls_ssl_setup() on it with + * prepared in one of the two following ways. The first way is + * to take a context freshly initialised with + * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with * the same ::mbedtls_ssl_config structure that was used in - * the original connection, and not using it with any other - * function between mbedtls_ssl_setup() and this one, or by - * calling mbedtls_ssl_session_reset() on a context that was + * the original connection. The second way is to + * call mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. + * Either way, you must not use the context to perform a + * handshake between calling mbedtls_ssl_setup() or + * mbedtls_ssl_session_reset() and calling this function. You + * may however call other setter functions in that time frame + * as indicated in the note below. * * \note Before or after calling this function successfully, you - * also need to configure some connection-specific callback + * also need to configure some connection-specific callbacks * and settings before you can use the connection again * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call - * at least mbedtls_ssl_set_bio() and possibly - * mbedtls_ssl_set_timer_cb(). You might also want to call - * mbedtls_ssl_set_mtu() if new information about the PMTU is - * available - otherwise the saved information will be used. + * at least mbedtls_ssl_set_bio(). If you're using a read + * timeout (that is, you called + * mbedtls_ssl_conf_read_timeout() with a non-zero timeout) + * and non-blocking I/O, you also need to set timer callbacks + * by calling mbedtls_ssl_set_timer_cb(). All other SSL setter + * functions are not necessary to call, either because they're + * only used in handshakes, or because the setting is already + * saved. You might choose to call them anyway, for example in + * order to share code between the cases of establishing a new + * connection and the case of loading an already-established + * connection. + * + * \note If you have new information about the path MTU, you want to + * call mbedtls_ssl_set_mtu() after calling this function, as + * otherwise this function would overwrite your + * newly-configured value with the value that was active when + * the context was saved. * * \param ssl The SSL context structure to be populated. It must have * been prepared as described in the note above.