diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 04f67ce939de9..5d6a0f1a72793 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -1407,6 +1407,7 @@ struct ssl_st { #ifndef OPENSSL_NO_QUIC OSSL_ENCRYPTION_LEVEL quic_read_level; OSSL_ENCRYPTION_LEVEL quic_write_level; + OSSL_ENCRYPTION_LEVEL quic_latest_level_received; BUF_MEM *quic_buf; /* buffer incoming handshake messages */ QUIC_DATA *quic_input_data_head; QUIC_DATA *quic_input_data_tail; diff --git a/ssl/ssl_quic.c b/ssl/ssl_quic.c index 2427342633a76..7e0495fd54a2a 100644 --- a/ssl/ssl_quic.c +++ b/ssl/ssl_quic.c @@ -100,7 +100,8 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, /* Level can be different than the current read, but not less */ if (level < ssl->quic_read_level - || (ssl->quic_input_data_tail != NULL && level < ssl->quic_input_data_tail->level)) { + || (ssl->quic_input_data_tail != NULL && level < ssl->quic_input_data_tail->level) + || level < ssl->quic_latest_level_received) { SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); return 0; } @@ -122,6 +123,15 @@ int SSL_provide_quic_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL level, buf = NULL; } + /* A TLS message must not cross an encryption level boundary */ + if (ssl->quic_buf->length != ssl->quic_next_record_start + && level != ssl->quic_latest_level_received) { + SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, + SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); + return 0; + } + ssl->quic_latest_level_received = level; + offset = ssl->quic_buf->length; if (!BUF_MEM_grow(ssl->quic_buf, offset + len)) { SSLerr(SSL_F_SSL_PROVIDE_QUIC_DATA, SSL_R_INTERNAL_ERROR);