blob: 203555cfc8c1649d2683626cf674dcf9417d0217 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 * acknowledgment:
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com).
108 *
109 */
110/* ====================================================================
111 * Copyright 2005 Nokia. All rights reserved.
112 *
113 * The portions of the attached software ("Contribution") is developed by
114 * Nokia Corporation and is licensed pursuant to the OpenSSL open source
115 * license.
116 *
117 * The Contribution, originally written by Mika Kousa and Pasi Eronen of
118 * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
119 * support (see RFC 4279) to OpenSSL.
120 *
121 * No patent licenses or other rights except those expressly stated in
122 * the OpenSSL open source license shall be deemed granted or received
123 * expressly, by implication, estoppel, or otherwise.
124 *
125 * No assurances are provided by Nokia that the Contribution does not
126 * infringe the patent or other intellectual property rights of any third
127 * party or that the license provides you with all the necessary rights
128 * to make use of the Contribution.
129 *
130 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
131 * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
132 * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
133 * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
134 * OTHERWISE. */
135
David Benjamin9e4e01e2015-09-15 01:48:04 -0400136#include <openssl/ssl.h>
137
David Benjamine3aa1d92015-06-16 15:34:50 -0400138#include <assert.h>
David Benjamin4d0be242016-09-01 01:10:07 -0400139#include <stdlib.h>
David Benjaminf0ae1702015-04-07 23:05:04 -0400140#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700141
David Benjamin31b0c9b2017-07-20 14:49:15 -0400142#include <utility>
143
Adam Langley95c29f32014-06-20 12:00:00 -0700144#include <openssl/err.h>
145#include <openssl/lhash.h>
146#include <openssl/mem.h>
147#include <openssl/rand.h>
148
David Benjamin2ee94aa2015-04-07 22:38:30 -0400149#include "internal.h"
David Benjamin546f1a52015-04-15 16:46:09 -0400150#include "../crypto/internal.h"
151
Adam Langley95c29f32014-06-20 12:00:00 -0700152
David Benjamin86e95b82017-07-18 16:34:25 -0400153namespace bssl {
154
David Benjaminc11ea9422017-08-29 16:33:21 -0400155// The address of this is a magic value, a pointer to which is returned by
156// SSL_magic_pending_session_ptr(). It allows a session callback to indicate
157// that it needs to asynchronously fetch session information.
Brian Smithefed2212015-01-28 16:20:02 -0800158static const char g_pending_session_magic = 0;
Adam Langleyb2ce0582014-06-20 12:00:00 -0700159
David Benjaminaa585132015-06-29 23:36:17 -0400160static CRYPTO_EX_DATA_CLASS g_ex_data_class =
161 CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
David Benjamin9f33fc62015-04-15 17:29:53 -0400162
David Benjamindafbdd42015-09-14 01:40:10 -0400163static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
164static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
165static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700166
David Benjamin31b0c9b2017-07-20 14:49:15 -0400167UniquePtr<SSL_SESSION> ssl_session_new(const SSL_X509_METHOD *x509_method) {
168 UniquePtr<SSL_SESSION> session(
169 (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)));
170 if (!session) {
David Benjaminabb6c1c2015-09-13 14:46:26 -0400171 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
172 return 0;
173 }
David Benjamin31b0c9b2017-07-20 14:49:15 -0400174 OPENSSL_memset(session.get(), 0, sizeof(SSL_SESSION));
David Benjaminabb6c1c2015-09-13 14:46:26 -0400175
Adam Langley46db7af2017-02-01 15:49:37 -0800176 session->x509_method = x509_method;
Adam Langley9498e742016-07-18 10:17:16 -0700177 session->verify_result = X509_V_ERR_INVALID_CALL;
David Benjaminabb6c1c2015-09-13 14:46:26 -0400178 session->references = 1;
179 session->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
David Benjamin17b30832017-01-28 14:00:32 -0500180 session->auth_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
David Benjaminad8f5e12017-02-20 17:00:20 -0500181 session->time = time(NULL);
David Benjamin8a589332015-12-04 23:14:35 -0500182 CRYPTO_new_ex_data(&session->ex_data);
David Benjaminabb6c1c2015-09-13 14:46:26 -0400183 return session;
184}
185
David Benjamin31b0c9b2017-07-20 14:49:15 -0400186UniquePtr<SSL_SESSION> SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
187 UniquePtr<SSL_SESSION> new_session = ssl_session_new(session->x509_method);
188 if (!new_session) {
189 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400190 }
191
Adam Langley364f7a62016-12-12 10:51:00 -0800192 new_session->is_server = session->is_server;
Steven Valdez87eab492016-06-27 16:34:59 -0400193 new_session->ssl_version = session->ssl_version;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400194 new_session->sid_ctx_length = session->sid_ctx_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500195 OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400196
David Benjaminc11ea9422017-08-29 16:33:21 -0400197 // Copy the key material.
Steven Valdez87eab492016-06-27 16:34:59 -0400198 new_session->master_key_length = session->master_key_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500199 OPENSSL_memcpy(new_session->master_key, session->master_key,
Steven Valdez87eab492016-06-27 16:34:59 -0400200 session->master_key_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400201 new_session->cipher = session->cipher;
202
David Benjaminc11ea9422017-08-29 16:33:21 -0400203 // Copy authentication state.
Steven Valdez87eab492016-06-27 16:34:59 -0400204 if (session->psk_identity != NULL) {
205 new_session->psk_identity = BUF_strdup(session->psk_identity);
206 if (new_session->psk_identity == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400207 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400208 }
209 }
Adam Langley68e71242016-12-12 11:06:16 -0800210 if (session->certs != NULL) {
211 new_session->certs = sk_CRYPTO_BUFFER_new_null();
212 if (new_session->certs == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400213 return nullptr;
Adam Langley68e71242016-12-12 11:06:16 -0800214 }
215 for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
216 CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
217 if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400218 return nullptr;
Adam Langley68e71242016-12-12 11:06:16 -0800219 }
220 CRYPTO_BUFFER_up_ref(buffer);
221 }
222 }
Adam Langley46db7af2017-02-01 15:49:37 -0800223
David Benjamin31b0c9b2017-07-20 14:49:15 -0400224 if (!session->x509_method->session_dup(new_session.get(), session)) {
225 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400226 }
Adam Langley46db7af2017-02-01 15:49:37 -0800227
Steven Valdez87eab492016-06-27 16:34:59 -0400228 new_session->verify_result = session->verify_result;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400229
Steven Valdez4aa154e2016-07-29 14:32:55 -0400230 if (session->ocsp_response != NULL) {
David Benjamin8fc2dc02017-08-22 15:07:51 -0700231 new_session->ocsp_response = session->ocsp_response;
232 CRYPTO_BUFFER_up_ref(new_session->ocsp_response);
Steven Valdez87eab492016-06-27 16:34:59 -0400233 }
Steven Valdez87eab492016-06-27 16:34:59 -0400234
David Benjamin8fc2dc02017-08-22 15:07:51 -0700235 if (session->signed_cert_timestamp_list != NULL) {
236 new_session->signed_cert_timestamp_list =
237 session->signed_cert_timestamp_list;
238 CRYPTO_BUFFER_up_ref(new_session->signed_cert_timestamp_list);
Steven Valdez87eab492016-06-27 16:34:59 -0400239 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400240
David Benjamin17cf2cb2016-12-13 01:07:13 -0500241 OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
242 SHA256_DIGEST_LENGTH);
Steven Valdez87eab492016-06-27 16:34:59 -0400243 new_session->peer_sha256_valid = session->peer_sha256_valid;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400244
David Benjaminf1050fd2016-12-13 20:05:36 -0500245 new_session->peer_signature_algorithm = session->peer_signature_algorithm;
246
David Benjamin01a90572016-09-22 00:11:43 -0400247 new_session->timeout = session->timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500248 new_session->auth_timeout = session->auth_timeout;
David Benjamin01a90572016-09-22 00:11:43 -0400249 new_session->time = session->time;
250
David Benjaminc11ea9422017-08-29 16:33:21 -0400251 // Copy non-authentication connection properties.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400252 if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
253 new_session->session_id_length = session->session_id_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500254 OPENSSL_memcpy(new_session->session_id, session->session_id,
255 session->session_id_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400256
David Benjamin4882a6c2016-12-11 02:48:12 -0500257 new_session->group_id = session->group_id;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400258
David Benjamin17cf2cb2016-12-13 01:07:13 -0500259 OPENSSL_memcpy(new_session->original_handshake_hash,
260 session->original_handshake_hash,
261 session->original_handshake_hash_len);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400262 new_session->original_handshake_hash_len =
263 session->original_handshake_hash_len;
264 new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400265 new_session->ticket_age_add = session->ticket_age_add;
Steven Valdez08b65f42016-12-07 15:29:45 -0500266 new_session->ticket_max_early_data = session->ticket_max_early_data;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400267 new_session->extended_master_secret = session->extended_master_secret;
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500268
269 if (session->early_alpn != NULL) {
270 new_session->early_alpn =
David Benjamin0238d8f2017-07-12 17:35:14 -0400271 (uint8_t *)BUF_memdup(session->early_alpn, session->early_alpn_len);
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500272 if (new_session->early_alpn == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400273 return nullptr;
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500274 }
275 }
276 new_session->early_alpn_len = session->early_alpn_len;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400277 }
278
David Benjaminc11ea9422017-08-29 16:33:21 -0400279 // Copy the ticket.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400280 if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
281 if (session->tlsext_tick != NULL) {
282 new_session->tlsext_tick =
David Benjamin0238d8f2017-07-12 17:35:14 -0400283 (uint8_t *)BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400284 if (new_session->tlsext_tick == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400285 return nullptr;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400286 }
287 }
288 new_session->tlsext_ticklen = session->tlsext_ticklen;
289 }
290
David Benjaminc11ea9422017-08-29 16:33:21 -0400291 // The new_session does not get a copy of the ex_data.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400292
Steven Valdez87eab492016-06-27 16:34:59 -0400293 new_session->not_resumable = 1;
294 return new_session;
Steven Valdez87eab492016-06-27 16:34:59 -0400295}
296
David Benjamin17b30832017-01-28 14:00:32 -0500297void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session) {
David Benjaminad8f5e12017-02-20 17:00:20 -0500298 struct OPENSSL_timeval now;
David Benjamin123db572016-11-03 16:59:25 -0400299 ssl_get_current_time(ssl, &now);
300
David Benjaminc11ea9422017-08-29 16:33:21 -0400301 // To avoid overflows and underflows, if we've gone back in time, update the
302 // time, but mark the session expired.
David Benjaminad8f5e12017-02-20 17:00:20 -0500303 if (session->time > now.tv_sec) {
David Benjamin123db572016-11-03 16:59:25 -0400304 session->time = now.tv_sec;
305 session->timeout = 0;
David Benjamin17b30832017-01-28 14:00:32 -0500306 session->auth_timeout = 0;
David Benjamin123db572016-11-03 16:59:25 -0400307 return;
308 }
309
David Benjaminc11ea9422017-08-29 16:33:21 -0400310 // Adjust the session time and timeouts. If the session has already expired,
311 // clamp the timeouts at zero.
David Benjaminad8f5e12017-02-20 17:00:20 -0500312 uint64_t delta = now.tv_sec - session->time;
David Benjamin123db572016-11-03 16:59:25 -0400313 session->time = now.tv_sec;
314 if (session->timeout < delta) {
315 session->timeout = 0;
316 } else {
317 session->timeout -= delta;
318 }
David Benjamin17b30832017-01-28 14:00:32 -0500319 if (session->auth_timeout < delta) {
320 session->auth_timeout = 0;
321 } else {
322 session->auth_timeout -= delta;
323 }
324}
325
David Benjaminad8f5e12017-02-20 17:00:20 -0500326void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
327 uint32_t timeout) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400328 // Rebase the timestamp relative to the current time so |timeout| is measured
329 // correctly.
David Benjamin17b30832017-01-28 14:00:32 -0500330 ssl_session_rebase_time(ssl, session);
331
332 if (session->timeout > timeout) {
333 return;
334 }
335
336 session->timeout = timeout;
337 if (session->timeout > session->auth_timeout) {
338 session->timeout = session->auth_timeout;
339 }
David Benjamin123db572016-11-03 16:59:25 -0400340}
341
Steven Valdez8f36c512017-06-20 10:55:02 -0400342uint16_t SSL_SESSION_protocol_version(const SSL_SESSION *session) {
343 uint16_t ret;
344 if (!ssl_protocol_version_from_wire(&ret, session->ssl_version)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400345 // An |SSL_SESSION| will never have an invalid version. This is enforced by
346 // the parser.
Steven Valdez8f36c512017-06-20 10:55:02 -0400347 assert(0);
348 return 0;
Steven Valdez908ac192017-01-12 13:17:07 -0500349 }
350
Steven Valdez8f36c512017-06-20 10:55:02 -0400351 return ret;
352}
353
354const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session) {
David Benjaminca9e8f52017-08-09 15:02:34 -0400355 return ssl_get_handshake_digest(SSL_SESSION_protocol_version(session),
356 session->cipher);
Steven Valdez908ac192017-01-12 13:17:07 -0500357}
358
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900359int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
360 SSL *const ssl = hs->ssl;
David Benjamindc2aea22015-10-18 12:50:32 -0400361 if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
David Benjamin3570d732015-06-29 00:28:17 -0400362 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
Adam Langleyfcf25832014-12-18 17:42:32 -0800363 return 0;
364 }
365
David Benjamin31b0c9b2017-07-20 14:49:15 -0400366 UniquePtr<SSL_SESSION> session = ssl_session_new(ssl->ctx->x509_method);
David Benjamindc2aea22015-10-18 12:50:32 -0400367 if (session == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800368 return 0;
369 }
370
Adam Langley364f7a62016-12-12 10:51:00 -0800371 session->is_server = is_server;
372 session->ssl_version = ssl->version;
373
David Benjaminc11ea9422017-08-29 16:33:21 -0400374 // Fill in the time from the |SSL_CTX|'s clock.
David Benjaminad8f5e12017-02-20 17:00:20 -0500375 struct OPENSSL_timeval now;
David Benjamin721e8b72016-08-03 13:13:17 -0400376 ssl_get_current_time(ssl, &now);
377 session->time = now.tv_sec;
378
David Benjamin17b30832017-01-28 14:00:32 -0500379 uint16_t version = ssl3_protocol_version(ssl);
380 if (version >= TLS1_3_VERSION) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400381 // TLS 1.3 uses tickets as authenticators, so we are willing to use them for
382 // longer.
David Benjaminbe497062017-03-10 16:08:36 -0500383 session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500384 session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
385 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400386 // TLS 1.2 resumption does not incorporate new key material, so we use a
387 // much shorter timeout.
David Benjaminbe497062017-03-10 16:08:36 -0500388 session->timeout = ssl->session_ctx->session_timeout;
389 session->auth_timeout = ssl->session_ctx->session_timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500390 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800391
David Benjamindc2aea22015-10-18 12:50:32 -0400392 if (is_server) {
David Benjamin17b30832017-01-28 14:00:32 -0500393 if (hs->ticket_expected || version >= TLS1_3_VERSION) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400394 // Don't set session IDs for sessions resumed with tickets. This will keep
395 // them out of the session cache.
David Benjamindc2aea22015-10-18 12:50:32 -0400396 session->session_id_length = 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800397 } else {
David Benjamindc2aea22015-10-18 12:50:32 -0400398 session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
399 if (!RAND_bytes(session->session_id, session->session_id_length)) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400400 return 0;
David Benjamindc2aea22015-10-18 12:50:32 -0400401 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800402 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800403 } else {
David Benjamindc2aea22015-10-18 12:50:32 -0400404 session->session_id_length = 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800405 }
406
David Benjamin5960a902017-02-14 20:07:11 -0500407 if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400408 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin31b0c9b2017-07-20 14:49:15 -0400409 return 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800410 }
David Benjamin5960a902017-02-14 20:07:11 -0500411 OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
412 ssl->cert->sid_ctx_length);
413 session->sid_ctx_length = ssl->cert->sid_ctx_length;
Adam Langleyfcf25832014-12-18 17:42:32 -0800414
David Benjaminc11ea9422017-08-29 16:33:21 -0400415 // The session is marked not resumable until it is completely filled in.
Steven Valdez87eab492016-06-27 16:34:59 -0400416 session->not_resumable = 1;
Adam Langley9498e742016-07-18 10:17:16 -0700417 session->verify_result = X509_V_ERR_INVALID_CALL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800418
David Benjamin31b0c9b2017-07-20 14:49:15 -0400419 hs->new_session = std::move(session);
David Benjamin4d0be242016-09-01 01:10:07 -0400420 ssl_set_session(ssl, NULL);
Adam Langleyfcf25832014-12-18 17:42:32 -0800421 return 1;
422}
Adam Langley95c29f32014-06-20 12:00:00 -0700423
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700424int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx) {
425 OPENSSL_timeval now;
426 ssl_ctx_get_current_time(ctx, &now);
427 {
David Benjaminc11ea9422017-08-29 16:33:21 -0400428 // Avoid acquiring a write lock in the common case (i.e. a non-default key
429 // is used or the default keys have not expired yet).
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700430 MutexReadLock lock(&ctx->lock);
431 if (ctx->tlsext_ticket_key_current &&
432 (ctx->tlsext_ticket_key_current->next_rotation_tv_sec == 0 ||
433 ctx->tlsext_ticket_key_current->next_rotation_tv_sec > now.tv_sec) &&
434 (!ctx->tlsext_ticket_key_prev ||
435 ctx->tlsext_ticket_key_prev->next_rotation_tv_sec > now.tv_sec)) {
436 return 1;
437 }
438 }
439
440 MutexWriteLock lock(&ctx->lock);
441 if (!ctx->tlsext_ticket_key_current ||
442 (ctx->tlsext_ticket_key_current->next_rotation_tv_sec != 0 &&
443 ctx->tlsext_ticket_key_current->next_rotation_tv_sec <= now.tv_sec)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400444 // The current key has not been initialized or it is expired.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700445 auto new_key = bssl::MakeUnique<struct tlsext_ticket_key>();
446 if (!new_key) {
447 return 0;
448 }
449 OPENSSL_memset(new_key.get(), 0, sizeof(struct tlsext_ticket_key));
450 if (ctx->tlsext_ticket_key_current) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400451 // The current key expired. Rotate it to prev and bump up its rotation
452 // timestamp. Note that even with the new rotation time it may still be
453 // expired and get droppped below.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700454 ctx->tlsext_ticket_key_current->next_rotation_tv_sec +=
455 SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
456 OPENSSL_free(ctx->tlsext_ticket_key_prev);
457 ctx->tlsext_ticket_key_prev = ctx->tlsext_ticket_key_current;
458 }
459 ctx->tlsext_ticket_key_current = new_key.release();
460 RAND_bytes(ctx->tlsext_ticket_key_current->name, 16);
461 RAND_bytes(ctx->tlsext_ticket_key_current->hmac_key, 16);
462 RAND_bytes(ctx->tlsext_ticket_key_current->aes_key, 16);
463 ctx->tlsext_ticket_key_current->next_rotation_tv_sec =
464 now.tv_sec + SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
465 }
466
David Benjaminc11ea9422017-08-29 16:33:21 -0400467 // Drop an expired prev key.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700468 if (ctx->tlsext_ticket_key_prev &&
469 ctx->tlsext_ticket_key_prev->next_rotation_tv_sec <= now.tv_sec) {
470 OPENSSL_free(ctx->tlsext_ticket_key_prev);
471 ctx->tlsext_ticket_key_prev = nullptr;
472 }
473
474 return 1;
475}
476
Adam Langley4c341d02017-03-08 19:33:21 -0800477static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
478 const uint8_t *session_buf,
479 size_t session_len) {
David Benjamin86e95b82017-07-18 16:34:25 -0400480 ScopedEVP_CIPHER_CTX ctx;
481 ScopedHMAC_CTX hctx;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400482
David Benjaminc11ea9422017-08-29 16:33:21 -0400483 // If the session is too long, emit a dummy value rather than abort the
484 // connection.
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400485 static const size_t kMaxTicketOverhead =
486 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
487 if (session_len > 0xffff - kMaxTicketOverhead) {
488 static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
David Benjamin0238d8f2017-07-12 17:35:14 -0400489 return CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder,
490 strlen(kTicketPlaceholder));
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400491 }
492
David Benjaminc11ea9422017-08-29 16:33:21 -0400493 // Initialize HMAC and cipher contexts. If callback present it does all the
494 // work otherwise use generated values from parent ctx.
David Benjaminbe497062017-03-10 16:08:36 -0500495 SSL_CTX *tctx = ssl->session_ctx;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400496 uint8_t iv[EVP_MAX_IV_LENGTH];
497 uint8_t key_name[16];
498 if (tctx->tlsext_ticket_key_cb != NULL) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400499 if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, ctx.get(), hctx.get(),
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400500 1 /* encrypt */) < 0) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400501 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400502 }
503 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400504 // Rotate ticket key if necessary.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700505 if (!ssl_ctx_rotate_ticket_encryption_key(tctx)) {
506 return 0;
507 }
508 MutexReadLock lock(&tctx->lock);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400509 if (!RAND_bytes(iv, 16) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400510 !EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL,
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700511 tctx->tlsext_ticket_key_current->aes_key, iv) ||
512 !HMAC_Init_ex(hctx.get(), tctx->tlsext_ticket_key_current->hmac_key, 16,
David Benjamin0238d8f2017-07-12 17:35:14 -0400513 tlsext_tick_md(), NULL)) {
514 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400515 }
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700516 OPENSSL_memcpy(key_name, tctx->tlsext_ticket_key_current->name, 16);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400517 }
518
519 uint8_t *ptr;
520 if (!CBB_add_bytes(out, key_name, 16) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400521 !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(ctx.get())) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400522 !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400523 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400524 }
525
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400526 size_t total = 0;
David Benjaminfbc45d72016-09-22 01:21:24 -0400527#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin17cf2cb2016-12-13 01:07:13 -0500528 OPENSSL_memcpy(ptr, session_buf, session_len);
David Benjaminfbc45d72016-09-22 01:21:24 -0400529 total = session_len;
530#else
531 int len;
David Benjamin0238d8f2017-07-12 17:35:14 -0400532 if (!EVP_EncryptUpdate(ctx.get(), ptr + total, &len, session_buf, session_len)) {
533 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400534 }
535 total += len;
David Benjamin0238d8f2017-07-12 17:35:14 -0400536 if (!EVP_EncryptFinal_ex(ctx.get(), ptr + total, &len)) {
537 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400538 }
539 total += len;
David Benjaminfbc45d72016-09-22 01:21:24 -0400540#endif
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400541 if (!CBB_did_write(out, total)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400542 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400543 }
544
545 unsigned hlen;
David Benjamin0238d8f2017-07-12 17:35:14 -0400546 if (!HMAC_Update(hctx.get(), CBB_data(out), CBB_len(out)) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400547 !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400548 !HMAC_Final(hctx.get(), ptr, &hlen) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400549 !CBB_did_write(out, hlen)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400550 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400551 }
552
David Benjamin0238d8f2017-07-12 17:35:14 -0400553 return 1;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400554}
555
Adam Langley4c341d02017-03-08 19:33:21 -0800556static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out,
557 const uint8_t *session_buf,
558 size_t session_len) {
559 const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
560 const size_t max_overhead = method->max_overhead(ssl);
561 const size_t max_out = session_len + max_overhead;
562 if (max_out < max_overhead) {
563 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
564 return 0;
565 }
566
567 uint8_t *ptr;
568 if (!CBB_reserve(out, &ptr, max_out)) {
569 return 0;
570 }
571
572 size_t out_len;
573 if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
574 OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
575 return 0;
576 }
577
578 if (!CBB_did_write(out, out_len)) {
579 return 0;
580 }
581
582 return 1;
583}
584
585int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400586 // Serialize the SSL_SESSION to be encoded into the ticket.
Adam Langley4c341d02017-03-08 19:33:21 -0800587 uint8_t *session_buf = NULL;
588 size_t session_len;
589 if (!SSL_SESSION_to_bytes_for_ticket(session, &session_buf, &session_len)) {
590 return -1;
591 }
592
593 int ret = 0;
594 if (ssl->session_ctx->ticket_aead_method) {
595 ret = ssl_encrypt_ticket_with_method(ssl, out, session_buf, session_len);
596 } else {
597 ret =
598 ssl_encrypt_ticket_with_cipher_ctx(ssl, out, session_buf, session_len);
599 }
600
601 OPENSSL_free(session_buf);
602 return ret;
603}
604
Steven Valdez4aa154e2016-07-29 14:32:55 -0400605int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session) {
606 if (session == NULL) {
607 return 0;
608 }
609
David Benjamin5960a902017-02-14 20:07:11 -0500610 return session->sid_ctx_length == ssl->cert->sid_ctx_length &&
611 OPENSSL_memcmp(session->sid_ctx, ssl->cert->sid_ctx,
612 ssl->cert->sid_ctx_length) == 0;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400613}
614
615int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
616 if (session == NULL) {
617 return 0;
618 }
619
David Benjaminad8f5e12017-02-20 17:00:20 -0500620 struct OPENSSL_timeval now;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400621 ssl_get_current_time(ssl, &now);
David Benjamin1b22f852016-10-27 16:36:32 -0400622
David Benjaminc11ea9422017-08-29 16:33:21 -0400623 // Reject tickets from the future to avoid underflow.
David Benjaminad8f5e12017-02-20 17:00:20 -0500624 if (now.tv_sec < session->time) {
David Benjamin1b22f852016-10-27 16:36:32 -0400625 return 0;
626 }
627
David Benjaminad8f5e12017-02-20 17:00:20 -0500628 return session->timeout > now.tv_sec - session->time;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400629}
630
David Benjamin45738dd2017-02-09 20:01:26 -0500631int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
632 const SSL_SESSION *session) {
633 const SSL *const ssl = hs->ssl;
David Benjamin75f99142016-11-12 12:36:06 +0900634 return ssl_session_is_context_valid(ssl, session) &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400635 // The session must have been created by the same type of end point as
636 // we're now using it with.
David Benjamin45738dd2017-02-09 20:01:26 -0500637 ssl->server == session->is_server &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400638 // The session must not be expired.
David Benjamin75f99142016-11-12 12:36:06 +0900639 ssl_session_is_time_valid(ssl, session) &&
640 /* Only resume if the session's version matches the negotiated
641 * version. */
642 ssl->version == session->ssl_version &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400643 // Only resume if the session's cipher matches the negotiated one.
David Benjamin45738dd2017-02-09 20:01:26 -0500644 hs->new_cipher == session->cipher &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400645 // If the session contains a client certificate (either the full
646 // certificate or just the hash) then require that the form of the
647 // certificate matches the current configuration.
Adam Langley46db7af2017-02-01 15:49:37 -0800648 ((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
649 !session->peer_sha256_valid) ||
David Benjaminbbaf3672016-11-17 10:53:09 +0900650 session->peer_sha256_valid ==
651 ssl->retain_only_sha256_of_client_certs);
David Benjamin75f99142016-11-12 12:36:06 +0900652}
653
David Benjaminc11ea9422017-08-29 16:33:21 -0400654// ssl_lookup_session looks up |session_id| in the session cache and sets
655// |*out_session| to an |SSL_SESSION| object if found.
Steven Valdez398085b2017-08-29 13:25:56 -0400656static enum ssl_hs_wait_t ssl_lookup_session(
David Benjamin37af90f2017-07-29 01:42:16 -0400657 SSL *ssl, UniquePtr<SSL_SESSION> *out_session, const uint8_t *session_id,
David Benjamine3aa1d92015-06-16 15:34:50 -0400658 size_t session_id_len) {
David Benjamin37af90f2017-07-29 01:42:16 -0400659 out_session->reset();
Adam Langley95c29f32014-06-20 12:00:00 -0700660
David Benjamine3aa1d92015-06-16 15:34:50 -0400661 if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
Steven Valdez398085b2017-08-29 13:25:56 -0400662 return ssl_hs_ok;
Adam Langleyfcf25832014-12-18 17:42:32 -0800663 }
Adam Langley95c29f32014-06-20 12:00:00 -0700664
David Benjamin37af90f2017-07-29 01:42:16 -0400665 UniquePtr<SSL_SESSION> session;
David Benjaminc11ea9422017-08-29 16:33:21 -0400666 // Try the internal cache, if it exists.
David Benjaminbe497062017-03-10 16:08:36 -0500667 if (!(ssl->session_ctx->session_cache_mode &
Adam Langleyfcf25832014-12-18 17:42:32 -0800668 SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
669 SSL_SESSION data;
David Benjamine3aa1d92015-06-16 15:34:50 -0400670 data.ssl_version = ssl->version;
671 data.session_id_length = session_id_len;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500672 OPENSSL_memcpy(data.session_id, session_id, session_id_len);
David Benjamine3aa1d92015-06-16 15:34:50 -0400673
David Benjaminbe497062017-03-10 16:08:36 -0500674 CRYPTO_MUTEX_lock_read(&ssl->session_ctx->lock);
David Benjamin37af90f2017-07-29 01:42:16 -0400675 session.reset(lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data));
676 if (session) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400677 // |lh_SSL_SESSION_retrieve| returns a non-owning pointer.
David Benjamin37af90f2017-07-29 01:42:16 -0400678 SSL_SESSION_up_ref(session.get());
Adam Langleyfcf25832014-12-18 17:42:32 -0800679 }
David Benjaminc11ea9422017-08-29 16:33:21 -0400680 // TODO(davidben): This should probably move it to the front of the list.
David Benjaminbe497062017-03-10 16:08:36 -0500681 CRYPTO_MUTEX_unlock_read(&ssl->session_ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800682 }
Adam Langley95c29f32014-06-20 12:00:00 -0700683
David Benjaminc11ea9422017-08-29 16:33:21 -0400684 // Fall back to the external cache, if it exists.
David Benjamin37af90f2017-07-29 01:42:16 -0400685 if (!session && ssl->session_ctx->get_session_cb != NULL) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400686 int copy = 1;
David Benjamin37af90f2017-07-29 01:42:16 -0400687 session.reset(ssl->session_ctx->get_session_cb(ssl, (uint8_t *)session_id,
688 session_id_len, &copy));
Steven Valdez4aa154e2016-07-29 14:32:55 -0400689
David Benjamin37af90f2017-07-29 01:42:16 -0400690 if (!session) {
Steven Valdez398085b2017-08-29 13:25:56 -0400691 return ssl_hs_ok;
Adam Langley81f43352016-08-26 09:22:56 -0700692 }
693
David Benjamin37af90f2017-07-29 01:42:16 -0400694 if (session.get() == SSL_magic_pending_session_ptr()) {
695 session.release(); // This pointer is not actually owned.
Steven Valdez398085b2017-08-29 13:25:56 -0400696 return ssl_hs_pending_session;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400697 }
698
David Benjaminc11ea9422017-08-29 16:33:21 -0400699 // Increment reference count now if the session callback asks us to do so
700 // (note that if the session structures returned by the callback are shared
701 // between threads, it must handle the reference count itself [i.e. copy ==
702 // 0], or things won't be thread-safe).
Steven Valdez4aa154e2016-07-29 14:32:55 -0400703 if (copy) {
David Benjamin37af90f2017-07-29 01:42:16 -0400704 SSL_SESSION_up_ref(session.get());
Steven Valdez4aa154e2016-07-29 14:32:55 -0400705 }
706
David Benjaminc11ea9422017-08-29 16:33:21 -0400707 // Add the externally cached session to the internal cache if necessary.
David Benjaminbe497062017-03-10 16:08:36 -0500708 if (!(ssl->session_ctx->session_cache_mode &
Steven Valdez4aa154e2016-07-29 14:32:55 -0400709 SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
David Benjamin37af90f2017-07-29 01:42:16 -0400710 SSL_CTX_add_session(ssl->session_ctx, session.get());
Steven Valdez4aa154e2016-07-29 14:32:55 -0400711 }
David Benjamine3aa1d92015-06-16 15:34:50 -0400712 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400713
David Benjamin37af90f2017-07-29 01:42:16 -0400714 if (session && !ssl_session_is_time_valid(ssl, session.get())) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400715 // The session was from the cache, so remove it.
David Benjamin37af90f2017-07-29 01:42:16 -0400716 SSL_CTX_remove_session(ssl->session_ctx, session.get());
717 session.reset();
David Benjamine3aa1d92015-06-16 15:34:50 -0400718 }
719
David Benjamin37af90f2017-07-29 01:42:16 -0400720 *out_session = std::move(session);
Steven Valdez398085b2017-08-29 13:25:56 -0400721 return ssl_hs_ok;
David Benjamine3aa1d92015-06-16 15:34:50 -0400722}
723
David Benjaminaba057a2017-09-11 15:21:43 -0400724bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello) {
725 CBS extension, groups;
726 if (SSL_is_dtls(client_hello->ssl) ||
727 !ssl_client_hello_get_extension(client_hello, &extension,
728 TLSEXT_TYPE_supported_groups) ||
729 !CBS_get_u16_length_prefixed(&extension, &groups) ||
730 CBS_len(&extension) != 0) {
731 return false;
732 }
733
734 // Original Java curve list.
735 static const uint8_t kCurveList1[] = {
736 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00, 0x15,
737 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18,
738 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e,
739 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12,
740 0x00, 0x04, 0x00, 0x05, 0x00, 0x14, 0x00, 0x08, 0x00, 0x16};
741
742 // Newer Java curve list.
743 static const uint8_t kCurveList2[] = {
744 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a,
745 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16};
746
747 // IcedTea curve list.
748 static const uint8_t kCurveList3[] = {0x00, 0x17, 0x00, 0x18, 0x00, 0x19};
749
750 auto groups_span = MakeConstSpan(CBS_data(&groups), CBS_len(&groups));
751 if (groups_span != kCurveList1 && groups_span != kCurveList2 &&
752 groups_span != kCurveList3) {
753 return false;
754 }
755
756 // Java has a very distinctive curve list, but IcedTea patches it to a more
757 // standard [P-256, P-384, P-521]. Additionally check the extension
758 // order. This is more likely to lead to false positives but false positives
759 // only mean a loss of resumption. Any client new enough to support one of
760 // X25519, extended master secret, session tickets, or TLS 1.3 will be
761 // unaffected.
762 //
763 // Java sends different extensions depending on configuration and version, but
764 // those which are present are always in the same order. Check if the
765 // extensions are an ordered subset of |kJavaExtensions|.
766 static const uint16_t kJavaExtensions[] = {
767 TLSEXT_TYPE_supported_groups,
768 TLSEXT_TYPE_ec_point_formats,
769 TLSEXT_TYPE_signature_algorithms,
770 TLSEXT_TYPE_server_name,
771 17 /* status_request_v2 */,
772 TLSEXT_TYPE_status_request,
773 TLSEXT_TYPE_application_layer_protocol_negotiation,
774 TLSEXT_TYPE_renegotiate,
775 };
776 CBS extensions;
777 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
778 for (uint16_t expected : kJavaExtensions) {
779 CBS extensions_copy = extensions, body;
780 uint16_t type;
781 // Peek at the next extension.
782 if (CBS_get_u16(&extensions_copy, &type) &&
783 CBS_get_u16_length_prefixed(&extensions_copy, &body) &&
784 type == expected) {
785 extensions = extensions_copy;
786 }
787 }
788 return CBS_len(&extensions) == 0;
789}
790
Steven Valdez398085b2017-08-29 13:25:56 -0400791enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
792 UniquePtr<SSL_SESSION> *out_session,
David Benjaminfd45ee72017-08-31 14:49:09 -0400793 bool *out_tickets_supported,
794 bool *out_renew_ticket,
Steven Valdez398085b2017-08-29 13:25:56 -0400795 const SSL_CLIENT_HELLO *client_hello) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400796 // This is used only by servers.
David Benjamine3aa1d92015-06-16 15:34:50 -0400797 assert(ssl->server);
David Benjamine3aa1d92015-06-16 15:34:50 -0400798
David Benjaminc11ea9422017-08-29 16:33:21 -0400799 // If tickets are disabled, always behave as if no tickets are present.
David Benjamin3e536332015-07-01 18:45:03 -0400800 const uint8_t *ticket = NULL;
801 size_t ticket_len = 0;
David Benjaminfd45ee72017-08-31 14:49:09 -0400802 const bool tickets_supported =
David Benjamine3aa1d92015-06-16 15:34:50 -0400803 !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
David Benjaminc7ce9772015-10-09 19:32:41 -0400804 ssl->version > SSL3_VERSION &&
David Benjamin731058e2016-12-03 23:15:13 -0500805 SSL_early_callback_ctx_extension_get(
806 client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
David Benjaminaba057a2017-09-11 15:21:43 -0400807
808 if (ssl_is_probably_java(client_hello)) {
809 // The Java client implementation of the 3SHAKE mitigation incorrectly
810 // rejects initial handshakes when all of the following are true:
811 //
812 // 1. The ClientHello offered a session.
813 // 2. The session was successfully resumed previously.
814 // 3. The server declines the session.
815 // 4. The server sends a certificate with a different SAN list than in the
816 // previous session.
817 //
818 // (Note the 3SHAKE mitigation is to reject certificates changes on
819 // renegotiation, while Java's logic applies to initial handshakes as well.)
820 //
821 // The end result is long-lived Java clients break on some certificate
822 // rotations. Fingerprint Java clients and decline all offered
823 // sessions. This avoids (2) while still introducing new sessions to clear
824 // any existing problematic sessions.
825 *out_session = nullptr;
826 *out_tickets_supported = tickets_supported;
827 *out_renew_ticket = false;
828 return ssl_hs_ok;
829 }
830
831 UniquePtr<SSL_SESSION> session;
832 bool renew_ticket = false;
David Benjaminef1b0092015-11-21 14:05:44 -0500833 if (tickets_supported && ticket_len > 0) {
Adam Langley4c341d02017-03-08 19:33:21 -0800834 switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
835 client_hello->session_id,
836 client_hello->session_id_len)) {
837 case ssl_ticket_aead_success:
838 break;
839 case ssl_ticket_aead_ignore_ticket:
David Benjamin37af90f2017-07-29 01:42:16 -0400840 assert(!session);
Adam Langley4c341d02017-03-08 19:33:21 -0800841 break;
842 case ssl_ticket_aead_error:
Steven Valdez398085b2017-08-29 13:25:56 -0400843 return ssl_hs_error;
Adam Langley4c341d02017-03-08 19:33:21 -0800844 case ssl_ticket_aead_retry:
Steven Valdez398085b2017-08-29 13:25:56 -0400845 return ssl_hs_pending_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -0400846 }
847 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400848 // The client didn't send a ticket, so the session ID is a real ID.
Steven Valdez398085b2017-08-29 13:25:56 -0400849 enum ssl_hs_wait_t lookup_ret = ssl_lookup_session(
David Benjamin731058e2016-12-03 23:15:13 -0500850 ssl, &session, client_hello->session_id, client_hello->session_id_len);
Steven Valdez398085b2017-08-29 13:25:56 -0400851 if (lookup_ret != ssl_hs_ok) {
David Benjamine3aa1d92015-06-16 15:34:50 -0400852 return lookup_ret;
853 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800854 }
Adam Langley95c29f32014-06-20 12:00:00 -0700855
David Benjamin37af90f2017-07-29 01:42:16 -0400856 *out_session = std::move(session);
David Benjamin75f99142016-11-12 12:36:06 +0900857 *out_tickets_supported = tickets_supported;
858 *out_renew_ticket = renew_ticket;
Steven Valdez398085b2017-08-29 13:25:56 -0400859 return ssl_hs_ok;
Adam Langley95c29f32014-06-20 12:00:00 -0700860}
861
David Benjamin86e95b82017-07-18 16:34:25 -0400862static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
863 int ret = 0;
864
865 if (session != NULL && session->session_id_length != 0) {
866 if (lock) {
867 CRYPTO_MUTEX_lock_write(&ctx->lock);
868 }
869 SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
870 session);
871 if (found_session == session) {
872 ret = 1;
873 found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
874 SSL_SESSION_list_remove(ctx, session);
875 }
876
877 if (lock) {
878 CRYPTO_MUTEX_unlock_write(&ctx->lock);
879 }
880
881 if (ret) {
882 if (ctx->remove_session_cb != NULL) {
883 ctx->remove_session_cb(ctx, found_session);
884 }
885 SSL_SESSION_free(found_session);
886 }
887 }
888
889 return ret;
890}
891
892void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
893 if (ssl->session == session) {
894 return;
895 }
896
897 SSL_SESSION_free(ssl->session);
898 ssl->session = session;
899 if (session != NULL) {
900 SSL_SESSION_up_ref(session);
901 }
902}
903
David Benjaminc11ea9422017-08-29 16:33:21 -0400904// locked by SSL_CTX in the calling function
David Benjamin86e95b82017-07-18 16:34:25 -0400905static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
906 if (session->next == NULL || session->prev == NULL) {
907 return;
908 }
909
910 if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400911 // last element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400912 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400913 // only one element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400914 ctx->session_cache_head = NULL;
915 ctx->session_cache_tail = NULL;
916 } else {
917 ctx->session_cache_tail = session->prev;
918 session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
919 }
920 } else {
921 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400922 // first element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400923 ctx->session_cache_head = session->next;
924 session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
David Benjaminc11ea9422017-08-29 16:33:21 -0400925 } else { // middle of list
David Benjamin86e95b82017-07-18 16:34:25 -0400926 session->next->prev = session->prev;
927 session->prev->next = session->next;
928 }
929 }
930 session->prev = session->next = NULL;
931}
932
933static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
934 if (session->next != NULL && session->prev != NULL) {
935 SSL_SESSION_list_remove(ctx, session);
936 }
937
938 if (ctx->session_cache_head == NULL) {
939 ctx->session_cache_head = session;
940 ctx->session_cache_tail = session;
941 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
942 session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
943 } else {
944 session->next = ctx->session_cache_head;
945 session->next->prev = session;
946 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
947 ctx->session_cache_head = session;
948 }
949}
950
951} // namespace bssl
952
953using namespace bssl;
954
955SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400956 return ssl_session_new(ctx->x509_method).release();
David Benjamin86e95b82017-07-18 16:34:25 -0400957}
958
959int SSL_SESSION_up_ref(SSL_SESSION *session) {
960 CRYPTO_refcount_inc(&session->references);
961 return 1;
962}
963
964void SSL_SESSION_free(SSL_SESSION *session) {
965 if (session == NULL ||
966 !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
967 return;
968 }
969
970 CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
971
972 OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
973 OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
974 sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
975 session->x509_method->session_clear(session);
David Benjamin86e95b82017-07-18 16:34:25 -0400976 OPENSSL_free(session->tlsext_tick);
David Benjamin8fc2dc02017-08-22 15:07:51 -0700977 CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
978 CRYPTO_BUFFER_free(session->ocsp_response);
David Benjamin86e95b82017-07-18 16:34:25 -0400979 OPENSSL_free(session->psk_identity);
980 OPENSSL_free(session->early_alpn);
981 OPENSSL_cleanse(session, sizeof(*session));
982 OPENSSL_free(session);
983}
984
985const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
986 unsigned *out_len) {
987 if (out_len != NULL) {
988 *out_len = session->session_id_length;
989 }
990 return session->session_id;
991}
992
993uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
994 return session->timeout;
995}
996
997uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
998 if (session == NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400999 // NULL should crash, but silently accept it here for compatibility.
David Benjamin86e95b82017-07-18 16:34:25 -04001000 return 0;
1001 }
1002 return session->time;
1003}
1004
1005X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
1006 return session->x509_peer;
1007}
1008
1009size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
1010 size_t max_out) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001011 // TODO(davidben): Fix master_key_length's type and remove these casts.
David Benjamin86e95b82017-07-18 16:34:25 -04001012 if (max_out == 0) {
1013 return (size_t)session->master_key_length;
1014 }
1015 if (max_out > (size_t)session->master_key_length) {
1016 max_out = (size_t)session->master_key_length;
1017 }
1018 OPENSSL_memcpy(out, session->master_key, max_out);
1019 return max_out;
1020}
1021
1022uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
1023 if (session == NULL) {
1024 return 0;
1025 }
1026
1027 session->time = time;
1028 return time;
1029}
1030
1031uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
1032 if (session == NULL) {
1033 return 0;
1034 }
1035
1036 session->timeout = timeout;
1037 session->auth_timeout = timeout;
1038 return 1;
1039}
1040
1041int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
1042 size_t sid_ctx_len) {
1043 if (sid_ctx_len > sizeof(session->sid_ctx)) {
1044 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
1045 return 0;
1046 }
1047
David Benjamin27e377e2017-07-31 19:09:42 -04001048 static_assert(sizeof(session->sid_ctx) < 256, "sid_ctx_len does not fit");
David Benjamin86e95b82017-07-18 16:34:25 -04001049 session->sid_ctx_length = (uint8_t)sid_ctx_len;
1050 OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
1051
1052 return 1;
1053}
1054
1055SSL_SESSION *SSL_magic_pending_session_ptr(void) {
1056 return (SSL_SESSION *)&g_pending_session_magic;
1057}
1058
1059SSL_SESSION *SSL_get_session(const SSL *ssl) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001060 // Once the handshake completes we return the established session. Otherwise
1061 // we return the intermediate session, either |session| (for resumption) or
1062 // |new_session| if doing a full handshake.
David Benjamin86e95b82017-07-18 16:34:25 -04001063 if (!SSL_in_init(ssl)) {
1064 return ssl->s3->established_session;
1065 }
1066 SSL_HANDSHAKE *hs = ssl->s3->hs;
David Benjamin31b0c9b2017-07-20 14:49:15 -04001067 if (hs->early_session) {
1068 return hs->early_session.get();
David Benjamin86e95b82017-07-18 16:34:25 -04001069 }
David Benjamin31b0c9b2017-07-20 14:49:15 -04001070 if (hs->new_session) {
1071 return hs->new_session.get();
David Benjamin86e95b82017-07-18 16:34:25 -04001072 }
1073 return ssl->session;
1074}
1075
1076SSL_SESSION *SSL_get1_session(SSL *ssl) {
1077 SSL_SESSION *ret = SSL_get_session(ssl);
1078 if (ret != NULL) {
1079 SSL_SESSION_up_ref(ret);
1080 }
1081 return ret;
1082}
1083
1084int SSL_SESSION_get_ex_new_index(long argl, void *argp,
1085 CRYPTO_EX_unused *unused,
1086 CRYPTO_EX_dup *dup_unused,
1087 CRYPTO_EX_free *free_func) {
1088 int index;
1089 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
1090 free_func)) {
1091 return -1;
1092 }
1093 return index;
1094}
1095
1096int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
1097 return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
1098}
1099
1100void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
1101 return CRYPTO_get_ex_data(&session->ex_data, idx);
1102}
1103
David Benjamindafbdd42015-09-14 01:40:10 -04001104int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001105 // Although |session| is inserted into two structures (a doubly-linked list
1106 // and the hash table), |ctx| only takes one reference.
David Benjamindafbdd42015-09-14 01:40:10 -04001107 SSL_SESSION_up_ref(session);
Adam Langley95c29f32014-06-20 12:00:00 -07001108
David Benjamin415660b2015-10-18 15:08:57 -04001109 SSL_SESSION *old_session;
Adam Langley4bdb6e42015-05-15 15:29:21 -07001110 CRYPTO_MUTEX_lock_write(&ctx->lock);
David Benjamindafbdd42015-09-14 01:40:10 -04001111 if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
David Benjamin29270de2016-05-24 15:28:36 +00001112 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamindafbdd42015-09-14 01:40:10 -04001113 SSL_SESSION_free(session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001114 return 0;
1115 }
Adam Langley95c29f32014-06-20 12:00:00 -07001116
David Benjamin415660b2015-10-18 15:08:57 -04001117 if (old_session != NULL) {
1118 if (old_session == session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001119 // |session| was already in the cache.
David Benjamin29270de2016-05-24 15:28:36 +00001120 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamin415660b2015-10-18 15:08:57 -04001121 SSL_SESSION_free(old_session);
1122 return 0;
1123 }
1124
David Benjaminc11ea9422017-08-29 16:33:21 -04001125 // There was a session ID collision. |old_session| must be removed from
1126 // the linked list and released.
David Benjamindafbdd42015-09-14 01:40:10 -04001127 SSL_SESSION_list_remove(ctx, old_session);
1128 SSL_SESSION_free(old_session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001129 }
Adam Langley95c29f32014-06-20 12:00:00 -07001130
David Benjamin415660b2015-10-18 15:08:57 -04001131 SSL_SESSION_list_add(ctx, session);
Adam Langley95c29f32014-06-20 12:00:00 -07001132
David Benjaminc11ea9422017-08-29 16:33:21 -04001133 // Enforce any cache size limits.
David Benjamin415660b2015-10-18 15:08:57 -04001134 if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
1135 while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
1136 if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
1137 break;
Adam Langleyfcf25832014-12-18 17:42:32 -08001138 }
1139 }
1140 }
Adam Langley95c29f32014-06-20 12:00:00 -07001141
David Benjamin29270de2016-05-24 15:28:36 +00001142 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamin415660b2015-10-18 15:08:57 -04001143 return 1;
Adam Langleyfcf25832014-12-18 17:42:32 -08001144}
Adam Langley95c29f32014-06-20 12:00:00 -07001145
David Benjamindafbdd42015-09-14 01:40:10 -04001146int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) {
1147 return remove_session_lock(ctx, session, 1);
Adam Langleyfcf25832014-12-18 17:42:32 -08001148}
Adam Langley95c29f32014-06-20 12:00:00 -07001149
David Benjamindafbdd42015-09-14 01:40:10 -04001150int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001151 // SSL_set_session may only be called before the handshake has started.
David Benjamin9e766d72017-02-10 23:14:17 -05001152 if (ssl->s3->initial_handshake_complete ||
1153 ssl->s3->hs == NULL ||
Steven Valdez4d71a9a2017-08-14 15:08:34 -04001154 ssl->s3->hs->state != 0) {
David Benjamin4d0be242016-09-01 01:10:07 -04001155 abort();
1156 }
1157
1158 ssl_set_session(ssl, session);
1159 return 1;
1160}
1161
David Benjaminad8f5e12017-02-20 17:00:20 -05001162uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
David Benjamindafbdd42015-09-14 01:40:10 -04001163 if (ctx == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001164 return 0;
1165 }
1166
David Benjaminc11ea9422017-08-29 16:33:21 -04001167 // Historically, zero was treated as |SSL_DEFAULT_SESSION_TIMEOUT|.
David Benjamin0b1bb122017-01-28 14:32:53 -05001168 if (timeout == 0) {
1169 timeout = SSL_DEFAULT_SESSION_TIMEOUT;
1170 }
1171
David Benjaminad8f5e12017-02-20 17:00:20 -05001172 uint32_t old_timeout = ctx->session_timeout;
David Benjamindafbdd42015-09-14 01:40:10 -04001173 ctx->session_timeout = timeout;
1174 return old_timeout;
Adam Langleyfcf25832014-12-18 17:42:32 -08001175}
1176
David Benjaminad8f5e12017-02-20 17:00:20 -05001177uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx) {
David Benjamindafbdd42015-09-14 01:40:10 -04001178 if (ctx == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001179 return 0;
1180 }
1181
David Benjamindafbdd42015-09-14 01:40:10 -04001182 return ctx->session_timeout;
Adam Langleyfcf25832014-12-18 17:42:32 -08001183}
1184
David Benjaminad8f5e12017-02-20 17:00:20 -05001185void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, uint32_t timeout) {
David Benjamin17b30832017-01-28 14:00:32 -05001186 ctx->session_psk_dhe_timeout = timeout;
1187}
1188
Adam Langleyfcf25832014-12-18 17:42:32 -08001189typedef struct timeout_param_st {
1190 SSL_CTX *ctx;
David Benjaminad8f5e12017-02-20 17:00:20 -05001191 uint64_t time;
David Benjamin60da0cd2015-05-03 15:21:28 -04001192 LHASH_OF(SSL_SESSION) *cache;
Adam Langleyfcf25832014-12-18 17:42:32 -08001193} TIMEOUT_PARAM;
1194
David Benjamindafbdd42015-09-14 01:40:10 -04001195static void timeout_doall_arg(SSL_SESSION *session, void *void_param) {
David Benjamin0238d8f2017-07-12 17:35:14 -04001196 TIMEOUT_PARAM *param = reinterpret_cast<TIMEOUT_PARAM *>(void_param);
Adam Langleyfcf25832014-12-18 17:42:32 -08001197
1198 if (param->time == 0 ||
David Benjaminad8f5e12017-02-20 17:00:20 -05001199 session->time + session->timeout < session->time ||
David Benjamindafbdd42015-09-14 01:40:10 -04001200 param->time > (session->time + session->timeout)) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001201 // The reason we don't call SSL_CTX_remove_session() is to
1202 // save on locking overhead
David Benjamindafbdd42015-09-14 01:40:10 -04001203 (void) lh_SSL_SESSION_delete(param->cache, session);
1204 SSL_SESSION_list_remove(param->ctx, session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001205 if (param->ctx->remove_session_cb != NULL) {
David Benjamindafbdd42015-09-14 01:40:10 -04001206 param->ctx->remove_session_cb(param->ctx, session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001207 }
David Benjamindafbdd42015-09-14 01:40:10 -04001208 SSL_SESSION_free(session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001209 }
1210}
1211
David Benjaminad8f5e12017-02-20 17:00:20 -05001212void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001213 TIMEOUT_PARAM tp;
1214
Adam Langley4bdb6e42015-05-15 15:29:21 -07001215 tp.ctx = ctx;
1216 tp.cache = ctx->sessions;
Adam Langleyfcf25832014-12-18 17:42:32 -08001217 if (tp.cache == NULL) {
1218 return;
1219 }
David Benjamindafbdd42015-09-14 01:40:10 -04001220 tp.time = time;
Adam Langley4bdb6e42015-05-15 15:29:21 -07001221 CRYPTO_MUTEX_lock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -08001222 lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
David Benjamin29270de2016-05-24 15:28:36 +00001223 CRYPTO_MUTEX_unlock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -08001224}
1225
Adam Langley95c29f32014-06-20 12:00:00 -07001226void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001227 int (*cb)(SSL *ssl, SSL_SESSION *session)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001228 ctx->new_session_cb = cb;
1229}
Adam Langley95c29f32014-06-20 12:00:00 -07001230
David Benjamindafbdd42015-09-14 01:40:10 -04001231int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001232 return ctx->new_session_cb;
1233}
Adam Langley95c29f32014-06-20 12:00:00 -07001234
David Benjamindafbdd42015-09-14 01:40:10 -04001235void SSL_CTX_sess_set_remove_cb(
1236 SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *session)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001237 ctx->remove_session_cb = cb;
1238}
Adam Langley95c29f32014-06-20 12:00:00 -07001239
Adam Langleyfcf25832014-12-18 17:42:32 -08001240void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001241 SSL_SESSION *session) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001242 return ctx->remove_session_cb;
1243}
Adam Langley95c29f32014-06-20 12:00:00 -07001244
1245void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001246 SSL_SESSION *(*cb)(SSL *ssl,
1247 uint8_t *id, int id_len,
1248 int *out_copy)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001249 ctx->get_session_cb = cb;
1250}
Adam Langley95c29f32014-06-20 12:00:00 -07001251
David Benjamindafbdd42015-09-14 01:40:10 -04001252SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
1253 SSL *ssl, uint8_t *id, int id_len, int *out_copy) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001254 return ctx->get_session_cb;
1255}
Adam Langley95c29f32014-06-20 12:00:00 -07001256
David Benjamin82170242015-10-17 22:51:17 -04001257void SSL_CTX_set_info_callback(
1258 SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001259 ctx->info_callback = cb;
1260}
Adam Langley95c29f32014-06-20 12:00:00 -07001261
Adam Langleyfcf25832014-12-18 17:42:32 -08001262void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type,
David Benjamin82170242015-10-17 22:51:17 -04001263 int value) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001264 return ctx->info_callback;
1265}
Adam Langley95c29f32014-06-20 12:00:00 -07001266
Adam Langley1258b6a2014-06-20 12:00:00 -07001267void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -08001268 void (*cb)(SSL *ssl, EVP_PKEY **pkey)) {
1269 ctx->channel_id_cb = cb;
1270}
Adam Langley1258b6a2014-06-20 12:00:00 -07001271
Adam Langleyfcf25832014-12-18 17:42:32 -08001272void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) {
1273 return ctx->channel_id_cb;
1274}