Make SSL3_BUFFER a proper C++ class. As with SSLTranscript before, we temporarily need some nastiness in SSL3_STATE, but this is in preparation of giving SSL3_STATE a constructor and destructor. Change-Id: Ifc0ce34fdcd8691d521d8ea03ff5e83dad43b4a3 Reviewed-on: https://boringssl-review.googlesource.com/21944 Reviewed-by: Steven Valdez <svaldez@google.com> Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/d1_pkt.cc b/ssl/d1_pkt.cc index c6be93d..d29a5c2 100644 --- a/ssl/d1_pkt.cc +++ b/ssl/d1_pkt.cc
@@ -187,8 +187,8 @@ return ssl_open_record_success; } -int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, - const uint8_t *buf, int len) { +int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in, + int len) { assert(!SSL_in_init(ssl)); *out_needs_handshake = false; @@ -211,7 +211,7 @@ return 0; } - int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf, (size_t)len, + int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, (size_t)len, dtls1_use_current_epoch); if (ret <= 0) { return ret; @@ -219,29 +219,29 @@ return len; } -int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len, +int dtls1_write_record(SSL *ssl, int type, const uint8_t *in, size_t len, enum dtls1_use_epoch_t use_epoch) { + SSLBuffer *buf = &ssl->s3->write_buffer; assert(len <= SSL3_RT_MAX_PLAIN_LENGTH); // There should never be a pending write buffer in DTLS. One can't write half // a datagram, so the write buffer is always dropped in // |ssl_write_buffer_flush|. - assert(!ssl_write_buffer_is_pending(ssl)); + assert(buf->empty()); if (len > SSL3_RT_MAX_PLAIN_LENGTH) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } - size_t max_out = len + SSL_max_seal_overhead(ssl); - uint8_t *out; size_t ciphertext_len; - if (!ssl_write_buffer_init(ssl, &out, max_out) || - !dtls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len, - use_epoch)) { - ssl_write_buffer_clear(ssl); + if (!buf->EnsureCap(ssl_seal_align_prefix_len(ssl), + len + SSL_max_seal_overhead(ssl)) || + !dtls_seal_record(ssl, buf->remaining().data(), &ciphertext_len, + buf->remaining().size(), type, in, len, use_epoch)) { + buf->Clear(); return -1; } - ssl_write_buffer_set_len(ssl, ciphertext_len); + buf->DidWrite(ciphertext_len); int ret = ssl_write_buffer_flush(ssl); if (ret <= 0) {
diff --git a/ssl/handshake.cc b/ssl/handshake.cc index 8531ca4..3cb9a9c 100644 --- a/ssl/handshake.cc +++ b/ssl/handshake.cc
@@ -505,10 +505,10 @@ ssl_open_record_t ret; if (hs->wait == ssl_hs_read_change_cipher_spec) { ret = ssl_open_change_cipher_spec(ssl, &consumed, &alert, - ssl_read_buffer(ssl)); + ssl->s3->read_buffer.span()); } else { - ret = - ssl_open_handshake(ssl, &consumed, &alert, ssl_read_buffer(ssl)); + ret = ssl_open_handshake(ssl, &consumed, &alert, + ssl->s3->read_buffer.span()); } if (ret == ssl_open_record_error && hs->wait == ssl_hs_read_server_hello) { @@ -533,7 +533,7 @@ if (retry) { continue; } - ssl_read_buffer_discard(ssl); + ssl->s3->read_buffer.DiscardConsumed(); break; }
diff --git a/ssl/internal.h b/ssl/internal.h index 174445a..e502ec0 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -1036,8 +1036,57 @@ // Transport buffers. -// ssl_read_buffer returns the current read buffer. -Span<uint8_t> ssl_read_buffer(SSL *ssl); +class SSLBuffer { + public: + SSLBuffer() {} + ~SSLBuffer() { Clear(); } + + SSLBuffer(const SSLBuffer &) = delete; + SSLBuffer &operator=(const SSLBuffer &) = delete; + + uint8_t *data() { return buf_ + offset_; } + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + size_t cap() const { return cap_; } + + Span<uint8_t> span() { return MakeSpan(data(), size()); } + + Span<uint8_t> remaining() { + return MakeSpan(data() + size(), cap() - size()); + } + + // Clear releases the buffer. + void Clear(); + + // EnsureCap ensures the buffer has capacity at least |new_cap|, aligned such + // that data written after |header_len| is aligned to a + // |SSL3_ALIGN_PAYLOAD|-byte boundary. It returns true on success and false + // on error. + bool EnsureCap(size_t header_len, size_t new_cap); + + // DidWrite extends the buffer by |len|. The caller must have filled in to + // this point. + void DidWrite(size_t len); + + // Consume consumes |len| bytes from the front of the buffer. The memory + // consumed will remain valid until the next call to |DiscardConsumed| or + // |Clear|. + void Consume(size_t len); + + // DiscardConsumed discards the consumed bytes from the buffer. If the buffer + // is now empty, it releases memory used by it. + void DiscardConsumed(); + + private: + // buf_ is the memory allocated for this buffer. + uint8_t *buf_ = nullptr; + // offset_ is the offset into |buf_| which the buffer contents start at. + uint16_t offset_ = 0; + // size_ is the size of the buffer contents from |buf_| + |offset_|. + uint16_t size_ = 0; + // cap_ is how much memory beyond |buf_| + |offset_| is available. + uint16_t cap_ = 0; +}; // ssl_read_buffer_extend_to extends the read buffer to the desired length. For // TLS, it reads to the end of the buffer until the buffer is |len| bytes @@ -1048,49 +1097,18 @@ // non-empty. int ssl_read_buffer_extend_to(SSL *ssl, size_t len); -// ssl_read_buffer_consume consumes |len| bytes from the read buffer. It -// advances the data pointer and decrements the length. The memory consumed will -// remain valid until the next call to |ssl_read_buffer_extend| or it is -// discarded with |ssl_read_buffer_discard|. -void ssl_read_buffer_consume(SSL *ssl, size_t len); - -// ssl_read_buffer_discard discards the consumed bytes from the read buffer. If -// the buffer is now empty, it releases memory used by it. -void ssl_read_buffer_discard(SSL *ssl); - -// ssl_read_buffer_clear releases all memory associated with the read buffer and -// zero-initializes it. -void ssl_read_buffer_clear(SSL *ssl); - -// ssl_handle_open_record handles the result of passing |ssl_read_buffer| to a -// record-processing function. If |ret| is a success or if the caller should -// retry, it returns one and sets |*out_retry|. Otherwise, it returns <= 0. +// ssl_handle_open_record handles the result of passing |ssl->s3->read_buffer| +// to a record-processing function. If |ret| is a success or if the caller +// should retry, it returns one and sets |*out_retry|. Otherwise, it returns <= +// 0. int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret, size_t consumed, uint8_t alert); -// ssl_write_buffer_is_pending returns one if the write buffer has pending data -// and zero if is empty. -int ssl_write_buffer_is_pending(const SSL *ssl); - -// ssl_write_buffer_init initializes the write buffer. On success, it sets -// |*out_ptr| to the start of the write buffer with space for up to |max_len| -// bytes. It returns one on success and zero on failure. Call -// |ssl_write_buffer_set_len| to complete initialization. -int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len); - -// ssl_write_buffer_set_len is called after |ssl_write_buffer_init| to complete -// initialization after |len| bytes are written to the buffer. -void ssl_write_buffer_set_len(SSL *ssl, size_t len); - // ssl_write_buffer_flush flushes the write buffer to the transport. It returns // one on success and <= 0 on error. For DTLS, whether or not the write // succeeds, the write buffer will be cleared. int ssl_write_buffer_flush(SSL *ssl); -// ssl_write_buffer_clear releases all memory associated with the write buffer -// and zero-initializes it. -void ssl_write_buffer_clear(SSL *ssl); - // Certificate functions. @@ -2134,17 +2152,6 @@ bool ed25519_enabled:1; }; -struct SSL3_BUFFER { - // buf is the memory allocated for this buffer. - uint8_t *buf; - // offset is the offset into |buf| which the buffer contents start at. - uint16_t offset; - // len is the length of the buffer contents from |buf| + |offset|. - uint16_t len; - // cap is how much memory beyond |buf| + |offset| is available. - uint16_t cap; -}; - // An ssl_shutdown_t describes the shutdown state of one end of the connection, // whether it is alive or has been shutdown via close_notify or fatal alert. enum ssl_shutdown_t { @@ -2161,9 +2168,9 @@ uint8_t client_random[SSL3_RANDOM_SIZE]; // read_buffer holds data from the transport to be processed. - SSL3_BUFFER read_buffer; + SSLBuffer read_buffer; // write_buffer holds data to be written to the transport. - SSL3_BUFFER write_buffer; + SSLBuffer write_buffer; // pending_app_data is the unconsumed application data. It points into // |read_buffer|.
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc index 1459085..8c41179 100644 --- a/ssl/s3_both.cc +++ b/ssl/s3_both.cc
@@ -246,7 +246,7 @@ // If there is pending data in the write buffer, it must be flushed out before // any new data in pending_flight. - if (ssl_write_buffer_is_pending(ssl)) { + if (!ssl->s3->write_buffer.empty()) { int ret = ssl_write_buffer_flush(ssl); if (ret <= 0) { ssl->rwstate = SSL_WRITING; @@ -303,7 +303,7 @@ return ssl_open_record_partial; } - CBS v2_client_hello = CBS(ssl_read_buffer(ssl).subspan(2, msg_length)); + CBS v2_client_hello = CBS(ssl->s3->read_buffer.span().subspan(2, msg_length)); // The V2ClientHello without the length is incorporated into the handshake // hash. This is only ever called at the start of the handshake, so hs is // guaranteed to be non-NULL.
diff --git a/ssl/s3_lib.cc b/ssl/s3_lib.cc index f3f99fa..d7af4f4 100644 --- a/ssl/s3_lib.cc +++ b/ssl/s3_lib.cc
@@ -178,6 +178,8 @@ return false; } OPENSSL_memset(s3, 0, sizeof *s3); + new (&s3->read_buffer) SSLBuffer(); + new (&s3->write_buffer) SSLBuffer(); s3->hs = ssl_handshake_new(ssl); if (s3->hs == NULL) { @@ -203,9 +205,8 @@ return; } - ssl_read_buffer_clear(ssl); - ssl_write_buffer_clear(ssl); - + ssl->s3->read_buffer.~SSLBuffer(); + ssl->s3->write_buffer.~SSLBuffer(); ERR_SAVE_STATE_free(ssl->s3->read_error); SSL_SESSION_free(ssl->s3->established_session); ssl_handshake_free(ssl->s3->hs);
diff --git a/ssl/s3_pkt.cc b/ssl/s3_pkt.cc index 7966e6f..ad4f82a 100644 --- a/ssl/s3_pkt.cc +++ b/ssl/s3_pkt.cc
@@ -124,9 +124,9 @@ namespace bssl { -static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len); +static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len); -int ssl3_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *buf, +int ssl3_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in, int len) { assert(ssl_can_write(ssl)); assert(!ssl->s3->aead_write_ctx->is_null_cipher()); @@ -180,7 +180,7 @@ nw = n; } - int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &buf[tot], nw); + int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &in[tot], nw); if (ret <= 0) { ssl->s3->wnum = tot; return ret; @@ -199,11 +199,11 @@ } } -static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf, +static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *in, unsigned int len) { if (ssl->s3->wpend_tot > (int)len || (!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) && - ssl->s3->wpend_buf != buf) || + ssl->s3->wpend_buf != in) || ssl->s3->wpend_type != type) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY); return -1; @@ -218,13 +218,14 @@ } // do_ssl3_write writes an SSL record of the given type. -static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) { +static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len) { // If there is still data from the previous record, flush it. if (ssl->s3->wpend_pending) { - return ssl3_write_pending(ssl, type, buf, len); + return ssl3_write_pending(ssl, type, in, len); } - if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + SSLBuffer *buf = &ssl->s3->write_buffer; + if (len > SSL3_RT_MAX_PLAIN_LENGTH || buf->size() > 0) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } @@ -246,9 +247,7 @@ } max_out += flight_len; - uint8_t *out; - size_t ciphertext_len; - if (!ssl_write_buffer_init(ssl, &out, max_out)) { + if (!buf->EnsureCap(flight_len + ssl_seal_align_prefix_len(ssl), max_out)) { return -1; } @@ -258,18 +257,21 @@ // order. if (ssl->s3->pending_flight != NULL) { OPENSSL_memcpy( - out, ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset, + buf->remaining().data(), + ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset, flight_len); BUF_MEM_free(ssl->s3->pending_flight); ssl->s3->pending_flight = NULL; ssl->s3->pending_flight_offset = 0; + buf->DidWrite(flight_len); } - if (!tls_seal_record(ssl, out + flight_len, &ciphertext_len, - max_out - flight_len, type, buf, len)) { + size_t ciphertext_len; + if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len, + buf->remaining().size(), type, in, len)) { return -1; } - ssl_write_buffer_set_len(ssl, flight_len + ciphertext_len); + buf->DidWrite(ciphertext_len); // Now that we've made progress on the connection, uncork KeyUpdate // acknowledgments. @@ -278,13 +280,13 @@ // Memorize arguments so that ssl3_write_pending can detect bad write retries // later. ssl->s3->wpend_tot = len; - ssl->s3->wpend_buf = buf; + ssl->s3->wpend_buf = in; ssl->s3->wpend_type = type; ssl->s3->wpend_ret = len; ssl->s3->wpend_pending = true; // We now just need to write the buffer. - return ssl3_write_pending(ssl, type, buf, len); + return ssl3_write_pending(ssl, type, in, len); } ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out, @@ -408,7 +410,7 @@ ssl->s3->alert_dispatch = 1; ssl->s3->send_alert[0] = level; ssl->s3->send_alert[1] = desc; - if (!ssl_write_buffer_is_pending(ssl)) { + if (ssl->s3->write_buffer.empty()) { // Nothing is being written out, so the alert may be dispatched // immediately. return ssl->method->dispatch_alert(ssl);
diff --git a/ssl/ssl_buffer.cc b/ssl/ssl_buffer.cc index 412df73..a942054 100644 --- a/ssl/ssl_buffer.cc +++ b/ssl/ssl_buffer.cc
@@ -36,17 +36,22 @@ static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0, "SSL3_ALIGN_PAYLOAD must be a power of 2"); -// ensure_buffer ensures |buf| has capacity at least |cap|, aligned such that -// data written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte -// boundary. It returns one on success and zero on error. -static int ensure_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) { - if (cap > 0xffff) { +void SSLBuffer::Clear() { + free(buf_); // Allocated with malloc(). + buf_ = nullptr; + offset_ = 0; + size_ = 0; + cap_ = 0; +} + +bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) { + if (new_cap > 0xffff) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; + return false; } - if (buf->cap >= cap) { - return 1; + if (cap_ >= new_cap) { + return true; } // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment. @@ -54,88 +59,88 @@ // Since this buffer gets allocated quite frequently and doesn't contain any // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and // avoid zeroing on free. - uint8_t *new_buf = (uint8_t *)malloc(cap + SSL3_ALIGN_PAYLOAD - 1); + uint8_t *new_buf = (uint8_t *)malloc(new_cap + SSL3_ALIGN_PAYLOAD - 1); if (new_buf == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); - return 0; + return false; } // Offset the buffer such that the record body is aligned. size_t new_offset = (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1); - if (buf->buf != NULL) { - OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len); - free(buf->buf); // Allocated with malloc(). + if (buf_ != NULL) { + OPENSSL_memcpy(new_buf + new_offset, buf_ + offset_, size_); + free(buf_); // Allocated with malloc(). } - buf->buf = new_buf; - buf->offset = new_offset; - buf->cap = cap; - return 1; + buf_ = new_buf; + offset_ = new_offset; + cap_ = new_cap; + return true; } -static void consume_buffer(SSL3_BUFFER *buf, size_t len) { - if (len > buf->len) { +void SSLBuffer::DidWrite(size_t new_size) { + if (new_size > cap() - size()) { abort(); } - buf->offset += (uint16_t)len; - buf->len -= (uint16_t)len; - buf->cap -= (uint16_t)len; + size_ += new_size; } -static void clear_buffer(SSL3_BUFFER *buf) { - free(buf->buf); // Allocated with malloc(). - OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER)); +void SSLBuffer::Consume(size_t len) { + if (len > size_) { + abort(); + } + offset_ += (uint16_t)len; + size_ -= (uint16_t)len; + cap_ -= (uint16_t)len; } -Span<uint8_t> ssl_read_buffer(SSL *ssl) { - return MakeSpan(ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset, - ssl->s3->read_buffer.len); +void SSLBuffer::DiscardConsumed() { + if (size_ == 0) { + Clear(); + } } static int dtls_read_buffer_next_packet(SSL *ssl) { - SSL3_BUFFER *buf = &ssl->s3->read_buffer; + SSLBuffer *buf = &ssl->s3->read_buffer; - if (buf->len > 0) { + if (!buf->empty()) { // It is an error to call |dtls_read_buffer_extend| when the read buffer is // not empty. OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; } - // Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int. - int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap); + // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int. + int ret = BIO_read(ssl->rbio, buf->data(), static_cast<int>(buf->cap())); if (ret <= 0) { ssl->rwstate = SSL_READING; return ret; } - // |BIO_read| was bound by |buf->cap|, so this cannot overflow. - buf->len = (uint16_t)ret; + buf->DidWrite(static_cast<size_t>(ret)); return 1; } static int tls_read_buffer_extend_to(SSL *ssl, size_t len) { - SSL3_BUFFER *buf = &ssl->s3->read_buffer; + SSLBuffer *buf = &ssl->s3->read_buffer; - if (len > buf->cap) { + if (len > buf->cap()) { OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); return -1; } // Read until the target length is reached. - while (buf->len < len) { + while (buf->size() < len) { // The amount of data to read is bounded by |buf->cap|, which must fit in an // int. - int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len, - (int)(len - buf->len)); + int ret = BIO_read(ssl->rbio, buf->data() + buf->size(), + static_cast<int>(len - buf->size())); if (ret <= 0) { ssl->rwstate = SSL_READING; return ret; } - // |BIO_read| was bound by |buf->cap - buf->len|, so this cannot - // overflow. - buf->len += (uint16_t)ret; + buf->DidWrite(static_cast<size_t>(ret)); } return 1; @@ -143,7 +148,7 @@ int ssl_read_buffer_extend_to(SSL *ssl, size_t len) { // |ssl_read_buffer_extend_to| implicitly discards any consumed data. - ssl_read_buffer_discard(ssl); + ssl->s3->read_buffer.DiscardConsumed(); if (SSL_is_dtls(ssl)) { static_assert( @@ -154,7 +159,7 @@ len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; } - if (!ensure_buffer(&ssl->s3->read_buffer, ssl_record_prefix_len(ssl), len)) { + if (!ssl->s3->read_buffer.EnsureCap(ssl_record_prefix_len(ssl), len)) { return -1; } @@ -174,43 +179,20 @@ if (ret <= 0) { // If the buffer was empty originally and remained empty after attempting to // extend it, release the buffer until the next attempt. - ssl_read_buffer_discard(ssl); + ssl->s3->read_buffer.DiscardConsumed(); } return ret; } -void ssl_read_buffer_consume(SSL *ssl, size_t len) { - SSL3_BUFFER *buf = &ssl->s3->read_buffer; - - consume_buffer(buf, len); - - // The TLS stack never reads beyond the current record, so there will never be - // unconsumed data. If read-ahead is ever reimplemented, - // |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back - // to the front of the buffer, to ensure there is enough space for the next - // record. - assert(SSL_is_dtls(ssl) || len == 0 || buf->len == 0); -} - -void ssl_read_buffer_discard(SSL *ssl) { - if (ssl->s3->read_buffer.len == 0) { - ssl_read_buffer_clear(ssl); - } -} - -void ssl_read_buffer_clear(SSL *ssl) { - clear_buffer(&ssl->s3->read_buffer); -} - int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret, size_t consumed, uint8_t alert) { *out_retry = false; if (ret != ssl_open_record_partial) { - ssl_read_buffer_consume(ssl, consumed); + ssl->s3->read_buffer.Consume(consumed); } if (ret != ssl_open_record_success) { // Nothing was returned to the caller, so discard anything marked consumed. - ssl_read_buffer_discard(ssl); + ssl->s3->read_buffer.DiscardConsumed(); } switch (ret) { case ssl_open_record_success: @@ -243,10 +225,6 @@ } -int ssl_write_buffer_is_pending(const SSL *ssl) { - return ssl->s3->write_buffer.len > 0; -} - static_assert(SSL3_RT_HEADER_LENGTH * 2 + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 + SSL3_RT_MAX_PLAIN_LENGTH <= @@ -258,61 +236,37 @@ 0xffff, "maximum DTLS write buffer is too large"); -int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) { - SSL3_BUFFER *buf = &ssl->s3->write_buffer; - - if (buf->buf != NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!ensure_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) { - return 0; - } - *out_ptr = buf->buf + buf->offset; - return 1; -} - -void ssl_write_buffer_set_len(SSL *ssl, size_t len) { - SSL3_BUFFER *buf = &ssl->s3->write_buffer; - - if (len > buf->cap) { - abort(); - } - buf->len = len; -} - static int tls_write_buffer_flush(SSL *ssl) { - SSL3_BUFFER *buf = &ssl->s3->write_buffer; + SSLBuffer *buf = &ssl->s3->write_buffer; - while (buf->len > 0) { - int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len); + while (!buf->empty()) { + int ret = BIO_write(ssl->wbio, buf->data(), buf->size()); if (ret <= 0) { ssl->rwstate = SSL_WRITING; return ret; } - consume_buffer(buf, (size_t)ret); + buf->Consume(static_cast<size_t>(ret)); } - ssl_write_buffer_clear(ssl); + buf->Clear(); return 1; } static int dtls_write_buffer_flush(SSL *ssl) { - SSL3_BUFFER *buf = &ssl->s3->write_buffer; - if (buf->len == 0) { + SSLBuffer *buf = &ssl->s3->write_buffer; + if (buf->empty()) { return 1; } - int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len); + int ret = BIO_write(ssl->wbio, buf->data(), buf->size()); if (ret <= 0) { ssl->rwstate = SSL_WRITING; // If the write failed, drop the write buffer anyway. Datagram transports // can't write half a packet, so the caller is expected to retry from the // top. - ssl_write_buffer_clear(ssl); + buf->Clear(); return ret; } - ssl_write_buffer_clear(ssl); + buf->Clear(); return 1; } @@ -329,8 +283,4 @@ } } -void ssl_write_buffer_clear(SSL *ssl) { - clear_buffer(&ssl->s3->write_buffer); -} - } // namespace bssl
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index e3f8a88..f5d1202 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc
@@ -937,7 +937,7 @@ // protocol, namely in HTTPS, just before reading the HTTP response. Require // the record-layer be idle and avoid complexities of sending a handshake // record while an application_data record is being written. - if (ssl_write_buffer_is_pending(ssl) || + if (!ssl->s3->write_buffer.empty() || ssl->s3->write_shutdown != ssl_shutdown_none) { goto no_renegotiation; } @@ -1004,7 +1004,7 @@ uint8_t alert = SSL_AD_DECODE_ERROR; size_t consumed = 0; auto ret = ssl_open_app_data(ssl, &ssl->s3->pending_app_data, &consumed, - &alert, ssl_read_buffer(ssl)); + &alert, ssl->s3->read_buffer.span()); bool retry; int bio_ret = ssl_handle_open_record(ssl, &retry, ret, consumed, alert); if (bio_ret <= 0) { @@ -1029,7 +1029,7 @@ ssl->s3->pending_app_data = ssl->s3->pending_app_data.subspan(static_cast<size_t>(ret)); if (ssl->s3->pending_app_data.empty()) { - ssl_read_buffer_discard(ssl); + ssl->s3->read_buffer.DiscardConsumed(); } return ret; }