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;
}