diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc index 2fa0183c..5fc93cbd 100644 --- a/ssl/d1_both.cc +++ b/ssl/d1_both.cc @@ -425,7 +425,7 @@ int dtls1_get_message(SSL *ssl) { assert(ssl->init_msg != NULL); ssl->s3->tmp.reuse_message = 0; } else { - dtls1_release_current_message(ssl, 0 /* don't free buffer */); + dtls1_release_current_message(ssl); } /* Process handshake records until the current message is ready. */ @@ -463,7 +463,7 @@ void dtls1_get_current_message(const SSL *ssl, CBS *out) { CBS_init(out, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len); } -void dtls1_release_current_message(SSL *ssl, int free_buffer) { +void dtls1_release_current_message(SSL *ssl) { if (ssl->init_msg == NULL) { return; } diff --git a/ssl/dtls_method.cc b/ssl/dtls_method.cc index 947cfceb..1508b990 100644 --- a/ssl/dtls_method.cc +++ b/ssl/dtls_method.cc @@ -73,6 +73,7 @@ static int dtls1_supports_cipher(const SSL_CIPHER *cipher) { } static void dtls1_on_handshake_complete(SSL *ssl) { + dtls1_release_current_message(ssl); /* If we wrote the last flight, we'll have a timer left over without waiting * for a read. Stop the timer but leave the flight around for post-handshake * transmission logic. */ diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc index 946316db..385f7260 100644 --- a/ssl/handshake_client.cc +++ b/ssl/handshake_client.cc @@ -492,7 +492,6 @@ int ssl3_connect(SSL_HANDSHAKE *hs) { case SSL3_ST_FINISH_CLIENT_HANDSHAKE: ssl->method->on_handshake_complete(ssl); - ssl->method->release_current_message(ssl, 1 /* free_buffer */); SSL_SESSION_free(ssl->s3->established_session); if (ssl->session != NULL) { diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc index 47fdc61c..907943fd 100644 --- a/ssl/handshake_server.cc +++ b/ssl/handshake_server.cc @@ -418,7 +418,6 @@ int ssl3_accept(SSL_HANDSHAKE *hs) { case SSL_ST_OK: ssl->method->on_handshake_complete(ssl); - ssl->method->release_current_message(ssl, 1 /* free_buffer */); /* If we aren't retaining peer certificates then we can discard it * now. */ diff --git a/ssl/internal.h b/ssl/internal.h index 2d3557cd..8e70ea79 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -2137,7 +2137,7 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs); int ssl3_send_alert(SSL *ssl, int level, int desc); int ssl3_get_message(SSL *ssl); void ssl3_get_current_message(const SSL *ssl, CBS *out); -void ssl3_release_current_message(SSL *ssl, int free_buffer); +void ssl3_release_current_message(SSL *ssl); int ssl3_send_finished(SSL_HANDSHAKE *hs); int ssl3_dispatch_alert(SSL *ssl); @@ -2216,7 +2216,7 @@ void dtls1_free(SSL *ssl); int dtls1_get_message(SSL *ssl); void dtls1_get_current_message(const SSL *ssl, CBS *out); -void dtls1_release_current_message(SSL *ssl, int free_buffer); +void dtls1_release_current_message(SSL *ssl); int dtls1_dispatch_alert(SSL *ssl); int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which); @@ -2362,9 +2362,9 @@ struct ssl_protocol_method_st { /* get_current_message sets |*out| to the current handshake message. This * includes the protocol-specific message header. */ void (*get_current_message)(const SSL *ssl, CBS *out); - /* release_current_message is called to release the current handshake message. - * If |free_buffer| is one, buffers will also be released. */ - void (*release_current_message)(SSL *ssl, int free_buffer); + /* release_current_message is called to release the current handshake + * message. */ + void (*release_current_message)(SSL *ssl); /* read_app_data reads up to |len| bytes of application data into |buf|. On * success, it returns the number of bytes read. Otherwise, it returns <= 0 * and sets |*out_got_handshake| to whether the failure was due to a diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc index 4d53d535..a96b910a 100644 --- a/ssl/s3_both.cc +++ b/ssl/s3_both.cc @@ -683,6 +683,14 @@ static int read_v2_client_hello(SSL *ssl) { } int ssl3_get_message(SSL *ssl) { + if (ssl->s3->tmp.reuse_message) { + /* There must be a current message. */ + assert(ssl->init_msg != NULL); + ssl->s3->tmp.reuse_message = 0; + } else { + ssl3_release_current_message(ssl); + } + /* Re-create the handshake buffer if needed. */ if (ssl->init_buf == NULL) { ssl->init_buf = BUF_MEM_new(); @@ -700,14 +708,6 @@ int ssl3_get_message(SSL *ssl) { ssl->s3->v2_hello_done = 1; } - if (ssl->s3->tmp.reuse_message) { - /* There must be a current message. */ - assert(ssl->init_msg != NULL); - ssl->s3->tmp.reuse_message = 0; - } else { - ssl3_release_current_message(ssl, 0 /* don't free buffer */); - } - /* Read the message header, if we haven't yet. */ int ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH); if (ret <= 0) { @@ -757,19 +757,23 @@ int ssl_hash_current_message(SSL_HANDSHAKE *hs) { return hs->transcript.Update(CBS_data(&cbs), CBS_len(&cbs)); } -void ssl3_release_current_message(SSL *ssl, int free_buffer) { - if (ssl->init_msg != NULL) { - /* |init_buf| never contains data beyond the current message. */ - assert(SSL3_HM_HEADER_LENGTH + ssl->init_num == ssl->init_buf->length); - - /* Clear the current message. */ - ssl->init_msg = NULL; - ssl->init_num = 0; - ssl->init_buf->length = 0; - ssl->s3->is_v2_hello = 0; +void ssl3_release_current_message(SSL *ssl) { + if (ssl->init_msg == NULL) { + return; } - if (free_buffer) { + /* |init_buf| never contains data beyond the current message. */ + assert(SSL3_HM_HEADER_LENGTH + ssl->init_num == ssl->init_buf->length); + + /* Clear the current message. */ + ssl->init_msg = NULL; + ssl->init_num = 0; + ssl->init_buf->length = 0; + ssl->s3->is_v2_hello = 0; + + /* Post-handshake messages are rare, so release the buffer after every + * message. During the handshake, |on_handshake_complete| will release it. */ + if (!SSL_in_init(ssl)) { BUF_MEM_free(ssl->init_buf); ssl->init_buf = NULL; } diff --git a/ssl/s3_pkt.cc b/ssl/s3_pkt.cc index 262df6df..a28cc2d5 100644 --- a/ssl/s3_pkt.cc +++ b/ssl/s3_pkt.cc @@ -377,7 +377,7 @@ int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len, assert(!ssl->s3->aead_read_ctx->is_null_cipher()); *out_got_handshake = 0; - ssl->method->release_current_message(ssl, 0 /* don't free buffer */); + ssl->method->release_current_message(ssl); SSL3_RECORD *rr = &ssl->s3->rrec; diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index 6611dd25..becf3ade 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc @@ -942,7 +942,7 @@ static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) { if (!ssl_do_post_handshake(ssl)) { return -1; } - ssl->method->release_current_message(ssl, 1 /* free buffer */); + ssl->method->release_current_message(ssl); } } diff --git a/ssl/tls_method.cc b/ssl/tls_method.cc index 02f5c076..89ff9ad9 100644 --- a/ssl/tls_method.cc +++ b/ssl/tls_method.cc @@ -69,7 +69,11 @@ namespace bssl { static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; } -static void ssl3_on_handshake_complete(SSL *ssl) {} +static void ssl3_on_handshake_complete(SSL *ssl) { + ssl3_release_current_message(ssl); + BUF_MEM_free(ssl->init_buf); + ssl->init_buf = NULL; +} static int ssl3_set_read_state(SSL *ssl, UniquePtr aead_ctx) { if (ssl->s3->rrec.length != 0) {