/src/boringssl/ssl/s3_both.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | | * All rights reserved. |
3 | | * |
4 | | * This package is an SSL implementation written |
5 | | * by Eric Young (eay@cryptsoft.com). |
6 | | * The implementation was written so as to conform with Netscapes SSL. |
7 | | * |
8 | | * This library is free for commercial and non-commercial use as long as |
9 | | * the following conditions are aheared to. The following conditions |
10 | | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | | * included with this distribution is covered by the same copyright terms |
13 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | | * |
15 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | | * the code are not to be removed. |
17 | | * If this package is used in a product, Eric Young should be given attribution |
18 | | * as the author of the parts of the library used. |
19 | | * This can be in the form of a textual message at program startup or |
20 | | * in documentation (online or textual) provided with the package. |
21 | | * |
22 | | * Redistribution and use in source and binary forms, with or without |
23 | | * modification, are permitted provided that the following conditions |
24 | | * are met: |
25 | | * 1. Redistributions of source code must retain the copyright |
26 | | * notice, this list of conditions and the following disclaimer. |
27 | | * 2. Redistributions in binary form must reproduce the above copyright |
28 | | * notice, this list of conditions and the following disclaimer in the |
29 | | * documentation and/or other materials provided with the distribution. |
30 | | * 3. All advertising materials mentioning features or use of this software |
31 | | * must display the following acknowledgement: |
32 | | * "This product includes cryptographic software written by |
33 | | * Eric Young (eay@cryptsoft.com)" |
34 | | * The word 'cryptographic' can be left out if the rouines from the library |
35 | | * being used are not cryptographic related :-). |
36 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | | * the apps directory (application code) you must include an acknowledgement: |
38 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | | * SUCH DAMAGE. |
51 | | * |
52 | | * The licence and distribution terms for any publically available version or |
53 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | | * copied and put under another distribution licence |
55 | | * [including the GNU Public Licence.] |
56 | | */ |
57 | | /* ==================================================================== |
58 | | * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. |
59 | | * |
60 | | * Redistribution and use in source and binary forms, with or without |
61 | | * modification, are permitted provided that the following conditions |
62 | | * are met: |
63 | | * |
64 | | * 1. Redistributions of source code must retain the above copyright |
65 | | * notice, this list of conditions and the following disclaimer. |
66 | | * |
67 | | * 2. Redistributions in binary form must reproduce the above copyright |
68 | | * notice, this list of conditions and the following disclaimer in |
69 | | * the documentation and/or other materials provided with the |
70 | | * distribution. |
71 | | * |
72 | | * 3. All advertising materials mentioning features or use of this |
73 | | * software must display the following acknowledgment: |
74 | | * "This product includes software developed by the OpenSSL Project |
75 | | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
76 | | * |
77 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
78 | | * endorse or promote products derived from this software without |
79 | | * prior written permission. For written permission, please contact |
80 | | * openssl-core@openssl.org. |
81 | | * |
82 | | * 5. Products derived from this software may not be called "OpenSSL" |
83 | | * nor may "OpenSSL" appear in their names without prior written |
84 | | * permission of the OpenSSL Project. |
85 | | * |
86 | | * 6. Redistributions of any form whatsoever must retain the following |
87 | | * acknowledgment: |
88 | | * "This product includes software developed by the OpenSSL Project |
89 | | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
90 | | * |
91 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
92 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
93 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
94 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
95 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
96 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
97 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
98 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
99 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
100 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
101 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
102 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
103 | | * ==================================================================== |
104 | | * |
105 | | * This product includes cryptographic software written by Eric Young |
106 | | * (eay@cryptsoft.com). This product includes software written by Tim |
107 | | * Hudson (tjh@cryptsoft.com). */ |
108 | | /* ==================================================================== |
109 | | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
110 | | * ECC cipher suite support in OpenSSL originally developed by |
111 | | * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ |
112 | | |
113 | | #include <openssl/ssl.h> |
114 | | |
115 | | #include <assert.h> |
116 | | #include <limits.h> |
117 | | #include <string.h> |
118 | | |
119 | | #include <tuple> |
120 | | |
121 | | #include <openssl/buf.h> |
122 | | #include <openssl/bytestring.h> |
123 | | #include <openssl/err.h> |
124 | | #include <openssl/evp.h> |
125 | | #include <openssl/mem.h> |
126 | | #include <openssl/md5.h> |
127 | | #include <openssl/nid.h> |
128 | | #include <openssl/rand.h> |
129 | | #include <openssl/sha.h> |
130 | | |
131 | | #include "../crypto/internal.h" |
132 | | #include "internal.h" |
133 | | |
134 | | |
135 | | BSSL_NAMESPACE_BEGIN |
136 | | |
137 | | static bool add_record_to_flight(SSL *ssl, uint8_t type, |
138 | 253k | Span<const uint8_t> in) { |
139 | | // The caller should have flushed |pending_hs_data| first. |
140 | 253k | assert(!ssl->s3->pending_hs_data); |
141 | | // We'll never add a flight while in the process of writing it out. |
142 | 0 | assert(ssl->s3->pending_flight_offset == 0); |
143 | | |
144 | 253k | if (ssl->s3->pending_flight == nullptr) { |
145 | 124k | ssl->s3->pending_flight.reset(BUF_MEM_new()); |
146 | 124k | if (ssl->s3->pending_flight == nullptr) { |
147 | 0 | return false; |
148 | 0 | } |
149 | 124k | } |
150 | | |
151 | 253k | size_t max_out = in.size() + SSL_max_seal_overhead(ssl); |
152 | 253k | size_t new_cap = ssl->s3->pending_flight->length + max_out; |
153 | 253k | if (max_out < in.size() || new_cap < max_out) { |
154 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); |
155 | 0 | return false; |
156 | 0 | } |
157 | | |
158 | 253k | size_t len; |
159 | 253k | if (!BUF_MEM_reserve(ssl->s3->pending_flight.get(), new_cap) || |
160 | 253k | !tls_seal_record(ssl, |
161 | 253k | (uint8_t *)ssl->s3->pending_flight->data + |
162 | 253k | ssl->s3->pending_flight->length, |
163 | 253k | &len, max_out, type, in.data(), in.size())) { |
164 | 0 | return false; |
165 | 0 | } |
166 | | |
167 | 253k | ssl->s3->pending_flight->length += len; |
168 | 253k | return true; |
169 | 253k | } |
170 | | |
171 | 252k | bool tls_init_message(const SSL *ssl, CBB *cbb, CBB *body, uint8_t type) { |
172 | | // Pick a modest size hint to save most of the |realloc| calls. |
173 | 252k | if (!CBB_init(cbb, 64) || |
174 | 252k | !CBB_add_u8(cbb, type) || |
175 | 252k | !CBB_add_u24_length_prefixed(cbb, body)) { |
176 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
177 | 0 | CBB_cleanup(cbb); |
178 | 0 | return false; |
179 | 0 | } |
180 | | |
181 | 252k | return true; |
182 | 252k | } |
183 | | |
184 | 252k | bool tls_finish_message(const SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg) { |
185 | 252k | return CBBFinishArray(cbb, out_msg); |
186 | 252k | } |
187 | | |
188 | 252k | bool tls_add_message(SSL *ssl, Array<uint8_t> msg) { |
189 | | // Pack handshake data into the minimal number of records. This avoids |
190 | | // unnecessary encryption overhead, notably in TLS 1.3 where we send several |
191 | | // encrypted messages in a row. For now, we do not do this for the null |
192 | | // cipher. The benefit is smaller and there is a risk of breaking buggy |
193 | | // implementations. |
194 | | // |
195 | | // TODO(davidben): See if we can do this uniformly. |
196 | 252k | Span<const uint8_t> rest = msg; |
197 | 252k | if (ssl->quic_method == nullptr && |
198 | 252k | ssl->s3->aead_write_ctx->is_null_cipher()) { |
199 | 47.2k | while (!rest.empty()) { |
200 | 23.6k | Span<const uint8_t> chunk = rest.subspan(0, ssl->max_send_fragment); |
201 | 23.6k | rest = rest.subspan(chunk.size()); |
202 | | |
203 | 23.6k | if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, chunk)) { |
204 | 0 | return false; |
205 | 0 | } |
206 | 23.6k | } |
207 | 228k | } else { |
208 | 457k | while (!rest.empty()) { |
209 | | // Flush if |pending_hs_data| is full. |
210 | 228k | if (ssl->s3->pending_hs_data && |
211 | 228k | ssl->s3->pending_hs_data->length >= ssl->max_send_fragment && |
212 | 228k | !tls_flush_pending_hs_data(ssl)) { |
213 | 0 | return false; |
214 | 0 | } |
215 | | |
216 | 228k | size_t pending_len = |
217 | 228k | ssl->s3->pending_hs_data ? ssl->s3->pending_hs_data->length : 0; |
218 | 228k | Span<const uint8_t> chunk = |
219 | 228k | rest.subspan(0, ssl->max_send_fragment - pending_len); |
220 | 228k | assert(!chunk.empty()); |
221 | 0 | rest = rest.subspan(chunk.size()); |
222 | | |
223 | 228k | if (!ssl->s3->pending_hs_data) { |
224 | 171k | ssl->s3->pending_hs_data.reset(BUF_MEM_new()); |
225 | 171k | } |
226 | 228k | if (!ssl->s3->pending_hs_data || |
227 | 228k | !BUF_MEM_append(ssl->s3->pending_hs_data.get(), chunk.data(), |
228 | 228k | chunk.size())) { |
229 | 0 | return false; |
230 | 0 | } |
231 | 228k | } |
232 | 228k | } |
233 | | |
234 | 252k | ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg); |
235 | | // TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on |
236 | | // hs. |
237 | 252k | if (ssl->s3->hs != NULL && |
238 | 252k | !ssl->s3->hs->transcript.Update(msg)) { |
239 | 0 | return false; |
240 | 0 | } |
241 | 252k | return true; |
242 | 252k | } |
243 | | |
244 | 248k | bool tls_flush_pending_hs_data(SSL *ssl) { |
245 | 248k | if (!ssl->s3->pending_hs_data || ssl->s3->pending_hs_data->length == 0) { |
246 | 77.2k | return true; |
247 | 77.2k | } |
248 | | |
249 | 171k | UniquePtr<BUF_MEM> pending_hs_data = std::move(ssl->s3->pending_hs_data); |
250 | 171k | auto data = |
251 | 171k | MakeConstSpan(reinterpret_cast<const uint8_t *>(pending_hs_data->data), |
252 | 171k | pending_hs_data->length); |
253 | 171k | if (ssl->quic_method) { |
254 | 0 | if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && |
255 | 0 | !ssl->quic_method->add_handshake_data(ssl, ssl->s3->write_level, |
256 | 0 | data.data(), data.size())) { |
257 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR); |
258 | 0 | return false; |
259 | 0 | } |
260 | 0 | return true; |
261 | 0 | } |
262 | | |
263 | 171k | return add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, data); |
264 | 171k | } |
265 | | |
266 | 59.1k | bool tls_add_change_cipher_spec(SSL *ssl) { |
267 | 59.1k | static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS}; |
268 | | |
269 | 59.1k | if (!tls_flush_pending_hs_data(ssl)) { |
270 | 0 | return false; |
271 | 0 | } |
272 | | |
273 | 59.1k | if (!ssl->quic_method && |
274 | 59.1k | !add_record_to_flight(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, |
275 | 59.1k | kChangeCipherSpec)) { |
276 | 0 | return false; |
277 | 0 | } |
278 | | |
279 | 59.1k | ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC, |
280 | 59.1k | kChangeCipherSpec); |
281 | 59.1k | return true; |
282 | 59.1k | } |
283 | | |
284 | 124k | int tls_flush_flight(SSL *ssl) { |
285 | 124k | if (!tls_flush_pending_hs_data(ssl)) { |
286 | 0 | return -1; |
287 | 0 | } |
288 | | |
289 | 124k | if (ssl->quic_method) { |
290 | 0 | if (ssl->s3->write_shutdown != ssl_shutdown_none) { |
291 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); |
292 | 0 | return -1; |
293 | 0 | } |
294 | | |
295 | 0 | if (!ssl->quic_method->flush_flight(ssl)) { |
296 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR); |
297 | 0 | return -1; |
298 | 0 | } |
299 | 0 | } |
300 | | |
301 | 124k | if (ssl->s3->pending_flight == nullptr) { |
302 | 0 | return 1; |
303 | 0 | } |
304 | | |
305 | 124k | if (ssl->s3->write_shutdown != ssl_shutdown_none) { |
306 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); |
307 | 0 | return -1; |
308 | 0 | } |
309 | | |
310 | 124k | static_assert(INT_MAX <= 0xffffffff, "int is larger than 32 bits"); |
311 | 124k | if (ssl->s3->pending_flight->length > INT_MAX) { |
312 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
313 | 0 | return -1; |
314 | 0 | } |
315 | | |
316 | | // If there is pending data in the write buffer, it must be flushed out before |
317 | | // any new data in pending_flight. |
318 | 124k | if (!ssl->s3->write_buffer.empty()) { |
319 | 0 | int ret = ssl_write_buffer_flush(ssl); |
320 | 0 | if (ret <= 0) { |
321 | 0 | ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; |
322 | 0 | return ret; |
323 | 0 | } |
324 | 0 | } |
325 | | |
326 | 124k | if (ssl->wbio == nullptr) { |
327 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); |
328 | 0 | return -1; |
329 | 0 | } |
330 | | |
331 | | // Write the pending flight. |
332 | 248k | while (ssl->s3->pending_flight_offset < ssl->s3->pending_flight->length) { |
333 | 124k | int ret = BIO_write( |
334 | 124k | ssl->wbio.get(), |
335 | 124k | ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset, |
336 | 124k | ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset); |
337 | 124k | if (ret <= 0) { |
338 | 0 | ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; |
339 | 0 | return ret; |
340 | 0 | } |
341 | | |
342 | 124k | ssl->s3->pending_flight_offset += ret; |
343 | 124k | } |
344 | | |
345 | 124k | if (BIO_flush(ssl->wbio.get()) <= 0) { |
346 | 0 | ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; |
347 | 0 | return -1; |
348 | 0 | } |
349 | | |
350 | 124k | ssl->s3->pending_flight.reset(); |
351 | 124k | ssl->s3->pending_flight_offset = 0; |
352 | 124k | return 1; |
353 | 124k | } |
354 | | |
355 | | static ssl_open_record_t read_v2_client_hello(SSL *ssl, size_t *out_consumed, |
356 | 735 | Span<const uint8_t> in) { |
357 | 735 | *out_consumed = 0; |
358 | 735 | assert(in.size() >= SSL3_RT_HEADER_LENGTH); |
359 | | // Determine the length of the V2ClientHello. |
360 | 0 | size_t msg_length = ((in[0] & 0x7f) << 8) | in[1]; |
361 | 735 | if (msg_length > (1024 * 4)) { |
362 | 8 | OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); |
363 | 8 | return ssl_open_record_error; |
364 | 8 | } |
365 | 727 | if (msg_length < SSL3_RT_HEADER_LENGTH - 2) { |
366 | | // Reject lengths that are too short early. We have already read |
367 | | // |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an |
368 | | // (invalid) V2ClientHello which would be shorter than that. |
369 | 2 | OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH); |
370 | 2 | return ssl_open_record_error; |
371 | 2 | } |
372 | | |
373 | | // Ask for the remainder of the V2ClientHello. |
374 | 725 | if (in.size() < 2 + msg_length) { |
375 | 382 | *out_consumed = 2 + msg_length; |
376 | 382 | return ssl_open_record_partial; |
377 | 382 | } |
378 | | |
379 | 343 | CBS v2_client_hello = CBS(ssl->s3->read_buffer.span().subspan(2, msg_length)); |
380 | | // The V2ClientHello without the length is incorporated into the handshake |
381 | | // hash. This is only ever called at the start of the handshake, so hs is |
382 | | // guaranteed to be non-NULL. |
383 | 343 | if (!ssl->s3->hs->transcript.Update(v2_client_hello)) { |
384 | 0 | return ssl_open_record_error; |
385 | 0 | } |
386 | | |
387 | 343 | ssl_do_msg_callback(ssl, 0 /* read */, 0 /* V2ClientHello */, |
388 | 343 | v2_client_hello); |
389 | | |
390 | 343 | uint8_t msg_type; |
391 | 343 | uint16_t version, cipher_spec_length, session_id_length, challenge_length; |
392 | 343 | CBS cipher_specs, session_id, challenge; |
393 | 343 | if (!CBS_get_u8(&v2_client_hello, &msg_type) || |
394 | 343 | !CBS_get_u16(&v2_client_hello, &version) || |
395 | 343 | !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || |
396 | 343 | !CBS_get_u16(&v2_client_hello, &session_id_length) || |
397 | 343 | !CBS_get_u16(&v2_client_hello, &challenge_length) || |
398 | 343 | !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || |
399 | 343 | !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || |
400 | 343 | !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || |
401 | 343 | CBS_len(&v2_client_hello) != 0) { |
402 | 55 | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); |
403 | 55 | return ssl_open_record_error; |
404 | 55 | } |
405 | | |
406 | | // msg_type has already been checked. |
407 | 288 | assert(msg_type == SSL2_MT_CLIENT_HELLO); |
408 | | |
409 | | // The client_random is the V2ClientHello challenge. Truncate or left-pad with |
410 | | // zeros as needed. |
411 | 0 | size_t rand_len = CBS_len(&challenge); |
412 | 288 | if (rand_len > SSL3_RANDOM_SIZE) { |
413 | 1 | rand_len = SSL3_RANDOM_SIZE; |
414 | 1 | } |
415 | 288 | uint8_t random[SSL3_RANDOM_SIZE]; |
416 | 288 | OPENSSL_memset(random, 0, SSL3_RANDOM_SIZE); |
417 | 288 | OPENSSL_memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), |
418 | 288 | rand_len); |
419 | | |
420 | | // Write out an equivalent TLS ClientHello directly to the handshake buffer. |
421 | 288 | size_t max_v3_client_hello = SSL3_HM_HEADER_LENGTH + 2 /* version */ + |
422 | 288 | SSL3_RANDOM_SIZE + 1 /* session ID length */ + |
423 | 288 | 2 /* cipher list length */ + |
424 | 288 | CBS_len(&cipher_specs) / 3 * 2 + |
425 | 288 | 1 /* compression length */ + 1 /* compression */; |
426 | 288 | ScopedCBB client_hello; |
427 | 288 | CBB hello_body, cipher_suites; |
428 | 288 | if (!ssl->s3->hs_buf) { |
429 | 288 | ssl->s3->hs_buf.reset(BUF_MEM_new()); |
430 | 288 | } |
431 | 288 | if (!ssl->s3->hs_buf || |
432 | 288 | !BUF_MEM_reserve(ssl->s3->hs_buf.get(), max_v3_client_hello) || |
433 | 288 | !CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->s3->hs_buf->data, |
434 | 288 | ssl->s3->hs_buf->max) || |
435 | 288 | !CBB_add_u8(client_hello.get(), SSL3_MT_CLIENT_HELLO) || |
436 | 288 | !CBB_add_u24_length_prefixed(client_hello.get(), &hello_body) || |
437 | 288 | !CBB_add_u16(&hello_body, version) || |
438 | 288 | !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || |
439 | | // No session id. |
440 | 288 | !CBB_add_u8(&hello_body, 0) || |
441 | 288 | !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) { |
442 | 0 | return ssl_open_record_error; |
443 | 0 | } |
444 | | |
445 | | // Copy the cipher suites. |
446 | 20.4k | while (CBS_len(&cipher_specs) > 0) { |
447 | 20.1k | uint32_t cipher_spec; |
448 | 20.1k | if (!CBS_get_u24(&cipher_specs, &cipher_spec)) { |
449 | 6 | OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); |
450 | 6 | return ssl_open_record_error; |
451 | 6 | } |
452 | | |
453 | | // Skip SSLv2 ciphers. |
454 | 20.1k | if ((cipher_spec & 0xff0000) != 0) { |
455 | 9.80k | continue; |
456 | 9.80k | } |
457 | 10.3k | if (!CBB_add_u16(&cipher_suites, cipher_spec)) { |
458 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
459 | 0 | return ssl_open_record_error; |
460 | 0 | } |
461 | 10.3k | } |
462 | | |
463 | | // Add the null compression scheme and finish. |
464 | 282 | if (!CBB_add_u8(&hello_body, 1) || |
465 | 282 | !CBB_add_u8(&hello_body, 0) || |
466 | 282 | !CBB_finish(client_hello.get(), NULL, &ssl->s3->hs_buf->length)) { |
467 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
468 | 0 | return ssl_open_record_error; |
469 | 0 | } |
470 | | |
471 | 282 | *out_consumed = 2 + msg_length; |
472 | 282 | ssl->s3->is_v2_hello = true; |
473 | 282 | return ssl_open_record_success; |
474 | 282 | } |
475 | | |
476 | | static bool parse_message(const SSL *ssl, SSLMessage *out, |
477 | 3.47M | size_t *out_bytes_needed) { |
478 | 3.47M | if (!ssl->s3->hs_buf) { |
479 | 499k | *out_bytes_needed = 4; |
480 | 499k | return false; |
481 | 499k | } |
482 | | |
483 | 2.97M | CBS cbs; |
484 | 2.97M | uint32_t len; |
485 | 2.97M | CBS_init(&cbs, reinterpret_cast<const uint8_t *>(ssl->s3->hs_buf->data), |
486 | 2.97M | ssl->s3->hs_buf->length); |
487 | 2.97M | if (!CBS_get_u8(&cbs, &out->type) || |
488 | 2.97M | !CBS_get_u24(&cbs, &len)) { |
489 | 1.76M | *out_bytes_needed = 4; |
490 | 1.76M | return false; |
491 | 1.76M | } |
492 | | |
493 | 1.20M | if (!CBS_get_bytes(&cbs, &out->body, len)) { |
494 | 104k | *out_bytes_needed = 4 + len; |
495 | 104k | return false; |
496 | 104k | } |
497 | | |
498 | 1.10M | CBS_init(&out->raw, reinterpret_cast<const uint8_t *>(ssl->s3->hs_buf->data), |
499 | 1.10M | 4 + len); |
500 | 1.10M | out->is_v2_hello = ssl->s3->is_v2_hello; |
501 | 1.10M | return true; |
502 | 1.20M | } |
503 | | |
504 | 1.64M | bool tls_get_message(const SSL *ssl, SSLMessage *out) { |
505 | 1.64M | size_t unused; |
506 | 1.64M | if (!parse_message(ssl, out, &unused)) { |
507 | 671k | return false; |
508 | 671k | } |
509 | 975k | if (!ssl->s3->has_message) { |
510 | 458k | if (!out->is_v2_hello) { |
511 | 458k | ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, out->raw); |
512 | 458k | } |
513 | 458k | ssl->s3->has_message = true; |
514 | 458k | } |
515 | 975k | return true; |
516 | 1.64M | } |
517 | | |
518 | 1.69M | bool tls_can_accept_handshake_data(const SSL *ssl, uint8_t *out_alert) { |
519 | | // If there is a complete message, the caller must have consumed it first. |
520 | 1.69M | SSLMessage msg; |
521 | 1.69M | size_t bytes_needed; |
522 | 1.69M | if (parse_message(ssl, &msg, &bytes_needed)) { |
523 | 7 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
524 | 7 | *out_alert = SSL_AD_INTERNAL_ERROR; |
525 | 7 | return false; |
526 | 7 | } |
527 | | |
528 | | // Enforce the limit so the peer cannot force us to buffer 16MB. |
529 | 1.69M | if (bytes_needed > 4 + ssl_max_handshake_message_len(ssl)) { |
530 | 211 | OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); |
531 | 211 | *out_alert = SSL_AD_ILLEGAL_PARAMETER; |
532 | 211 | return false; |
533 | 211 | } |
534 | | |
535 | 1.69M | return true; |
536 | 1.69M | } |
537 | | |
538 | 250k | bool tls_has_unprocessed_handshake_data(const SSL *ssl) { |
539 | 250k | size_t msg_len = 0; |
540 | 250k | if (ssl->s3->has_message) { |
541 | 126k | SSLMessage msg; |
542 | 126k | size_t unused; |
543 | 126k | if (parse_message(ssl, &msg, &unused)) { |
544 | 126k | msg_len = CBS_len(&msg.raw); |
545 | 126k | } |
546 | 126k | } |
547 | | |
548 | 250k | return ssl->s3->hs_buf && ssl->s3->hs_buf->length > msg_len; |
549 | 250k | } |
550 | | |
551 | 499k | bool tls_append_handshake_data(SSL *ssl, Span<const uint8_t> data) { |
552 | | // Re-create the handshake buffer if needed. |
553 | 499k | if (!ssl->s3->hs_buf) { |
554 | 78.5k | ssl->s3->hs_buf.reset(BUF_MEM_new()); |
555 | 78.5k | } |
556 | 499k | return ssl->s3->hs_buf && |
557 | 499k | BUF_MEM_append(ssl->s3->hs_buf.get(), data.data(), data.size()); |
558 | 499k | } |
559 | | |
560 | | ssl_open_record_t tls_open_handshake(SSL *ssl, size_t *out_consumed, |
561 | 1.29M | uint8_t *out_alert, Span<uint8_t> in) { |
562 | 1.29M | *out_consumed = 0; |
563 | | // Bypass the record layer for the first message to handle V2ClientHello. |
564 | 1.29M | if (ssl->server && !ssl->s3->v2_hello_done) { |
565 | | // Ask for the first 5 bytes, the size of the TLS record header. This is |
566 | | // sufficient to detect a V2ClientHello and ensures that we never read |
567 | | // beyond the first record. |
568 | 10.6k | if (in.size() < SSL3_RT_HEADER_LENGTH) { |
569 | 5.18k | *out_consumed = SSL3_RT_HEADER_LENGTH; |
570 | 5.18k | return ssl_open_record_partial; |
571 | 5.18k | } |
572 | | |
573 | | // Some dedicated error codes for protocol mixups should the application |
574 | | // wish to interpret them differently. (These do not overlap with |
575 | | // ClientHello or V2ClientHello.) |
576 | 5.49k | const char *str = reinterpret_cast<const char*>(in.data()); |
577 | 5.49k | if (strncmp("GET ", str, 4) == 0 || |
578 | 5.49k | strncmp("POST ", str, 5) == 0 || |
579 | 5.49k | strncmp("HEAD ", str, 5) == 0 || |
580 | 5.49k | strncmp("PUT ", str, 4) == 0) { |
581 | 4 | OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST); |
582 | 4 | *out_alert = 0; |
583 | 4 | return ssl_open_record_error; |
584 | 4 | } |
585 | 5.48k | if (strncmp("CONNE", str, 5) == 0) { |
586 | 1 | OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST); |
587 | 1 | *out_alert = 0; |
588 | 1 | return ssl_open_record_error; |
589 | 1 | } |
590 | | |
591 | | // Check for a V2ClientHello. |
592 | 5.48k | if ((in[0] & 0x80) != 0 && in[2] == SSL2_MT_CLIENT_HELLO && |
593 | 5.48k | in[3] == SSL3_VERSION_MAJOR) { |
594 | 735 | auto ret = read_v2_client_hello(ssl, out_consumed, in); |
595 | 735 | if (ret == ssl_open_record_error) { |
596 | 71 | *out_alert = 0; |
597 | 664 | } else if (ret == ssl_open_record_success) { |
598 | 282 | ssl->s3->v2_hello_done = true; |
599 | 282 | } |
600 | 735 | return ret; |
601 | 735 | } |
602 | | |
603 | 4.75k | ssl->s3->v2_hello_done = true; |
604 | 4.75k | } |
605 | | |
606 | 1.28M | uint8_t type; |
607 | 1.28M | Span<uint8_t> body; |
608 | 1.28M | auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in); |
609 | 1.28M | if (ret != ssl_open_record_success) { |
610 | 858k | return ret; |
611 | 858k | } |
612 | | |
613 | | // WatchGuard's TLS 1.3 interference bug is very distinctive: they drop the |
614 | | // ServerHello and send the remaining encrypted application data records |
615 | | // as-is. This manifests as an application data record when we expect |
616 | | // handshake. Report a dedicated error code for this case. |
617 | 429k | if (!ssl->server && type == SSL3_RT_APPLICATION_DATA && |
618 | 429k | ssl->s3->aead_read_ctx->is_null_cipher()) { |
619 | 1 | OPENSSL_PUT_ERROR(SSL, SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE); |
620 | 1 | *out_alert = SSL_AD_UNEXPECTED_MESSAGE; |
621 | 1 | return ssl_open_record_error; |
622 | 1 | } |
623 | | |
624 | 429k | if (type != SSL3_RT_HANDSHAKE) { |
625 | 83 | OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); |
626 | 83 | *out_alert = SSL_AD_UNEXPECTED_MESSAGE; |
627 | 83 | return ssl_open_record_error; |
628 | 83 | } |
629 | | |
630 | | // Append the entire handshake record to the buffer. |
631 | 429k | if (!tls_append_handshake_data(ssl, body)) { |
632 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
633 | 0 | return ssl_open_record_error; |
634 | 0 | } |
635 | | |
636 | 429k | return ssl_open_record_success; |
637 | 429k | } |
638 | | |
639 | 455k | void tls_next_message(SSL *ssl) { |
640 | 455k | SSLMessage msg; |
641 | 455k | if (!tls_get_message(ssl, &msg) || |
642 | 455k | !ssl->s3->hs_buf || |
643 | 455k | ssl->s3->hs_buf->length < CBS_len(&msg.raw)) { |
644 | 0 | assert(0); |
645 | 0 | return; |
646 | 0 | } |
647 | | |
648 | 455k | OPENSSL_memmove(ssl->s3->hs_buf->data, |
649 | 455k | ssl->s3->hs_buf->data + CBS_len(&msg.raw), |
650 | 455k | ssl->s3->hs_buf->length - CBS_len(&msg.raw)); |
651 | 455k | ssl->s3->hs_buf->length -= CBS_len(&msg.raw); |
652 | 455k | ssl->s3->is_v2_hello = false; |
653 | 455k | ssl->s3->has_message = false; |
654 | | |
655 | | // Post-handshake messages are rare, so release the buffer after every |
656 | | // message. During the handshake, |on_handshake_complete| will release it. |
657 | 455k | if (!SSL_in_init(ssl) && ssl->s3->hs_buf->length == 0) { |
658 | 12.2k | ssl->s3->hs_buf.reset(); |
659 | 12.2k | } |
660 | 455k | } |
661 | | |
662 | | // CipherScorer produces a "score" for each possible cipher suite offered by |
663 | | // the client. |
664 | | class CipherScorer { |
665 | | public: |
666 | 834 | CipherScorer(bool has_aes_hw) : aes_is_fine_(has_aes_hw) {} |
667 | | |
668 | | typedef std::tuple<bool, bool> Score; |
669 | | |
670 | | // MinScore returns a |Score| that will compare less than the score of all |
671 | | // cipher suites. |
672 | 834 | Score MinScore() const { |
673 | 834 | return Score(false, false); |
674 | 834 | } |
675 | | |
676 | 1.09k | Score Evaluate(const SSL_CIPHER *a) const { |
677 | 1.09k | return Score( |
678 | | // Something is always preferable to nothing. |
679 | 1.09k | true, |
680 | | // Either AES is fine, or else ChaCha20 is preferred. |
681 | 1.09k | aes_is_fine_ || a->algorithm_enc == SSL_CHACHA20POLY1305); |
682 | 1.09k | } |
683 | | |
684 | | private: |
685 | | const bool aes_is_fine_; |
686 | | }; |
687 | | |
688 | | bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id, |
689 | 188k | enum ssl_compliance_policy_t policy) { |
690 | 188k | switch (policy) { |
691 | 188k | case ssl_compliance_policy_none: |
692 | 188k | return true; |
693 | | |
694 | 0 | case ssl_compliance_policy_fips_202205: |
695 | 0 | switch (cipher_id) { |
696 | 0 | case TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff: |
697 | 0 | case TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff: |
698 | 0 | return true; |
699 | 0 | case TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff: |
700 | 0 | return false; |
701 | 0 | default: |
702 | 0 | assert(false); |
703 | 0 | return false; |
704 | 0 | } |
705 | | |
706 | 0 | case ssl_compliance_policy_wpa3_192_202304: |
707 | 0 | switch (cipher_id) { |
708 | 0 | case TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff: |
709 | 0 | return true; |
710 | 0 | case TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff: |
711 | 0 | case TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff: |
712 | 0 | return false; |
713 | 0 | default: |
714 | 0 | assert(false); |
715 | 0 | return false; |
716 | 0 | } |
717 | 188k | } |
718 | | |
719 | 0 | assert(false); |
720 | 0 | return false; |
721 | 188k | } |
722 | | |
723 | | const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw, |
724 | | uint16_t version, uint16_t group_id, |
725 | 834 | enum ssl_compliance_policy_t policy) { |
726 | 834 | if (CBS_len(&cipher_suites) % 2 != 0) { |
727 | 0 | return nullptr; |
728 | 0 | } |
729 | | |
730 | 834 | const SSL_CIPHER *best = nullptr; |
731 | 834 | CipherScorer scorer(has_aes_hw); |
732 | 834 | CipherScorer::Score best_score = scorer.MinScore(); |
733 | | |
734 | 12.6k | while (CBS_len(&cipher_suites) > 0) { |
735 | 11.7k | uint16_t cipher_suite; |
736 | 11.7k | if (!CBS_get_u16(&cipher_suites, &cipher_suite)) { |
737 | 0 | return nullptr; |
738 | 0 | } |
739 | | |
740 | | // Limit to TLS 1.3 ciphers we know about. |
741 | 11.7k | const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite); |
742 | 11.7k | if (candidate == nullptr || |
743 | 11.7k | SSL_CIPHER_get_min_version(candidate) > version || |
744 | 11.7k | SSL_CIPHER_get_max_version(candidate) < version) { |
745 | 10.6k | continue; |
746 | 10.6k | } |
747 | | |
748 | 1.09k | if (!ssl_tls13_cipher_meets_policy(SSL_CIPHER_get_protocol_id(candidate), |
749 | 1.09k | policy)) { |
750 | 0 | continue; |
751 | 0 | } |
752 | | |
753 | 1.09k | const CipherScorer::Score candidate_score = scorer.Evaluate(candidate); |
754 | | // |candidate_score| must be larger to displace the current choice. That way |
755 | | // the client's order controls between ciphers with an equal score. |
756 | 1.09k | if (candidate_score > best_score) { |
757 | 823 | best = candidate; |
758 | 823 | best_score = candidate_score; |
759 | 823 | } |
760 | 1.09k | } |
761 | | |
762 | 834 | return best; |
763 | 834 | } |
764 | | |
765 | | BSSL_NAMESPACE_END |