blob: 26d0b7bc062438578733525e124bab3758f5341e [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
David Benjamin5a79ff52017-09-14 16:36:18 -0400758 // order. This may still flag other clients, but false positives only mean a
759 // loss of resumption. Any client new enough to support one of X25519,
760 // extended master secret, session tickets, or TLS 1.3 will be unaffected.
David Benjaminaba057a2017-09-11 15:21:43 -0400761 //
762 // Java sends different extensions depending on configuration and version, but
763 // those which are present are always in the same order. Check if the
764 // extensions are an ordered subset of |kJavaExtensions|.
765 static const uint16_t kJavaExtensions[] = {
766 TLSEXT_TYPE_supported_groups,
767 TLSEXT_TYPE_ec_point_formats,
768 TLSEXT_TYPE_signature_algorithms,
769 TLSEXT_TYPE_server_name,
770 17 /* status_request_v2 */,
771 TLSEXT_TYPE_status_request,
772 TLSEXT_TYPE_application_layer_protocol_negotiation,
773 TLSEXT_TYPE_renegotiate,
774 };
775 CBS extensions;
776 CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
777 for (uint16_t expected : kJavaExtensions) {
778 CBS extensions_copy = extensions, body;
779 uint16_t type;
780 // Peek at the next extension.
781 if (CBS_get_u16(&extensions_copy, &type) &&
782 CBS_get_u16_length_prefixed(&extensions_copy, &body) &&
783 type == expected) {
784 extensions = extensions_copy;
785 }
786 }
787 return CBS_len(&extensions) == 0;
788}
789
Steven Valdez398085b2017-08-29 13:25:56 -0400790enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
791 UniquePtr<SSL_SESSION> *out_session,
David Benjaminfd45ee72017-08-31 14:49:09 -0400792 bool *out_tickets_supported,
793 bool *out_renew_ticket,
Steven Valdez398085b2017-08-29 13:25:56 -0400794 const SSL_CLIENT_HELLO *client_hello) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400795 // This is used only by servers.
David Benjamine3aa1d92015-06-16 15:34:50 -0400796 assert(ssl->server);
David Benjamine3aa1d92015-06-16 15:34:50 -0400797
David Benjaminc11ea9422017-08-29 16:33:21 -0400798 // If tickets are disabled, always behave as if no tickets are present.
David Benjamin3e536332015-07-01 18:45:03 -0400799 const uint8_t *ticket = NULL;
800 size_t ticket_len = 0;
David Benjaminfd45ee72017-08-31 14:49:09 -0400801 const bool tickets_supported =
David Benjamine3aa1d92015-06-16 15:34:50 -0400802 !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
David Benjaminc7ce9772015-10-09 19:32:41 -0400803 ssl->version > SSL3_VERSION &&
David Benjamin731058e2016-12-03 23:15:13 -0500804 SSL_early_callback_ctx_extension_get(
805 client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
David Benjaminaba057a2017-09-11 15:21:43 -0400806
807 if (ssl_is_probably_java(client_hello)) {
808 // The Java client implementation of the 3SHAKE mitigation incorrectly
809 // rejects initial handshakes when all of the following are true:
810 //
811 // 1. The ClientHello offered a session.
812 // 2. The session was successfully resumed previously.
813 // 3. The server declines the session.
David Benjamin5a79ff52017-09-14 16:36:18 -0400814 // 4. The server sends a certificate with a different (see below) SAN list
815 // than in the previous session.
David Benjaminaba057a2017-09-11 15:21:43 -0400816 //
817 // (Note the 3SHAKE mitigation is to reject certificates changes on
818 // renegotiation, while Java's logic applies to initial handshakes as well.)
819 //
David Benjamin5a79ff52017-09-14 16:36:18 -0400820 // The end result is long-lived Java clients break on certificate rotations
821 // where the SAN list changes too much. Older versions of Java break if the
822 // first DNS name of the two certificates is different. Newer ones will
823 // break if there is no intersection. The new logic mostly mitigates this,
824 // but this can still cause problems if switching to or from wildcards.
825 //
826 // Thus, fingerprint Java clients and decline all offered sessions. This
827 // avoids (2) while still introducing new sessions to clear any existing
828 // problematic sessions.
David Benjaminaba057a2017-09-11 15:21:43 -0400829 *out_session = nullptr;
830 *out_tickets_supported = tickets_supported;
831 *out_renew_ticket = false;
832 return ssl_hs_ok;
833 }
834
835 UniquePtr<SSL_SESSION> session;
836 bool renew_ticket = false;
David Benjaminef1b0092015-11-21 14:05:44 -0500837 if (tickets_supported && ticket_len > 0) {
Adam Langley4c341d02017-03-08 19:33:21 -0800838 switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
839 client_hello->session_id,
840 client_hello->session_id_len)) {
841 case ssl_ticket_aead_success:
842 break;
843 case ssl_ticket_aead_ignore_ticket:
David Benjamin37af90f2017-07-29 01:42:16 -0400844 assert(!session);
Adam Langley4c341d02017-03-08 19:33:21 -0800845 break;
846 case ssl_ticket_aead_error:
Steven Valdez398085b2017-08-29 13:25:56 -0400847 return ssl_hs_error;
Adam Langley4c341d02017-03-08 19:33:21 -0800848 case ssl_ticket_aead_retry:
Steven Valdez398085b2017-08-29 13:25:56 -0400849 return ssl_hs_pending_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -0400850 }
851 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400852 // The client didn't send a ticket, so the session ID is a real ID.
Steven Valdez398085b2017-08-29 13:25:56 -0400853 enum ssl_hs_wait_t lookup_ret = ssl_lookup_session(
David Benjamin731058e2016-12-03 23:15:13 -0500854 ssl, &session, client_hello->session_id, client_hello->session_id_len);
Steven Valdez398085b2017-08-29 13:25:56 -0400855 if (lookup_ret != ssl_hs_ok) {
David Benjamine3aa1d92015-06-16 15:34:50 -0400856 return lookup_ret;
857 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800858 }
Adam Langley95c29f32014-06-20 12:00:00 -0700859
David Benjamin37af90f2017-07-29 01:42:16 -0400860 *out_session = std::move(session);
David Benjamin75f99142016-11-12 12:36:06 +0900861 *out_tickets_supported = tickets_supported;
862 *out_renew_ticket = renew_ticket;
Steven Valdez398085b2017-08-29 13:25:56 -0400863 return ssl_hs_ok;
Adam Langley95c29f32014-06-20 12:00:00 -0700864}
865
David Benjamin86e95b82017-07-18 16:34:25 -0400866static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
867 int ret = 0;
868
869 if (session != NULL && session->session_id_length != 0) {
870 if (lock) {
871 CRYPTO_MUTEX_lock_write(&ctx->lock);
872 }
873 SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
874 session);
875 if (found_session == session) {
876 ret = 1;
877 found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
878 SSL_SESSION_list_remove(ctx, session);
879 }
880
881 if (lock) {
882 CRYPTO_MUTEX_unlock_write(&ctx->lock);
883 }
884
885 if (ret) {
886 if (ctx->remove_session_cb != NULL) {
887 ctx->remove_session_cb(ctx, found_session);
888 }
889 SSL_SESSION_free(found_session);
890 }
891 }
892
893 return ret;
894}
895
896void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
897 if (ssl->session == session) {
898 return;
899 }
900
901 SSL_SESSION_free(ssl->session);
902 ssl->session = session;
903 if (session != NULL) {
904 SSL_SESSION_up_ref(session);
905 }
906}
907
David Benjaminc11ea9422017-08-29 16:33:21 -0400908// locked by SSL_CTX in the calling function
David Benjamin86e95b82017-07-18 16:34:25 -0400909static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
910 if (session->next == NULL || session->prev == NULL) {
911 return;
912 }
913
914 if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400915 // last element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400916 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400917 // only one element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400918 ctx->session_cache_head = NULL;
919 ctx->session_cache_tail = NULL;
920 } else {
921 ctx->session_cache_tail = session->prev;
922 session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
923 }
924 } else {
925 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400926 // first element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400927 ctx->session_cache_head = session->next;
928 session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
David Benjaminc11ea9422017-08-29 16:33:21 -0400929 } else { // middle of list
David Benjamin86e95b82017-07-18 16:34:25 -0400930 session->next->prev = session->prev;
931 session->prev->next = session->next;
932 }
933 }
934 session->prev = session->next = NULL;
935}
936
937static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
938 if (session->next != NULL && session->prev != NULL) {
939 SSL_SESSION_list_remove(ctx, session);
940 }
941
942 if (ctx->session_cache_head == NULL) {
943 ctx->session_cache_head = session;
944 ctx->session_cache_tail = session;
945 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
946 session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
947 } else {
948 session->next = ctx->session_cache_head;
949 session->next->prev = session;
950 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
951 ctx->session_cache_head = session;
952 }
953}
954
955} // namespace bssl
956
957using namespace bssl;
958
959SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400960 return ssl_session_new(ctx->x509_method).release();
David Benjamin86e95b82017-07-18 16:34:25 -0400961}
962
963int SSL_SESSION_up_ref(SSL_SESSION *session) {
964 CRYPTO_refcount_inc(&session->references);
965 return 1;
966}
967
968void SSL_SESSION_free(SSL_SESSION *session) {
969 if (session == NULL ||
970 !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
971 return;
972 }
973
974 CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
975
976 OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
977 OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
978 sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
979 session->x509_method->session_clear(session);
David Benjamin86e95b82017-07-18 16:34:25 -0400980 OPENSSL_free(session->tlsext_tick);
David Benjamin8fc2dc02017-08-22 15:07:51 -0700981 CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
982 CRYPTO_BUFFER_free(session->ocsp_response);
David Benjamin86e95b82017-07-18 16:34:25 -0400983 OPENSSL_free(session->psk_identity);
984 OPENSSL_free(session->early_alpn);
985 OPENSSL_cleanse(session, sizeof(*session));
986 OPENSSL_free(session);
987}
988
989const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
990 unsigned *out_len) {
991 if (out_len != NULL) {
992 *out_len = session->session_id_length;
993 }
994 return session->session_id;
995}
996
997uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
998 return session->timeout;
999}
1000
1001uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
1002 if (session == NULL) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001003 // NULL should crash, but silently accept it here for compatibility.
David Benjamin86e95b82017-07-18 16:34:25 -04001004 return 0;
1005 }
1006 return session->time;
1007}
1008
1009X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
1010 return session->x509_peer;
1011}
1012
1013size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
1014 size_t max_out) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001015 // TODO(davidben): Fix master_key_length's type and remove these casts.
David Benjamin86e95b82017-07-18 16:34:25 -04001016 if (max_out == 0) {
1017 return (size_t)session->master_key_length;
1018 }
1019 if (max_out > (size_t)session->master_key_length) {
1020 max_out = (size_t)session->master_key_length;
1021 }
1022 OPENSSL_memcpy(out, session->master_key, max_out);
1023 return max_out;
1024}
1025
1026uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
1027 if (session == NULL) {
1028 return 0;
1029 }
1030
1031 session->time = time;
1032 return time;
1033}
1034
1035uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
1036 if (session == NULL) {
1037 return 0;
1038 }
1039
1040 session->timeout = timeout;
1041 session->auth_timeout = timeout;
1042 return 1;
1043}
1044
1045int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
1046 size_t sid_ctx_len) {
1047 if (sid_ctx_len > sizeof(session->sid_ctx)) {
1048 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
1049 return 0;
1050 }
1051
David Benjamin27e377e2017-07-31 19:09:42 -04001052 static_assert(sizeof(session->sid_ctx) < 256, "sid_ctx_len does not fit");
David Benjamin86e95b82017-07-18 16:34:25 -04001053 session->sid_ctx_length = (uint8_t)sid_ctx_len;
1054 OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
1055
1056 return 1;
1057}
1058
1059SSL_SESSION *SSL_magic_pending_session_ptr(void) {
1060 return (SSL_SESSION *)&g_pending_session_magic;
1061}
1062
1063SSL_SESSION *SSL_get_session(const SSL *ssl) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001064 // Once the handshake completes we return the established session. Otherwise
1065 // we return the intermediate session, either |session| (for resumption) or
1066 // |new_session| if doing a full handshake.
David Benjamin86e95b82017-07-18 16:34:25 -04001067 if (!SSL_in_init(ssl)) {
1068 return ssl->s3->established_session;
1069 }
1070 SSL_HANDSHAKE *hs = ssl->s3->hs;
David Benjamin31b0c9b2017-07-20 14:49:15 -04001071 if (hs->early_session) {
1072 return hs->early_session.get();
David Benjamin86e95b82017-07-18 16:34:25 -04001073 }
David Benjamin31b0c9b2017-07-20 14:49:15 -04001074 if (hs->new_session) {
1075 return hs->new_session.get();
David Benjamin86e95b82017-07-18 16:34:25 -04001076 }
1077 return ssl->session;
1078}
1079
1080SSL_SESSION *SSL_get1_session(SSL *ssl) {
1081 SSL_SESSION *ret = SSL_get_session(ssl);
1082 if (ret != NULL) {
1083 SSL_SESSION_up_ref(ret);
1084 }
1085 return ret;
1086}
1087
1088int SSL_SESSION_get_ex_new_index(long argl, void *argp,
1089 CRYPTO_EX_unused *unused,
1090 CRYPTO_EX_dup *dup_unused,
1091 CRYPTO_EX_free *free_func) {
1092 int index;
1093 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
1094 free_func)) {
1095 return -1;
1096 }
1097 return index;
1098}
1099
1100int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
1101 return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
1102}
1103
1104void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
1105 return CRYPTO_get_ex_data(&session->ex_data, idx);
1106}
1107
David Benjamindafbdd42015-09-14 01:40:10 -04001108int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001109 // Although |session| is inserted into two structures (a doubly-linked list
1110 // and the hash table), |ctx| only takes one reference.
David Benjamindafbdd42015-09-14 01:40:10 -04001111 SSL_SESSION_up_ref(session);
Adam Langley95c29f32014-06-20 12:00:00 -07001112
David Benjamin415660b2015-10-18 15:08:57 -04001113 SSL_SESSION *old_session;
Adam Langley4bdb6e42015-05-15 15:29:21 -07001114 CRYPTO_MUTEX_lock_write(&ctx->lock);
David Benjamindafbdd42015-09-14 01:40:10 -04001115 if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
David Benjamin29270de2016-05-24 15:28:36 +00001116 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamindafbdd42015-09-14 01:40:10 -04001117 SSL_SESSION_free(session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001118 return 0;
1119 }
Adam Langley95c29f32014-06-20 12:00:00 -07001120
David Benjamin415660b2015-10-18 15:08:57 -04001121 if (old_session != NULL) {
1122 if (old_session == session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001123 // |session| was already in the cache.
David Benjamin29270de2016-05-24 15:28:36 +00001124 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamin415660b2015-10-18 15:08:57 -04001125 SSL_SESSION_free(old_session);
1126 return 0;
1127 }
1128
David Benjaminc11ea9422017-08-29 16:33:21 -04001129 // There was a session ID collision. |old_session| must be removed from
1130 // the linked list and released.
David Benjamindafbdd42015-09-14 01:40:10 -04001131 SSL_SESSION_list_remove(ctx, old_session);
1132 SSL_SESSION_free(old_session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001133 }
Adam Langley95c29f32014-06-20 12:00:00 -07001134
David Benjamin415660b2015-10-18 15:08:57 -04001135 SSL_SESSION_list_add(ctx, session);
Adam Langley95c29f32014-06-20 12:00:00 -07001136
David Benjaminc11ea9422017-08-29 16:33:21 -04001137 // Enforce any cache size limits.
David Benjamin415660b2015-10-18 15:08:57 -04001138 if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
1139 while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
1140 if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
1141 break;
Adam Langleyfcf25832014-12-18 17:42:32 -08001142 }
1143 }
1144 }
Adam Langley95c29f32014-06-20 12:00:00 -07001145
David Benjamin29270de2016-05-24 15:28:36 +00001146 CRYPTO_MUTEX_unlock_write(&ctx->lock);
David Benjamin415660b2015-10-18 15:08:57 -04001147 return 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_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) {
1151 return remove_session_lock(ctx, session, 1);
Adam Langleyfcf25832014-12-18 17:42:32 -08001152}
Adam Langley95c29f32014-06-20 12:00:00 -07001153
David Benjamindafbdd42015-09-14 01:40:10 -04001154int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001155 // SSL_set_session may only be called before the handshake has started.
David Benjamin9e766d72017-02-10 23:14:17 -05001156 if (ssl->s3->initial_handshake_complete ||
1157 ssl->s3->hs == NULL ||
Steven Valdez4d71a9a2017-08-14 15:08:34 -04001158 ssl->s3->hs->state != 0) {
David Benjamin4d0be242016-09-01 01:10:07 -04001159 abort();
1160 }
1161
1162 ssl_set_session(ssl, session);
1163 return 1;
1164}
1165
David Benjaminad8f5e12017-02-20 17:00:20 -05001166uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
David Benjamindafbdd42015-09-14 01:40:10 -04001167 if (ctx == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001168 return 0;
1169 }
1170
David Benjaminc11ea9422017-08-29 16:33:21 -04001171 // Historically, zero was treated as |SSL_DEFAULT_SESSION_TIMEOUT|.
David Benjamin0b1bb122017-01-28 14:32:53 -05001172 if (timeout == 0) {
1173 timeout = SSL_DEFAULT_SESSION_TIMEOUT;
1174 }
1175
David Benjaminad8f5e12017-02-20 17:00:20 -05001176 uint32_t old_timeout = ctx->session_timeout;
David Benjamindafbdd42015-09-14 01:40:10 -04001177 ctx->session_timeout = timeout;
1178 return old_timeout;
Adam Langleyfcf25832014-12-18 17:42:32 -08001179}
1180
David Benjaminad8f5e12017-02-20 17:00:20 -05001181uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx) {
David Benjamindafbdd42015-09-14 01:40:10 -04001182 if (ctx == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001183 return 0;
1184 }
1185
David Benjamindafbdd42015-09-14 01:40:10 -04001186 return ctx->session_timeout;
Adam Langleyfcf25832014-12-18 17:42:32 -08001187}
1188
David Benjaminad8f5e12017-02-20 17:00:20 -05001189void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, uint32_t timeout) {
David Benjamin17b30832017-01-28 14:00:32 -05001190 ctx->session_psk_dhe_timeout = timeout;
1191}
1192
Adam Langleyfcf25832014-12-18 17:42:32 -08001193typedef struct timeout_param_st {
1194 SSL_CTX *ctx;
David Benjaminad8f5e12017-02-20 17:00:20 -05001195 uint64_t time;
David Benjamin60da0cd2015-05-03 15:21:28 -04001196 LHASH_OF(SSL_SESSION) *cache;
Adam Langleyfcf25832014-12-18 17:42:32 -08001197} TIMEOUT_PARAM;
1198
David Benjamindafbdd42015-09-14 01:40:10 -04001199static void timeout_doall_arg(SSL_SESSION *session, void *void_param) {
David Benjamin0238d8f2017-07-12 17:35:14 -04001200 TIMEOUT_PARAM *param = reinterpret_cast<TIMEOUT_PARAM *>(void_param);
Adam Langleyfcf25832014-12-18 17:42:32 -08001201
1202 if (param->time == 0 ||
David Benjaminad8f5e12017-02-20 17:00:20 -05001203 session->time + session->timeout < session->time ||
David Benjamindafbdd42015-09-14 01:40:10 -04001204 param->time > (session->time + session->timeout)) {
David Benjaminc11ea9422017-08-29 16:33:21 -04001205 // The reason we don't call SSL_CTX_remove_session() is to
1206 // save on locking overhead
David Benjamindafbdd42015-09-14 01:40:10 -04001207 (void) lh_SSL_SESSION_delete(param->cache, session);
1208 SSL_SESSION_list_remove(param->ctx, session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001209 if (param->ctx->remove_session_cb != NULL) {
David Benjamindafbdd42015-09-14 01:40:10 -04001210 param->ctx->remove_session_cb(param->ctx, session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001211 }
David Benjamindafbdd42015-09-14 01:40:10 -04001212 SSL_SESSION_free(session);
Adam Langleyfcf25832014-12-18 17:42:32 -08001213 }
1214}
1215
David Benjaminad8f5e12017-02-20 17:00:20 -05001216void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001217 TIMEOUT_PARAM tp;
1218
Adam Langley4bdb6e42015-05-15 15:29:21 -07001219 tp.ctx = ctx;
1220 tp.cache = ctx->sessions;
Adam Langleyfcf25832014-12-18 17:42:32 -08001221 if (tp.cache == NULL) {
1222 return;
1223 }
David Benjamindafbdd42015-09-14 01:40:10 -04001224 tp.time = time;
Adam Langley4bdb6e42015-05-15 15:29:21 -07001225 CRYPTO_MUTEX_lock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -08001226 lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
David Benjamin29270de2016-05-24 15:28:36 +00001227 CRYPTO_MUTEX_unlock_write(&ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -08001228}
1229
Adam Langley95c29f32014-06-20 12:00:00 -07001230void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001231 int (*cb)(SSL *ssl, SSL_SESSION *session)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001232 ctx->new_session_cb = cb;
1233}
Adam Langley95c29f32014-06-20 12:00:00 -07001234
David Benjamindafbdd42015-09-14 01:40:10 -04001235int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001236 return ctx->new_session_cb;
1237}
Adam Langley95c29f32014-06-20 12:00:00 -07001238
David Benjamindafbdd42015-09-14 01:40:10 -04001239void SSL_CTX_sess_set_remove_cb(
1240 SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *session)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001241 ctx->remove_session_cb = cb;
1242}
Adam Langley95c29f32014-06-20 12:00:00 -07001243
Adam Langleyfcf25832014-12-18 17:42:32 -08001244void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001245 SSL_SESSION *session) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001246 return ctx->remove_session_cb;
1247}
Adam Langley95c29f32014-06-20 12:00:00 -07001248
1249void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
David Benjamindafbdd42015-09-14 01:40:10 -04001250 SSL_SESSION *(*cb)(SSL *ssl,
1251 uint8_t *id, int id_len,
1252 int *out_copy)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001253 ctx->get_session_cb = cb;
1254}
Adam Langley95c29f32014-06-20 12:00:00 -07001255
David Benjamindafbdd42015-09-14 01:40:10 -04001256SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
1257 SSL *ssl, uint8_t *id, int id_len, int *out_copy) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001258 return ctx->get_session_cb;
1259}
Adam Langley95c29f32014-06-20 12:00:00 -07001260
David Benjamin82170242015-10-17 22:51:17 -04001261void SSL_CTX_set_info_callback(
1262 SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001263 ctx->info_callback = cb;
1264}
Adam Langley95c29f32014-06-20 12:00:00 -07001265
Adam Langleyfcf25832014-12-18 17:42:32 -08001266void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type,
David Benjamin82170242015-10-17 22:51:17 -04001267 int value) {
Adam Langleyfcf25832014-12-18 17:42:32 -08001268 return ctx->info_callback;
1269}
Adam Langley95c29f32014-06-20 12:00:00 -07001270
Adam Langley1258b6a2014-06-20 12:00:00 -07001271void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx,
Adam Langleyfcf25832014-12-18 17:42:32 -08001272 void (*cb)(SSL *ssl, EVP_PKEY **pkey)) {
1273 ctx->channel_id_cb = cb;
1274}
Adam Langley1258b6a2014-06-20 12:00:00 -07001275
Adam Langleyfcf25832014-12-18 17:42:32 -08001276void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) {
1277 return ctx->channel_id_cb;
1278}