1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com).
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to.  The following conditions
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed.
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package.
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in the
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    documentation and/or other materials provided with the distribution.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    must display the following acknowledgement:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes cryptographic software written by
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *     Eric Young (eay@cryptsoft.com)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    being used are not cryptographic related :-).
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE.
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.]
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    openssl-core@openssl.org.
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
109b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <openssl/ssl.h>
110b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <assert.h>
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <limits.h>
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <string.h>
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/buf.h>
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/evp.h>
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/rand.h>
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
12169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan#include "../crypto/internal.h"
122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "internal.h"
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
127b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* ssl3_get_record reads a new input record. On success, it places it in
128b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
129b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * more data is needed. */
130b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic int ssl3_get_record(SSL *ssl) {
131b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootagain:
132d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  switch (ssl->s3->recv_shutdown) {
133d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    case ssl_shutdown_none:
134d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin      break;
135d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    case ssl_shutdown_fatal_alert:
136d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin      OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
137d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin      return -1;
138d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    case ssl_shutdown_close_notify:
139d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin      return 0;
140d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  }
141d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin
1426e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  CBS body;
1435d625781eb8ff5cc8111d2302efe900103bf0adeRobert Sloan  uint8_t type, alert = SSL_AD_DECODE_ERROR;
1446e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  size_t consumed;
1456e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  enum ssl_open_record_t open_ret =
1466e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      tls_open_record(ssl, &type, &body, &consumed, &alert,
1476e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin                      ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
1486e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  if (open_ret != ssl_open_record_partial) {
1496e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    ssl_read_buffer_consume(ssl, consumed);
150b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
1516e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  switch (open_ret) {
1526e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    case ssl_open_record_partial: {
1536e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      int read_ret = ssl_read_buffer_extend_to(ssl, consumed);
1546e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      if (read_ret <= 0) {
1556e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin        return read_ret;
1566e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      }
1576e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      goto again;
1586e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    }
159b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
160b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_success:
1616e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      if (CBS_len(&body) > 0xffff) {
162b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
163b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        return -1;
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
166b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      SSL3_RECORD *rr = &ssl->s3->rrec;
167b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      rr->type = type;
1686e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      rr->length = (uint16_t)CBS_len(&body);
1696e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      rr->data = (uint8_t *)CBS_data(&body);
170b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      return 1;
171b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
172b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_discard:
173b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      goto again;
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1756e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    case ssl_open_record_close_notify:
1766e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      return 0;
1776e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin
1786e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    case ssl_open_record_fatal_alert:
1796e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      return -1;
1806e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin
181b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_error:
182b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
183b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      return -1;
184a04d78d392463df4e69a64360c952ffa5abd22f7Kenny Root  }
185a04d78d392463df4e69a64360c952ffa5abd22f7Kenny Root
186b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  assert(0);
187b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
188b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return -1;
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1914d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloanint ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
1926d0d00e090b753250659b9a2d67dab7467257900Robert Sloan  assert(ssl_can_write(ssl));
1934969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
1944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  unsigned tot, n, nw;
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1964139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  assert(ssl->s3->wnum <= INT_MAX);
1974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  tot = ssl->s3->wnum;
1984139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wnum = 0;
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Ensure that if we end up with a smaller value of data to write out than
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * the the original len from a write which didn't complete for non-blocking
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * I/O and also somehow ended up avoiding the check for this in
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * end up with (len-tot) as a large number that will then promptly send
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * beyond the end of the users buffer ... so we trap and report the error in
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * a way the user will notice. */
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (len < 0 || (size_t)len < tot) {
208b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2124d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  n = len - tot;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  for (;;) {
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* max contains the maximum number of bytes that we can put into a
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * record. */
2164139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    unsigned max = ssl->max_send_fragment;
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (n > max) {
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      nw = max;
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      nw = n;
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2234d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &buf[tot], nw);
2244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    if (ret <= 0) {
2254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->wnum = tot;
2264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      return ret;
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2294d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    if (ret == (int)n || (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
2304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      return tot + ret;
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2334969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    n -= ret;
2344969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    tot += ret;
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2384139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf,
239fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                              unsigned int len) {
2404139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->s3->wpend_tot > (int)len ||
241909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez      (!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) &&
242909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez       ssl->s3->wpend_buf != buf) ||
2434139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->wpend_type != type) {
244fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY);
245fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return -1;
246fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
247fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
2484139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  int ret = ssl_write_buffer_flush(ssl);
249fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ret <= 0) {
250fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return ret;
251fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
2524139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return ssl->s3->wpend_ret;
253fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley}
254fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
255b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* do_ssl3_write writes an SSL record of the given type. */
2564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
257b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* If there is still data from the previous record, flush it. */
2584139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl_write_buffer_is_pending(ssl)) {
2594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return ssl3_write_pending(ssl, type, buf, len);
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2624d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  /* The handshake flight buffer is mutually exclusive with application data.
2634d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan   *
2644d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan   * TODO(davidben): This will not be true when closure alerts use this. */
2654d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  if (ssl->s3->pending_flight != NULL) {
2664d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
2674d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    return -1;
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
270b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
271b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (len == 0) {
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
279909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez  size_t max_out = len + SSL_max_seal_overhead(ssl);
280b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (max_out < len) {
281b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
282b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return -1;
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
284b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  uint8_t *out;
285e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  size_t ciphertext_len;
2864139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl_write_buffer_init(ssl, &out, max_out) ||
2874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !tls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len)) {
288e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return -1;
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
2904139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl_write_buffer_set_len(ssl, ciphertext_len);
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* memorize arguments so that ssl3_write_pending can detect bad write retries
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * later */
2944139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_tot = len;
2954139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_buf = buf;
2964139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_type = type;
2974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_ret = len;
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* we now just need to write the buffer */
3004139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return ssl3_write_pending(ssl, type, buf, len);
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
303c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminstatic int consume_record(SSL *ssl, uint8_t *out, int len, int peek) {
304c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  SSL3_RECORD *rr = &ssl->s3->rrec;
305c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
306c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (len <= 0) {
307c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return len;
308c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
309c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
310c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (len > (int)rr->length) {
311c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    len = (int)rr->length;
312c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
313c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
31469939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  OPENSSL_memcpy(out, rr->data, len);
315c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!peek) {
316c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    rr->length -= len;
317c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    rr->data += len;
318c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->length == 0) {
319c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      /* The record has been consumed, so we may now clear the buffer. */
320c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      ssl_read_buffer_discard(ssl);
321c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
322c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
323c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  return len;
324c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin}
325c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
326c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminint ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
327c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin                       int peek) {
3286d0d00e090b753250659b9a2d67dab7467257900Robert Sloan  assert(ssl_can_read(ssl));
329c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  *out_got_handshake = 0;
330c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
3316d0d00e090b753250659b9a2d67dab7467257900Robert Sloan  ssl->method->release_current_message(ssl, 0 /* don't free buffer */);
3326d0d00e090b753250659b9a2d67dab7467257900Robert Sloan
333c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  SSL3_RECORD *rr = &ssl->s3->rrec;
334c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
335c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  for (;;) {
336c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    /* A previous iteration may have read a partial handshake message. Do not
337c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin     * allow more app data in that case. */
338c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    int has_hs_data = ssl->init_buf != NULL && ssl->init_buf->length > 0;
339c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
340c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    /* Get new packet if necessary. */
341c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->length == 0 && !has_hs_data) {
342c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      int ret = ssl3_get_record(ssl);
343c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (ret <= 0) {
344c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        return ret;
345c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      }
346c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
347c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
348c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (has_hs_data || rr->type == SSL3_RT_HANDSHAKE) {
3496d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      /* If reading 0-RTT data, reject handshake data. 0-RTT data is terminated
3506d0d00e090b753250659b9a2d67dab7467257900Robert Sloan       * by an alert. */
3516d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      if (SSL_in_init(ssl)) {
3526d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
3536d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
3546d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        return -1;
3556d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      }
3566d0d00e090b753250659b9a2d67dab7467257900Robert Sloan
357c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      /* Post-handshake data prior to TLS 1.3 is always renegotiation, which we
358c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin       * never accept as a server. Otherwise |ssl3_get_message| will send
359c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin       * |SSL_R_EXCESSIVE_MESSAGE_SIZE|. */
360c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (ssl->server && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
361c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION);
362c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
363c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        return -1;
364c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      }
3656e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin
366c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      /* Parse post-handshake handshake messages. */
3674d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan      int ret = ssl3_get_message(ssl);
368c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (ret <= 0) {
369c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        return ret;
370c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      }
371c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      *out_got_handshake = 1;
372c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      return -1;
373c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
374c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
3756d0d00e090b753250659b9a2d67dab7467257900Robert Sloan    /* Handle the end_of_early_data alert. */
3766d0d00e090b753250659b9a2d67dab7467257900Robert Sloan    if (rr->type == SSL3_RT_ALERT &&
3776d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        rr->length == 2 &&
3786d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        rr->data[0] == SSL3_AL_WARNING &&
3796d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        rr->data[1] == TLS1_AD_END_OF_EARLY_DATA &&
3806d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        ssl->server &&
3816d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        ssl->s3->hs != NULL &&
3826d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        ssl->s3->hs->can_early_read &&
3836d0d00e090b753250659b9a2d67dab7467257900Robert Sloan        ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
3846d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      /* Consume the record. */
3856d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      rr->length = 0;
3866d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      ssl_read_buffer_discard(ssl);
3876d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      /* Stop accepting early data. */
3886d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      ssl->s3->hs->can_early_read = 0;
3896d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      *out_got_handshake = 1;
3906d0d00e090b753250659b9a2d67dab7467257900Robert Sloan      return -1;
3916d0d00e090b753250659b9a2d67dab7467257900Robert Sloan    }
3926d0d00e090b753250659b9a2d67dab7467257900Robert Sloan
393c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->type != SSL3_RT_APPLICATION_DATA) {
394c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
395c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
396c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      return -1;
397c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
398c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
399c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->length != 0) {
400c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      return consume_record(ssl, buf, len, peek);
401c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
402c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
403c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    /* Discard empty records and loop again. */
404c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
4054139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley}
4064139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
4074139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_read_change_cipher_spec(SSL *ssl) {
4086e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  SSL3_RECORD *rr = &ssl->s3->rrec;
4096e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin
4106e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  if (rr->length == 0) {
4116e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    int ret = ssl3_get_record(ssl);
4126e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    if (ret <= 0) {
4136e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin      return ret;
4146e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    }
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4176e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
4186e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
4196e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
4206e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    return -1;
4216e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  }
4226e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin
4236e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
4244139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
4254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
4264139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return -1;
4274139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4297c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data,
4307c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin                      rr->length);
4314139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
4326e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  rr->length = 0;
4336e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  ssl_read_buffer_discard(ssl);
4344139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return 1;
435f4e427204234da139fd0585def4b4e22502e33f0Adam Langley}
436f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
437f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyvoid ssl3_read_close_notify(SSL *ssl) {
4386e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  /* Read records until an error or close_notify. */
4396e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  while (ssl3_get_record(ssl) > 0) {
4406e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin    ;
4416e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  }
442f4e427204234da139fd0585def4b4e22502e33f0Adam Langley}
443f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
444c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminint ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
445c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  SSL3_RECORD *rr = &ssl->s3->rrec;
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
447c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  for (;;) {
448c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    /* Get new packet if necessary. */
449b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    if (rr->length == 0) {
450c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      int ret = ssl3_get_record(ssl);
451c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (ret <= 0) {
452c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        return ret;
4534139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      }
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
456c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->type != SSL3_RT_HANDSHAKE) {
457c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
458c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
459c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      return -1;
460f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    }
461f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
462c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (rr->length != 0) {
463c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      return consume_record(ssl, buf, len, 0 /* consume data */);
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
465f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
466c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    /* Discard empty records and loop again. */
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4704139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_send_alert(SSL *ssl, int level, int desc) {
471d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  /* It is illegal to send an alert when we've already sent a closing one. */
472d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  if (ssl->s3->send_shutdown != ssl_shutdown_none) {
473d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
474d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    return -1;
475d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  }
476d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin
4774d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) {
478d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin    ssl->s3->send_shutdown = ssl_shutdown_close_notify;
4794d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  } else {
4804d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    assert(level == SSL3_AL_FATAL);
4814d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan    ssl->s3->send_shutdown = ssl_shutdown_fatal_alert;
482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4844139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->alert_dispatch = 1;
4854139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->send_alert[0] = level;
4864139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->send_alert[1] = desc;
4874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl_write_buffer_is_pending(ssl)) {
488b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    /* Nothing is being written out, so the alert may be dispatched
489b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root     * immediately. */
490c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    return ssl->method->dispatch_alert(ssl);
491d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
492d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
493d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin  /* The alert will be dispatched later. */
494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return -1;
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_dispatch_alert(SSL *ssl) {
4984969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
4994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  if (ret <= 0) {
5004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    return ret;
5014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  }
5024d1ac508237e73d6596202e4fa36d93ecf2321d8Robert Sloan  ssl->s3->alert_dispatch = 0;
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  /* If the alert is fatal, flush the BIO now. */
5054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
5064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    BIO_flush(ssl->wbio);
5074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  }
508d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5097c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
5107c0d06c221ce9edf44bbf978b909b38a0aee2084David Benjamin                      2);
511d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5126e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
5136e899c7d3f4c7bd6383a0ca171a50e95aa9d8e2dDavid Benjamin  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
514d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  return 1;
516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
517