blob: abc6798e6be30704dc883f59a1793d61f5f3db99 [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
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100235 if (!tls_flush_pending_hs_data(ssl)) {
236 return -1;
237 }
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800238
Robert Sloan572a4e22017-04-17 10:52:19 -0700239 size_t flight_len = 0;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700240 if (ssl->s3->pending_flight != nullptr) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700241 flight_len =
242 ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset;
243 }
244
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800245 size_t max_out = flight_len;
246 if (len > 0) {
247 const size_t max_ciphertext_len = len + SSL_max_seal_overhead(ssl);
248 if (max_ciphertext_len < len || max_out + max_ciphertext_len < max_out) {
249 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
250 return -1;
251 }
252 max_out += max_ciphertext_len;
Adam Langley1e4884f2015-09-24 10:57:52 -0700253 }
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800254
255 if (max_out == 0) {
256 return 0;
257 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700258
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700259 if (!buf->EnsureCap(flight_len + ssl_seal_align_prefix_len(ssl), max_out)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000260 return -1;
261 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700262
Robert Sloana27a6a42017-09-05 08:39:28 -0700263 // Add any unflushed handshake data as a prefix. This may be a KeyUpdate
264 // acknowledgment or 0-RTT key change messages. |pending_flight| must be clear
265 // when data is added to |write_buffer| or it will be written in the wrong
266 // order.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700267 if (ssl->s3->pending_flight != nullptr) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700268 OPENSSL_memcpy(
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700269 buf->remaining().data(),
270 ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
Robert Sloan572a4e22017-04-17 10:52:19 -0700271 flight_len);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700272 ssl->s3->pending_flight.reset();
Robert Sloan572a4e22017-04-17 10:52:19 -0700273 ssl->s3->pending_flight_offset = 0;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700274 buf->DidWrite(flight_len);
Robert Sloan572a4e22017-04-17 10:52:19 -0700275 }
276
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800277 if (len > 0) {
278 size_t ciphertext_len;
279 if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
280 buf->remaining().size(), type, in, len)) {
281 return -1;
282 }
283 buf->DidWrite(ciphertext_len);
Robert Sloan572a4e22017-04-17 10:52:19 -0700284 }
Robert Sloan572a4e22017-04-17 10:52:19 -0700285
Robert Sloana27a6a42017-09-05 08:39:28 -0700286 // Now that we've made progress on the connection, uncork KeyUpdate
287 // acknowledgments.
288 ssl->s3->key_update_pending = false;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800289
Robert Sloana27a6a42017-09-05 08:39:28 -0700290 // Memorize arguments so that ssl3_write_pending can detect bad write retries
291 // later.
Adam Langley4139edb2016-01-13 15:00:54 -0800292 ssl->s3->wpend_tot = len;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700293 ssl->s3->wpend_buf = in;
Adam Langley4139edb2016-01-13 15:00:54 -0800294 ssl->s3->wpend_type = type;
295 ssl->s3->wpend_ret = len;
Robert Sloana27a6a42017-09-05 08:39:28 -0700296 ssl->s3->wpend_pending = true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800297
Robert Sloana27a6a42017-09-05 08:39:28 -0700298 // We now just need to write the buffer.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700299 return ssl3_write_pending(ssl, type, in, len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800300}
301
Robert Sloan36272962017-10-23 10:28:39 -0700302ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
303 size_t *out_consumed, uint8_t *out_alert,
304 Span<uint8_t> in) {
Robert Sloan6d0d00e2017-03-27 07:13:07 -0700305 assert(ssl_can_read(ssl));
Robert Sloanb6d070c2017-07-24 08:40:01 -0700306 assert(!ssl->s3->aead_read_ctx->is_null_cipher());
David Benjamin6e899c72016-06-09 18:02:18 -0400307
Robert Sloan36272962017-10-23 10:28:39 -0700308 uint8_t type;
309 Span<uint8_t> body;
310 auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in);
311 if (ret != ssl_open_record_success) {
312 return ret;
313 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400314
Robert Sloan36272962017-10-23 10:28:39 -0700315 const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl);
David Benjaminc895d6b2016-08-11 13:26:41 -0400316
Robert Sloan36272962017-10-23 10:28:39 -0700317 if (type == SSL3_RT_HANDSHAKE) {
Robert Sloan36272962017-10-23 10:28:39 -0700318 // Post-handshake data prior to TLS 1.3 is always renegotiation, which we
319 // never accept as a server. Otherwise |ssl3_get_message| will send
320 // |SSL_R_EXCESSIVE_MESSAGE_SIZE|.
321 if (ssl->server && ssl_protocol_version(ssl) < TLS1_3_VERSION) {
322 OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
323 *out_alert = SSL_AD_NO_RENEGOTIATION;
324 return ssl_open_record_error;
David Benjaminc895d6b2016-08-11 13:26:41 -0400325 }
326
Robert Sloana51059f2018-11-12 13:38:50 -0800327 if (!tls_append_handshake_data(ssl, body)) {
Robert Sloan36272962017-10-23 10:28:39 -0700328 *out_alert = SSL_AD_INTERNAL_ERROR;
329 return ssl_open_record_error;
330 }
331 return ssl_open_record_discard;
David Benjamin6e899c72016-06-09 18:02:18 -0400332 }
333
Robert Sloan36272962017-10-23 10:28:39 -0700334 if (type != SSL3_RT_APPLICATION_DATA) {
David Benjamin6e899c72016-06-09 18:02:18 -0400335 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
Robert Sloan36272962017-10-23 10:28:39 -0700336 *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
337 return ssl_open_record_error;
David Benjamin6e899c72016-06-09 18:02:18 -0400338 }
339
Robert Sloan36272962017-10-23 10:28:39 -0700340 if (is_early_data_read) {
341 if (body.size() > kMaxEarlyDataAccepted - ssl->s3->hs->early_data_read) {
342 OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_READ_EARLY_DATA);
343 *out_alert = SSL3_AD_UNEXPECTED_MESSAGE;
344 return ssl_open_record_error;
345 }
346
347 ssl->s3->hs->early_data_read += body.size();
Adam Langley4139edb2016-01-13 15:00:54 -0800348 }
349
Robert Sloan36272962017-10-23 10:28:39 -0700350 if (body.empty()) {
351 return ssl_open_record_discard;
352 }
Adam Langley4139edb2016-01-13 15:00:54 -0800353
Robert Sloan36272962017-10-23 10:28:39 -0700354 *out = body;
355 return ssl_open_record_success;
Adam Langley4139edb2016-01-13 15:00:54 -0800356}
357
Robert Sloan36272962017-10-23 10:28:39 -0700358ssl_open_record_t ssl3_open_change_cipher_spec(SSL *ssl, size_t *out_consumed,
359 uint8_t *out_alert,
360 Span<uint8_t> in) {
361 uint8_t type;
362 Span<uint8_t> body;
363 auto ret = tls_open_record(ssl, &type, &body, out_consumed, out_alert, in);
364 if (ret != ssl_open_record_success) {
365 return ret;
David Benjamin6e899c72016-06-09 18:02:18 -0400366 }
Robert Sloan36272962017-10-23 10:28:39 -0700367
368 if (type != SSL3_RT_CHANGE_CIPHER_SPEC) {
369 OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
370 *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
371 return ssl_open_record_error;
372 }
373
374 if (body.size() != 1 || body[0] != SSL3_MT_CCS) {
375 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
376 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
377 return ssl_open_record_error;
378 }
379
380 ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, body);
381 return ssl_open_record_success;
Adam Langleyf4e42722015-06-04 17:45:09 -0700382}
383
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000384int ssl_send_alert(SSL *ssl, int level, int desc) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700385 // It is illegal to send an alert when we've already sent a closing one.
Robert Sloan921ef2c2017-10-17 09:02:20 -0700386 if (ssl->s3->write_shutdown != ssl_shutdown_none) {
David Benjamind316cba2016-06-02 16:17:39 -0400387 OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
388 return -1;
389 }
390
Robert Sloan4d1ac502017-02-06 08:36:14 -0800391 if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) {
Robert Sloan921ef2c2017-10-17 09:02:20 -0700392 ssl->s3->write_shutdown = ssl_shutdown_close_notify;
Robert Sloan4d1ac502017-02-06 08:36:14 -0800393 } else {
394 assert(level == SSL3_AL_FATAL);
Robert Sloan921ef2c2017-10-17 09:02:20 -0700395 assert(desc != SSL_AD_CLOSE_NOTIFY);
Robert Sloan36272962017-10-23 10:28:39 -0700396 ssl->s3->write_shutdown = ssl_shutdown_error;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800397 }
398
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000399 ssl->s3->alert_dispatch = 1;
Adam Langley4139edb2016-01-13 15:00:54 -0800400 ssl->s3->send_alert[0] = level;
401 ssl->s3->send_alert[1] = desc;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700402 if (ssl->s3->write_buffer.empty()) {
Robert Sloana27a6a42017-09-05 08:39:28 -0700403 // Nothing is being written out, so the alert may be dispatched
404 // immediately.
David Benjaminc895d6b2016-08-11 13:26:41 -0400405 return ssl->method->dispatch_alert(ssl);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800406 }
407
Robert Sloana27a6a42017-09-05 08:39:28 -0700408 // The alert will be dispatched later.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800409 return -1;
410}
411
Adam Langley4139edb2016-01-13 15:00:54 -0800412int ssl3_dispatch_alert(SSL *ssl) {
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800413 if (ssl->quic_method) {
414 if (!ssl->quic_method->send_alert(ssl, ssl->s3->write_level,
415 ssl->s3->send_alert[1])) {
Robert Sloancbf5ea62018-11-05 11:56:34 -0800416 OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
417 return 0;
418 }
419 } else {
420 int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
421 if (ret <= 0) {
422 return ret;
423 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800424 }
Robert Sloancbf5ea62018-11-05 11:56:34 -0800425
Srinivas Paladugudd42a612019-08-09 19:30:39 +0000426 ssl->s3->alert_dispatch = 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800427
Robert Sloana27a6a42017-09-05 08:39:28 -0700428 // If the alert is fatal, flush the BIO now.
David Benjamin4969cc92016-04-22 15:02:23 -0400429 if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100430 BIO_flush(ssl->wbio.get());
David Benjamin4969cc92016-04-22 15:02:23 -0400431 }
432
Robert Sloan921ef2c2017-10-17 09:02:20 -0700433 ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);
David Benjamin4969cc92016-04-22 15:02:23 -0400434
David Benjamin6e899c72016-06-09 18:02:18 -0400435 int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
436 ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
David Benjamin4969cc92016-04-22 15:02:23 -0400437
438 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800439}
Robert Sloanb6d070c2017-07-24 08:40:01 -0700440
Robert Sloan726e9d12018-09-11 11:45:04 -0700441BSSL_NAMESPACE_END