diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index c99e8f9a2..9dd9c4ab1 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -641,6 +641,9 @@ typedef enum #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ } mbedtls_ssl_states; diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 296b62859..86220d237 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -1676,6 +1676,12 @@ int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl ); */ int mbedtls_ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl ); +/* + * Write of dummy-CCS's for middlebox compatibility + */ +int mbedtls_ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + + /* * Write TLS 1.3 handshake message tail */ diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 1874d4fde..80cb4bf7b 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -723,8 +723,18 @@ static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, * ( also known as ossification ). Otherwise, it MUST be set as a zero-length * vector ( i.e., a zero-valued single byte length field ). */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ssl->session_negotiate->id_len + 1 ); + *p++ = (unsigned char)ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); +#else MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); *p++ = 0; /* session id length set to zero */ +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ /* Write cipher_suites */ ret = ssl_tls13_write_client_hello_cipher_suites( ssl, p, end, &output_len ); @@ -843,6 +853,24 @@ static int ssl_tls13_prepare_client_hello( mbedtls_ssl_context *ssl ) return( ret ); } +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* + * Create a session identifier for the purpose of middlebox compatibility + * only if one has not been created already. + */ + if( ssl->session_negotiate->id_len == 0 ) + { + /* Creating a session id with 32 byte length */ + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "creating session id failed", ret ); + return( ret ); + } + ssl->session_negotiate->id_len = 32; + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + return( 0 ); } @@ -1611,8 +1639,14 @@ static int ssl_tls13_process_server_finished( mbedtls_ssl_context *ssl ) if( ret != 0 ) return( ret ); - mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_handshake ); +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED ); +#else mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED ); +#endif + return( 0 ); } @@ -1623,6 +1657,8 @@ static int ssl_tls13_write_client_finished( mbedtls_ssl_context *ssl ) { int ret; + mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_handshake ); + ret = mbedtls_ssl_tls13_write_finished_message( ssl ); if( ret != 0 ) return( ret ); @@ -1713,6 +1749,15 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ) ret = ssl_tls13_handshake_wrapup( ssl ); break; + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + ret = mbedtls_ssl_tls13_write_change_cipher_spec( ssl ); + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + default: MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 066147a5e..228303ee8 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -1148,6 +1148,76 @@ void mbedtls_ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); } +/* + * + * STATE HANDLING: Write ChangeCipherSpec + * + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + +static int ssl_tls13_write_change_cipher_spec_body( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 1 ); + buf[0] = 1; + *olen = 1; + + return( 0 ); +} + +static int ssl_tls13_finalize_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + +int mbedtls_ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_flush_output( ssl ) ); + + /* Write CCS message */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_change_cipher_spec_body( + ssl, ssl->out_msg, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &ssl->out_msglen ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_change_cipher_spec( ssl ) ); + + /* Dispatch message */ + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_write_record( ssl, 1 ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_SSL_TLS_C */