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>
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h>
114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <string.h>
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/buf.h>
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/evp.h>
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/rand.h>
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
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/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
128b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * processed. */
129b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic const uint8_t kMaxWarningAlerts = 4;
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
131b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* ssl3_get_record reads a new input record. On success, it places it in
132b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
133b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * more data is needed. */
134b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic int ssl3_get_record(SSL *ssl) {
135b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  int ret;
136b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootagain:
137b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* Ensure the buffer is large enough to decrypt in-place. */
138b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  ret = ssl_read_buffer_extend_to(ssl, ssl_record_prefix_len(ssl));
139b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (ret <= 0) {
140b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return ret;
141b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
142b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  assert(ssl_read_buffer_len(ssl) >= ssl_record_prefix_len(ssl));
143b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
144b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl);
145b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl);
146b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  uint8_t type, alert;
147b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t len, consumed;
148b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  switch (tls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out,
149b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root                          ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) {
150b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_success:
151b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      ssl_read_buffer_consume(ssl, consumed);
152b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
153b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      if (len > 0xffff) {
154b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
155b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        return -1;
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
158b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      SSL3_RECORD *rr = &ssl->s3->rrec;
159b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      rr->type = type;
160b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      rr->length = (uint16_t)len;
161b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      rr->data = out;
162b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      return 1;
163b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
164b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_partial:
165b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      ret = ssl_read_buffer_extend_to(ssl, consumed);
166b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      if (ret <= 0) {
167b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        return ret;
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
169b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      goto again;
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
171b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_discard:
172b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      ssl_read_buffer_consume(ssl, consumed);
173b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      goto again;
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
175b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    case ssl_open_record_error:
176b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
177b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      return -1;
178a04d78d392463df4e69a64360c952ffa5abd22f7Kenny Root  }
179a04d78d392463df4e69a64360c952ffa5abd22f7Kenny Root
180b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  assert(0);
181b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
182b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return -1;
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
185f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyint ssl3_write_app_data(SSL *ssl, const void *buf, int len) {
186f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  return ssl3_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len);
187f4e427204234da139fd0585def4b4e22502e33f0Adam Langley}
188f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Call this to write data in records of type |type|. It will return <= 0 if
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * not all data has been sent or non-blocking IO. */
1914139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_write_bytes(SSL *ssl, int type, const void *buf_, int len) {
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t *buf = buf_;
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned int tot, n, nw;
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int i;
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1964139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->rwstate = SSL_NOTHING;
1974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  assert(ssl->s3->wnum <= INT_MAX);
1984139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  tot = ssl->s3->wnum;
1994139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wnum = 0;
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2014139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl->in_handshake && SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
2024139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    i = ssl->handshake_func(ssl);
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i < 0) {
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return i;
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i == 0) {
207b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return -1;
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Ensure that if we end up with a smaller value of data to write out than
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * the the original len from a write which didn't complete for non-blocking
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * I/O and also somehow ended up avoiding the check for this in
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * end up with (len-tot) as a large number that will then promptly send
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * beyond the end of the users buffer ... so we trap and report the error in
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * a way the user will notice. */
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (len < 0 || (size_t)len < tot) {
220b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  n = (len - tot);
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  for (;;) {
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* max contains the maximum number of bytes that we can put into a
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * record. */
2284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    unsigned max = ssl->max_send_fragment;
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (n > max) {
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      nw = max;
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      nw = n;
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2354139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    i = do_ssl3_write(ssl, type, &buf[tot], nw);
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i <= 0) {
2374139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->wnum = tot;
238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return i;
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i == (int)n || (type == SSL3_RT_APPLICATION_DATA &&
2424139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                        (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return tot + i;
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n -= i;
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    tot += i;
248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf,
252fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                              unsigned int len) {
2534139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->s3->wpend_tot > (int)len ||
2544139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      (ssl->s3->wpend_buf != buf &&
2554139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley       !(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) ||
2564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->wpend_type != type) {
257fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY);
258fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return -1;
259fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
260fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
2614139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  int ret = ssl_write_buffer_flush(ssl);
262fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ret <= 0) {
263fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return ret;
264fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
2654139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return ssl->s3->wpend_ret;
266fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley}
267fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
268b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* do_ssl3_write writes an SSL record of the given type. */
2694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleystatic int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
270b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* If there is still data from the previous record, flush it. */
2714139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl_write_buffer_is_pending(ssl)) {
2724139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return ssl3_write_pending(ssl, type, buf, len);
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* If we have an alert to send, lets send it */
2764139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->s3->alert_dispatch) {
2774139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    int ret = ssl->method->ssl_dispatch_alert(ssl);
278e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (ret <= 0) {
279e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return ret;
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* if it went, fall through and send more stuff */
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
284b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
285b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (len == 0) {
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2934139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  size_t max_out = len + ssl_max_seal_overhead(ssl);
294b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (max_out < len) {
295b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
296b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return -1;
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
298b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  uint8_t *out;
299e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  size_t ciphertext_len;
3004139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl_write_buffer_init(ssl, &out, max_out) ||
3014139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      !tls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len)) {
302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return -1;
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
3044139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl_write_buffer_set_len(ssl, ciphertext_len);
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* memorize arguments so that ssl3_write_pending can detect bad write retries
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * later */
3084139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_tot = len;
3094139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_buf = buf;
3104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_type = type;
3114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->wpend_ret = len;
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* we now just need to write the buffer */
3144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return ssl3_write_pending(ssl, type, buf, len);
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3174139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) {
3184139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return ssl3_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek);
3194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley}
3204139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
3214139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_read_change_cipher_spec(SSL *ssl) {
3224139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  uint8_t byte;
3234139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  int ret = ssl3_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1 /* len */,
3244139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                            0 /* no peek */);
3254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ret <= 0) {
3264139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return ret;
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
3284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  assert(ret == 1);
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3304139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) {
3314139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
3324139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
3334139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return -1;
3344139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3364139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->msg_callback != NULL) {
3374139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
3384139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                      ssl, ssl->msg_callback_arg);
3394139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
3404139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
3414139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  return 1;
342f4e427204234da139fd0585def4b4e22502e33f0Adam Langley}
343f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
344f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyvoid ssl3_read_close_notify(SSL *ssl) {
345f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  ssl3_read_bytes(ssl, 0, NULL, 0, 0);
346f4e427204234da139fd0585def4b4e22502e33f0Adam Langley}
347f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
348e99801b603dea8893dcc61c70b327ef2d00b652cKenny Rootstatic int ssl3_can_renegotiate(SSL *ssl) {
349e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  switch (ssl->renegotiate_mode) {
350e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    case ssl_renegotiate_never:
351e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      return 0;
352e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    case ssl_renegotiate_once:
353e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      return ssl->s3->total_renegotiations == 0;
354e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root    case ssl_renegotiate_freely:
355e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root      return 1;
356fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    case ssl_renegotiate_ignore:
357fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      return 1;
358e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  }
359e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
360e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  assert(0);
361e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  return 0;
362e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root}
363e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Return up to 'len' payload bytes received in 'type' records.
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 'type' is one of the following:
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
3684139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley *   -  SSL3_RT_CHANGE_CIPHER_SPEC (when ssl3_read_change_cipher_spec calls us)
3694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us)
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *   -  0 (during a shutdown, no data has to be returned)
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If we don't have stored data to work from, read a SSL/TLS record first
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (possibly multiple records if we still don't have anything to return).
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This function must handle any surprises the peer may have for us, such as
3764139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley * Alert records (e.g. close_notify) or renegotiation requests. */
3774139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek) {
378e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int al, i, ret;
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned int n;
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  SSL3_RECORD *rr;
381e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  void (*cb)(const SSL *ssl, int type, int value) = NULL;
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3834139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
3844139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley       type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      (peek && type != SSL3_RT_APPLICATION_DATA)) {
386b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
390e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  /* This may require multiple iterations. False Start will cause
3914139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley   * |ssl->handshake_func| to signal success one step early, but the handshake
392e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley   * must be completely finished before other modes are accepted.
393e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley   *
394e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley   * TODO(davidben): Move this check up to a higher level. */
3954139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  while (!ssl->in_handshake && SSL_in_init(ssl)) {
396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    assert(type == SSL3_RT_APPLICATION_DATA);
3974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    i = ssl->handshake_func(ssl);
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i < 0) {
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return i;
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (i == 0) {
402b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return -1;
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystart:
4084139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->rwstate = SSL_NOTHING;
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  /* ssl->s3->rrec.type    - is the type of record
4114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley   * ssl->s3->rrec.data    - data
4124139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley   * ssl->s3->rrec.off     - offset into 'data' for next read
4134139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley   * ssl->s3->rrec.length  - number of bytes. */
4144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  rr = &ssl->s3->rrec;
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* get new packet if necessary */
417b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (rr->length == 0) {
4184139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ret = ssl3_get_record(ssl);
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (ret <= 0) {
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return ret;
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* we now have a packet which can be read and processed */
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* If the other end has shut down, throw anything we read away (even in
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * 'peek' mode) */
4284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rr->length = 0;
4304139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->rwstate = SSL_NOTHING;
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
434b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (type != 0 && type == rr->type) {
4354139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->s3->warning_alert_count = 0;
436b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
4374139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    /* Make sure that we are not getting application data when we are doing a
4384139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley     * handshake for the first time. */
4394139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (SSL_in_init(ssl) && type == SSL3_RT_APPLICATION_DATA &&
4404139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        ssl->aead_read_ctx == NULL) {
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      /* TODO(davidben): Is this check redundant with the handshake_func
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * check? */
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      al = SSL_AD_UNEXPECTED_MESSAGE;
444b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE);
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto f_err;
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
448b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    /* Discard empty records. */
449b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    if (rr->length == 0) {
450b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      goto start;
451b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    }
452b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (len <= 0) {
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return len;
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if ((unsigned int)len > rr->length) {
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      n = rr->length;
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      n = (unsigned int)len;
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4634139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    memcpy(buf, rr->data, n);
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!peek) {
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      rr->length -= n;
4664139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      rr->data += n;
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (rr->length == 0) {
468b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        /* The record has been consumed, so we may now clear the buffer. */
4694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        ssl_read_buffer_discard(ssl);
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return n;
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
476f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  /* Process unexpected records. */
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4784139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) {
479e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    /* If peer renegotiations are disabled, all out-of-order handshake records
480f4e427204234da139fd0585def4b4e22502e33f0Adam Langley     * are fatal. Renegotiations as a server are never supported. */
4814139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->server || !ssl3_can_renegotiate(ssl)) {
482e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      al = SSL_AD_NO_RENEGOTIATION;
483b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
484e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      goto f_err;
485e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
486e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
4874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    /* This must be a HelloRequest, possibly fragmented over multiple records.
4884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley     * Consume data from the handshake protocol until it is complete. */
4894139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    static const uint8_t kHelloRequest[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
4904139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    while (ssl->s3->hello_request_len < sizeof(kHelloRequest)) {
4914139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      if (rr->length == 0) {
4924139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        /* Get a new record. */
4934139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        goto start;
4944139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      }
4954139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      if (rr->data[0] != kHelloRequest[ssl->s3->hello_request_len]) {
4964139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        al = SSL_AD_DECODE_ERROR;
4974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST);
4984139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        goto f_err;
4994139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      }
5004139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      rr->data++;
5014139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      rr->length--;
5024139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->hello_request_len++;
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
5044139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->s3->hello_request_len = 0;
505d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5064139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->msg_callback) {
5074139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, kHelloRequest,
5084139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                      sizeof(kHelloRequest), ssl, ssl->msg_callback_arg);
509d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (!SSL_is_init_finished(ssl) || !ssl->s3->initial_handshake_complete) {
512f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      /* This cannot happen. If a handshake is in progress, |type| must be
513f4e427204234da139fd0585def4b4e22502e33f0Adam Langley       * |SSL3_RT_HANDSHAKE|. */
514f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      assert(0);
515b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
516f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      goto err;
517f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    }
518f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
5194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->renegotiate_mode == ssl_renegotiate_ignore) {
520fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto start;
521fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
522fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
523f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    /* Renegotiation is only supported at quiescent points in the application
524f4e427204234da139fd0585def4b4e22502e33f0Adam Langley     * protocol, namely in HTTPS, just before reading the HTTP response. Require
525f4e427204234da139fd0585def4b4e22502e33f0Adam Langley     * the record-layer be idle and avoid complexities of sending a handshake
526f4e427204234da139fd0585def4b4e22502e33f0Adam Langley     * record while an application_data record is being written. */
5274139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl_write_buffer_is_pending(ssl)) {
528f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      al = SSL_AD_NO_RENEGOTIATION;
529b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
530f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      goto f_err;
531f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    }
532f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
533f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    /* Begin a new handshake. */
5344139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->s3->total_renegotiations++;
5354139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->state = SSL_ST_CONNECT;
5364139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    i = ssl->handshake_func(ssl);
537f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    if (i < 0) {
538f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      return i;
539f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    }
540f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    if (i == 0) {
541b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
542f4e427204234da139fd0585def4b4e22502e33f0Adam Langley      return -1;
543d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
544f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
545f4e427204234da139fd0585def4b4e22502e33f0Adam Langley    /* The handshake completed synchronously. Continue reading records. */
546d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto start;
547d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
548d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
549e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  /* If an alert record, process one alert out of the record. Note that we allow
550e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley   * a single record to contain multiple alerts. */
551d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (rr->type == SSL3_RT_ALERT) {
552e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    /* Alerts may not be fragmented. */
553e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (rr->length < 2) {
554e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      al = SSL_AD_DECODE_ERROR;
555b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
556e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      goto f_err;
557e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
558d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->msg_callback) {
5604139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
5614139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                        ssl->msg_callback_arg);
562d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
5634139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    const uint8_t alert_level = rr->data[0];
5644139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    const uint8_t alert_descr = rr->data[1];
565e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    rr->length -= 2;
5664139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    rr->data += 2;
567d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
5684139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->info_callback != NULL) {
5694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb = ssl->info_callback;
5704139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    } else if (ssl->ctx->info_callback != NULL) {
5714139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb = ssl->ctx->info_callback;
572d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
573d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
574d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (cb != NULL) {
575e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      uint16_t alert = (alert_level << 8) | alert_descr;
5764139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb(ssl, SSL_CB_READ_ALERT, alert);
577d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
578d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
579e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (alert_level == SSL3_AL_WARNING) {
5804139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->warn_alert = alert_descr;
581d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
5824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley        ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
583d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return 0;
584d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
585d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
586d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      /* This is a warning but we receive it if we requested renegotiation and
587d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * the peer denied it. Terminate with a fatal alert because if
588d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * application tried to renegotiatie it presumably had a good reason and
589d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * expects it to succeed.
590d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       *
591d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * In future we might have a renegotiation where we don't care if the
592d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * peer refused it where we carry on. */
593d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
594d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        al = SSL_AD_HANDSHAKE_FAILURE;
595b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
596b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        goto f_err;
597b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      }
598b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
5994139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->warning_alert_count++;
6004139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      if (ssl->s3->warning_alert_count > kMaxWarningAlerts) {
601b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        al = SSL_AD_UNEXPECTED_MESSAGE;
602b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS);
603d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto f_err;
604d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
605e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    } else if (alert_level == SSL3_AL_FATAL) {
606d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      char tmp[16];
607d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6084139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->rwstate = SSL_NOTHING;
6094139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->s3->fatal_alert = alert_descr;
610b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
611d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
612d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      ERR_add_error_data(2, "SSL alert number ", tmp);
6134139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
6144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      SSL_CTX_remove_session(ssl->ctx, ssl->session);
615d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
616d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
617d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      al = SSL_AD_ILLEGAL_PARAMETER;
618b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
619d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto f_err;
620d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
621d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
622d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto start;
623d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
624d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->shutdown & SSL_SENT_SHUTDOWN) {
626b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    /* close_notify has been sent, so discard all records other than alerts. */
627d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rr->length = 0;
628b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    goto start;
629d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
630d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
631e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  al = SSL_AD_UNEXPECTED_MESSAGE;
632b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
633d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
634d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyf_err:
6354139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
636d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
637d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return -1;
638d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
639d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6404139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_do_change_cipher_spec(SSL *ssl) {
641d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int i;
642d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6434139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->state & SSL_ST_ACCEPT) {
644d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    i = SSL3_CHANGE_CIPHER_SERVER_READ;
645d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
646d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    i = SSL3_CHANGE_CIPHER_CLIENT_READ;
647d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
648d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6494139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->s3->tmp.key_block == NULL) {
6504139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->session == NULL || ssl->session->master_key_length == 0) {
651d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      /* might happen if dtls1_read_bytes() calls this */
652b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(SSL, SSL_R_CCS_RECEIVED_EARLY);
653d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
654d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
655d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->session->cipher = ssl->s3->tmp.new_cipher;
6574139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (!ssl->enc_method->setup_key_block(ssl)) {
658d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
659d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
660d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
661d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6624139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl->enc_method->change_cipher_state(ssl, i)) {
663d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
664d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
665d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
666d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
667d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
668d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_send_alert(SSL *ssl, int level, int desc) {
670d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Map tls/ssl alert value to correct one */
6714139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  desc = ssl->enc_method->alert_value(desc);
6724139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (ssl->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) {
673d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* SSL 3.0 does not have protocol_version alerts */
674d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    desc = SSL_AD_HANDSHAKE_FAILURE;
675d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
676d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (desc < 0) {
677d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return -1;
678d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
679d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
680d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* If a fatal one, remove from cache */
6814139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (level == 2 && ssl->session != NULL) {
6824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    SSL_CTX_remove_session(ssl->ctx, ssl->session);
683d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
684d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6854139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->alert_dispatch = 1;
6864139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->send_alert[0] = level;
6874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->send_alert[1] = desc;
6884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!ssl_write_buffer_is_pending(ssl)) {
689b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    /* Nothing is being written out, so the alert may be dispatched
690b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root     * immediately. */
6914139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    return ssl->method->ssl_dispatch_alert(ssl);
692d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
693d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
694d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* else data is still being written out, we will get written some time in the
695d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * future */
696d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return -1;
697d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
698d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6994139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ssl3_dispatch_alert(SSL *ssl) {
700d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int i, j;
701e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  void (*cb)(const SSL *ssl, int type, int value) = NULL;
702d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
7034139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  ssl->s3->alert_dispatch = 0;
7044139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  i = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
705d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (i <= 0) {
7064139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    ssl->s3->alert_dispatch = 1;
707d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
708d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* Alert sent to BIO.  If it is important, flush it now. If the message
709d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * does not get sent due to non-blocking IO, we will not worry too much. */
7104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
7114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      BIO_flush(ssl->wbio);
712d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
713d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
7144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->msg_callback) {
7154139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      ssl->msg_callback(1, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2,
7164139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                        ssl, ssl->msg_callback_arg);
717d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
718d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
7194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    if (ssl->info_callback != NULL) {
7204139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb = ssl->info_callback;
7214139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    } else if (ssl->ctx->info_callback != NULL) {
7224139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb = ssl->ctx->info_callback;
723d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
724d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
725d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (cb != NULL) {
7264139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      j = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
7274139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      cb(ssl, SSL_CB_WRITE_ALERT, j);
728d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
729d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
730d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
731d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return i;
732d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
733