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
30BSSL_NAMESPACE_BEGIN
31
32// BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will
33// not overflow.
34static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int");
35
36static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0,
37 "SSL3_ALIGN_PAYLOAD must be a power of 2");
38
39void SSLBuffer::Clear() {
40 free(buf_); // Allocated with malloc().
41 buf_ = nullptr;
42 offset_ = 0;
43 size_ = 0;
44 cap_ = 0;
45}
46
47bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) {
48 if (new_cap > 0xffff) {
49 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
50 return false;
51 }
52
53 if (cap_ >= new_cap) {
54 return true;
55 }
56
57 // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
58 //
59 // Since this buffer gets allocated quite frequently and doesn't contain any
60 // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
61 // avoid zeroing on free.
62 uint8_t *new_buf = (uint8_t *)malloc(new_cap + SSL3_ALIGN_PAYLOAD - 1);
63 if (new_buf == NULL) {
64 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
65 return false;
66 }
67
68 // Offset the buffer such that the record body is aligned.
69 size_t new_offset =
70 (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1);
71
72 if (buf_ != NULL) {
73 OPENSSL_memcpy(new_buf + new_offset, buf_ + offset_, size_);
74 free(buf_); // Allocated with malloc().
75 }
76
77 buf_ = new_buf;
78 offset_ = new_offset;
79 cap_ = new_cap;
80 return true;
81}
82
83void SSLBuffer::DidWrite(size_t new_size) {
84 if (new_size > cap() - size()) {
85 abort();
86 }
87 size_ += new_size;
88}
89
90void SSLBuffer::Consume(size_t len) {
91 if (len > size_) {
92 abort();
93 }
94 offset_ += (uint16_t)len;
95 size_ -= (uint16_t)len;
96 cap_ -= (uint16_t)len;
97}
98
99void SSLBuffer::DiscardConsumed() {
100 if (size_ == 0) {
101 Clear();
102 }
103}
104
105static int dtls_read_buffer_next_packet(SSL *ssl) {
106 SSLBuffer *buf = &ssl->s3->read_buffer;
107
108 if (!buf->empty()) {
109 // It is an error to call |dtls_read_buffer_extend| when the read buffer is
110 // not empty.
111 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
112 return -1;
113 }
114
115 // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int.
116 int ret =
117 BIO_read(ssl->rbio.get(), buf->data(), static_cast<int>(buf->cap()));
118 if (ret <= 0) {
119 ssl->s3->rwstate = SSL_READING;
120 return ret;
121 }
122 buf->DidWrite(static_cast<size_t>(ret));
123 return 1;
124}
125
126static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
127 SSLBuffer *buf = &ssl->s3->read_buffer;
128
129 if (len > buf->cap()) {
130 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
131 return -1;
132 }
133
134 // Read until the target length is reached.
135 while (buf->size() < len) {
136 // The amount of data to read is bounded by |buf->cap|, which must fit in an
137 // int.
138 int ret = BIO_read(ssl->rbio.get(), buf->data() + buf->size(),
139 static_cast<int>(len - buf->size()));
140 if (ret <= 0) {
141 ssl->s3->rwstate = SSL_READING;
142 return ret;
143 }
144 buf->DidWrite(static_cast<size_t>(ret));
145 }
146
147 return 1;
148}
149
150int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
151 // |ssl_read_buffer_extend_to| implicitly discards any consumed data.
152 ssl->s3->read_buffer.DiscardConsumed();
153
154 if (SSL_is_dtls(ssl)) {
155 static_assert(
156 DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff,
157 "DTLS read buffer is too large");
158
159 // The |len| parameter is ignored in DTLS.
160 len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
161 }
162
163 if (!ssl->s3->read_buffer.EnsureCap(ssl_record_prefix_len(ssl), len)) {
164 return -1;
165 }
166
167 if (ssl->rbio == nullptr) {
168 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
169 return -1;
170 }
171
172 int ret;
173 if (SSL_is_dtls(ssl)) {
174 // |len| is ignored for a datagram transport.
175 ret = dtls_read_buffer_next_packet(ssl);
176 } else {
177 ret = tls_read_buffer_extend_to(ssl, len);
178 }
179
180 if (ret <= 0) {
181 // If the buffer was empty originally and remained empty after attempting to
182 // extend it, release the buffer until the next attempt.
183 ssl->s3->read_buffer.DiscardConsumed();
184 }
185 return ret;
186}
187
188int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret,
189 size_t consumed, uint8_t alert) {
190 *out_retry = false;
191 if (ret != ssl_open_record_partial) {
192 ssl->s3->read_buffer.Consume(consumed);
193 }
194 if (ret != ssl_open_record_success) {
195 // Nothing was returned to the caller, so discard anything marked consumed.
196 ssl->s3->read_buffer.DiscardConsumed();
197 }
198 switch (ret) {
199 case ssl_open_record_success:
200 return 1;
201
202 case ssl_open_record_partial: {
203 int read_ret = ssl_read_buffer_extend_to(ssl, consumed);
204 if (read_ret <= 0) {
205 return read_ret;
206 }
207 *out_retry = true;
208 return 1;
209 }
210
211 case ssl_open_record_discard:
212 *out_retry = true;
213 return 1;
214
215 case ssl_open_record_close_notify:
216 return 0;
217
218 case ssl_open_record_error:
219 if (alert != 0) {
220 ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
221 }
222 return -1;
223 }
224 assert(0);
225 return -1;
226}
227
228
229static_assert(SSL3_RT_HEADER_LENGTH * 2 +
230 SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 +
231 SSL3_RT_MAX_PLAIN_LENGTH <=
232 0xffff,
233 "maximum TLS write buffer is too large");
234
235static_assert(DTLS1_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD +
236 SSL3_RT_MAX_PLAIN_LENGTH <=
237 0xffff,
238 "maximum DTLS write buffer is too large");
239
240static int tls_write_buffer_flush(SSL *ssl) {
241 SSLBuffer *buf = &ssl->s3->write_buffer;
242
243 while (!buf->empty()) {
244 int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
245 if (ret <= 0) {
246 ssl->s3->rwstate = SSL_WRITING;
247 return ret;
248 }
249 buf->Consume(static_cast<size_t>(ret));
250 }
251 buf->Clear();
252 return 1;
253}
254
255static int dtls_write_buffer_flush(SSL *ssl) {
256 SSLBuffer *buf = &ssl->s3->write_buffer;
257 if (buf->empty()) {
258 return 1;
259 }
260
261 int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size());
262 if (ret <= 0) {
263 ssl->s3->rwstate = SSL_WRITING;
264 // If the write failed, drop the write buffer anyway. Datagram transports
265 // can't write half a packet, so the caller is expected to retry from the
266 // top.
267 buf->Clear();
268 return ret;
269 }
270 buf->Clear();
271 return 1;
272}
273
274int ssl_write_buffer_flush(SSL *ssl) {
275 if (ssl->wbio == nullptr) {
276 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
277 return -1;
278 }
279
280 if (SSL_is_dtls(ssl)) {
281 return dtls_write_buffer_flush(ssl);
282 } else {
283 return tls_write_buffer_flush(ssl);
284 }
285}
286
287BSSL_NAMESPACE_END
288