From f03b7de1a2200996e6b8c908602316c9e3d5a72c Mon Sep 17 00:00:00 2001 From: lhuang04 Date: Thu, 4 Feb 2021 06:33:49 -0800 Subject: [PATCH] Integration for QUIC Summary: * Main goal * + Integrate QUIC with TLS1.3 state machine + Integrate QUIC with TLS1.3 implementation. + Unify code path for TCP TLS1.3 and QUIC so that both can be used in one binary. * What is not in the QUIC * + QUIC doesn't support change of cipher suite + QUIC doesn't support legacy session id + QUIC doesn't have end of early data * What is new in the QUIC * + transport parameters Test Plan: ssl-opt.sh Reviewers: Subscribers: Tasks: Tags: --- include/mbedtls/debug.h | 8 + include/mbedtls/ssl.h | 66 ++++- include/mbedtls/ssl_internal.h | 8 + library/ssl_msg.c | 87 ++++++- library/ssl_tls.c | 21 ++ library/ssl_tls13_client.c | 454 +++++++++++++++++++++++++++------ library/ssl_tls13_generic.c | 112 +++++++- 7 files changed, 672 insertions(+), 84 deletions(-) diff --git a/include/mbedtls/debug.h b/include/mbedtls/debug.h index ab5b0370342c..cc8987b5a894 100644 --- a/include/mbedtls/debug.h +++ b/include/mbedtls/debug.h @@ -34,6 +34,11 @@ #include "mbedtls/ecp.h" #endif +#if defined(MBEDTLS_DEBUG_C) +#include +#endif + +#define MBEDTLS_SSL_DEBUG_QUIC_HS_MSG( level, text, hs_msg ) do { } while ( 0 ) #if defined(MBEDTLS_DEBUG_C) #define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ @@ -68,6 +73,8 @@ mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) #endif +#define MBEDTLS_ASSERT(cond) assert(cond) + #else /* MBEDTLS_DEBUG_C */ #define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) @@ -77,6 +84,7 @@ #define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) +#define MBEDTLS_ASSERT(cond) do { } while( 0 ) #endif /* MBEDTLS_DEBUG_C */ diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 35d5b7c4a287..53afc2bd9849 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -75,6 +75,10 @@ #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) +#include "quic.h" +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + /* * SSL Error codes */ @@ -217,6 +221,7 @@ #define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ +#define MBEDTLS_SSL_TRANSPORT_QUIC 2 /*!< QUIC */ #define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ #define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ @@ -566,6 +571,10 @@ #define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 +#define MBEDTLS_TLS_EXT_QUIC_TRANSPORT_PARAMS 0xFFA5 + +#define MBEDTLS_QUIC_TRANSPORT_PARAMS_MAX_LEN 65535 + /* * Size defines */ @@ -855,6 +864,28 @@ typedef enum #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL && MBEDTLS_SSL_NEW_SESSION_TICKET */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) +/** + * \brief set the QUIC transport params buffer for this endpoint. + * + * \param ssl SSL context. + * \param params the QUIC transport params buffer. + * \param len length of the the QUIC transport params buffer. + */ +int mbedtls_ssl_set_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t *params, size_t len); + +/** + * \brief get the quic transport params for the peer endpoint. + * + * \param ssl SSL context. + */ +void mbedtls_ssl_get_peer_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t **params, size_t *len); + +int mbedtls_ssl_quic_post_handshake(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if defined(MBEDTLS_SSL_EXPORT_KEYS) && \ defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) typedef enum @@ -1497,7 +1528,7 @@ struct mbedtls_ssl_config */ unsigned int endpoint : 1; /*!< 0: client, 1: server */ - unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int transport : 2; /*!< 0: TLS, 1: DTLS, 2: QUIC */ unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ @@ -1827,6 +1858,39 @@ struct mbedtls_ssl_context int early_data_status; #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL && MBEDTLS_ZERO_RTT && MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + /* + * QUIC method callbacks and the callback context pointer. + */ + mbedtls_quic_method *quic_method; + + /* + * Context parameter for the QUIC method callbacks. + */ + void *p_quic_method; + + /* + * QUIC outgoing and incoming crypto levels. + */ + mbedtls_ssl_crypto_level quic_hs_crypto_level; + + /* + * The QUIC input data queue. + */ + mbedtls_quic_input quic_input; + + /* + * QUIC transport parameters. + */ + uint8_t *quic_transport_params; + size_t quic_transport_params_len; + + /* + * QUIC peer transport parameters. + */ + uint8_t *peer_quic_transport_params; + size_t peer_quic_transport_params_len; +#endif /* MBEDTLS_SSL_PROTO_QUIC */ }; #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index fb0f99e43d64..b9f1cf9aaaac 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -1892,4 +1892,12 @@ int mbedtls_ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ); void mbedtls_ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_QUIC) +int mbedtls_set_quic_traffic_key(mbedtls_ssl_context *ssl, mbedtls_ssl_crypto_level level); +/* Shared implementation for the QUIC transport params setting */ +int ssl_set_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t *params, size_t len, + uint8_t **oparams, size_t *olen); +#endif #endif /* ssl_internal.h */ diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 44e4bd87655a..4a9b76f39aed 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -2283,6 +2283,12 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) */ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + // In QUIC mode, we do not employ byte-granular I/O. Therefore, + // there is no leftover output to flush. + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + return 0; +#endif /* MBEDTLS_SSL_PROTO_QUIC */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; @@ -2886,6 +2892,22 @@ int mbedtls_ssl_write_handshake_msg_ext( mbedtls_ssl_context *ssl, */ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + MBEDTLS_SSL_DEBUG_MSG(5, ("=> write record (quic)")); + + ssl->quic_method->add_handshake_data( + ssl->p_quic_method, + ssl->quic_hs_crypto_level, + ssl->out_msg, + ssl->out_msglen); + + MBEDTLS_SSL_DEBUG_MSG(5, ("<= write record (quic)")); + + return(0); + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ int ret, done = 0; size_t len = ssl->out_msglen; uint8_t flush = force_flush; @@ -4139,6 +4161,47 @@ static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, unsigned update_hs_digest ) { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + if( ssl->keep_current_message == 0 ) + { + /* Check for sufficient space in the `ssl->in_buf` buffer. + * We can use the entire span of the allocated memory past the `ssl->in_msg`: + * + * *- ssl->in_msg + * / + * v + * ssl->in_buf = [ | ... ] + * | MBEDTLS_SSL_IN_BUFFER_LEN | + */ + size_t available = MBEDTLS_SSL_IN_BUFFER_LEN - + (size_t)( ssl->in_msg - ssl->in_buf ); + + size_t len = mbedtls_quic_input_read( + ssl, ssl->quic_hs_crypto_level, ssl->in_msg, available); + + if ( len == 0 ) + { + return (MBEDTLS_ERR_SSL_INTERNAL_ERROR); + } + + // Successfully read the message, store the length. + ssl->in_msglen = len; + + // Mark the message type as handshake + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + + return mbedtls_ssl_prepare_handshake_record( ssl ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + return 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); @@ -5211,15 +5274,27 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, #else /* MBEDTLS_SSL_USE_MPS */ - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = level; - ssl->out_msg[1] = message; - - if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) { + if ( ( ret = ssl->quic_method->send_alert(ssl->p_quic_method, ssl->quic_hs_crypto_level, message ) ) != 0 ) + { + return ret; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); + } } #endif /* MBEDTLS_SSL_USE_MPS */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 41b06a21fcc9..8fc47b9df9da 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4449,6 +4449,18 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + mbedtls_quic_input_init(ssl, &ssl->quic_input); + if ((ret = mbedtls_quic_input_setup(ssl, &ssl->quic_input)) != 0) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_quic_input_setup", ret ); + return ret; + } + ssl->quic_hs_crypto_level = MBEDTLS_SSL_CRYPTO_LEVEL_INITIAL; + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ ssl->out_ctr = ssl->out_buf; ssl->out_hdr = ssl->out_buf + 8; ssl->out_len = ssl->out_buf + 11; @@ -7589,6 +7601,15 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) mbedtls_free( ssl->cli_id ); #endif +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf != NULL && ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + mbedtls_quic_input_free(ssl, &ssl->quic_input); + mbedtls_free(ssl->quic_transport_params); + mbedtls_free(ssl->peer_quic_transport_params); + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); /* Actually clear after last debug message */ diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 4fb0cb4b9826..bdebe93461f0 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -37,6 +37,7 @@ #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" #include "ssl_tls13_keys.h" #include @@ -161,18 +162,23 @@ int ssl_write_early_data_process( mbedtls_ssl_context* ssl ) #else /* MBEDTLS_SSL_USE_MPS */ - /* Make sure we can write a new message. */ - MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_flush_output( ssl ) ); +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + /* Make sure we can write a new message. */ + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_flush_output( ssl ) ); - /* Write early-data to message buffer. */ - MBEDTLS_SSL_PROC_CHK( ssl_write_early_data_write( ssl, ssl->out_msg, - MBEDTLS_SSL_MAX_CONTENT_LEN, - &ssl->out_msglen ) ); + /* Write early-data to message buffer. */ + MBEDTLS_SSL_PROC_CHK( ssl_write_early_data_write( ssl, ssl->out_msg, + MBEDTLS_SSL_MAX_CONTENT_LEN, + &ssl->out_msglen ) ); - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - /* Dispatch message */ - MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ); + /* Dispatch message */ + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ); + } #endif /* MBEDTLS_SSL_USE_MPS */ @@ -246,6 +252,11 @@ static int ssl_write_early_data_prepare( mbedtls_ssl_context* ssl ) #else /* MBEDTLS_SSL_USE_MPS */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + mbedtls_set_quic_traffic_key(ssl, MBEDTLS_SSL_CRYPTO_LEVEL_EARLY_DATA); +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + ret = mbedtls_ssl_tls13_build_transform( ssl, &traffic_keys, ssl->transform_earlydata, 0 ); if( ret != 0 ) { @@ -396,6 +407,11 @@ static int ssl_write_end_of_early_data_coordinate( mbedtls_ssl_context* ssl ) { ((void) ssl); +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + return( SSL_END_OF_EARLY_DATA_SKIP ); +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if defined(MBEDTLS_ZERO_RTT) if( ssl->handshake->early_data == MBEDTLS_SSL_EARLY_DATA_ON ) return( SSL_END_OF_EARLY_DATA_WRITE ); @@ -406,6 +422,14 @@ static int ssl_write_end_of_early_data_coordinate( mbedtls_ssl_context* ssl ) static int ssl_write_end_of_early_data_postprocess( mbedtls_ssl_context* ssl ) { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE ); + return ( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) #if defined(MBEDTLS_ZERO_RTT) if( ssl->handshake->early_data != MBEDTLS_SSL_EARLY_DATA_ON ) @@ -420,6 +444,56 @@ static int ssl_write_end_of_early_data_postprocess( mbedtls_ssl_context* ssl ) return ( 0 ); } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + +/* QUIC transport parameters extensions. [draft-ietf-quic-tls 8.2] + * + * QUIC transport parameters are carried in a TLS extension. Different + * versions of QUIC might define a different method for negotiating + * transport configuration. + * + * Including transport parameters in the TLS handshake provides + * integrity protection for these values. + * + * QUIC transport parameters MUST be included in the ClientHello message. + * + * enum { + * quic_transport_parameters(0xffa5), (65535) + * } ExtensionType; + * + */ +static void ssl_write_quic_transport_parameters_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char* end, + size_t *olen) +{ + unsigned char *p = buf; + const uint8_t *tp = ssl->quic_transport_params; + size_t tp_len = ssl->quic_transport_params_len; + // Extension wire size - ext_header[2] + ext_length[2] + tp_len + size_t ext_len = sizeof(uint16_t) + sizeof(uint16_t) + tp_len; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding quic_transport_parameters extension: %p %u", + tp, tp_len)); + + if ((end - p) < (ptrdiff_t)ext_len) + { + MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); + return; + } + + *p++ = (unsigned char)((MBEDTLS_TLS_EXT_QUIC_TRANSPORT_PARAMS >> 8) & 0xFF); + *p++ = (unsigned char)((MBEDTLS_TLS_EXT_QUIC_TRANSPORT_PARAMS) & 0xFF); + + *p++ = (unsigned char)((tp_len >> 8) & 0xFF); + *p++ = (unsigned char)(tp_len & 0xFF); + + memcpy(p, tp, tp_len); + *olen = ext_len; +} +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, @@ -1499,19 +1573,24 @@ static int ssl_client_hello_prepare( mbedtls_ssl_context* ssl ) } #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) - /* Determine whether session id has not been created already */ - if( ssl->session_negotiate->id_len == 0 ) +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ { + /* Determine whether session id 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 ); + MBEDTLS_SSL_DEBUG_RET( 1, "creating session id failed", ret ); + return( ret ); } - } + } - ssl->session_negotiate->id_len = 32; + ssl->session_negotiate->id_len = 32; + } #endif /* MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE */ return( 0 ); @@ -1660,21 +1739,39 @@ static int ssl_client_hello_write_partial( mbedtls_ssl_context* ssl, * ( i.e., a zero-valued single byte length field ). */ #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) - if( buflen < ( ssl->session_negotiate->id_len + 1 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + if( buflen < ( ssl->session_negotiate->id_len + 1 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + *buf++ = (unsigned char)ssl->session_negotiate->id_len; /* write session id length */ + memcpy( buf, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); /* write session id */ - *buf++ = (unsigned char)ssl->session_negotiate->id_len; /* write session id length */ - memcpy( buf, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); /* write session id */ + buf += ssl->session_negotiate->id_len; + buflen -= ssl->session_negotiate->id_len; - buf += ssl->session_negotiate->id_len; - buflen -= ssl->session_negotiate->id_len; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id len.: %d", ssl->session_negotiate->id_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + else + { + if( buflen < 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id len.: %d", ssl->session_negotiate->id_len ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + *buf++ = 0; /* session id length set to zero */ + buflen -= 1; + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #else #if defined(MBEDTLS_SSL_TLS13_CTLS) /* For cTLS we are not using a session id */ @@ -1850,6 +1947,15 @@ static int ssl_client_hello_write_partial( mbedtls_ssl_context* ssl, buf += cur_ext_len; #endif +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + ssl_write_quic_transport_parameters_ext( ssl, buf, end, &cur_ext_len ); + total_ext_len += cur_ext_len; + buf += cur_ext_len; + } +#endif + #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /* For PSK-based ciphersuites we need the pre-shared-key extension * and the psk_key_exchange_modes extension. @@ -2103,6 +2209,40 @@ int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_ZERO_RTT */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + +/* QUIC transport parameters extensions. [draft-ietf-quic-tls 8.2] + * + * QUIC transport parameters are carried in a TLS extension. Different + * versions of QUIC might define a different method for negotiating + * transport configuration. + * + * Including transport parameters in the TLS handshake provides + * integrity protection for these values. + * + * QUIC transport parameters MUST be included in the ServerHello handshake message. + * + * enum { + * quic_transport_parameters(0xffa5), (65535) + * } ExtensionType; + * + */ +static int ssl_parse_quic_transport_parameters_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + // We are not expecting peer transport params to be communicated + // more than once. + if (ssl->peer_quic_transport_params != NULL) + { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + return ssl_set_quic_transport_params(ssl, buf, len, + &ssl->peer_quic_transport_params, &ssl->peer_quic_transport_params_len); +} + +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if ( defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ) /* TODO: Code for MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED missing */ @@ -2875,6 +3015,18 @@ static int ssl_encrypted_extensions_parse( mbedtls_ssl_context* ssl, break; #endif /* MBEDTLS_ZERO_RTT */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + case MBEDTLS_TLS_EXT_QUIC_TRANSPORT_PARAMS: + MBEDTLS_SSL_DEBUG_MSG(3, ("found quic_transport_parameters extension")); + + if ((ret = ssl_parse_quic_transport_parameters_ext(ssl, ext + 4, (size_t)ext_size)) != 0) + { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_parse_quic_transport_parameters_ext", ret); + return(ret); + } + break; +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + default: MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d ( ignoring )", ext_id ) ); } @@ -3265,28 +3417,48 @@ static int ssl_server_hello_parse( mbedtls_ssl_context* ssl, #endif /* MBEDTLS_SSL_TLS13_CTLS */ { #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) - /* legacy_session_id_echo */ - if( ssl->session_negotiate->id_len != buf[0] ) +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id length" ) ); - SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - buf++; /* skip session id length */ + /* legacy_session_id_echo */ + if( ssl->session_negotiate->id_len != buf[0] ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id length" ) ); + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + buf++; /* skip session id length */ - if( memcmp( ssl->session_negotiate->id, &buf[0], ssl->session_negotiate->id_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id" ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "- expected session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "- received session id", &buf[0], ssl->session_negotiate->id_len ); + if( memcmp( ssl->session_negotiate->id, &buf[0], ssl->session_negotiate->id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "- expected session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "- received session id", &buf[0], ssl->session_negotiate->id_len ); - SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - buf += ssl->session_negotiate->id_len; /* skip session id */ + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + buf += ssl->session_negotiate->id_len; /* skip session id */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id length ( %d )", ssl->session_negotiate->id_len ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id length ( %d )", ssl->session_negotiate->id_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + else + { + /* Length of the session id must be zero */ + if( *buf == 0 ) + { + buf++; /* skip session id length */ + } + else + { + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #else /* Length of the session id must be zero */ if( *buf == 0 ) @@ -3536,6 +3708,13 @@ static int ssl_server_hello_postprocess( mbedtls_ssl_context* ssl ) return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + { + mbedtls_set_quic_traffic_key(ssl, MBEDTLS_SSL_CRYPTO_LEVEL_HANDSHAKE); + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + ret = mbedtls_ssl_tls13_build_transform( ssl, &traffic_keys, ssl->transform_handshake, 0 ); if( ret != 0 ) { @@ -3722,28 +3901,48 @@ static int ssl_hrr_parse( mbedtls_ssl_context* ssl, #endif /* MBEDTLS_SSL_TLS13_CTLS */ { #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) - /* legacy_session_id_echo */ - if( ssl->session_negotiate->id_len != buf[0] ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id length" ) ); - SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_HELLO_RETRY_REQUEST ); - } - buf++; /* skip session id length */ - - if( memcmp( ssl->session_negotiate->id, &buf[0], ssl->session_negotiate->id_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id" ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "- expected session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "- received session id", &buf[0], ssl->session_negotiate->id_len ); - - SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_HELLO_RETRY_REQUEST ); - } - buf += ssl->session_negotiate->id_len; /* skip session id */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id length ( %d )", ssl->session_negotiate->id_len ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + /* legacy_session_id_echo */ + if( ssl->session_negotiate->id_len != buf[0] ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id length" ) ); + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_HELLO_RETRY_REQUEST ); + } + buf++; /* skip session id length */ + + if( memcmp( ssl->session_negotiate->id, &buf[0], ssl->session_negotiate->id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Mismatch of session id" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "- expected session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "- received session id", &buf[0], ssl->session_negotiate->id_len ); + + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_HELLO_RETRY_REQUEST ); + } + buf += ssl->session_negotiate->id_len; /* skip session id */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session id length ( %d )", ssl->session_negotiate->id_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + } +#if defined(MBEDTLS_SSL_PROTO_QUIC) + else + { + /* Length of the session id must be zero */ + if( *buf == 0 ) + { + buf++; /* skip session id length */ + } + else + { + SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_HELLO_RETRY_REQUEST ); + } + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #else /* Length of the session id must be zero */ if( *buf == 0 ) @@ -4130,6 +4329,25 @@ static void mbedtls_patch_pointers( mbedtls_ssl_context* ssl ) /* * TLS and DTLS 1.3 State Maschine -- client side */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) +static int ssl_handshake_state_requires_input(int state) +{ + switch (state) + { + case MBEDTLS_SSL_SERVER_HELLO: + case MBEDTLS_SSL_SECOND_SERVER_HELLO: + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + case MBEDTLS_SSL_SERVER_CERTIFICATE: + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + case MBEDTLS_SSL_SERVER_FINISHED: + return 1; + default: + return 0; + } +} +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) { int ret = 0; @@ -4143,6 +4361,27 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) return( ret ); +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if ((ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + && ssl_handshake_state_requires_input(ssl->state)) + { + uint8_t msg_type = 0; // Sentinel value for debugging. + size_t msg_size = 0; + size_t available_len = 0; + if ((ret = mbedtls_quic_input_peek(ssl, ssl->quic_hs_crypto_level, + &msg_type, &msg_size, &available_len)) != 0) + { + // We are not ready to consume a message. + // The `ret` is either "MBEDTLS_ERR_SSL_WANT_READ", in which + // case more data is required, or some other error code + // that should be surfaced to the callsite. + MBEDTLS_SSL_DEBUG_MSG(1, + ("mbedtls_quic_input_peek: ret: %d type: %hhu size: %u len: %u", + ret, msg_type, msg_size, available_len)); + return ret; + } + } +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && @@ -4161,9 +4400,14 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) ssl->handshake->hello_retry_requests_received = 0; #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) - /* Reset session id */ - memset( ssl->session_negotiate->id, 0, 32 ); - ssl->session_negotiate->id_len = 0; +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + /* Reset session id */ + memset( ssl->session_negotiate->id, 0, 32 ); + ssl->session_negotiate->id_len = 0; + } #endif /* MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE */ #if defined(MBEDTLS_ECP_C) @@ -4305,16 +4549,21 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) mbedtls_ack_add_record( ssl, MBEDTLS_SSL_HS_HELLO_RETRY_REQUEST, MBEDTLS_SSL_ACK_RECORDS_RECEIVED ); #endif /* MBEDTLS_SSL_PROTO_DTLS */ + int state = MBEDTLS_SSL_SECOND_CLIENT_HELLO; #if defined(MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE) /* If not offering early data, the client sends a dummy * change_cipher_spec record immediately before its * second flight. This may either be before its second * ClientHello or before its encrypted handshake flight. */ - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO ); -#else - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SECOND_CLIENT_HELLO ); +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_QUIC) +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + { + state = MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO; + } #endif /* MBEDTLS_SSL_TLS13_COMPATIBILITY_MODE */ + mbedtls_ssl_handshake_set_state( ssl, state ); } else { @@ -4595,6 +4844,67 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) mbedtls_ssl_handle_pending_alert( ssl ); return( ret ); } + +#if defined(MBEDTLS_SSL_PROTO_QUIC) + +int mbedtls_ssl_quic_post_handshake(mbedtls_ssl_context *ssl) +{ + MBEDTLS_ASSERT( + ssl->quic_hs_crypto_level == MBEDTLS_SSL_CRYPTO_LEVEL_APPLICATION); + + uint8_t msg_type; + size_t msg_size = 0; + size_t available_len = 0; + int ret = 0; + + if ((ret = mbedtls_quic_input_peek(ssl, ssl->quic_hs_crypto_level, + &msg_type, &msg_size, &available_len)) != 0) + { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_quic_input_peek", ret); + return(ret); + } + + if (available_len != msg_size) + { + return MBEDTLS_ERR_SSL_WANT_READ; + } + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + return(ret); + } + + if (ssl->in_msg[0] == MBEDTLS_SSL_HS_NEW_SESSION_TICKET) + { + MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received")); + + if ((ret = mbedtls_ssl_new_session_ticket_process(ssl)) != 0) + { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_parse_new_session_ticket", ret); + return(ret); + } + mbedtls_ssl_ticket* ticket = mbedtls_calloc(1, sizeof(mbedtls_ssl_ticket)); + if (ticket == NULL) + { + return (MBEDTLS_ERR_SSL_ALLOC_FAILED); + } + if ((mbedtls_ssl_get_client_ticket(ssl, ticket) != 0)) + { + mbedtls_free(ticket->ticket); + mbedtls_free(ticket); + return (MBEDTLS_ERR_SSL_INTERNAL_ERROR); + } + // the ticket will be transfered to and be released by the app + ssl->quic_method->process_new_session( + ssl->p_quic_method, + ticket); + return (ret); + } + + return 0; +} +#endif /* MBEDTLS_SSL_PROTO_QUIC */ #endif /* MBEDTLS_SSL_CLI_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 8de3aa7826f5..e2de2ffc5b35 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -798,6 +798,11 @@ static int ssl_write_change_cipher_spec_coordinate( mbedtls_ssl_context* ssl ) { int ret = SSL_WRITE_CCS_NEEDED; +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + return( SSL_WRITE_CCS_SKIP ); +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if defined(MBEDTLS_SSL_SRV_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) { @@ -3759,6 +3764,10 @@ int mbedtls_ssl_tls13_build_transform( mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, int remove_old_keys ) { +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + return 0; +#endif /* MBEDTLS_SSL_PROTO_QUIC */ int ret; mbedtls_cipher_info_t const *cipher_info; const mbedtls_ssl_ciphersuite_t *suite_info; @@ -3888,6 +3897,49 @@ int mbedtls_ssl_tls13_build_transform( mbedtls_ssl_context *ssl, return ( 0 ); } +#if defined(MBEDTLS_SSL_PROTO_QUIC) +/** + * Install the secrets into the QUIC transport. + */ +int mbedtls_set_quic_traffic_key(mbedtls_ssl_context *ssl, mbedtls_ssl_crypto_level level) +{ + uint8_t *read_secret = NULL; + uint8_t *write_secret = NULL; + + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; + + size_t secret_len = mbedtls_hash_size_for_ciphersuite(ciphersuite_info); + + switch (level) + { + case MBEDTLS_SSL_CRYPTO_LEVEL_HANDSHAKE: + ssl->quic_hs_crypto_level = level; + read_secret = ssl->handshake->server_handshake_traffic_secret; + write_secret = ssl->handshake->client_handshake_traffic_secret; + break; + case MBEDTLS_SSL_CRYPTO_LEVEL_EARLY_DATA: + read_secret = NULL; + write_secret = ssl->handshake->client_early_traffic_secret; + break; + case MBEDTLS_SSL_CRYPTO_LEVEL_APPLICATION: + ssl->quic_hs_crypto_level = level; + read_secret = ssl->handshake->server_traffic_secret; + write_secret = ssl->handshake->client_traffic_secret; + break; + default: + break; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("setting QUIC secrets, level = %d", level)); + return ssl->quic_method->set_encryption_secrets( + ssl->p_quic_method, + level, + read_secret, + write_secret, + secret_len); +} +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #if defined(MBEDTLS_ZERO_RTT) /* Early Data Key Derivation for TLS 1.3 */ int mbedtls_ssl_generate_early_data_keys( mbedtls_ssl_context *ssl, @@ -4333,6 +4385,11 @@ static int ssl_finished_out_postprocess( mbedtls_ssl_context* ssl ) ssl->out_epoch = 3; #endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_QUIC) + mbedtls_set_quic_traffic_key(ssl, MBEDTLS_SSL_CRYPTO_LEVEL_APPLICATION); +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_FINISH_ACK ); else @@ -4750,16 +4807,16 @@ static int ssl_finished_in_postprocess_cli( mbedtls_ssl_context *ssl ) if( ret != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_generate_application_traffic_keys", ret ); - return( ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_generate_application_traffic_keys", ret ); + return( ret ); } ret = mbedtls_ssl_tls13_build_transform( ssl, &traffic_keys, - ssl->transform_application, 0 ); + ssl->transform_application, 0 ); if( ret != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_build_transform", ret ); - return( ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_build_transform", ret ); + return( ret ); } #if defined(MBEDTLS_SSL_USE_MPS) @@ -5468,6 +5525,51 @@ int mbedtls_ssl_write_early_data_ext( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_ZERO_RTT */ +#if defined(MBEDTLS_SSL_PROTO_QUIC) + +/* declared in ssl_internal.h */ +int ssl_set_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t *params, size_t len, + uint8_t **oparams, size_t *olen) +{ + if (len > MBEDTLS_QUIC_TRANSPORT_PARAMS_MAX_LEN) + { + MBEDTLS_SSL_DEBUG_MSG(1, ("ssl_set_quic_transport_params: bad transport_params length")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if ((*oparams = mbedtls_calloc(1, len)) == NULL) + { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(*oparams, params, len); + *olen = len; + + return 0; +} + +int mbedtls_ssl_set_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t *params, size_t len) +{ + // Setting transport params more than once is not expected, but + // permitted. + mbedtls_free(ssl->quic_transport_params); + ssl->quic_transport_params = NULL; + + return ssl_set_quic_transport_params(ssl, params, len, + &ssl->quic_transport_params, &ssl->quic_transport_params_len); +} + +void mbedtls_ssl_get_peer_quic_transport_params(mbedtls_ssl_context *ssl, + const uint8_t **oparams, size_t *olen) +{ + *oparams = (const uint8_t*)(ssl->peer_quic_transport_params); + *olen = ssl->peer_quic_transport_params_len; +} + +#endif /* MBEDTLS_SSL_PROTO_QUIC */ + #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_SSL_TLS_C */