ssl_buffer.cc
Go to the documentation of this file.
1 /* Copyright (c) 2015, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/ssl.h>
16 
17 #include <assert.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <openssl/bio.h>
23 #include <openssl/err.h>
24 #include <openssl/mem.h>
25 
26 #include "../crypto/internal.h"
27 #include "internal.h"
28 
29 
31 
32 // BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will
33 // not overflow.
34 static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int");
35 
36 static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0,
37  "SSL3_ALIGN_PAYLOAD must be a power of 2");
38 
40  if (buf_allocated_) {
41  free(buf_); // Allocated with malloc().
42  }
43  buf_ = nullptr;
44  buf_allocated_ = false;
45  offset_ = 0;
46  size_ = 0;
47  cap_ = 0;
48 }
49 
50 bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) {
51  if (new_cap > 0xffff) {
53  return false;
54  }
55 
56  if (cap_ >= new_cap) {
57  return true;
58  }
59 
60  uint8_t *new_buf;
61  bool new_buf_allocated;
62  size_t new_offset;
63  if (new_cap <= sizeof(inline_buf_)) {
64  // This function is called twice per TLS record, first for the five-byte
65  // header. To avoid allocating twice, use an inline buffer for short inputs.
66  new_buf = inline_buf_;
67  new_buf_allocated = false;
68  new_offset = 0;
69  } else {
70  // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
71  //
72  // Since this buffer gets allocated quite frequently and doesn't contain any
73  // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
74  // avoid zeroing on free.
75  new_buf = (uint8_t *)malloc(new_cap + SSL3_ALIGN_PAYLOAD - 1);
76  if (new_buf == NULL) {
78  return false;
79  }
80  new_buf_allocated = true;
81 
82  // Offset the buffer such that the record body is aligned.
83  new_offset =
84  (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1);
85  }
86 
87  // Note if the both old and new buffer are inline, the source and destination
88  // may alias.
89  OPENSSL_memmove(new_buf + new_offset, buf_ + offset_, size_);
90 
91  if (buf_allocated_) {
92  free(buf_); // Allocated with malloc().
93  }
94 
95  buf_ = new_buf;
96  buf_allocated_ = new_buf_allocated;
97  offset_ = new_offset;
98  cap_ = new_cap;
99  return true;
100 }
101 
103  if (new_size > cap() - size()) {
104  abort();
105  }
106  size_ += new_size;
107 }
108 
109 void SSLBuffer::Consume(size_t len) {
110  if (len > size_) {
111  abort();
112  }
113  offset_ += (uint16_t)len;
114  size_ -= (uint16_t)len;
115  cap_ -= (uint16_t)len;
116 }
117 
119  if (size_ == 0) {
120  Clear();
121  }
122 }
123 
125  SSLBuffer *buf = &ssl->s3->read_buffer;
126 
127  if (!buf->empty()) {
128  // It is an error to call |dtls_read_buffer_extend| when the read buffer is
129  // not empty.
131  return -1;
132  }
133 
134  // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int.
135  int ret =
136  BIO_read(ssl->rbio.get(), buf->data(), static_cast<int>(buf->cap()));
137  if (ret <= 0) {
138  ssl->s3->rwstate = SSL_ERROR_WANT_READ;
139  return ret;
140  }
141  buf->DidWrite(static_cast<size_t>(ret));
142  return 1;
143 }
144 
145 static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
146  SSLBuffer *buf = &ssl->s3->read_buffer;
147 
148  if (len > buf->cap()) {
150  return -1;
151  }
152 
153  // Read until the target length is reached.
154  while (buf->size() < len) {
155  // The amount of data to read is bounded by |buf->cap|, which must fit in an
156  // int.
157  int ret = BIO_read(ssl->rbio.get(), buf->data() + buf->size(),
158  static_cast<int>(len - buf->size()));
159  if (ret <= 0) {
160  ssl->s3->rwstate = SSL_ERROR_WANT_READ;
161  return ret;
162  }
163  buf->DidWrite(static_cast<size_t>(ret));
164  }
165 
166  return 1;
167 }
168 
169 int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
170  // |ssl_read_buffer_extend_to| implicitly discards any consumed data.
171  ssl->s3->read_buffer.DiscardConsumed();
172 
173  if (SSL_is_dtls(ssl)) {
174  static_assert(
176  "DTLS read buffer is too large");
177 
178  // The |len| parameter is ignored in DTLS.
180  }
181 
182  if (!ssl->s3->read_buffer.EnsureCap(ssl_record_prefix_len(ssl), len)) {
183  return -1;
184  }
185 
186  if (ssl->rbio == nullptr) {
188  return -1;
189  }
190 
191  int ret;
192  if (SSL_is_dtls(ssl)) {
193  // |len| is ignored for a datagram transport.
195  } else {
197  }
198 
199  if (ret <= 0) {
200  // If the buffer was empty originally and remained empty after attempting to
201  // extend it, release the buffer until the next attempt.
202  ssl->s3->read_buffer.DiscardConsumed();
203  }
204  return ret;
205 }
206 
207 int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret,
208  size_t consumed, uint8_t alert) {
209  *out_retry = false;
210  if (ret != ssl_open_record_partial) {
211  ssl->s3->read_buffer.Consume(consumed);
212  }
213  if (ret != ssl_open_record_success) {
214  // Nothing was returned to the caller, so discard anything marked consumed.
215  ssl->s3->read_buffer.DiscardConsumed();
216  }
217  switch (ret) {
219  return 1;
220 
222  int read_ret = ssl_read_buffer_extend_to(ssl, consumed);
223  if (read_ret <= 0) {
224  return read_ret;
225  }
226  *out_retry = true;
227  return 1;
228  }
229 
231  *out_retry = true;
232  return 1;
233 
235  return 0;
236 
238  if (alert != 0) {
239  ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
240  }
241  return -1;
242  }
243  assert(0);
244  return -1;
245 }
246 
247 
248 static_assert(SSL3_RT_HEADER_LENGTH * 2 +
251  0xffff,
252  "maximum TLS write buffer is too large");
253 
256  0xffff,
257  "maximum DTLS write buffer is too large");
258 
259 static int tls_write_buffer_flush(SSL *ssl) {
260  SSLBuffer *buf = &ssl->s3->write_buffer;
261 
262  while (!buf->empty()) {
263  int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
264  if (ret <= 0) {
265  ssl->s3->rwstate = SSL_ERROR_WANT_WRITE;
266  return ret;
267  }
268  buf->Consume(static_cast<size_t>(ret));
269  }
270  buf->Clear();
271  return 1;
272 }
273 
274 static int dtls_write_buffer_flush(SSL *ssl) {
275  SSLBuffer *buf = &ssl->s3->write_buffer;
276  if (buf->empty()) {
277  return 1;
278  }
279 
280  int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
281  if (ret <= 0) {
282  ssl->s3->rwstate = SSL_ERROR_WANT_WRITE;
283  // If the write failed, drop the write buffer anyway. Datagram transports
284  // can't write half a packet, so the caller is expected to retry from the
285  // top.
286  buf->Clear();
287  return ret;
288  }
289  buf->Clear();
290  return 1;
291 }
292 
294  if (ssl->wbio == nullptr) {
296  return -1;
297  }
298 
299  if (SSL_is_dtls(ssl)) {
300  return dtls_write_buffer_flush(ssl);
301  } else {
302  return tls_write_buffer_flush(ssl);
303  }
304 }
305 
SSLBuffer::EnsureCap
bool EnsureCap(size_t header_len, size_t new_cap)
Definition: ssl_buffer.cc:50
dtls_write_buffer_flush
static int dtls_write_buffer_flush(SSL *ssl)
Definition: ssl_buffer.cc:274
ssl_send_alert
void ssl_send_alert(SSL *ssl, int level, int desc)
Definition: s3_pkt.cc:379
ssl_open_record_partial
@ ssl_open_record_partial
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:936
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
SSL_R_BIO_NOT_SET
#define SSL_R_BIO_NOT_SET
Definition: ssl.h:5387
SSL_ERROR_WANT_READ
#define SSL_ERROR_WANT_READ
Definition: ssl.h:494
ssl_write_buffer_flush
int ssl_write_buffer_flush(SSL *ssl)
Definition: ssl_buffer.cc:293
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
internal.h
bio.h
string.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
binary_size.new_size
def new_size
Definition: binary_size.py:124
tls_read_buffer_extend_to
static int tls_read_buffer_extend_to(SSL *ssl, size_t len)
Definition: ssl_buffer.cc:145
BIO_write
#define BIO_write
Definition: boringssl_prefix_symbols.h:870
SSLBuffer::Consume
void Consume(size_t len)
Definition: ssl_buffer.cc:109
BIO_read
#define BIO_read
Definition: boringssl_prefix_symbols.h:831
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
ssl_handle_open_record
int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret, size_t consumed, uint8_t alert)
Definition: ssl_buffer.cc:207
SSLBuffer::cap_
uint16_t cap_
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1262
ssl_record_prefix_len
size_t ssl_record_prefix_len(const SSL *ssl)
Definition: tls_record.cc:165
SSL3_RT_MAX_ENCRYPTED_LENGTH
#define SSL3_RT_MAX_ENCRYPTED_LENGTH
Definition: ssl3.h:263
SSL3_RT_MAX_PLAIN_LENGTH
#define SSL3_RT_MAX_PLAIN_LENGTH
Definition: ssl3.h:235
DTLS1_RT_HEADER_LENGTH
#define DTLS1_RT_HEADER_LENGTH
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:2833
ssl_open_record_discard
@ ssl_open_record_discard
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:935
ssl_st
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3698
SSLBuffer::Clear
void Clear()
Definition: ssl_buffer.cc:39
SSLBuffer::buf_
uint8_t * buf_
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1256
SSL_is_dtls
#define SSL_is_dtls
Definition: boringssl_prefix_symbols.h:402
SSLBuffer::size
size_t size() const
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1222
ssl_st::wbio
bssl::UniquePtr< BIO > wbio
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3723
BSSL_NAMESPACE_END
#define BSSL_NAMESPACE_END
Definition: base.h:480
SSLBuffer::size_
uint16_t size_
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1260
err.h
ERR_R_INTERNAL_ERROR
#define ERR_R_INTERNAL_ERROR
Definition: err.h:374
SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
Definition: ssl3.h:251
SSL3_ALIGN_PAYLOAD
#define SSL3_ALIGN_PAYLOAD
Definition: ssl3.h:216
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
dtls_read_buffer_next_packet
static int dtls_read_buffer_next_packet(SSL *ssl)
Definition: ssl_buffer.cc:124
ssl_st::rbio
bssl::UniquePtr< BIO > rbio
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3722
SSL3_AL_FATAL
#define SSL3_AL_FATAL
Definition: ssl3.h:280
SSLBuffer::inline_buf_
uint8_t inline_buf_[SSL3_RT_HEADER_LENGTH]
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1264
ssl.h
SSLBuffer::DiscardConsumed
void DiscardConsumed()
Definition: ssl_buffer.cc:118
SSLBuffer::offset_
uint16_t offset_
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1258
SSL_ERROR_WANT_WRITE
#define SSL_ERROR_WANT_WRITE
Definition: ssl.h:499
ssl_open_record_t
ssl_open_record_t
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:933
ssl_open_record_close_notify
@ ssl_open_record_close_notify
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:937
BSSL_NAMESPACE_BEGIN
Definition: trust_token_test.cc:45
ssl_st::s3
bssl::SSL3_STATE * s3
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3730
ssl_open_record_success
@ ssl_open_record_success
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:934
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
SSLBuffer::cap
size_t cap() const
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1224
ssl_open_record_error
@ ssl_open_record_error
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:938
OPENSSL_memmove
static void * OPENSSL_memmove(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:827
SSL_R_BUFFER_TOO_SMALL
#define SSL_R_BUFFER_TOO_SMALL
Definition: ssl.h:5389
mem.h
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
SSLBuffer::buf_allocated_
bool buf_allocated_
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1267
tls_write_buffer_flush
static int tls_write_buffer_flush(SSL *ssl)
Definition: ssl_buffer.cc:259
ssl_read_buffer_extend_to
int ssl_read_buffer_extend_to(SSL *ssl, size_t len)
Definition: ssl_buffer.cc:169
SSL3_RT_HEADER_LENGTH
#define SSL3_RT_HEADER_LENGTH
Definition: ssl3.h:206
SSLBuffer
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:1213
ERR_R_MALLOC_FAILURE
#define ERR_R_MALLOC_FAILURE
Definition: err.h:371
SSLBuffer::DidWrite
void DidWrite(size_t len)
Definition: ssl_buffer.cc:102


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:20