/src/boringssl/ssl/ssl_buffer.cc
Line | Count | Source |
1 | | // Copyright 2015 The BoringSSL Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
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 | | |
30 | | BSSL_NAMESPACE_BEGIN |
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 | | |
39 | 2.50M | void SSLBuffer::Clear() { |
40 | 2.50M | if (buf_ != inline_buf_) { |
41 | 2.47M | free(buf_); // Allocated with malloc(). |
42 | 2.47M | } |
43 | 2.50M | buf_ = nullptr; |
44 | 2.50M | offset_ = 0; |
45 | 2.50M | size_ = 0; |
46 | 2.50M | cap_ = 0; |
47 | 2.50M | } |
48 | | |
49 | 1.30M | bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) { |
50 | 1.30M | if (new_cap > 0xffff) { |
51 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
52 | 0 | return false; |
53 | 0 | } |
54 | | |
55 | 1.30M | if (cap_ >= new_cap) { |
56 | 0 | return true; |
57 | 0 | } |
58 | | |
59 | 1.30M | uint8_t *new_buf; |
60 | 1.30M | size_t new_offset; |
61 | 1.30M | if (new_cap <= sizeof(inline_buf_)) { |
62 | | // This function is called twice per TLS record, first for the five-byte |
63 | | // header. To avoid allocating twice, use an inline buffer for short inputs. |
64 | 575k | new_buf = inline_buf_; |
65 | 575k | new_offset = 0; |
66 | 734k | } else { |
67 | | // Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment. |
68 | | // |
69 | | // Since this buffer gets allocated quite frequently and doesn't contain any |
70 | | // sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and |
71 | | // avoid zeroing on free. |
72 | 734k | new_buf = (uint8_t *)malloc(new_cap + SSL3_ALIGN_PAYLOAD - 1); |
73 | 734k | if (new_buf == nullptr) { |
74 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
75 | 0 | return false; |
76 | 0 | } |
77 | | |
78 | | // Offset the buffer such that the record body is aligned. |
79 | 734k | new_offset = |
80 | 734k | (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1); |
81 | 734k | } |
82 | | |
83 | | // Note if the both old and new buffer are inline, the source and destination |
84 | | // may alias. |
85 | 1.30M | OPENSSL_memmove(new_buf + new_offset, buf_ + offset_, size_); |
86 | | |
87 | 1.30M | if (buf_ != inline_buf_) { |
88 | 761k | free(buf_); // Allocated with malloc(). |
89 | 761k | } |
90 | | |
91 | 1.30M | buf_ = new_buf; |
92 | 1.30M | offset_ = new_offset; |
93 | 1.30M | cap_ = new_cap; |
94 | 1.30M | return true; |
95 | 1.30M | } |
96 | | |
97 | 1.29M | void SSLBuffer::DidWrite(size_t new_size) { |
98 | 1.29M | if (new_size > cap() - size()) { |
99 | 0 | abort(); |
100 | 0 | } |
101 | 1.29M | size_ += new_size; |
102 | 1.29M | } |
103 | | |
104 | 758k | void SSLBuffer::Consume(size_t len) { |
105 | 758k | if (len > size_) { |
106 | 0 | abort(); |
107 | 0 | } |
108 | 758k | offset_ += (uint16_t)len; |
109 | 758k | size_ -= (uint16_t)len; |
110 | 758k | cap_ -= (uint16_t)len; |
111 | 758k | } |
112 | | |
113 | 3.34M | void SSLBuffer::DiscardConsumed() { |
114 | 3.34M | if (size_ == 0) { |
115 | 2.23M | Clear(); |
116 | 2.23M | } |
117 | 3.34M | } |
118 | | |
119 | 169k | static int dtls_read_buffer_next_packet(SSL *ssl) { |
120 | 169k | SSLBuffer *buf = &ssl->s3->read_buffer; |
121 | | |
122 | 169k | if (!buf->empty()) { |
123 | | // It is an error to call |dtls_read_buffer_extend| when the read buffer is |
124 | | // not empty. |
125 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
126 | 0 | return -1; |
127 | 0 | } |
128 | | |
129 | | // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int. |
130 | 169k | int ret = |
131 | 169k | BIO_read(ssl->rbio.get(), buf->data(), static_cast<int>(buf->cap())); |
132 | 169k | if (ret <= 0) { |
133 | 7.28k | ssl->s3->rwstate = SSL_ERROR_WANT_READ; |
134 | 7.28k | return ret; |
135 | 7.28k | } |
136 | 162k | buf->DidWrite(static_cast<size_t>(ret)); |
137 | 162k | return 1; |
138 | 169k | } |
139 | | |
140 | 1.12M | static int tls_read_buffer_extend_to(SSL *ssl, size_t len) { |
141 | 1.12M | SSLBuffer *buf = &ssl->s3->read_buffer; |
142 | | |
143 | 1.12M | if (len > buf->cap()) { |
144 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); |
145 | 0 | return -1; |
146 | 0 | } |
147 | | |
148 | | // Read until the target length is reached. |
149 | 2.24M | while (buf->size() < len) { |
150 | | // The amount of data to read is bounded by |buf->cap|, which must fit in an |
151 | | // int. |
152 | 1.12M | int ret = BIO_read(ssl->rbio.get(), buf->data() + buf->size(), |
153 | 1.12M | static_cast<int>(len - buf->size())); |
154 | 1.12M | if (ret <= 0) { |
155 | 7.32k | ssl->s3->rwstate = SSL_ERROR_WANT_READ; |
156 | 7.32k | return ret; |
157 | 7.32k | } |
158 | 1.11M | buf->DidWrite(static_cast<size_t>(ret)); |
159 | 1.11M | } |
160 | | |
161 | 1.11M | return 1; |
162 | 1.12M | } |
163 | | |
164 | 1.29M | int ssl_read_buffer_extend_to(SSL *ssl, size_t len) { |
165 | | // |ssl_read_buffer_extend_to| implicitly discards any consumed data. |
166 | 1.29M | ssl->s3->read_buffer.DiscardConsumed(); |
167 | | |
168 | 1.29M | if (SSL_is_dtls(ssl)) { |
169 | 169k | static_assert( |
170 | 169k | DTLS1_RT_MAX_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff, |
171 | 169k | "DTLS read buffer is too large"); |
172 | | |
173 | | // The |len| parameter is ignored in DTLS. |
174 | 169k | len = DTLS1_RT_MAX_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; |
175 | 169k | } |
176 | | |
177 | | // The DTLS record header can have a variable length, so the |header_len| |
178 | | // value provided for buffer alignment only works if the header is the maximum |
179 | | // length. |
180 | 1.29M | if (!ssl->s3->read_buffer.EnsureCap(DTLS1_RT_MAX_HEADER_LENGTH, len)) { |
181 | 0 | return -1; |
182 | 0 | } |
183 | | |
184 | 1.29M | if (ssl->rbio == nullptr) { |
185 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); |
186 | 0 | return -1; |
187 | 0 | } |
188 | | |
189 | 1.29M | int ret; |
190 | 1.29M | if (SSL_is_dtls(ssl)) { |
191 | | // |len| is ignored for a datagram transport. |
192 | 169k | ret = dtls_read_buffer_next_packet(ssl); |
193 | 1.12M | } else { |
194 | 1.12M | ret = tls_read_buffer_extend_to(ssl, len); |
195 | 1.12M | } |
196 | | |
197 | 1.29M | if (ret <= 0) { |
198 | | // If the buffer was empty originally and remained empty after attempting to |
199 | | // extend it, release the buffer until the next attempt. |
200 | 14.6k | ssl->s3->read_buffer.DiscardConsumed(); |
201 | 14.6k | } |
202 | 1.29M | return ret; |
203 | 1.29M | } |
204 | | |
205 | | int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret, |
206 | 2.04M | size_t consumed, uint8_t alert) { |
207 | 2.04M | *out_retry = false; |
208 | 2.04M | if (ret != ssl_open_record_partial) { |
209 | 746k | ssl->s3->read_buffer.Consume(consumed); |
210 | 746k | } |
211 | 2.04M | if (ret != ssl_open_record_success) { |
212 | | // Nothing was returned to the caller, so discard anything marked consumed. |
213 | 1.43M | ssl->s3->read_buffer.DiscardConsumed(); |
214 | 1.43M | } |
215 | 2.04M | switch (ret) { |
216 | 602k | case ssl_open_record_success: |
217 | 602k | return 1; |
218 | | |
219 | 1.29M | case ssl_open_record_partial: { |
220 | 1.29M | int read_ret = ssl_read_buffer_extend_to(ssl, consumed); |
221 | 1.29M | if (read_ret <= 0) { |
222 | 14.6k | return read_ret; |
223 | 14.6k | } |
224 | 1.27M | *out_retry = true; |
225 | 1.27M | return 1; |
226 | 1.29M | } |
227 | | |
228 | 139k | case ssl_open_record_discard: |
229 | 139k | *out_retry = true; |
230 | 139k | return 1; |
231 | | |
232 | 104 | case ssl_open_record_close_notify: |
233 | 104 | ssl->s3->rwstate = SSL_ERROR_ZERO_RETURN; |
234 | 104 | return 0; |
235 | | |
236 | 4.61k | case ssl_open_record_error: |
237 | 4.61k | if (alert != 0) { |
238 | 4.45k | ssl_send_alert(ssl, SSL3_AL_FATAL, alert); |
239 | 4.45k | } |
240 | 4.61k | return -1; |
241 | 2.04M | } |
242 | 2.04M | assert(0); |
243 | 0 | return -1; |
244 | 0 | } |
245 | | |
246 | | |
247 | | static_assert(SSL3_RT_HEADER_LENGTH * 2 + |
248 | | SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 + |
249 | | SSL3_RT_MAX_PLAIN_LENGTH <= |
250 | | 0xffff, |
251 | | "maximum TLS write buffer is too large"); |
252 | | |
253 | | static_assert(DTLS1_RT_MAX_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + |
254 | | SSL3_RT_MAX_PLAIN_LENGTH <= |
255 | | 0xffff, |
256 | | "maximum DTLS write buffer is too large"); |
257 | | |
258 | 23.0k | static int tls_write_buffer_flush(SSL *ssl) { |
259 | 23.0k | SSLBuffer *buf = &ssl->s3->write_buffer; |
260 | | |
261 | 34.6k | while (!buf->empty()) { |
262 | 11.5k | int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size()); |
263 | 11.5k | if (ret <= 0) { |
264 | 0 | ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; |
265 | 0 | return ret; |
266 | 0 | } |
267 | 11.5k | buf->Consume(static_cast<size_t>(ret)); |
268 | 11.5k | } |
269 | 23.0k | buf->Clear(); |
270 | 23.0k | return 1; |
271 | 23.0k | } |
272 | | |
273 | 4.67k | static int dtls_write_buffer_flush(SSL *ssl) { |
274 | 4.67k | SSLBuffer *buf = &ssl->s3->write_buffer; |
275 | 4.67k | if (buf->empty()) { |
276 | 0 | return 1; |
277 | 0 | } |
278 | | |
279 | 4.67k | int ret = BIO_write(ssl->wbio.get(), buf->data(), buf->size()); |
280 | 4.67k | if (ret <= 0) { |
281 | 0 | ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; |
282 | | // If the write failed, drop the write buffer anyway. Datagram transports |
283 | | // can't write half a packet, so the caller is expected to retry from the |
284 | | // top. |
285 | 0 | buf->Clear(); |
286 | 0 | return ret; |
287 | 0 | } |
288 | 4.67k | buf->Clear(); |
289 | 4.67k | return 1; |
290 | 4.67k | } |
291 | | |
292 | 27.7k | int ssl_write_buffer_flush(SSL *ssl) { |
293 | 27.7k | if (ssl->wbio == nullptr) { |
294 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); |
295 | 0 | return -1; |
296 | 0 | } |
297 | | |
298 | 27.7k | if (SSL_is_dtls(ssl)) { |
299 | 4.67k | return dtls_write_buffer_flush(ssl); |
300 | 23.0k | } else { |
301 | 23.0k | return tls_write_buffer_flush(ssl); |
302 | 23.0k | } |
303 | 27.7k | } |
304 | | |
305 | | BSSL_NAMESPACE_END |