blob: b424138c969a85128b655f1e22f17a8b513eba2a [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
David Benjamin86e95b82017-07-18 16:34:25 -040030namespace bssl {
31
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 Benjaminc11ea9422017-08-29 16:33:21 -040039// ensure_buffer ensures |buf| has capacity at least |cap|, aligned such that
40// data written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte
41// boundary. It returns one on success and zero on error.
David Benjamin31209502017-06-22 18:07:15 -040042static int ensure_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) {
43 if (cap > 0xffff) {
David Benjaminb8d28cf2015-07-28 21:34:45 -040044 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
45 return 0;
46 }
47
David Benjamin31209502017-06-22 18:07:15 -040048 if (buf->cap >= cap) {
49 return 1;
50 }
51
David Benjaminc11ea9422017-08-29 16:33:21 -040052 // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -070053 //
54 // Since this buffer gets allocated quite frequently and doesn't contain any
55 // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
56 // avoid zeroing on free.
57 uint8_t *new_buf = (uint8_t *)malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
David Benjamin31209502017-06-22 18:07:15 -040058 if (new_buf == NULL) {
David Benjaminb8d28cf2015-07-28 21:34:45 -040059 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
60 return 0;
61 }
62
David Benjaminc11ea9422017-08-29 16:33:21 -040063 // Offset the buffer such that the record body is aligned.
David Benjamin31209502017-06-22 18:07:15 -040064 size_t new_offset =
65 (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1);
66
67 if (buf->buf != NULL) {
68 OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len);
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -070069 free(buf->buf); // Allocated with malloc().
David Benjamin31209502017-06-22 18:07:15 -040070 }
71
72 buf->buf = new_buf;
73 buf->offset = new_offset;
David Benjaminb8d28cf2015-07-28 21:34:45 -040074 buf->cap = cap;
75 return 1;
76}
77
78static void consume_buffer(SSL3_BUFFER *buf, size_t len) {
79 if (len > buf->len) {
80 abort();
81 }
82 buf->offset += (uint16_t)len;
83 buf->len -= (uint16_t)len;
84 buf->cap -= (uint16_t)len;
85}
86
87static void clear_buffer(SSL3_BUFFER *buf) {
Martin Kreichgauerc0e15d12017-08-18 14:24:36 -070088 free(buf->buf); // Allocated with malloc().
David Benjamin17cf2cb2016-12-13 01:07:13 -050089 OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
David Benjaminb8d28cf2015-07-28 21:34:45 -040090}
91
David Benjaminb8d28cf2015-07-28 21:34:45 -040092uint8_t *ssl_read_buffer(SSL *ssl) {
93 return ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset;
94}
95
96size_t ssl_read_buffer_len(const SSL *ssl) {
97 return ssl->s3->read_buffer.len;
98}
99
100static int dtls_read_buffer_next_packet(SSL *ssl) {
101 SSL3_BUFFER *buf = &ssl->s3->read_buffer;
102
103 if (buf->len > 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400104 // It is an error to call |dtls_read_buffer_extend| when the read buffer is
105 // not empty.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400106 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
107 return -1;
108 }
109
David Benjaminc11ea9422017-08-29 16:33:21 -0400110 // Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400111 int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap);
112 if (ret <= 0) {
David Benjamin4c5ddb82016-03-11 22:56:19 -0500113 ssl->rwstate = SSL_READING;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400114 return ret;
115 }
David Benjaminc11ea9422017-08-29 16:33:21 -0400116 // |BIO_read| was bound by |buf->cap|, so this cannot overflow.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400117 buf->len = (uint16_t)ret;
118 return 1;
119}
120
121static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
122 SSL3_BUFFER *buf = &ssl->s3->read_buffer;
123
124 if (len > buf->cap) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400125 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
126 return -1;
127 }
128
David Benjaminc11ea9422017-08-29 16:33:21 -0400129 // Read until the target length is reached.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400130 while (buf->len < len) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400131 // The amount of data to read is bounded by |buf->cap|, which must fit in an
132 // int.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400133 int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len,
134 (int)(len - buf->len));
135 if (ret <= 0) {
David Benjamin4c5ddb82016-03-11 22:56:19 -0500136 ssl->rwstate = SSL_READING;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400137 return ret;
138 }
David Benjaminc11ea9422017-08-29 16:33:21 -0400139 // |BIO_read| was bound by |buf->cap - buf->len|, so this cannot
140 // overflow.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400141 buf->len += (uint16_t)ret;
142 }
143
144 return 1;
145}
146
147int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400148 // |ssl_read_buffer_extend_to| implicitly discards any consumed data.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400149 ssl_read_buffer_discard(ssl);
150
David Benjamin31209502017-06-22 18:07:15 -0400151 if (SSL_is_dtls(ssl)) {
David Benjamina3d76d02017-07-14 19:36:07 -0400152 static_assert(
David Benjamin31209502017-06-22 18:07:15 -0400153 DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff,
David Benjamina3d76d02017-07-14 19:36:07 -0400154 "DTLS read buffer is too large");
David Benjamin31209502017-06-22 18:07:15 -0400155
David Benjaminc11ea9422017-08-29 16:33:21 -0400156 // The |len| parameter is ignored in DTLS.
David Benjamin31209502017-06-22 18:07:15 -0400157 len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
158 }
159
160 if (!ensure_buffer(&ssl->s3->read_buffer, ssl_record_prefix_len(ssl), len)) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400161 return -1;
162 }
163
164 if (ssl->rbio == NULL) {
165 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
166 return -1;
167 }
168
David Benjaminb8d28cf2015-07-28 21:34:45 -0400169 int ret;
David Benjamince079fd2016-08-02 16:22:34 -0400170 if (SSL_is_dtls(ssl)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400171 // |len| is ignored for a datagram transport.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400172 ret = dtls_read_buffer_next_packet(ssl);
173 } else {
174 ret = tls_read_buffer_extend_to(ssl, len);
175 }
176
177 if (ret <= 0) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400178 // If the buffer was empty originally and remained empty after attempting to
179 // extend it, release the buffer until the next attempt.
David Benjaminb8d28cf2015-07-28 21:34:45 -0400180 ssl_read_buffer_discard(ssl);
181 }
182 return ret;
183}
184
185void ssl_read_buffer_consume(SSL *ssl, size_t len) {
186 SSL3_BUFFER *buf = &ssl->s3->read_buffer;
187
188 consume_buffer(buf, len);
David Benjamin728f3542016-06-02 15:42:01 -0400189
David Benjaminc11ea9422017-08-29 16:33:21 -0400190 // The TLS stack never reads beyond the current record, so there will never be
191 // unconsumed data. If read-ahead is ever reimplemented,
192 // |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back
193 // to the front of the buffer, to ensure there is enough space for the next
194 // record.
David Benjamince079fd2016-08-02 16:22:34 -0400195 assert(SSL_is_dtls(ssl) || len == 0 || buf->len == 0);
David Benjaminb8d28cf2015-07-28 21:34:45 -0400196}
197
198void ssl_read_buffer_discard(SSL *ssl) {
199 if (ssl->s3->read_buffer.len == 0) {
200 ssl_read_buffer_clear(ssl);
201 }
202}
203
204void ssl_read_buffer_clear(SSL *ssl) {
205 clear_buffer(&ssl->s3->read_buffer);
206}
207
208
209int ssl_write_buffer_is_pending(const SSL *ssl) {
210 return ssl->s3->write_buffer.len > 0;
211}
212
David Benjamina3d76d02017-07-14 19:36:07 -0400213static_assert(SSL3_RT_HEADER_LENGTH * 2 +
214 SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 +
215 SSL3_RT_MAX_PLAIN_LENGTH <=
216 0xffff,
217 "maximum TLS write buffer is too large");
David Benjaminb8d28cf2015-07-28 21:34:45 -0400218
David Benjamina3d76d02017-07-14 19:36:07 -0400219static_assert(DTLS1_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD +
220 SSL3_RT_MAX_PLAIN_LENGTH <=
221 0xffff,
222 "maximum DTLS write buffer is too large");
David Benjaminb8d28cf2015-07-28 21:34:45 -0400223
224int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) {
225 SSL3_BUFFER *buf = &ssl->s3->write_buffer;
226
227 if (buf->buf != NULL) {
228 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
229 return 0;
230 }
231
David Benjamin31209502017-06-22 18:07:15 -0400232 if (!ensure_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400233 return 0;
234 }
235 *out_ptr = buf->buf + buf->offset;
236 return 1;
237}
238
239void ssl_write_buffer_set_len(SSL *ssl, size_t len) {
240 SSL3_BUFFER *buf = &ssl->s3->write_buffer;
241
242 if (len > buf->cap) {
243 abort();
244 }
245 buf->len = len;
246}
247
248static int tls_write_buffer_flush(SSL *ssl) {
249 SSL3_BUFFER *buf = &ssl->s3->write_buffer;
250
251 while (buf->len > 0) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400252 int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
253 if (ret <= 0) {
David Benjamin4c5ddb82016-03-11 22:56:19 -0500254 ssl->rwstate = SSL_WRITING;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400255 return ret;
256 }
David Benjaminb8d28cf2015-07-28 21:34:45 -0400257 consume_buffer(buf, (size_t)ret);
258 }
259 ssl_write_buffer_clear(ssl);
260 return 1;
261}
262
263static int dtls_write_buffer_flush(SSL *ssl) {
264 SSL3_BUFFER *buf = &ssl->s3->write_buffer;
265 if (buf->len == 0) {
266 return 1;
267 }
268
269 int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
David Benjamin13e81fc2015-11-02 17:16:13 -0500270 if (ret <= 0) {
David Benjamin4c5ddb82016-03-11 22:56:19 -0500271 ssl->rwstate = SSL_WRITING;
David Benjaminc11ea9422017-08-29 16:33:21 -0400272 // If the write failed, drop the write buffer anyway. Datagram transports
273 // can't write half a packet, so the caller is expected to retry from the
274 // top.
David Benjamin13e81fc2015-11-02 17:16:13 -0500275 ssl_write_buffer_clear(ssl);
276 return ret;
277 }
David Benjaminb8d28cf2015-07-28 21:34:45 -0400278 ssl_write_buffer_clear(ssl);
David Benjamin13e81fc2015-11-02 17:16:13 -0500279 return 1;
David Benjaminb8d28cf2015-07-28 21:34:45 -0400280}
281
282int ssl_write_buffer_flush(SSL *ssl) {
283 if (ssl->wbio == NULL) {
284 OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
285 return -1;
286 }
David Benjaminb8d28cf2015-07-28 21:34:45 -0400287
David Benjamince079fd2016-08-02 16:22:34 -0400288 if (SSL_is_dtls(ssl)) {
David Benjaminb8d28cf2015-07-28 21:34:45 -0400289 return dtls_write_buffer_flush(ssl);
290 } else {
291 return tls_write_buffer_flush(ssl);
292 }
293}
294
295void ssl_write_buffer_clear(SSL *ssl) {
296 clear_buffer(&ssl->s3->write_buffer);
297}
David Benjamin86e95b82017-07-18 16:34:25 -0400298
299} // namespace bssl