blob: f0ae8a2e98f2b648492005e0e95916e4c93c1165 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* 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
Kenny Rootb8494592015-09-25 02:29:14 +0000109#include <openssl/ssl.h>
110
Adam Langleyd9e397b2015-01-22 14:27:53 -0800111#include <assert.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -0800112#include <limits.h>
Adam Langleye9ada862015-05-11 17:20:37 -0700113#include <string.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -0800114
115#include <openssl/buf.h>
116#include <openssl/err.h>
117#include <openssl/evp.h>
118#include <openssl/mem.h>
119#include <openssl/rand.h>
120
Robert Sloan69939df2017-01-09 10:53:07 -0800121#include "../crypto/internal.h"
Adam Langleye9ada862015-05-11 17:20:37 -0700122#include "internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -0800123
124
Robert Sloan726e9d12018-09-11 11:45:04 -0700125BSSL_NAMESPACE_BEGIN
Robert Sloanb6d070c2017-07-24 08:40:01 -0700126
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700127static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800128
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700129int ssl3_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in,
Robert Sloane56da3e2017-06-26 08:26:42 -0700130 int len) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700131 assert(ssl_can_write(ssl));
Robert Sloanb6d070c2017-07-24 08:40:01 -0700132 assert(!ssl->s3->aead_write_ctx->is_null_cipher());
David Benjamin4969cc92016-04-22 15:02:23 -0400133
Robert Sloana27a6a42017-09-05 08:39:28 -0700134 *out_needs_handshake = false;
Robert Sloane56da3e2017-06-26 08:26:42 -0700135
Robert Sloan36272962017-10-23 10:28:39 -0700136 if (ssl->s3->write_shutdown != ssl_shutdown_none) {
137 OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
138 return -1;
139 }
140
David Benjamin4969cc92016-04-22 15:02:23 -0400141 unsigned tot, n, nw;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800142
Adam Langley4139edb2016-01-13 15:00:54 -0800143 assert(ssl->s3->wnum <= INT_MAX);
144 tot = ssl->s3->wnum;
145 ssl->s3->wnum = 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800146
Robert Sloana27a6a42017-09-05 08:39:28 -0700147 // Ensure that if we end up with a smaller value of data to write out than
148 // the the original len from a write which didn't complete for non-blocking
149 // I/O and also somehow ended up avoiding the check for this in
150 // ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to
151 // end up with (len-tot) as a large number that will then promptly send
152 // beyond the end of the users buffer ... so we trap and report the error in
153 // a way the user will notice.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800154 if (len < 0 || (size_t)len < tot) {
Kenny Rootb8494592015-09-25 02:29:14 +0000155 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800156 return -1;
157 }
158
Robert Sloane56da3e2017-06-26 08:26:42 -0700159 const int is_early_data_write =
160 !ssl->server && SSL_in_early_data(ssl) && ssl->s3->hs->can_early_write;
161
Robert Sloan4d1ac502017-02-06 08:36:14 -0800162 n = len - tot;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800163 for (;;) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700164 // max contains the maximum number of bytes that we can put into a record.
Adam Langley4139edb2016-01-13 15:00:54 -0800165 unsigned max = ssl->max_send_fragment;
Robert Sloancbf5ea62018-11-05 11:56:34 -0800166 if (is_early_data_write &&
167 max > ssl->session->ticket_max_early_data -
168 ssl->s3->hs->early_data_written) {
169 max =
170 ssl->session->ticket_max_early_data - ssl->s3->hs->early_data_written;
Robert Sloane56da3e2017-06-26 08:26:42 -0700171 if (max == 0) {
172 ssl->s3->wnum = tot;
Robert Sloana27a6a42017-09-05 08:39:28 -0700173 ssl->s3->hs->can_early_write = false;
174 *out_needs_handshake = true;
Robert Sloane56da3e2017-06-26 08:26:42 -0700175 return -1;
176 }
177 }
178
Adam Langleyd9e397b2015-01-22 14:27:53 -0800179 if (n > max) {
180 nw = max;
181 } else {
182 nw = n;
183 }
184
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700185 int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &in[tot], nw);
David Benjamin4969cc92016-04-22 15:02:23 -0400186 if (ret <= 0) {
Adam Langley4139edb2016-01-13 15:00:54 -0800187 ssl->s3->wnum = tot;
David Benjamin4969cc92016-04-22 15:02:23 -0400188 return ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800189 }
190
Robert Sloane56da3e2017-06-26 08:26:42 -0700191 if (is_early_data_write) {
192 ssl->s3->hs->early_data_written += ret;
193 }
194
Robert Sloan4d1ac502017-02-06 08:36:14 -0800195 if (ret == (int)n || (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
David Benjamin4969cc92016-04-22 15:02:23 -0400196 return tot + ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800197 }
198
David Benjamin4969cc92016-04-22 15:02:23 -0400199 n -= ret;
200 tot += ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800201 }
202}
203
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700204static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *in,
Adam Langleyfad63272015-11-12 12:15:39 -0800205 unsigned int len) {
Adam Langley4139edb2016-01-13 15:00:54 -0800206 if (ssl->s3->wpend_tot > (int)len ||
Steven Valdez909b19f2016-11-21 15:35:44 -0500207 (!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) &&
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700208 ssl->s3->wpend_buf != in) ||
Adam Langley4139edb2016-01-13 15:00:54 -0800209 ssl->s3->wpend_type != type) {
Adam Langleyfad63272015-11-12 12:15:39 -0800210 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY);
211 return -1;
212 }
213
Adam Langley4139edb2016-01-13 15:00:54 -0800214 int ret = ssl_write_buffer_flush(ssl);
Adam Langleyfad63272015-11-12 12:15:39 -0800215 if (ret <= 0) {
216 return ret;
217 }
Robert Sloana27a6a42017-09-05 08:39:28 -0700218 ssl->s3->wpend_pending = false;
Adam Langley4139edb2016-01-13 15:00:54 -0800219 return ssl->s3->wpend_ret;
Adam Langleyfad63272015-11-12 12:15:39 -0800220}
221
Robert Sloana27a6a42017-09-05 08:39:28 -0700222// do_ssl3_write writes an SSL record of the given type.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700223static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700224 // If there is still data from the previous record, flush it.
Robert Sloane56da3e2017-06-26 08:26:42 -0700225 if (ssl->s3->wpend_pending) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700226 return ssl3_write_pending(ssl, type, in, len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800227 }
228
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700229 SSLBuffer *buf = &ssl->s3->write_buffer;
230 if (len > SSL3_RT_MAX_PLAIN_LENGTH || buf->size() > 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000231 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800232 return -1;
233 }
234
235 if (len == 0) {
236 return 0;
237 }
238
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100239 if (!tls_flush_pending_hs_data(ssl)) {
240 return -1;
241 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700242 size_t flight_len = 0;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700243 if (ssl->s3->pending_flight != nullptr) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700244 flight_len =
245 ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset;
246 }
247
Steven Valdez909b19f2016-11-21 15:35:44 -0500248 size_t max_out = len + SSL_max_seal_overhead(ssl);
Robert Sloan572a4e22017-04-17 10:52:19 -0700249 if (max_out < len || max_out + flight_len < max_out) {
Kenny Rootb8494592015-09-25 02:29:14 +0000250 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langley1e4884f2015-09-24 10:57:52 -0700251 return -1;
252 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700253 max_out += flight_len;
254
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700255 if (!buf->EnsureCap(flight_len + ssl_seal_align_prefix_len(ssl), max_out)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000256 return -1;
257 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700258
Robert Sloana27a6a42017-09-05 08:39:28 -0700259 // Add any unflushed handshake data as a prefix. This may be a KeyUpdate
260 // acknowledgment or 0-RTT key change messages. |pending_flight| must be clear
261 // when data is added to |write_buffer| or it will be written in the wrong
262 // order.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700263 if (ssl->s3->pending_flight != nullptr) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700264 OPENSSL_memcpy(
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700265 buf->remaining().data(),
266 ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
Robert Sloan572a4e22017-04-17 10:52:19 -0700267 flight_len);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700268 ssl->s3->pending_flight.reset();
Robert Sloan572a4e22017-04-17 10:52:19 -0700269 ssl->s3->pending_flight_offset = 0;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700270 buf->DidWrite(flight_len);
Robert Sloan572a4e22017-04-17 10:52:19 -0700271 }
272
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700273 size_t ciphertext_len;
274 if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
275 buf->remaining().size(), type, in, len)) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700276 return -1;
277 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700278 buf->DidWrite(ciphertext_len);
Robert Sloan572a4e22017-04-17 10:52:19 -0700279
Robert Sloana27a6a42017-09-05 08:39:28 -0700280 // Now that we've made progress on the connection, uncork KeyUpdate
281 // acknowledgments.
282 ssl->s3->key_update_pending = false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800283
Robert Sloana27a6a42017-09-05 08:39:28 -0700284 // Memorize arguments so that ssl3_write_pending can detect bad write retries
285 // later.
Adam Langley4139edb2016-01-13 15:00:54 -0800286 ssl->s3->wpend_tot = len;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700287 ssl->s3->wpend_buf = in;
Adam Langley4139edb2016-01-13 15:00:54 -0800288 ssl->s3->wpend_type = type;
289 ssl->s3->wpend_ret = len;
Robert Sloana27a6a42017-09-05 08:39:28 -0700290 ssl->s3->wpend_pending = true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800291
Robert Sloana27a6a42017-09-05 08:39:28 -0700292 // We now just need to write the buffer.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700293 return ssl3_write_pending(ssl, type, in, len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800294}
295
Robert Sloan36272962017-10-23 10:28:39 -0700296ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
297 size_t *out_consumed, uint8_t *out_alert,
298 Span<uint8_t> in) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700299 assert(ssl_can_read(ssl));
Robert Sloanb6d070c2017-07-24 08:40:01 -0700300 assert(!ssl->s3->aead_read_ctx->is_null_cipher());
David Benjamin6e899c72016-06-09 18:02:18 -0400301
Robert Sloan36272962017-10-23 10:28:39 -0700302 uint8_t type;
303 Span<uint8_t> body;
304 auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in);
305 if (ret != ssl_open_record_success) {
306 return ret;
307 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400308
Robert Sloan36272962017-10-23 10:28:39 -0700309 const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl);
David Benjaminc895d6b2016-08-11 13:26:41 -0400310
Robert Sloan36272962017-10-23 10:28:39 -0700311 if (type == SSL3_RT_HANDSHAKE) {
Robert Sloan36272962017-10-23 10:28:39 -0700312 // Post-handshake data prior to TLS 1.3 is always renegotiation, which we
313 // never accept as a server. Otherwise |ssl3_get_message| will send
314 // |SSL_R_EXCESSIVE_MESSAGE_SIZE|.
315 if (ssl->server && ssl_protocol_version(ssl) < TLS1_3_VERSION) {
316 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
317 *out_alert = SSL_AD_NO_RENEGOTIATION;
318 return ssl_open_record_error;
David Benjaminc895d6b2016-08-11 13:26:41 -0400319 }
320
Robert Sloana51059f2018-11-12 13:38:50 -0800321 if (!tls_append_handshake_data(ssl, body)) {
Robert Sloan36272962017-10-23 10:28:39 -0700322 *out_alert = SSL_AD_INTERNAL_ERROR;
323 return ssl_open_record_error;
324 }
325 return ssl_open_record_discard;
David Benjamin6e899c72016-06-09 18:02:18 -0400326 }
327
Robert Sloan36272962017-10-23 10:28:39 -0700328 if (type != SSL3_RT_APPLICATION_DATA) {
David Benjamin6e899c72016-06-09 18:02:18 -0400329 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
Robert Sloan36272962017-10-23 10:28:39 -0700330 *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
331 return ssl_open_record_error;
David Benjamin6e899c72016-06-09 18:02:18 -0400332 }
333
Robert Sloan36272962017-10-23 10:28:39 -0700334 if (is_early_data_read) {
335 if (body.size() > kMaxEarlyDataAccepted - ssl->s3->hs->early_data_read) {
336 OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_READ_EARLY_DATA);
337 *out_alert = SSL3_AD_UNEXPECTED_MESSAGE;
338 return ssl_open_record_error;
339 }
340
341 ssl->s3->hs->early_data_read += body.size();
Adam Langley4139edb2016-01-13 15:00:54 -0800342 }
343
Robert Sloan36272962017-10-23 10:28:39 -0700344 if (body.empty()) {
345 return ssl_open_record_discard;
346 }
Adam Langley4139edb2016-01-13 15:00:54 -0800347
Robert Sloan36272962017-10-23 10:28:39 -0700348 *out = body;
349 return ssl_open_record_success;
Adam Langley4139edb2016-01-13 15:00:54 -0800350}
351
Robert Sloan36272962017-10-23 10:28:39 -0700352ssl_open_record_t ssl3_open_change_cipher_spec(SSL *ssl, size_t *out_consumed,
353 uint8_t *out_alert,
354 Span<uint8_t> in) {
355 uint8_t type;
356 Span<uint8_t> body;
357 auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in);
358 if (ret != ssl_open_record_success) {
359 return ret;
David Benjamin6e899c72016-06-09 18:02:18 -0400360 }
Robert Sloan36272962017-10-23 10:28:39 -0700361
362 if (type != SSL3_RT_CHANGE_CIPHER_SPEC) {
363 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
364 *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
365 return ssl_open_record_error;
366 }
367
368 if (body.size() != 1 || body[0] != SSL3_MT_CCS) {
369 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
370 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
371 return ssl_open_record_error;
372 }
373
374 ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, body);
375 return ssl_open_record_success;
Adam Langleyf4e42722015-06-04 17:45:09 -0700376}
377
Robert Sloan921ef2c2017-10-17 09:02:20 -0700378int ssl_send_alert(SSL *ssl, int level, int desc) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700379 // It is illegal to send an alert when we've already sent a closing one.
Robert Sloan921ef2c2017-10-17 09:02:20 -0700380 if (ssl->s3->write_shutdown != ssl_shutdown_none) {
David Benjamind316cba2016-06-02 16:17:39 -0400381 OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
382 return -1;
383 }
384
Robert Sloan4d1ac502017-02-06 08:36:14 -0800385 if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) {
Robert Sloan921ef2c2017-10-17 09:02:20 -0700386 ssl->s3->write_shutdown = ssl_shutdown_close_notify;
Robert Sloan4d1ac502017-02-06 08:36:14 -0800387 } else {
388 assert(level == SSL3_AL_FATAL);
Robert Sloan921ef2c2017-10-17 09:02:20 -0700389 assert(desc != SSL_AD_CLOSE_NOTIFY);
Robert Sloan36272962017-10-23 10:28:39 -0700390 ssl->s3->write_shutdown = ssl_shutdown_error;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800391 }
392
Adam Langley4139edb2016-01-13 15:00:54 -0800393 ssl->s3->alert_dispatch = 1;
394 ssl->s3->send_alert[0] = level;
395 ssl->s3->send_alert[1] = desc;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700396 if (ssl->s3->write_buffer.empty()) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700397 // Nothing is being written out, so the alert may be dispatched
398 // immediately.
David Benjaminc895d6b2016-08-11 13:26:41 -0400399 return ssl->method->dispatch_alert(ssl);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800400 }
401
Robert Sloana27a6a42017-09-05 08:39:28 -0700402 // The alert will be dispatched later.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800403 return -1;
404}
405
Adam Langley4139edb2016-01-13 15:00:54 -0800406int ssl3_dispatch_alert(SSL *ssl) {
Robert Sloancbf5ea62018-11-05 11:56:34 -0800407 if (ssl->ctx->quic_method) {
408 if (!ssl->ctx->quic_method->send_alert(ssl, ssl->s3->write_level,
409 ssl->s3->send_alert[1])) {
410 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
411 return 0;
412 }
413 } else {
414 int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
415 if (ret <= 0) {
416 return ret;
417 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800418 }
Robert Sloancbf5ea62018-11-05 11:56:34 -0800419
Robert Sloan4d1ac502017-02-06 08:36:14 -0800420 ssl->s3->alert_dispatch = 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800421
Robert Sloana27a6a42017-09-05 08:39:28 -0700422 // If the alert is fatal, flush the BIO now.
David Benjamin4969cc92016-04-22 15:02:23 -0400423 if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100424 BIO_flush(ssl->wbio.get());
David Benjamin4969cc92016-04-22 15:02:23 -0400425 }
426
Robert Sloan921ef2c2017-10-17 09:02:20 -0700427 ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);
David Benjamin4969cc92016-04-22 15:02:23 -0400428
David Benjamin6e899c72016-06-09 18:02:18 -0400429 int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
430 ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
David Benjamin4969cc92016-04-22 15:02:23 -0400431
432 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800433}
Robert Sloanb6d070c2017-07-24 08:40:01 -0700434
Robert Sloan726e9d12018-09-11 11:45:04 -0700435BSSL_NAMESPACE_END