/src/boringssl/ssl/s3_pkt.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 | | #include <openssl/ssl.h> |
110 | | |
111 | | #include <assert.h> |
112 | | #include <limits.h> |
113 | | #include <string.h> |
114 | | |
115 | | #include <algorithm> |
116 | | |
117 | | #include <openssl/err.h> |
118 | | #include <openssl/evp.h> |
119 | | #include <openssl/mem.h> |
120 | | #include <openssl/rand.h> |
121 | | |
122 | | #include "../crypto/err/internal.h" |
123 | | #include "../crypto/internal.h" |
124 | | #include "internal.h" |
125 | | |
126 | | |
127 | | BSSL_NAMESPACE_BEGIN |
128 | | |
129 | | static int do_tls_write(SSL *ssl, size_t *out_bytes_written, uint8_t type, |
130 | | Span<const uint8_t> in); |
131 | | |
132 | | int tls_write_app_data(SSL *ssl, bool *out_needs_handshake, |
133 | 0 | size_t *out_bytes_written, Span<const uint8_t> in) { |
134 | 0 | assert(ssl_can_write(ssl)); |
135 | 0 | assert(!ssl->s3->aead_write_ctx->is_null_cipher()); |
136 | | |
137 | 0 | *out_needs_handshake = false; |
138 | |
|
139 | 0 | if (ssl->s3->write_shutdown != ssl_shutdown_none) { |
140 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); |
141 | 0 | return -1; |
142 | 0 | } |
143 | | |
144 | 0 | size_t total_bytes_written = ssl->s3->unreported_bytes_written; |
145 | 0 | if (in.size() < total_bytes_written) { |
146 | | // This can happen if the caller disables |SSL_MODE_ENABLE_PARTIAL_WRITE|, |
147 | | // asks us to write some input of length N, we successfully encrypt M bytes |
148 | | // and write it, but fail to write the rest. We will report |
149 | | // |SSL_ERROR_WANT_WRITE|. If the caller then retries with fewer than M |
150 | | // bytes, we cannot satisfy that request. The caller is required to always |
151 | | // retry with at least as many bytes as the previous attempt. |
152 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH); |
153 | 0 | return -1; |
154 | 0 | } |
155 | | |
156 | 0 | in = in.subspan(total_bytes_written); |
157 | |
|
158 | 0 | const bool is_early_data_write = |
159 | 0 | !ssl->server && SSL_in_early_data(ssl) && ssl->s3->hs->can_early_write; |
160 | 0 | for (;;) { |
161 | 0 | size_t max_send_fragment = ssl->max_send_fragment; |
162 | 0 | if (is_early_data_write) { |
163 | 0 | SSL_HANDSHAKE *hs = ssl->s3->hs.get(); |
164 | 0 | if (hs->early_data_written >= hs->early_session->ticket_max_early_data) { |
165 | 0 | ssl->s3->unreported_bytes_written = total_bytes_written; |
166 | 0 | hs->can_early_write = false; |
167 | 0 | *out_needs_handshake = true; |
168 | 0 | return -1; |
169 | 0 | } |
170 | 0 | max_send_fragment = std::min( |
171 | 0 | max_send_fragment, size_t{hs->early_session->ticket_max_early_data - |
172 | 0 | hs->early_data_written}); |
173 | 0 | } |
174 | | |
175 | 0 | const size_t to_write = std::min(max_send_fragment, in.size()); |
176 | 0 | size_t bytes_written; |
177 | 0 | int ret = do_tls_write(ssl, &bytes_written, SSL3_RT_APPLICATION_DATA, |
178 | 0 | in.subspan(0, to_write)); |
179 | 0 | if (ret <= 0) { |
180 | 0 | ssl->s3->unreported_bytes_written = total_bytes_written; |
181 | 0 | return ret; |
182 | 0 | } |
183 | | |
184 | | // Note |bytes_written| may be less than |to_write| if there was a pending |
185 | | // record from a smaller write attempt. |
186 | 0 | assert(bytes_written <= to_write); |
187 | 0 | total_bytes_written += bytes_written; |
188 | 0 | in = in.subspan(bytes_written); |
189 | 0 | if (is_early_data_write) { |
190 | 0 | ssl->s3->hs->early_data_written += bytes_written; |
191 | 0 | } |
192 | |
|
193 | 0 | if (in.empty() || (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) { |
194 | 0 | ssl->s3->unreported_bytes_written = 0; |
195 | 0 | *out_bytes_written = total_bytes_written; |
196 | 0 | return 1; |
197 | 0 | } |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | | // do_tls_write writes an SSL record of the given type. On success, it sets |
202 | | // |*out_bytes_written| to number of bytes successfully written and returns one. |
203 | | // On error, it returns a value <= 0 from the underlying |BIO|. |
204 | | static int do_tls_write(SSL *ssl, size_t *out_bytes_written, uint8_t type, |
205 | 2.28k | Span<const uint8_t> in) { |
206 | | // If there is a pending write, the retry must be consistent. |
207 | 2.28k | if (!ssl->s3->pending_write.empty() && |
208 | 2.28k | (ssl->s3->pending_write.size() > in.size() || |
209 | 0 | (!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) && |
210 | 0 | ssl->s3->pending_write.data() != in.data()) || |
211 | 0 | ssl->s3->pending_write_type != type)) { |
212 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY); |
213 | 0 | return -1; |
214 | 0 | } |
215 | | |
216 | | // Flush any unwritten data to the transport. There may be data to flush even |
217 | | // if |wpend_tot| is zero. |
218 | 2.28k | int ret = ssl_write_buffer_flush(ssl); |
219 | 2.28k | if (ret <= 0) { |
220 | 0 | return ret; |
221 | 0 | } |
222 | | |
223 | | // If there is a pending write, we just completed it. Report it to the caller. |
224 | 2.28k | if (!ssl->s3->pending_write.empty()) { |
225 | 0 | *out_bytes_written = ssl->s3->pending_write.size(); |
226 | 0 | ssl->s3->pending_write = {}; |
227 | 0 | return 1; |
228 | 0 | } |
229 | | |
230 | 2.28k | SSLBuffer *buf = &ssl->s3->write_buffer; |
231 | 2.28k | if (in.size() > SSL3_RT_MAX_PLAIN_LENGTH || buf->size() > 0) { |
232 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
233 | 0 | return -1; |
234 | 0 | } |
235 | | |
236 | 2.28k | if (!tls_flush_pending_hs_data(ssl)) { |
237 | 0 | return -1; |
238 | 0 | } |
239 | | |
240 | | // We may have unflushed handshake data that must be written before |in|. This |
241 | | // may be a KeyUpdate acknowledgment, 0-RTT key change messages, or a |
242 | | // NewSessionTicket. |
243 | 2.28k | Span<const uint8_t> pending_flight; |
244 | 2.28k | if (ssl->s3->pending_flight != nullptr) { |
245 | 98 | pending_flight = MakeConstSpan( |
246 | 98 | reinterpret_cast<const uint8_t *>(ssl->s3->pending_flight->data), |
247 | 98 | ssl->s3->pending_flight->length); |
248 | 98 | pending_flight = pending_flight.subspan(ssl->s3->pending_flight_offset); |
249 | 98 | } |
250 | | |
251 | 2.28k | size_t max_out = pending_flight.size(); |
252 | 2.28k | if (!in.empty()) { |
253 | 2.28k | const size_t max_ciphertext_len = in.size() + SSL_max_seal_overhead(ssl); |
254 | 2.28k | if (max_ciphertext_len < in.size() || |
255 | 2.28k | max_out + max_ciphertext_len < max_out) { |
256 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); |
257 | 0 | return -1; |
258 | 0 | } |
259 | 2.28k | max_out += max_ciphertext_len; |
260 | 2.28k | } |
261 | | |
262 | 2.28k | if (max_out == 0) { |
263 | | // Nothing to write. |
264 | 0 | *out_bytes_written = 0; |
265 | 0 | return 1; |
266 | 0 | } |
267 | | |
268 | 2.28k | if (!buf->EnsureCap(pending_flight.size() + ssl_seal_align_prefix_len(ssl), |
269 | 2.28k | max_out)) { |
270 | 0 | return -1; |
271 | 0 | } |
272 | | |
273 | | // Copy |pending_flight| to the output. |
274 | 2.28k | if (!pending_flight.empty()) { |
275 | 98 | OPENSSL_memcpy(buf->remaining().data(), pending_flight.data(), |
276 | 98 | pending_flight.size()); |
277 | 98 | ssl->s3->pending_flight.reset(); |
278 | 98 | ssl->s3->pending_flight_offset = 0; |
279 | 98 | buf->DidWrite(pending_flight.size()); |
280 | 98 | } |
281 | | |
282 | 2.28k | if (!in.empty()) { |
283 | 2.28k | size_t ciphertext_len; |
284 | 2.28k | if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len, |
285 | 2.28k | buf->remaining().size(), type, in.data(), in.size())) { |
286 | 0 | return -1; |
287 | 0 | } |
288 | 2.28k | buf->DidWrite(ciphertext_len); |
289 | 2.28k | } |
290 | | |
291 | | // Now that we've made progress on the connection, uncork KeyUpdate |
292 | | // acknowledgments. |
293 | 2.28k | ssl->s3->key_update_pending = false; |
294 | | |
295 | | // Flush the write buffer. |
296 | 2.28k | ret = ssl_write_buffer_flush(ssl); |
297 | 2.28k | if (ret <= 0) { |
298 | | // Track the unfinished write. |
299 | 0 | if (!in.empty()) { |
300 | 0 | ssl->s3->pending_write = in; |
301 | 0 | ssl->s3->pending_write_type = type; |
302 | 0 | } |
303 | 0 | return ret; |
304 | 0 | } |
305 | | |
306 | 2.28k | *out_bytes_written = in.size(); |
307 | 2.28k | return 1; |
308 | 2.28k | } |
309 | | |
310 | | ssl_open_record_t tls_open_app_data(SSL *ssl, Span<uint8_t> *out, |
311 | | size_t *out_consumed, uint8_t *out_alert, |
312 | 31.3k | Span<uint8_t> in) { |
313 | 31.3k | assert(ssl_can_read(ssl)); |
314 | 0 | assert(!ssl->s3->aead_read_ctx->is_null_cipher()); |
315 | | |
316 | 0 | uint8_t type; |
317 | 31.3k | Span<uint8_t> body; |
318 | 31.3k | auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in); |
319 | 31.3k | if (ret != ssl_open_record_success) { |
320 | 20.5k | return ret; |
321 | 20.5k | } |
322 | | |
323 | 10.7k | const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl); |
324 | | |
325 | 10.7k | if (type == SSL3_RT_HANDSHAKE) { |
326 | | // Post-handshake data prior to TLS 1.3 is always renegotiation, which we |
327 | | // never accept as a server. Otherwise |tls_get_message| will send |
328 | | // |SSL_R_EXCESSIVE_MESSAGE_SIZE|. |
329 | 6.49k | if (ssl->server && ssl_protocol_version(ssl) < TLS1_3_VERSION) { |
330 | 4 | OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION); |
331 | 4 | *out_alert = SSL_AD_NO_RENEGOTIATION; |
332 | 4 | return ssl_open_record_error; |
333 | 4 | } |
334 | | |
335 | 6.49k | if (!tls_append_handshake_data(ssl, body)) { |
336 | 0 | *out_alert = SSL_AD_INTERNAL_ERROR; |
337 | 0 | return ssl_open_record_error; |
338 | 0 | } |
339 | 6.49k | return ssl_open_record_discard; |
340 | 6.49k | } |
341 | | |
342 | 4.25k | if (type != SSL3_RT_APPLICATION_DATA) { |
343 | 18 | OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); |
344 | 18 | *out_alert = SSL_AD_UNEXPECTED_MESSAGE; |
345 | 18 | return ssl_open_record_error; |
346 | 18 | } |
347 | | |
348 | 4.24k | if (is_early_data_read) { |
349 | 54 | if (body.size() > kMaxEarlyDataAccepted - ssl->s3->hs->early_data_read) { |
350 | 1 | OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_READ_EARLY_DATA); |
351 | 1 | *out_alert = SSL3_AD_UNEXPECTED_MESSAGE; |
352 | 1 | return ssl_open_record_error; |
353 | 1 | } |
354 | | |
355 | 53 | ssl->s3->hs->early_data_read += body.size(); |
356 | 53 | } |
357 | | |
358 | 4.23k | if (body.empty()) { |
359 | 1.44k | return ssl_open_record_discard; |
360 | 1.44k | } |
361 | | |
362 | 2.79k | *out = body; |
363 | 2.79k | return ssl_open_record_success; |
364 | 4.23k | } |
365 | | |
366 | | ssl_open_record_t tls_open_change_cipher_spec(SSL *ssl, size_t *out_consumed, |
367 | | uint8_t *out_alert, |
368 | 2.64k | Span<uint8_t> in) { |
369 | 2.64k | uint8_t type; |
370 | 2.64k | Span<uint8_t> body; |
371 | 2.64k | auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in); |
372 | 2.64k | if (ret != ssl_open_record_success) { |
373 | 2.14k | return ret; |
374 | 2.14k | } |
375 | | |
376 | 493 | if (type != SSL3_RT_CHANGE_CIPHER_SPEC) { |
377 | 4 | OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); |
378 | 4 | *out_alert = SSL_AD_UNEXPECTED_MESSAGE; |
379 | 4 | return ssl_open_record_error; |
380 | 4 | } |
381 | | |
382 | 489 | if (body.size() != 1 || body[0] != SSL3_MT_CCS) { |
383 | 9 | OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); |
384 | 9 | *out_alert = SSL_AD_ILLEGAL_PARAMETER; |
385 | 9 | return ssl_open_record_error; |
386 | 9 | } |
387 | | |
388 | 480 | ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, body); |
389 | 480 | return ssl_open_record_success; |
390 | 489 | } |
391 | | |
392 | 2.28k | void ssl_send_alert(SSL *ssl, int level, int desc) { |
393 | | // This function is called in response to a fatal error from the peer. Ignore |
394 | | // any failures writing the alert and report only the original error. In |
395 | | // particular, if the transport uses |SSL_write|, our existing error will be |
396 | | // clobbered so we must save and restore the error queue. See |
397 | | // https://crbug.com/959305. |
398 | | // |
399 | | // TODO(davidben): Return the alert out of the handshake, rather than calling |
400 | | // this function internally everywhere. |
401 | | // |
402 | | // TODO(davidben): This does not allow retrying if the alert hit EAGAIN. See |
403 | | // https://crbug.com/boringssl/130. |
404 | 2.28k | UniquePtr<ERR_SAVE_STATE> err_state(ERR_save_state()); |
405 | 2.28k | ssl_send_alert_impl(ssl, level, desc); |
406 | 2.28k | ERR_restore_state(err_state.get()); |
407 | 2.28k | } |
408 | | |
409 | 2.28k | int ssl_send_alert_impl(SSL *ssl, int level, int desc) { |
410 | | // It is illegal to send an alert when we've already sent a closing one. |
411 | 2.28k | if (ssl->s3->write_shutdown != ssl_shutdown_none) { |
412 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); |
413 | 0 | return -1; |
414 | 0 | } |
415 | | |
416 | 2.28k | if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) { |
417 | 0 | ssl->s3->write_shutdown = ssl_shutdown_close_notify; |
418 | 2.28k | } else { |
419 | 2.28k | assert(level == SSL3_AL_FATAL); |
420 | 0 | assert(desc != SSL_AD_CLOSE_NOTIFY); |
421 | 0 | ssl->s3->write_shutdown = ssl_shutdown_error; |
422 | 2.28k | } |
423 | | |
424 | 0 | ssl->s3->alert_dispatch = true; |
425 | 2.28k | ssl->s3->send_alert[0] = level; |
426 | 2.28k | ssl->s3->send_alert[1] = desc; |
427 | 2.28k | if (ssl->s3->write_buffer.empty()) { |
428 | | // Nothing is being written out, so the alert may be dispatched |
429 | | // immediately. |
430 | 2.28k | return ssl->method->dispatch_alert(ssl); |
431 | 2.28k | } |
432 | | |
433 | | // The alert will be dispatched later. |
434 | 0 | return -1; |
435 | 2.28k | } |
436 | | |
437 | 2.28k | int tls_dispatch_alert(SSL *ssl) { |
438 | 2.28k | if (ssl->quic_method) { |
439 | 0 | if (!ssl->quic_method->send_alert(ssl, ssl->s3->write_level, |
440 | 0 | ssl->s3->send_alert[1])) { |
441 | 0 | OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR); |
442 | 0 | return 0; |
443 | 0 | } |
444 | 2.28k | } else { |
445 | 2.28k | size_t bytes_written; |
446 | 2.28k | int ret = |
447 | 2.28k | do_tls_write(ssl, &bytes_written, SSL3_RT_ALERT, ssl->s3->send_alert); |
448 | 2.28k | if (ret <= 0) { |
449 | 0 | return ret; |
450 | 0 | } |
451 | 2.28k | assert(bytes_written == 2); |
452 | 2.28k | } |
453 | | |
454 | 2.28k | ssl->s3->alert_dispatch = false; |
455 | | |
456 | | // If the alert is fatal, flush the BIO now. |
457 | 2.28k | if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) { |
458 | 2.28k | BIO_flush(ssl->wbio.get()); |
459 | 2.28k | } |
460 | | |
461 | 2.28k | ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert); |
462 | | |
463 | 2.28k | int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1]; |
464 | 2.28k | ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert); |
465 | | |
466 | 2.28k | return 1; |
467 | 2.28k | } |
468 | | |
469 | | BSSL_NAMESPACE_END |