Skip to content

Commit

Permalink
Merge remote-tracking branch 'public/pr/2642' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbutcher committed Jun 4, 2019
2 parents ca6aee4 + 1c1f046 commit 150deca
Show file tree
Hide file tree
Showing 9 changed files with 629 additions and 63 deletions.
12 changes: 12 additions & 0 deletions include/mbedtls/check_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,18 @@
#error "MBEDTLS_SSL_CID defined, but not all prerequisites"
#endif

#if defined(MBEDTLS_SSL_CID) && \
defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \
MBEDTLS_SSL_CID_IN_LEN_MAX > 255
#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)"
#endif

#if defined(MBEDTLS_SSL_CID) && \
defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \
MBEDTLS_SSL_CID_OUT_LEN_MAX > 255
#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)"
#endif

#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
Expand Down
28 changes: 27 additions & 1 deletion include/mbedtls/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@

#define MBEDTLS_TLS_EXT_SESSION_TICKET 35

/* The value of the CID extension is still TBD as of
* https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-04. */
#define MBEDTLS_TLS_EXT_CID 254 /* TBD */

#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */

#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01
Expand Down Expand Up @@ -1266,6 +1270,21 @@ struct mbedtls_ssl_context
char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
#endif /* MBEDTLS_SSL_RENEGOTIATION */

#if defined(MBEDTLS_SSL_CID)
/* CID configuration to use in subsequent handshakes. */

/*! The next incoming CID, chosen by the user and applying to
* all subsequent handshakes. This may be different from the
* CID currently used in case the user has re-configured the CID
* after an initial handshake. */
unsigned char own_cid[ MBEDTLS_SSL_CID_IN_LEN_MAX ];
uint8_t own_cid_len; /*!< The length of \c own_cid. */
uint8_t negotiate_cid; /*!< This indicates whether the CID extension should
* be negotiated in the next handshake or not.
* Possible values are #MBEDTLS_SSL_CID_ENABLED
* and #MBEDTLS_SSL_CID_DISABLED. */
#endif /* MBEDTLS_SSL_CID */
};

#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
Expand Down Expand Up @@ -1609,6 +1628,13 @@ int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl,
* progress, this function will attempt to complete
* the handshake first.
*
* \note If CID extensions have been exchanged but both client
* and server chose to use an empty CID, this function
* sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED
* (the rationale for this is that the resulting
* communication is the same as if the CID extensions
* hadn't been used).
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
Expand Down Expand Up @@ -3135,7 +3161,7 @@ void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_
* (Default: 2^48 - 1)
*
* Renegotiation is automatically triggered when a record
* counter (outgoing or ingoing) crosses the defined
* counter (outgoing or incoming) crosses the defined
* threshold. The default value is meant to prevent the
* connection from being closed when the counter is about to
* reached its maximal value (it is not allowed to wrap).
Expand Down
19 changes: 19 additions & 0 deletions include/mbedtls/ssl_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ struct mbedtls_ssl_handshake_params
unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter
for resending messages */

#if defined(MBEDTLS_SSL_CID)
/* The state of CID configuration in this handshake. */

uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
* has been negotited. Possible values are
* #MBEDTLS_SSL_CID_ENABLED and
* #MBEDTLS_SSL_CID_DISABLED. */
unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
uint8_t peer_cid_len; /*!< The length of
* \c peer_cid. */
#endif /* MBEDTLS_SSL_CID */

struct
{
size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
Expand Down Expand Up @@ -597,6 +609,13 @@ struct mbedtls_ssl_transform
mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */
int minor_ver;

#if defined(MBEDTLS_SSL_CID)
uint8_t in_cid_len;
uint8_t out_cid_len;
unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
#endif /* MBEDTLS_SSL_CID */

/*
* Session specific compression layer
*/
Expand Down
123 changes: 123 additions & 0 deletions library/ssl_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,54 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */

#if defined(MBEDTLS_SSL_CID)
static void ssl_write_cid_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t *olen )
{
unsigned char *p = buf;
size_t ext_len;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;

/*
* Quoting
* https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-04:
*
* struct {
* opaque cid<0..2^8-1>;
* } ConnectionId;
*/

*olen = 0;
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
{
return;
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) );

/* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
* which is at most 255, so the increment cannot overflow. */
if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
return;
}

/* Add extension ID + size */
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID ) & 0xFF );
ext_len = (size_t) ssl->own_cid_len + 1;
*p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( ext_len ) & 0xFF );

*p++ = (uint8_t) ssl->own_cid_len;
memcpy( p, ssl->own_cid, ssl->own_cid_len );

*olen = ssl->own_cid_len + 5;
}
#endif /* MBEDTLS_SSL_CID */

#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
Expand Down Expand Up @@ -1085,6 +1133,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
ext_len += olen;
#endif

#if defined(MBEDTLS_SSL_CID)
ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
#endif /* MBEDTLS_SSL_CID */

#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
Expand Down Expand Up @@ -1242,6 +1295,62 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */

#if defined(MBEDTLS_SSL_CID)
static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
size_t peer_cid_len;

if( /* CID extension only makes sense in DTLS */
ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
/* The server must only send the CID extension if we have offered it. */
ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}

if( len == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}

peer_cid_len = *buf++;
len--;

if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}

if( len != peer_cid_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}

ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
memcpy( ssl->handshake->peer_cid, buf, peer_cid_len );

MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len );

return( 0 );
}
#endif /* MBEDTLS_SSL_CID */

#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
Expand Down Expand Up @@ -1893,6 +2002,20 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
break;
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */

#if defined(MBEDTLS_SSL_CID)
case MBEDTLS_TLS_EXT_CID:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) );

if( ( ret = ssl_parse_cid_ext( ssl,
ext + 4,
ext_size ) ) != 0 )
{
return( ret );
}

break;
#endif /* MBEDTLS_SSL_CID */

#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
Expand Down
Loading

0 comments on commit 150deca

Please sign in to comment.