blob: 2ca14efae5ea478f43794a81883b00dfdb1a37b0 [file] [log] [blame]
David Benjaminb8d28cf2015-07-28 21:34:45 -04001/* 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>
David Benjaminb8d28cf2015-07-28 21:34:45 -040025
David Benjamin17cf2cb2016-12-13 01:07:13 -050026#include "../crypto/internal.h"
David Benjaminb8d28cf2015-07-28 21:34:45 -040027#include "internal.h"
28
29
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -070030BSSL_NAMESPACE_BEGIN
David Benjamin86e95b82017-07-18 16:34:25 -040031
David Benjaminc11ea9422017-08-29 16:33:21 -040032// BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will
33// not overflow.
David Benjamina3d76d02017-07-14 19:36:07 -040034static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int");
David Benjaminb8d28cf2015-07-28 21:34:45 -040035
David Benjamina3d76d02017-07-14 19:36:07 -040036static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0,
37 "SSL3_ALIGN_PAYLOAD must be a power of 2");
David Benjaminb8d28cf2015-07-28 21:34:45 -040038
David Benjaminea712e32017-10-13 16:50:39 -040039void SSLBuffer::Clear() {
David Benjaminc7337542019-11-28 08:32:16 -050040 if (buf_allocated_) {
41 free(buf_); // Allocated with malloc().
42 }
David Benjaminea712e32017-10-13 16:50:39 -040043 buf_ = nullptr;
David Benjaminc7337542019-11-28 08:32:16 -050044 buf_allocated_ = false;
David Benjaminea712e32017-10-13 16:50:39 -040045 offset_ = 0;
46 size_ = 0;
47 cap_ = 0;
48}
49
50bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) {
51 if (new_cap > 0xffff) {
David Benjaminb8d28cf2015-07-28 21:34:45 -040052 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjaminea712e32017-10-13 16:50:39 -040053 return false;
David Benjaminb8d28cf2015-07-28 21:34:45 -040054 }
55
David Benjaminea712e32017-10-13 16:50:39 -040056 if (cap_ >= new_cap) {
57 return true;
David Benjamin31209502017-06-22 18:07:15 -040058 }
59
David Benjaminc7337542019-11-28 08:32:16 -050060 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) {
77 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
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);
David Benjaminb8d28cf2015-07-28 21:34:45 -040085 }
86
David Benjaminc7337542019-11-28 08:32:16 -050087 // 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_);
David Benjamin31209502017-06-22 18:07:15 -040090
David Benjaminc7337542019-11-28 08:32:16 -050091 if (buf_allocated_) {
David Benjaminea712e32017-10-13 16:50:39 -040092 free(buf_); // Allocated with malloc().
David Benjamin31209502017-06-22 18:07:15 -040093 }
94
David Benjaminea712e32017-10-13 16:50:39 -040095 buf_ = new_buf;
David Benjaminc7337542019-11-28 08:32:16 -050096 buf_allocated_ = new_buf_allocated;
David Benjaminea712e32017-10-13 16:50:39 -040097 offset_ = new_offset;
98 cap_ = new_cap;
99 return true;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400100}
101
David Benjaminea712e32017-10-13 16:50:39 -0400102void SSLBuffer::DidWrite(size_t new_size) {
103 if (new_size > cap() - size()) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400104 abort();
105 }
David Benjaminea712e32017-10-13 16:50:39 -0400106 size_ += new_size;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400107}
108
David Benjaminea712e32017-10-13 16:50:39 -0400109void 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;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400116}
117
David Benjaminea712e32017-10-13 16:50:39 -0400118void SSLBuffer::DiscardConsumed() {
119 if (size_ == 0) {
120 Clear();
121 }
David Benjaminb8d28cf2015-07-28 21:34:45 -0400122}
123
124static int dtls_read_buffer_next_packet(SSL *ssl) {
David Benjaminea712e32017-10-13 16:50:39 -0400125 SSLBuffer *buf = &ssl->s3->read_buffer;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400126
David Benjaminea712e32017-10-13 16:50:39 -0400127 if (!buf->empty()) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400128 // It is an error to call |dtls_read_buffer_extend| when the read buffer is
129 // not empty.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400130 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
131 return -1;
132 }
133
David Benjaminea712e32017-10-13 16:50:39 -0400134 // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int.
David Benjamin50596f82018-07-02 19:47:27 -0400135 int ret =
136 BIO_read(ssl->rbio.get(), buf->data(), static_cast<int>(buf->cap()));
David Benjaminb8d28cf2015-07-28 21:34:45 -0400137 if (ret <= 0) {
David Benjaminf4928302019-08-21 16:04:53 -0400138 ssl->s3->rwstate = SSL_ERROR_WANT_READ;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400139 return ret;
140 }
David Benjaminea712e32017-10-13 16:50:39 -0400141 buf->DidWrite(static_cast<size_t>(ret));
David Benjaminb8d28cf2015-07-28 21:34:45 -0400142 return 1;
143}
144
145static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
David Benjaminea712e32017-10-13 16:50:39 -0400146 SSLBuffer *buf = &ssl->s3->read_buffer;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400147
David Benjaminea712e32017-10-13 16:50:39 -0400148 if (len > buf->cap()) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400149 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
150 return -1;
151 }
152
David Benjaminc11ea9422017-08-29 16:33:21 -0400153 // Read until the target length is reached.
David Benjaminea712e32017-10-13 16:50:39 -0400154 while (buf->size() < len) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400155 // The amount of data to read is bounded by |buf->cap|, which must fit in an
156 // int.
David Benjamin50596f82018-07-02 19:47:27 -0400157 int ret = BIO_read(ssl->rbio.get(), buf->data() + buf->size(),
David Benjaminea712e32017-10-13 16:50:39 -0400158 static_cast<int>(len - buf->size()));
David Benjaminb8d28cf2015-07-28 21:34:45 -0400159 if (ret <= 0) {
David Benjaminf4928302019-08-21 16:04:53 -0400160 ssl->s3->rwstate = SSL_ERROR_WANT_READ;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400161 return ret;
162 }
David Benjaminea712e32017-10-13 16:50:39 -0400163 buf->DidWrite(static_cast<size_t>(ret));
David Benjaminb8d28cf2015-07-28 21:34:45 -0400164 }
165
166 return 1;
167}
168
169int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400170 // |ssl_read_buffer_extend_to| implicitly discards any consumed data.
David Benjaminea712e32017-10-13 16:50:39 -0400171 ssl->s3->read_buffer.DiscardConsumed();
David Benjaminb8d28cf2015-07-28 21:34:45 -0400172
David Benjamin31209502017-06-22 18:07:15 -0400173 if (SSL_is_dtls(ssl)) {
David Benjamina3d76d02017-07-14 19:36:07 -0400174 static_assert(
David Benjamin31209502017-06-22 18:07:15 -0400175 DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff,
David Benjamina3d76d02017-07-14 19:36:07 -0400176 "DTLS read buffer is too large");
David Benjamin31209502017-06-22 18:07:15 -0400177
David Benjaminc11ea9422017-08-29 16:33:21 -0400178 // The |len| parameter is ignored in DTLS.
David Benjamin31209502017-06-22 18:07:15 -0400179 len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
180 }
181
David Benjaminea712e32017-10-13 16:50:39 -0400182 if (!ssl->s3->read_buffer.EnsureCap(ssl_record_prefix_len(ssl), len)) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400183 return -1;
184 }
185
David Benjamin50596f82018-07-02 19:47:27 -0400186 if (ssl->rbio == nullptr) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400187 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
188 return -1;
189 }
190
David Benjaminb8d28cf2015-07-28 21:34:45 -0400191 int ret;
David Benjamince079fd2016-08-02 16:22:34 -0400192 if (SSL_is_dtls(ssl)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400193 // |len| is ignored for a datagram transport.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400194 ret = dtls_read_buffer_next_packet(ssl);
195 } else {
196 ret = tls_read_buffer_extend_to(ssl, len);
197 }
198
199 if (ret <= 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400200 // If the buffer was empty originally and remained empty after attempting to
201 // extend it, release the buffer until the next attempt.
David Benjaminea712e32017-10-13 16:50:39 -0400202 ssl->s3->read_buffer.DiscardConsumed();
David Benjaminb8d28cf2015-07-28 21:34:45 -0400203 }
204 return ret;
205}
206
David Benjamind9229f92017-10-06 17:36:20 -0400207int 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) {
David Benjaminea712e32017-10-13 16:50:39 -0400211 ssl->s3->read_buffer.Consume(consumed);
David Benjamind9229f92017-10-06 17:36:20 -0400212 }
213 if (ret != ssl_open_record_success) {
214 // Nothing was returned to the caller, so discard anything marked consumed.
David Benjaminea712e32017-10-13 16:50:39 -0400215 ssl->s3->read_buffer.DiscardConsumed();
David Benjamind9229f92017-10-06 17:36:20 -0400216 }
217 switch (ret) {
218 case ssl_open_record_success:
219 return 1;
220
221 case ssl_open_record_partial: {
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
230 case ssl_open_record_discard:
231 *out_retry = true;
232 return 1;
233
234 case ssl_open_record_close_notify:
David Benjaminebd8b892022-07-27 18:41:51 -0700235 ssl->s3->rwstate = SSL_ERROR_ZERO_RETURN;
David Benjamind9229f92017-10-06 17:36:20 -0400236 return 0;
237
238 case ssl_open_record_error:
239 if (alert != 0) {
240 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
241 }
242 return -1;
243 }
244 assert(0);
245 return -1;
246}
247
David Benjaminb8d28cf2015-07-28 21:34:45 -0400248
David Benjamina3d76d02017-07-14 19:36:07 -0400249static_assert(SSL3_RT_HEADER_LENGTH * 2 +
250 SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 +
251 SSL3_RT_MAX_PLAIN_LENGTH <=
252 0xffff,
253 "maximum TLS write buffer is too large");
David Benjaminb8d28cf2015-07-28 21:34:45 -0400254
David Benjamina3d76d02017-07-14 19:36:07 -0400255static_assert(DTLS1_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD +
256 SSL3_RT_MAX_PLAIN_LENGTH <=
257 0xffff,
258 "maximum DTLS write buffer is too large");
David Benjaminb8d28cf2015-07-28 21:34:45 -0400259
David Benjaminb8d28cf2015-07-28 21:34:45 -0400260static int tls_write_buffer_flush(SSL *ssl) {
David Benjaminea712e32017-10-13 16:50:39 -0400261 SSLBuffer *buf = &ssl->s3->write_buffer;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400262
David Benjaminea712e32017-10-13 16:50:39 -0400263 while (!buf->empty()) {
David Benjamin50596f82018-07-02 19:47:27 -0400264 int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
David Benjaminb8d28cf2015-07-28 21:34:45 -0400265 if (ret <= 0) {
David Benjaminf4928302019-08-21 16:04:53 -0400266 ssl->s3->rwstate = SSL_ERROR_WANT_WRITE;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400267 return ret;
268 }
David Benjaminea712e32017-10-13 16:50:39 -0400269 buf->Consume(static_cast<size_t>(ret));
David Benjaminb8d28cf2015-07-28 21:34:45 -0400270 }
David Benjaminea712e32017-10-13 16:50:39 -0400271 buf->Clear();
David Benjaminb8d28cf2015-07-28 21:34:45 -0400272 return 1;
273}
274
275static int dtls_write_buffer_flush(SSL *ssl) {
David Benjaminea712e32017-10-13 16:50:39 -0400276 SSLBuffer *buf = &ssl->s3->write_buffer;
277 if (buf->empty()) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400278 return 1;
279 }
280
David Benjamin50596f82018-07-02 19:47:27 -0400281 int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
David Benjamin13e81fc2015-11-02 17:16:13 -0500282 if (ret <= 0) {
David Benjaminf4928302019-08-21 16:04:53 -0400283 ssl->s3->rwstate = SSL_ERROR_WANT_WRITE;
David Benjaminc11ea9422017-08-29 16:33:21 -0400284 // If the write failed, drop the write buffer anyway. Datagram transports
285 // can't write half a packet, so the caller is expected to retry from the
286 // top.
David Benjaminea712e32017-10-13 16:50:39 -0400287 buf->Clear();
David Benjamin13e81fc2015-11-02 17:16:13 -0500288 return ret;
289 }
David Benjaminea712e32017-10-13 16:50:39 -0400290 buf->Clear();
David Benjamin13e81fc2015-11-02 17:16:13 -0500291 return 1;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400292}
293
294int ssl_write_buffer_flush(SSL *ssl) {
David Benjamin50596f82018-07-02 19:47:27 -0400295 if (ssl->wbio == nullptr) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400296 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
297 return -1;
298 }
David Benjaminb8d28cf2015-07-28 21:34:45 -0400299
David Benjamince079fd2016-08-02 16:22:34 -0400300 if (SSL_is_dtls(ssl)) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400301 return dtls_write_buffer_flush(ssl);
302 } else {
303 return tls_write_buffer_flush(ssl);
304 }
305}
306
Joshua Liebow-Feeser8c7c6352018-08-26 18:53:36 -0700307BSSL_NAMESPACE_END