Merge pull request #273 from ARMmbed/iotssl-411-port-reuse
Iotssl 411 port reuse
This commit is contained in:
commit
ea4b76d54a
13 changed files with 403 additions and 29 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,13 +1,20 @@
|
|||
mbed TLS ChangeLog (Sorted per branch, date)
|
||||
|
||||
= mbed TLS 2.1.1 released 2015-09-??
|
||||
= mbed TLS 2.1.1 released 2015-09-16
|
||||
|
||||
Bugfix
|
||||
* Fix warning when using a 64bit platform. (found by embedthis) (#275)
|
||||
|
||||
|
||||
Changes
|
||||
* Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow
|
||||
use of mbedtls_x509_crt_profile_next. (found by NWilson)
|
||||
* When a client initiates a reconnect from the same port as a live
|
||||
connection, if cookie verification is available
|
||||
(MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie
|
||||
callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be
|
||||
detected and mbedtls_ssl_read() will return
|
||||
MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new
|
||||
handshake with the same context. (See RFC 6347 section 4.2.8.)
|
||||
|
||||
= mbed TLS 2.1.0 released 2015-09-04
|
||||
|
||||
|
|
|
@ -421,6 +421,11 @@
|
|||
#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \
|
||||
!defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
|
||||
#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
|
||||
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
|
||||
#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
|
||||
|
|
|
@ -1134,6 +1134,22 @@
|
|||
*/
|
||||
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
|
||||
*
|
||||
* Enable server-side support for clients that reconnect from the same port.
|
||||
*
|
||||
* Some clients unexpectedly close the connection and try to reconnect using the
|
||||
* same source port. This needs special support from the server to handle the
|
||||
* new connection securely, as described in section 4.2.8 of RFC 6347. This
|
||||
* flag enables that support.
|
||||
*
|
||||
* Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY
|
||||
*
|
||||
* Comment this to disable support for clients reusing the source port.
|
||||
*/
|
||||
#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
|
||||
*
|
||||
|
|
|
@ -125,6 +125,7 @@
|
|||
#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */
|
||||
#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */
|
||||
#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */
|
||||
#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */
|
||||
|
||||
/*
|
||||
* Various constants
|
||||
|
@ -1169,6 +1170,11 @@ typedef int mbedtls_ssl_cookie_check_t( void *ctx,
|
|||
* the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected
|
||||
* on the first handshake attempt when this is enabled.
|
||||
*
|
||||
* \note This is also necessary to handle client reconnection from
|
||||
* the same port as described in RFC 6347 section 4.2.8 (only
|
||||
* the variant with cookies is supported currently). See
|
||||
* comments on \c mbedtls_ssl_read() for details.
|
||||
*
|
||||
* \param conf SSL configuration
|
||||
* \param f_cookie_write Cookie write callback
|
||||
* \param f_cookie_check Cookie check callback
|
||||
|
@ -2089,29 +2095,35 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
|
|||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return 0 if successful, MBEDTLS_ERR_SSL_WANT_READ,
|
||||
* MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code.
|
||||
* \return 0 if successful, or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
|
||||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
|
||||
* a specific SSL error code.
|
||||
*
|
||||
* \note If this function returns non-zero, then the ssl context
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it.
|
||||
* If DTLS is in use, then you may choose to handle
|
||||
*
|
||||
* \note If DTLS is in use, then you may choose to handle
|
||||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
|
||||
* purposes, but you still need to reset/free the context.
|
||||
* purposes, as it is an expected return value rather than an
|
||||
* actual error, but you still need to reset/free the context.
|
||||
*/
|
||||
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
|
||||
|
||||
/**
|
||||
* \brief Perform a single step of the SSL handshake
|
||||
*
|
||||
* Note: the state of the context (ssl->state) will be at
|
||||
* \note The state of the context (ssl->state) will be at
|
||||
* the following state after execution of this function.
|
||||
* Do not call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return 0 if successful, MBEDTLS_ERR_SSL_WANT_READ,
|
||||
* MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code.
|
||||
* \return 0 if successful, or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
|
||||
* a specific SSL error code.
|
||||
*/
|
||||
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
|
||||
|
||||
|
@ -2138,7 +2150,23 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
|||
*
|
||||
* \return the number of bytes read, or
|
||||
* 0 for EOF, or
|
||||
* a negative error code.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
|
||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or
|
||||
* another negative error code.
|
||||
*
|
||||
* \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
||||
* (which can only happen server-side), it means that a client
|
||||
* is initiating a new connection using the same source port.
|
||||
* You can either treat that as a connection close and wait
|
||||
* for the client to resend a ClientHello, or directly
|
||||
* continue with \c mbedtls_ssl_handshake() with the same
|
||||
* context (as it has beeen reset internally). Either way, you
|
||||
* should make sure this is seen by the application as a new
|
||||
* connection: application state, if any, should be reset, and
|
||||
* most importantly the identity of the client must be checked
|
||||
* again. WARNING: not validating the identity of the client
|
||||
* again, or not transmitting the new identity to the
|
||||
* application layer, would allow authentication bypass!
|
||||
*/
|
||||
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len );
|
||||
|
||||
|
|
|
@ -428,6 +428,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" );
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||
|
|
|
@ -3250,6 +3250,196 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
|
|||
}
|
||||
#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
|
||||
/* Forward declaration */
|
||||
static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
|
||||
|
||||
/*
|
||||
* Without any SSL context, check if a datagram looks like a ClientHello with
|
||||
* a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
|
||||
* Both input and output include full DTLS headers.
|
||||
*
|
||||
* - if cookie is valid, return 0
|
||||
* - if ClientHello looks superficially valid but cookie is not,
|
||||
* fill obuf and set olen, then
|
||||
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
|
||||
* - otherwise return a specific error code
|
||||
*/
|
||||
static int ssl_check_dtls_clihlo_cookie(
|
||||
mbedtls_ssl_cookie_write_t *f_cookie_write,
|
||||
mbedtls_ssl_cookie_check_t *f_cookie_check,
|
||||
void *p_cookie,
|
||||
const unsigned char *cli_id, size_t cli_id_len,
|
||||
const unsigned char *in, size_t in_len,
|
||||
unsigned char *obuf, size_t buf_len, size_t *olen )
|
||||
{
|
||||
size_t sid_len, cookie_len;
|
||||
unsigned char *p;
|
||||
|
||||
if( f_cookie_write == NULL || f_cookie_check == NULL )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* Structure of ClientHello with record and handshake headers,
|
||||
* and expected values. We don't need to check a lot, more checks will be
|
||||
* done when actually parsing the ClientHello - skipping those checks
|
||||
* avoids code duplication and does not make cookie forging any easier.
|
||||
*
|
||||
* 0-0 ContentType type; copied, must be handshake
|
||||
* 1-2 ProtocolVersion version; copied
|
||||
* 3-4 uint16 epoch; copied, must be 0
|
||||
* 5-10 uint48 sequence_number; copied
|
||||
* 11-12 uint16 length; (ignored)
|
||||
*
|
||||
* 13-13 HandshakeType msg_type; (ignored)
|
||||
* 14-16 uint24 length; (ignored)
|
||||
* 17-18 uint16 message_seq; copied
|
||||
* 19-21 uint24 fragment_offset; copied, must be 0
|
||||
* 22-24 uint24 fragment_length; (ignored)
|
||||
*
|
||||
* 25-26 ProtocolVersion client_version; (ignored)
|
||||
* 27-58 Random random; (ignored)
|
||||
* 59-xx SessionID session_id; 1 byte len + sid_len content
|
||||
* 60+ opaque cookie<0..2^8-1>; 1 byte len + content
|
||||
* ...
|
||||
*
|
||||
* Minimum length is 61 bytes.
|
||||
*/
|
||||
if( in_len < 61 ||
|
||||
in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
|
||||
in[3] != 0 || in[4] != 0 ||
|
||||
in[19] != 0 || in[20] != 0 || in[21] != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
|
||||
sid_len = in[59];
|
||||
if( sid_len > in_len - 61 )
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
|
||||
cookie_len = in[60 + sid_len];
|
||||
if( cookie_len > in_len - 60 )
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
|
||||
if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
|
||||
cli_id, cli_id_len ) == 0 )
|
||||
{
|
||||
/* Valid cookie */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here, we've got an invalid cookie, let's prepare HVR.
|
||||
*
|
||||
* 0-0 ContentType type; copied
|
||||
* 1-2 ProtocolVersion version; copied
|
||||
* 3-4 uint16 epoch; copied
|
||||
* 5-10 uint48 sequence_number; copied
|
||||
* 11-12 uint16 length; olen - 13
|
||||
*
|
||||
* 13-13 HandshakeType msg_type; hello_verify_request
|
||||
* 14-16 uint24 length; olen - 25
|
||||
* 17-18 uint16 message_seq; copied
|
||||
* 19-21 uint24 fragment_offset; copied
|
||||
* 22-24 uint24 fragment_length; olen - 25
|
||||
*
|
||||
* 25-26 ProtocolVersion server_version; 0xfe 0xff
|
||||
* 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie
|
||||
*
|
||||
* Minimum length is 28.
|
||||
*/
|
||||
if( buf_len < 28 )
|
||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
|
||||
/* Copy most fields and adapt others */
|
||||
memcpy( obuf, in, 25 );
|
||||
obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
|
||||
obuf[25] = 0xfe;
|
||||
obuf[26] = 0xff;
|
||||
|
||||
/* Generate and write actual cookie */
|
||||
p = obuf + 28;
|
||||
if( f_cookie_write( p_cookie,
|
||||
&p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
*olen = p - obuf;
|
||||
|
||||
/* Go back and fill length fields */
|
||||
obuf[27] = (unsigned char)( *olen - 28 );
|
||||
|
||||
obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
|
||||
obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 );
|
||||
obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) );
|
||||
|
||||
obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 );
|
||||
obuf[12] = (unsigned char)( ( *olen - 13 ) );
|
||||
|
||||
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle possible client reconnect with the same UDP quadruplet
|
||||
* (RFC 6347 Section 4.2.8).
|
||||
*
|
||||
* Called by ssl_parse_record_header() in case we receive an epoch 0 record
|
||||
* that looks like a ClientHello.
|
||||
*
|
||||
* - if the input looks like a ClientHello without cookies,
|
||||
* send back HelloVerifyRequest, then
|
||||
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
|
||||
* - if the input looks like a ClientHello with a valid cookie,
|
||||
* reset the session of the current context, and
|
||||
* return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
||||
* - if anything goes wrong, return a specific error code
|
||||
*
|
||||
* mbedtls_ssl_read_record() will ignore the record if anything else than
|
||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function
|
||||
* cannot not return 0.
|
||||
*/
|
||||
static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
ret = ssl_check_dtls_clihlo_cookie(
|
||||
ssl->conf->f_cookie_write,
|
||||
ssl->conf->f_cookie_check,
|
||||
ssl->conf->p_cookie,
|
||||
ssl->cli_id, ssl->cli_id_len,
|
||||
ssl->in_buf, ssl->in_left,
|
||||
ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
|
||||
|
||||
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
|
||||
{
|
||||
/* Dont check write errors as we can't do anything here.
|
||||
* If the error is permanent we'll catch it later,
|
||||
* if it's not, then hopefully it'll work next time. */
|
||||
(void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
|
||||
|
||||
return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
|
||||
}
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
/* Got a valid cookie, partially reset context */
|
||||
if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
|
||||
|
||||
/*
|
||||
* ContentType type;
|
||||
* ProtocolVersion version;
|
||||
|
@ -3341,13 +3531,36 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||
if( rec_epoch != ssl->in_epoch )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
|
||||
"expected %d, received %d",
|
||||
ssl->in_epoch, rec_epoch ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
"expected %d, received %d",
|
||||
ssl->in_epoch, rec_epoch ) );
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
|
||||
/*
|
||||
* Check for an epoch 0 ClientHello. We can't use in_msg here to
|
||||
* access the first byte of record content (handshake type), as we
|
||||
* have an active transform (possibly iv_len != 0), so use the
|
||||
* fact that the record header len is 13 instead.
|
||||
*/
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
|
||||
rec_epoch == 0 &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_left > 13 &&
|
||||
ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
|
||||
"from the same port" ) );
|
||||
return( ssl_handle_possible_reconnect( ssl ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
|
||||
if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
|
||||
/* Replay detection only works for the current epoch */
|
||||
if( rec_epoch == ssl->in_epoch &&
|
||||
mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
|
@ -3528,7 +3741,8 @@ read_record_header:
|
|||
if( ( ret = ssl_parse_record_header( ssl ) ) != 0 )
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
|
||||
{
|
||||
/* Ignore bad record and get next one; drop the whole datagram
|
||||
* since current header cannot be trusted to find the next record
|
||||
|
@ -5123,8 +5337,11 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
|
|||
/*
|
||||
* Reset an initialized and used SSL context for re-use while retaining
|
||||
* all application-set variables, function pointers and data.
|
||||
*
|
||||
* If partial is non-zero, keep data in the input buffer and client ID.
|
||||
* (Use when a DTLS client reconnects from the same port.)
|
||||
*/
|
||||
int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
||||
static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -5148,7 +5365,8 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
|||
ssl->in_msg = ssl->in_buf + 13;
|
||||
ssl->in_msgtype = 0;
|
||||
ssl->in_msglen = 0;
|
||||
ssl->in_left = 0;
|
||||
if( partial == 0 )
|
||||
ssl->in_left = 0;
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
ssl->next_record_offset = 0;
|
||||
ssl->in_epoch = 0;
|
||||
|
@ -5174,7 +5392,8 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
|||
ssl->transform_out = NULL;
|
||||
|
||||
memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
|
||||
memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
|
||||
if( partial == 0 )
|
||||
memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
|
||||
|
||||
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
|
||||
if( mbedtls_ssl_hw_record_reset != NULL )
|
||||
|
@ -5207,9 +5426,12 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
|||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
|
||||
mbedtls_free( ssl->cli_id );
|
||||
ssl->cli_id = NULL;
|
||||
ssl->cli_id_len = 0;
|
||||
if( partial == 0 )
|
||||
{
|
||||
mbedtls_free( ssl->cli_id );
|
||||
ssl->cli_id = NULL;
|
||||
ssl->cli_id_len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
|
||||
|
@ -5218,6 +5440,15 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset an initialized and used SSL context for re-use while retaining
|
||||
* all application-set variables, function pointers and data.
|
||||
*/
|
||||
int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
return( ssl_session_reset_int( ssl, 0 ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* SSL set accessors
|
||||
*/
|
||||
|
|
|
@ -369,6 +369,9 @@ static const char *features[] = {
|
|||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
|
||||
"MBEDTLS_SSL_DTLS_HELLO_VERIFY",
|
||||
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
|
||||
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
|
||||
"MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE",
|
||||
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */
|
||||
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
|
||||
"MBEDTLS_SSL_DTLS_BADMAC_LIMIT",
|
||||
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
int main( void )
|
||||
{
|
||||
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
|
||||
"MBEDTLS_SHA256_C and/or MBEDLTS_MD_C and/or "
|
||||
"MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or "
|
||||
"MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
|
||||
"MBEDTLS_CTR_DRBG_C not defined.\n");
|
||||
return( 0 );
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
int main( void )
|
||||
{
|
||||
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
|
||||
"MBEDLTS_MD_C and/or "
|
||||
"MBEDTLS_MD_C and/or "
|
||||
"MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
|
||||
return( 0 );
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
int main( void )
|
||||
{
|
||||
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
|
||||
"MBEDLTS_MD_C and/or "
|
||||
"MBEDTLS_MD_C and/or "
|
||||
"MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
|
||||
return( 0 );
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ int main( void )
|
|||
#define DFL_DHMLEN -1
|
||||
#define DFL_RECONNECT 0
|
||||
#define DFL_RECO_DELAY 0
|
||||
#define DFL_RECONNECT_HARD 0
|
||||
#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED
|
||||
#define DFL_ALPN_STRING NULL
|
||||
#define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM
|
||||
|
@ -222,7 +223,7 @@ int main( void )
|
|||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||
" read_timeout=%%d default: 0 (no timeout)\n" \
|
||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||
" max_resend=%%d default: 0 (no resend on timeout)\n" \
|
||||
"\n" \
|
||||
USAGE_DTLS \
|
||||
|
@ -238,6 +239,7 @@ int main( void )
|
|||
" exchanges=%%d default: 1\n" \
|
||||
" reconnect=%%d default: 0 (disabled)\n" \
|
||||
" reco_delay=%%d default: 0 seconds\n" \
|
||||
" reconnect_hard=%%d default: 0 (disabled)\n" \
|
||||
USAGE_TICKETS \
|
||||
USAGE_MAX_FRAG_LEN \
|
||||
USAGE_TRUNC_HMAC \
|
||||
|
@ -293,6 +295,7 @@ struct options
|
|||
int dhmlen; /* minimum DHM params len in bits */
|
||||
int reconnect; /* attempt to resume session */
|
||||
int reco_delay; /* delay in seconds before resuming session */
|
||||
int reconnect_hard; /* unexpectedly reconnect from the same port */
|
||||
int tickets; /* enable / disable session tickets */
|
||||
const char *alpn_string; /* ALPN supported protocols */
|
||||
int transport; /* TLS or DTLS? */
|
||||
|
@ -481,6 +484,7 @@ int main( int argc, char *argv[] )
|
|||
opt.dhmlen = DFL_DHMLEN;
|
||||
opt.reconnect = DFL_RECONNECT;
|
||||
opt.reco_delay = DFL_RECO_DELAY;
|
||||
opt.reconnect_hard = DFL_RECONNECT_HARD;
|
||||
opt.tickets = DFL_TICKETS;
|
||||
opt.alpn_string = DFL_ALPN_STRING;
|
||||
opt.transport = DFL_TRANSPORT;
|
||||
|
@ -603,6 +607,12 @@ int main( int argc, char *argv[] )
|
|||
if( opt.reco_delay < 0 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "reconnect_hard" ) == 0 )
|
||||
{
|
||||
opt.reconnect_hard = atoi( q );
|
||||
if( opt.reconnect_hard < 0 || opt.reconnect_hard > 1 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "tickets" ) == 0 )
|
||||
{
|
||||
opt.tickets = atoi( q );
|
||||
|
@ -1479,7 +1489,38 @@ send_request:
|
|||
}
|
||||
|
||||
/*
|
||||
* 7b. Continue doing data exchanges?
|
||||
* 7b. Simulate hard reset and reconnect from same port?
|
||||
*/
|
||||
if( opt.reconnect_hard != 0 )
|
||||
{
|
||||
opt.reconnect_hard = 0;
|
||||
|
||||
mbedtls_printf( " . Restarting connection from same port..." );
|
||||
fflush( stdout );
|
||||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf( " ok\n" );
|
||||
|
||||
goto send_request;
|
||||
}
|
||||
|
||||
/*
|
||||
* 7c. Continue doing data exchanges?
|
||||
*/
|
||||
if( --opt.exchanges > 0 )
|
||||
goto send_request;
|
||||
|
@ -1489,6 +1530,7 @@ send_request:
|
|||
*/
|
||||
close_notify:
|
||||
mbedtls_printf( " . Closing the connection..." );
|
||||
fflush( stdout );
|
||||
|
||||
/* No error checking, the connection might be closed already */
|
||||
do ret = mbedtls_ssl_close_notify( &ssl );
|
||||
|
@ -1513,7 +1555,6 @@ reconnect:
|
|||
#endif
|
||||
|
||||
mbedtls_printf( " . Reconnecting with saved session..." );
|
||||
fflush( stdout );
|
||||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
|
|
|
@ -301,7 +301,7 @@ int main( void )
|
|||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||
" read_timeout=%%d default: 0 (no timeout)\n" \
|
||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||
"\n" \
|
||||
USAGE_DTLS \
|
||||
USAGE_COOKIES \
|
||||
|
@ -1838,6 +1838,12 @@ reset:
|
|||
}
|
||||
#endif
|
||||
|
||||
if( ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
|
||||
{
|
||||
mbedtls_printf( " ! Client initiated reconnection from same port\n" );
|
||||
goto handshake;
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
if( ret != 0 )
|
||||
{
|
||||
|
@ -1903,6 +1909,7 @@ reset:
|
|||
/*
|
||||
* 4. Handshake
|
||||
*/
|
||||
handshake:
|
||||
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
|
||||
fflush( stdout );
|
||||
|
||||
|
|
|
@ -2867,6 +2867,40 @@ run_test "DTLS cookie: enabled, nbio" \
|
|||
-s "hello verification requested" \
|
||||
-S "SSL - The requested feature is not available"
|
||||
|
||||
# Tests for client reconnecting from the same port with DTLS
|
||||
|
||||
not_with_valgrind # spurious resend
|
||||
run_test "DTLS client reconnect from same port: reference" \
|
||||
"$P_SRV dtls=1 exchanges=2 read_timeout=1000" \
|
||||
"$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000" \
|
||||
0 \
|
||||
-C "resend" \
|
||||
-S "The operation timed out" \
|
||||
-S "Client initiated reconnection from same port"
|
||||
|
||||
not_with_valgrind # spurious resend
|
||||
run_test "DTLS client reconnect from same port: reconnect" \
|
||||
"$P_SRV dtls=1 exchanges=2 read_timeout=1000" \
|
||||
"$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \
|
||||
0 \
|
||||
-C "resend" \
|
||||
-S "The operation timed out" \
|
||||
-s "Client initiated reconnection from same port"
|
||||
|
||||
run_test "DTLS client reconnect from same port: reconnect, nbio" \
|
||||
"$P_SRV dtls=1 exchanges=2 read_timeout=1000 nbio=2" \
|
||||
"$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \
|
||||
0 \
|
||||
-S "The operation timed out" \
|
||||
-s "Client initiated reconnection from same port"
|
||||
|
||||
run_test "DTLS client reconnect from same port: no cookies" \
|
||||
"$P_SRV dtls=1 exchanges=2 read_timeout=1000 cookies=0" \
|
||||
"$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-8000 reconnect_hard=1" \
|
||||
0 \
|
||||
-s "The operation timed out" \
|
||||
-S "Client initiated reconnection from same port"
|
||||
|
||||
# Tests for various cases of client authentication with DTLS
|
||||
# (focused on handshake flows and message parsing)
|
||||
|
||||
|
|
Loading…
Reference in a new issue