blob: 0e6c66cc15fbd0ce93d0af2fa9b6210d6b3e45a6 [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>
David Benjamin9a4876e2017-09-15 18:22:43 -0400145#include <openssl/hmac.h>
Adam Langley95c29f32014-06-20 12:00:00 -0700146#include <openssl/lhash.h>
147#include <openssl/mem.h>
148#include <openssl/rand.h>
149
David Benjamin2ee94aa2015-04-07 22:38:30 -0400150#include "internal.h"
David Benjamin546f1a52015-04-15 16:46:09 -0400151#include "../crypto/internal.h"
152
Adam Langley95c29f32014-06-20 12:00:00 -0700153
David Benjamin86e95b82017-07-18 16:34:25 -0400154namespace bssl {
155
David Benjaminc11ea9422017-08-29 16:33:21 -0400156// The address of this is a magic value, a pointer to which is returned by
157// SSL_magic_pending_session_ptr(). It allows a session callback to indicate
158// that it needs to asynchronously fetch session information.
Brian Smithefed2212015-01-28 16:20:02 -0800159static const char g_pending_session_magic = 0;
Adam Langleyb2ce0582014-06-20 12:00:00 -0700160
David Benjaminaa585132015-06-29 23:36:17 -0400161static CRYPTO_EX_DATA_CLASS g_ex_data_class =
162 CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
David Benjamin9f33fc62015-04-15 17:29:53 -0400163
David Benjamindafbdd42015-09-14 01:40:10 -0400164static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
165static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
166static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
Adam Langley95c29f32014-06-20 12:00:00 -0700167
David Benjamin31b0c9b2017-07-20 14:49:15 -0400168UniquePtr<SSL_SESSION> ssl_session_new(const SSL_X509_METHOD *x509_method) {
169 UniquePtr<SSL_SESSION> session(
170 (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)));
171 if (!session) {
David Benjaminabb6c1c2015-09-13 14:46:26 -0400172 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
173 return 0;
174 }
David Benjamin31b0c9b2017-07-20 14:49:15 -0400175 OPENSSL_memset(session.get(), 0, sizeof(SSL_SESSION));
David Benjaminabb6c1c2015-09-13 14:46:26 -0400176
Adam Langley46db7af2017-02-01 15:49:37 -0800177 session->x509_method = x509_method;
Adam Langley9498e742016-07-18 10:17:16 -0700178 session->verify_result = X509_V_ERR_INVALID_CALL;
David Benjaminabb6c1c2015-09-13 14:46:26 -0400179 session->references = 1;
180 session->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
David Benjamin17b30832017-01-28 14:00:32 -0500181 session->auth_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
David Benjaminad8f5e12017-02-20 17:00:20 -0500182 session->time = time(NULL);
David Benjamin8a589332015-12-04 23:14:35 -0500183 CRYPTO_new_ex_data(&session->ex_data);
David Benjaminabb6c1c2015-09-13 14:46:26 -0400184 return session;
185}
186
David Benjamin31b0c9b2017-07-20 14:49:15 -0400187UniquePtr<SSL_SESSION> SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
188 UniquePtr<SSL_SESSION> new_session = ssl_session_new(session->x509_method);
189 if (!new_session) {
190 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400191 }
192
Adam Langley364f7a62016-12-12 10:51:00 -0800193 new_session->is_server = session->is_server;
Steven Valdez87eab492016-06-27 16:34:59 -0400194 new_session->ssl_version = session->ssl_version;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400195 new_session->sid_ctx_length = session->sid_ctx_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500196 OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400197
David Benjaminc11ea9422017-08-29 16:33:21 -0400198 // Copy the key material.
Steven Valdez87eab492016-06-27 16:34:59 -0400199 new_session->master_key_length = session->master_key_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500200 OPENSSL_memcpy(new_session->master_key, session->master_key,
Steven Valdez87eab492016-06-27 16:34:59 -0400201 session->master_key_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400202 new_session->cipher = session->cipher;
203
David Benjaminc11ea9422017-08-29 16:33:21 -0400204 // Copy authentication state.
Steven Valdez87eab492016-06-27 16:34:59 -0400205 if (session->psk_identity != NULL) {
206 new_session->psk_identity = BUF_strdup(session->psk_identity);
207 if (new_session->psk_identity == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400208 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400209 }
210 }
Adam Langley68e71242016-12-12 11:06:16 -0800211 if (session->certs != NULL) {
212 new_session->certs = sk_CRYPTO_BUFFER_new_null();
213 if (new_session->certs == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400214 return nullptr;
Adam Langley68e71242016-12-12 11:06:16 -0800215 }
216 for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
217 CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
218 if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400219 return nullptr;
Adam Langley68e71242016-12-12 11:06:16 -0800220 }
221 CRYPTO_BUFFER_up_ref(buffer);
222 }
223 }
Adam Langley46db7af2017-02-01 15:49:37 -0800224
David Benjamin31b0c9b2017-07-20 14:49:15 -0400225 if (!session->x509_method->session_dup(new_session.get(), session)) {
226 return nullptr;
Steven Valdez87eab492016-06-27 16:34:59 -0400227 }
Adam Langley46db7af2017-02-01 15:49:37 -0800228
Steven Valdez87eab492016-06-27 16:34:59 -0400229 new_session->verify_result = session->verify_result;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400230
Steven Valdez4aa154e2016-07-29 14:32:55 -0400231 if (session->ocsp_response != NULL) {
David Benjamin8fc2dc02017-08-22 15:07:51 -0700232 new_session->ocsp_response = session->ocsp_response;
233 CRYPTO_BUFFER_up_ref(new_session->ocsp_response);
Steven Valdez87eab492016-06-27 16:34:59 -0400234 }
Steven Valdez87eab492016-06-27 16:34:59 -0400235
David Benjamin8fc2dc02017-08-22 15:07:51 -0700236 if (session->signed_cert_timestamp_list != NULL) {
237 new_session->signed_cert_timestamp_list =
238 session->signed_cert_timestamp_list;
239 CRYPTO_BUFFER_up_ref(new_session->signed_cert_timestamp_list);
Steven Valdez87eab492016-06-27 16:34:59 -0400240 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400241
David Benjamin17cf2cb2016-12-13 01:07:13 -0500242 OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
243 SHA256_DIGEST_LENGTH);
Steven Valdez87eab492016-06-27 16:34:59 -0400244 new_session->peer_sha256_valid = session->peer_sha256_valid;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400245
David Benjaminf1050fd2016-12-13 20:05:36 -0500246 new_session->peer_signature_algorithm = session->peer_signature_algorithm;
247
David Benjamin01a90572016-09-22 00:11:43 -0400248 new_session->timeout = session->timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500249 new_session->auth_timeout = session->auth_timeout;
David Benjamin01a90572016-09-22 00:11:43 -0400250 new_session->time = session->time;
251
David Benjaminc11ea9422017-08-29 16:33:21 -0400252 // Copy non-authentication connection properties.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400253 if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
254 new_session->session_id_length = session->session_id_length;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500255 OPENSSL_memcpy(new_session->session_id, session->session_id,
256 session->session_id_length);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400257
David Benjamin4882a6c2016-12-11 02:48:12 -0500258 new_session->group_id = session->group_id;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400259
David Benjamin17cf2cb2016-12-13 01:07:13 -0500260 OPENSSL_memcpy(new_session->original_handshake_hash,
261 session->original_handshake_hash,
262 session->original_handshake_hash_len);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400263 new_session->original_handshake_hash_len =
264 session->original_handshake_hash_len;
265 new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400266 new_session->ticket_age_add = session->ticket_age_add;
Steven Valdez08b65f42016-12-07 15:29:45 -0500267 new_session->ticket_max_early_data = session->ticket_max_early_data;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400268 new_session->extended_master_secret = session->extended_master_secret;
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500269
270 if (session->early_alpn != NULL) {
271 new_session->early_alpn =
David Benjamin0238d8f2017-07-12 17:35:14 -0400272 (uint8_t *)BUF_memdup(session->early_alpn, session->early_alpn_len);
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500273 if (new_session->early_alpn == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400274 return nullptr;
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500275 }
276 }
277 new_session->early_alpn_len = session->early_alpn_len;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400278 }
279
David Benjaminc11ea9422017-08-29 16:33:21 -0400280 // Copy the ticket.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400281 if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
282 if (session->tlsext_tick != NULL) {
283 new_session->tlsext_tick =
David Benjamin0238d8f2017-07-12 17:35:14 -0400284 (uint8_t *)BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
Steven Valdez4aa154e2016-07-29 14:32:55 -0400285 if (new_session->tlsext_tick == NULL) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400286 return nullptr;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400287 }
288 }
289 new_session->tlsext_ticklen = session->tlsext_ticklen;
290 }
291
David Benjaminc11ea9422017-08-29 16:33:21 -0400292 // The new_session does not get a copy of the ex_data.
Steven Valdez4aa154e2016-07-29 14:32:55 -0400293
Steven Valdez87eab492016-06-27 16:34:59 -0400294 new_session->not_resumable = 1;
295 return new_session;
Steven Valdez87eab492016-06-27 16:34:59 -0400296}
297
David Benjamin17b30832017-01-28 14:00:32 -0500298void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session) {
David Benjaminad8f5e12017-02-20 17:00:20 -0500299 struct OPENSSL_timeval now;
David Benjamin123db572016-11-03 16:59:25 -0400300 ssl_get_current_time(ssl, &now);
301
David Benjaminc11ea9422017-08-29 16:33:21 -0400302 // To avoid overflows and underflows, if we've gone back in time, update the
303 // time, but mark the session expired.
David Benjaminad8f5e12017-02-20 17:00:20 -0500304 if (session->time > now.tv_sec) {
David Benjamin123db572016-11-03 16:59:25 -0400305 session->time = now.tv_sec;
306 session->timeout = 0;
David Benjamin17b30832017-01-28 14:00:32 -0500307 session->auth_timeout = 0;
David Benjamin123db572016-11-03 16:59:25 -0400308 return;
309 }
310
David Benjaminc11ea9422017-08-29 16:33:21 -0400311 // Adjust the session time and timeouts. If the session has already expired,
312 // clamp the timeouts at zero.
David Benjaminad8f5e12017-02-20 17:00:20 -0500313 uint64_t delta = now.tv_sec - session->time;
David Benjamin123db572016-11-03 16:59:25 -0400314 session->time = now.tv_sec;
315 if (session->timeout < delta) {
316 session->timeout = 0;
317 } else {
318 session->timeout -= delta;
319 }
David Benjamin17b30832017-01-28 14:00:32 -0500320 if (session->auth_timeout < delta) {
321 session->auth_timeout = 0;
322 } else {
323 session->auth_timeout -= delta;
324 }
325}
326
David Benjaminad8f5e12017-02-20 17:00:20 -0500327void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
328 uint32_t timeout) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400329 // Rebase the timestamp relative to the current time so |timeout| is measured
330 // correctly.
David Benjamin17b30832017-01-28 14:00:32 -0500331 ssl_session_rebase_time(ssl, session);
332
333 if (session->timeout > timeout) {
334 return;
335 }
336
337 session->timeout = timeout;
338 if (session->timeout > session->auth_timeout) {
339 session->timeout = session->auth_timeout;
340 }
David Benjamin123db572016-11-03 16:59:25 -0400341}
342
Steven Valdez8f36c512017-06-20 10:55:02 -0400343uint16_t SSL_SESSION_protocol_version(const SSL_SESSION *session) {
344 uint16_t ret;
345 if (!ssl_protocol_version_from_wire(&ret, session->ssl_version)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400346 // An |SSL_SESSION| will never have an invalid version. This is enforced by
347 // the parser.
Steven Valdez8f36c512017-06-20 10:55:02 -0400348 assert(0);
349 return 0;
Steven Valdez908ac192017-01-12 13:17:07 -0500350 }
351
Steven Valdez8f36c512017-06-20 10:55:02 -0400352 return ret;
353}
354
355const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session) {
David Benjaminca9e8f52017-08-09 15:02:34 -0400356 return ssl_get_handshake_digest(SSL_SESSION_protocol_version(session),
357 session->cipher);
Steven Valdez908ac192017-01-12 13:17:07 -0500358}
359
David Benjaminf3c8f8d2016-11-17 17:20:47 +0900360int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
361 SSL *const ssl = hs->ssl;
David Benjamindc2aea22015-10-18 12:50:32 -0400362 if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
David Benjamin3570d732015-06-29 00:28:17 -0400363 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
Adam Langleyfcf25832014-12-18 17:42:32 -0800364 return 0;
365 }
366
David Benjamin31b0c9b2017-07-20 14:49:15 -0400367 UniquePtr<SSL_SESSION> session = ssl_session_new(ssl->ctx->x509_method);
David Benjamindc2aea22015-10-18 12:50:32 -0400368 if (session == NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800369 return 0;
370 }
371
Adam Langley364f7a62016-12-12 10:51:00 -0800372 session->is_server = is_server;
373 session->ssl_version = ssl->version;
374
David Benjaminc11ea9422017-08-29 16:33:21 -0400375 // Fill in the time from the |SSL_CTX|'s clock.
David Benjaminad8f5e12017-02-20 17:00:20 -0500376 struct OPENSSL_timeval now;
David Benjamin721e8b72016-08-03 13:13:17 -0400377 ssl_get_current_time(ssl, &now);
378 session->time = now.tv_sec;
379
David Benjamin17b30832017-01-28 14:00:32 -0500380 uint16_t version = ssl3_protocol_version(ssl);
381 if (version >= TLS1_3_VERSION) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400382 // TLS 1.3 uses tickets as authenticators, so we are willing to use them for
383 // longer.
David Benjaminbe497062017-03-10 16:08:36 -0500384 session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500385 session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
386 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400387 // TLS 1.2 resumption does not incorporate new key material, so we use a
388 // much shorter timeout.
David Benjaminbe497062017-03-10 16:08:36 -0500389 session->timeout = ssl->session_ctx->session_timeout;
390 session->auth_timeout = ssl->session_ctx->session_timeout;
David Benjamin17b30832017-01-28 14:00:32 -0500391 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800392
David Benjamindc2aea22015-10-18 12:50:32 -0400393 if (is_server) {
David Benjamin17b30832017-01-28 14:00:32 -0500394 if (hs->ticket_expected || version >= TLS1_3_VERSION) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400395 // Don't set session IDs for sessions resumed with tickets. This will keep
396 // them out of the session cache.
David Benjamindc2aea22015-10-18 12:50:32 -0400397 session->session_id_length = 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800398 } else {
David Benjamindc2aea22015-10-18 12:50:32 -0400399 session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
400 if (!RAND_bytes(session->session_id, session->session_id_length)) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400401 return 0;
David Benjamindc2aea22015-10-18 12:50:32 -0400402 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800403 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800404 } else {
David Benjamindc2aea22015-10-18 12:50:32 -0400405 session->session_id_length = 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800406 }
407
David Benjamin5960a902017-02-14 20:07:11 -0500408 if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
David Benjamin3570d732015-06-29 00:28:17 -0400409 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamin31b0c9b2017-07-20 14:49:15 -0400410 return 0;
Adam Langleyfcf25832014-12-18 17:42:32 -0800411 }
David Benjamin5960a902017-02-14 20:07:11 -0500412 OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
413 ssl->cert->sid_ctx_length);
414 session->sid_ctx_length = ssl->cert->sid_ctx_length;
Adam Langleyfcf25832014-12-18 17:42:32 -0800415
David Benjaminc11ea9422017-08-29 16:33:21 -0400416 // The session is marked not resumable until it is completely filled in.
Steven Valdez87eab492016-06-27 16:34:59 -0400417 session->not_resumable = 1;
Adam Langley9498e742016-07-18 10:17:16 -0700418 session->verify_result = X509_V_ERR_INVALID_CALL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800419
David Benjamin31b0c9b2017-07-20 14:49:15 -0400420 hs->new_session = std::move(session);
David Benjamin4d0be242016-09-01 01:10:07 -0400421 ssl_set_session(ssl, NULL);
Adam Langleyfcf25832014-12-18 17:42:32 -0800422 return 1;
423}
Adam Langley95c29f32014-06-20 12:00:00 -0700424
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700425int ssl_ctx_rotate_ticket_encryption_key(SSL_CTX *ctx) {
426 OPENSSL_timeval now;
427 ssl_ctx_get_current_time(ctx, &now);
428 {
David Benjaminc11ea9422017-08-29 16:33:21 -0400429 // Avoid acquiring a write lock in the common case (i.e. a non-default key
430 // is used or the default keys have not expired yet).
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700431 MutexReadLock lock(&ctx->lock);
432 if (ctx->tlsext_ticket_key_current &&
433 (ctx->tlsext_ticket_key_current->next_rotation_tv_sec == 0 ||
434 ctx->tlsext_ticket_key_current->next_rotation_tv_sec > now.tv_sec) &&
435 (!ctx->tlsext_ticket_key_prev ||
436 ctx->tlsext_ticket_key_prev->next_rotation_tv_sec > now.tv_sec)) {
437 return 1;
438 }
439 }
440
441 MutexWriteLock lock(&ctx->lock);
442 if (!ctx->tlsext_ticket_key_current ||
443 (ctx->tlsext_ticket_key_current->next_rotation_tv_sec != 0 &&
444 ctx->tlsext_ticket_key_current->next_rotation_tv_sec <= now.tv_sec)) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400445 // The current key has not been initialized or it is expired.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700446 auto new_key = bssl::MakeUnique<struct tlsext_ticket_key>();
447 if (!new_key) {
448 return 0;
449 }
450 OPENSSL_memset(new_key.get(), 0, sizeof(struct tlsext_ticket_key));
451 if (ctx->tlsext_ticket_key_current) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400452 // The current key expired. Rotate it to prev and bump up its rotation
453 // timestamp. Note that even with the new rotation time it may still be
454 // expired and get droppped below.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700455 ctx->tlsext_ticket_key_current->next_rotation_tv_sec +=
456 SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
457 OPENSSL_free(ctx->tlsext_ticket_key_prev);
458 ctx->tlsext_ticket_key_prev = ctx->tlsext_ticket_key_current;
459 }
460 ctx->tlsext_ticket_key_current = new_key.release();
461 RAND_bytes(ctx->tlsext_ticket_key_current->name, 16);
462 RAND_bytes(ctx->tlsext_ticket_key_current->hmac_key, 16);
463 RAND_bytes(ctx->tlsext_ticket_key_current->aes_key, 16);
464 ctx->tlsext_ticket_key_current->next_rotation_tv_sec =
465 now.tv_sec + SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
466 }
467
David Benjaminc11ea9422017-08-29 16:33:21 -0400468 // Drop an expired prev key.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700469 if (ctx->tlsext_ticket_key_prev &&
470 ctx->tlsext_ticket_key_prev->next_rotation_tv_sec <= now.tv_sec) {
471 OPENSSL_free(ctx->tlsext_ticket_key_prev);
472 ctx->tlsext_ticket_key_prev = nullptr;
473 }
474
475 return 1;
476}
477
Adam Langley4c341d02017-03-08 19:33:21 -0800478static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
479 const uint8_t *session_buf,
480 size_t session_len) {
David Benjamin86e95b82017-07-18 16:34:25 -0400481 ScopedEVP_CIPHER_CTX ctx;
482 ScopedHMAC_CTX hctx;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400483
David Benjaminc11ea9422017-08-29 16:33:21 -0400484 // If the session is too long, emit a dummy value rather than abort the
485 // connection.
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400486 static const size_t kMaxTicketOverhead =
487 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
488 if (session_len > 0xffff - kMaxTicketOverhead) {
489 static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
David Benjamin0238d8f2017-07-12 17:35:14 -0400490 return CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder,
491 strlen(kTicketPlaceholder));
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400492 }
493
David Benjaminc11ea9422017-08-29 16:33:21 -0400494 // Initialize HMAC and cipher contexts. If callback present it does all the
495 // work otherwise use generated values from parent ctx.
David Benjaminbe497062017-03-10 16:08:36 -0500496 SSL_CTX *tctx = ssl->session_ctx;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400497 uint8_t iv[EVP_MAX_IV_LENGTH];
498 uint8_t key_name[16];
499 if (tctx->tlsext_ticket_key_cb != NULL) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400500 if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, ctx.get(), hctx.get(),
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400501 1 /* encrypt */) < 0) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400502 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400503 }
504 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400505 // Rotate ticket key if necessary.
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700506 if (!ssl_ctx_rotate_ticket_encryption_key(tctx)) {
507 return 0;
508 }
509 MutexReadLock lock(&tctx->lock);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400510 if (!RAND_bytes(iv, 16) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400511 !EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), NULL,
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700512 tctx->tlsext_ticket_key_current->aes_key, iv) ||
513 !HMAC_Init_ex(hctx.get(), tctx->tlsext_ticket_key_current->hmac_key, 16,
David Benjamin0238d8f2017-07-12 17:35:14 -0400514 tlsext_tick_md(), NULL)) {
515 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400516 }
Martin Kreichgauer72912d22017-08-04 12:06:43 -0700517 OPENSSL_memcpy(key_name, tctx->tlsext_ticket_key_current->name, 16);
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400518 }
519
520 uint8_t *ptr;
521 if (!CBB_add_bytes(out, key_name, 16) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400522 !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(ctx.get())) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400523 !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400524 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400525 }
526
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400527 size_t total = 0;
David Benjaminfbc45d72016-09-22 01:21:24 -0400528#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
David Benjamin17cf2cb2016-12-13 01:07:13 -0500529 OPENSSL_memcpy(ptr, session_buf, session_len);
David Benjaminfbc45d72016-09-22 01:21:24 -0400530 total = session_len;
531#else
532 int len;
David Benjamin0238d8f2017-07-12 17:35:14 -0400533 if (!EVP_EncryptUpdate(ctx.get(), ptr + total, &len, session_buf, session_len)) {
534 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400535 }
536 total += len;
David Benjamin0238d8f2017-07-12 17:35:14 -0400537 if (!EVP_EncryptFinal_ex(ctx.get(), ptr + total, &len)) {
538 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400539 }
540 total += len;
David Benjaminfbc45d72016-09-22 01:21:24 -0400541#endif
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400542 if (!CBB_did_write(out, total)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400543 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400544 }
545
546 unsigned hlen;
David Benjamin0238d8f2017-07-12 17:35:14 -0400547 if (!HMAC_Update(hctx.get(), CBB_data(out), CBB_len(out)) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400548 !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) ||
David Benjamin0238d8f2017-07-12 17:35:14 -0400549 !HMAC_Final(hctx.get(), ptr, &hlen) ||
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400550 !CBB_did_write(out, hlen)) {
David Benjamin0238d8f2017-07-12 17:35:14 -0400551 return 0;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400552 }
553
David Benjamin0238d8f2017-07-12 17:35:14 -0400554 return 1;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400555}
556
Adam Langley4c341d02017-03-08 19:33:21 -0800557static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out,
558 const uint8_t *session_buf,
559 size_t session_len) {
560 const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
561 const size_t max_overhead = method->max_overhead(ssl);
562 const size_t max_out = session_len + max_overhead;
563 if (max_out < max_overhead) {
564 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
565 return 0;
566 }
567
568 uint8_t *ptr;
569 if (!CBB_reserve(out, &ptr, max_out)) {
570 return 0;
571 }
572
573 size_t out_len;
574 if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
575 OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
576 return 0;
577 }
578
579 if (!CBB_did_write(out, out_len)) {
580 return 0;
581 }
582
583 return 1;
584}
585
586int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400587 // Serialize the SSL_SESSION to be encoded into the ticket.
Adam Langley4c341d02017-03-08 19:33:21 -0800588 uint8_t *session_buf = NULL;
589 size_t session_len;
590 if (!SSL_SESSION_to_bytes_for_ticket(session, &session_buf, &session_len)) {
591 return -1;
592 }
593
594 int ret = 0;
595 if (ssl->session_ctx->ticket_aead_method) {
596 ret = ssl_encrypt_ticket_with_method(ssl, out, session_buf, session_len);
597 } else {
598 ret =
599 ssl_encrypt_ticket_with_cipher_ctx(ssl, out, session_buf, session_len);
600 }
601
602 OPENSSL_free(session_buf);
603 return ret;
604}
605
Steven Valdez4aa154e2016-07-29 14:32:55 -0400606int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session) {
607 if (session == NULL) {
608 return 0;
609 }
610
David Benjamin5960a902017-02-14 20:07:11 -0500611 return session->sid_ctx_length == ssl->cert->sid_ctx_length &&
612 OPENSSL_memcmp(session->sid_ctx, ssl->cert->sid_ctx,
613 ssl->cert->sid_ctx_length) == 0;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400614}
615
616int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
617 if (session == NULL) {
618 return 0;
619 }
620
David Benjaminad8f5e12017-02-20 17:00:20 -0500621 struct OPENSSL_timeval now;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400622 ssl_get_current_time(ssl, &now);
David Benjamin1b22f852016-10-27 16:36:32 -0400623
David Benjaminc11ea9422017-08-29 16:33:21 -0400624 // Reject tickets from the future to avoid underflow.
David Benjaminad8f5e12017-02-20 17:00:20 -0500625 if (now.tv_sec < session->time) {
David Benjamin1b22f852016-10-27 16:36:32 -0400626 return 0;
627 }
628
David Benjaminad8f5e12017-02-20 17:00:20 -0500629 return session->timeout > now.tv_sec - session->time;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400630}
631
David Benjamin45738dd2017-02-09 20:01:26 -0500632int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
633 const SSL_SESSION *session) {
634 const SSL *const ssl = hs->ssl;
David Benjamin75f99142016-11-12 12:36:06 +0900635 return ssl_session_is_context_valid(ssl, session) &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400636 // The session must have been created by the same type of end point as
637 // we're now using it with.
David Benjamin45738dd2017-02-09 20:01:26 -0500638 ssl->server == session->is_server &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400639 // The session must not be expired.
David Benjamin75f99142016-11-12 12:36:06 +0900640 ssl_session_is_time_valid(ssl, session) &&
641 /* Only resume if the session's version matches the negotiated
642 * version. */
643 ssl->version == session->ssl_version &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400644 // Only resume if the session's cipher matches the negotiated one.
David Benjamin45738dd2017-02-09 20:01:26 -0500645 hs->new_cipher == session->cipher &&
David Benjaminc11ea9422017-08-29 16:33:21 -0400646 // If the session contains a client certificate (either the full
647 // certificate or just the hash) then require that the form of the
648 // certificate matches the current configuration.
Adam Langley46db7af2017-02-01 15:49:37 -0800649 ((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
650 !session->peer_sha256_valid) ||
David Benjaminbbaf3672016-11-17 10:53:09 +0900651 session->peer_sha256_valid ==
652 ssl->retain_only_sha256_of_client_certs);
David Benjamin75f99142016-11-12 12:36:06 +0900653}
654
David Benjaminc11ea9422017-08-29 16:33:21 -0400655// ssl_lookup_session looks up |session_id| in the session cache and sets
656// |*out_session| to an |SSL_SESSION| object if found.
Steven Valdez398085b2017-08-29 13:25:56 -0400657static enum ssl_hs_wait_t ssl_lookup_session(
David Benjamin37af90f2017-07-29 01:42:16 -0400658 SSL *ssl, UniquePtr<SSL_SESSION> *out_session, const uint8_t *session_id,
David Benjamine3aa1d92015-06-16 15:34:50 -0400659 size_t session_id_len) {
David Benjamin37af90f2017-07-29 01:42:16 -0400660 out_session->reset();
Adam Langley95c29f32014-06-20 12:00:00 -0700661
David Benjamine3aa1d92015-06-16 15:34:50 -0400662 if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
Steven Valdez398085b2017-08-29 13:25:56 -0400663 return ssl_hs_ok;
Adam Langleyfcf25832014-12-18 17:42:32 -0800664 }
Adam Langley95c29f32014-06-20 12:00:00 -0700665
David Benjamin37af90f2017-07-29 01:42:16 -0400666 UniquePtr<SSL_SESSION> session;
David Benjaminc11ea9422017-08-29 16:33:21 -0400667 // Try the internal cache, if it exists.
David Benjaminbe497062017-03-10 16:08:36 -0500668 if (!(ssl->session_ctx->session_cache_mode &
Adam Langleyfcf25832014-12-18 17:42:32 -0800669 SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
670 SSL_SESSION data;
David Benjamine3aa1d92015-06-16 15:34:50 -0400671 data.ssl_version = ssl->version;
672 data.session_id_length = session_id_len;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500673 OPENSSL_memcpy(data.session_id, session_id, session_id_len);
David Benjamine3aa1d92015-06-16 15:34:50 -0400674
David Benjaminbe497062017-03-10 16:08:36 -0500675 CRYPTO_MUTEX_lock_read(&ssl->session_ctx->lock);
David Benjamin37af90f2017-07-29 01:42:16 -0400676 session.reset(lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data));
677 if (session) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400678 // |lh_SSL_SESSION_retrieve| returns a non-owning pointer.
David Benjamin37af90f2017-07-29 01:42:16 -0400679 SSL_SESSION_up_ref(session.get());
Adam Langleyfcf25832014-12-18 17:42:32 -0800680 }
David Benjaminc11ea9422017-08-29 16:33:21 -0400681 // TODO(davidben): This should probably move it to the front of the list.
David Benjaminbe497062017-03-10 16:08:36 -0500682 CRYPTO_MUTEX_unlock_read(&ssl->session_ctx->lock);
Adam Langleyfcf25832014-12-18 17:42:32 -0800683 }
Adam Langley95c29f32014-06-20 12:00:00 -0700684
David Benjaminc11ea9422017-08-29 16:33:21 -0400685 // Fall back to the external cache, if it exists.
David Benjamin37af90f2017-07-29 01:42:16 -0400686 if (!session && ssl->session_ctx->get_session_cb != NULL) {
Steven Valdez4aa154e2016-07-29 14:32:55 -0400687 int copy = 1;
David Benjamin37af90f2017-07-29 01:42:16 -0400688 session.reset(ssl->session_ctx->get_session_cb(ssl, (uint8_t *)session_id,
689 session_id_len, &copy));
Steven Valdez4aa154e2016-07-29 14:32:55 -0400690
David Benjamin37af90f2017-07-29 01:42:16 -0400691 if (!session) {
Steven Valdez398085b2017-08-29 13:25:56 -0400692 return ssl_hs_ok;
Adam Langley81f43352016-08-26 09:22:56 -0700693 }
694
David Benjamin37af90f2017-07-29 01:42:16 -0400695 if (session.get() == SSL_magic_pending_session_ptr()) {
696 session.release(); // This pointer is not actually owned.
Steven Valdez398085b2017-08-29 13:25:56 -0400697 return ssl_hs_pending_session;
Steven Valdez4aa154e2016-07-29 14:32:55 -0400698 }
699
David Benjaminc11ea9422017-08-29 16:33:21 -0400700 // Increment reference count now if the session callback asks us to do so
701 // (note that if the session structures returned by the callback are shared
702 // between threads, it must handle the reference count itself [i.e. copy ==
703 // 0], or things won't be thread-safe).
Steven Valdez4aa154e2016-07-29 14:32:55 -0400704 if (copy) {
David Benjamin37af90f2017-07-29 01:42:16 -0400705 SSL_SESSION_up_ref(session.get());
Steven Valdez4aa154e2016-07-29 14:32:55 -0400706 }
707
David Benjaminc11ea9422017-08-29 16:33:21 -0400708 // Add the externally cached session to the internal cache if necessary.
David Benjaminbe497062017-03-10 16:08:36 -0500709 if (!(ssl->session_ctx->session_cache_mode &
Steven Valdez4aa154e2016-07-29 14:32:55 -0400710 SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
David Benjamin37af90f2017-07-29 01:42:16 -0400711 SSL_CTX_add_session(ssl->session_ctx, session.get());
Steven Valdez4aa154e2016-07-29 14:32:55 -0400712 }
David Benjamine3aa1d92015-06-16 15:34:50 -0400713 }
Steven Valdez4aa154e2016-07-29 14:32:55 -0400714
David Benjamin37af90f2017-07-29 01:42:16 -0400715 if (session && !ssl_session_is_time_valid(ssl, session.get())) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400716 // The session was from the cache, so remove it.
David Benjamin37af90f2017-07-29 01:42:16 -0400717 SSL_CTX_remove_session(ssl->session_ctx, session.get());
718 session.reset();
David Benjamine3aa1d92015-06-16 15:34:50 -0400719 }
720
David Benjamin37af90f2017-07-29 01:42:16 -0400721 *out_session = std::move(session);
Steven Valdez398085b2017-08-29 13:25:56 -0400722 return ssl_hs_ok;
David Benjamine3aa1d92015-06-16 15:34:50 -0400723}
724
David Benjaminaba057a2017-09-11 15:21:43 -0400725bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello) {
726 CBS extension, groups;
727 if (SSL_is_dtls(client_hello->ssl) ||
728 !ssl_client_hello_get_extension(client_hello, &extension,
729 TLSEXT_TYPE_supported_groups) ||
730 !CBS_get_u16_length_prefixed(&extension, &groups) ||
731 CBS_len(&extension) != 0) {
732 return false;
733 }
734
735 // Original Java curve list.
736 static const uint8_t kCurveList1[] = {
737 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00, 0x15,
738 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18,
739 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e,
740 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12,
741 0x00, 0x04, 0x00, 0x05, 0x00, 0x14, 0x00, 0x08, 0x00, 0x16};
742
743 // Newer Java curve list.
744 static const uint8_t kCurveList2[] = {
745 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a,
746 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16};
747
748 // IcedTea curve list.
749 static const uint8_t kCurveList3[] = {0x00, 0x17, 0x00, 0x18, 0x00, 0x19};
750
751 auto groups_span = MakeConstSpan(CBS_data(&groups), CBS_len(&groups));
752 if (groups_span != kCurveList1 && groups_span != kCurveList2 &&
753 groups_span != kCurveList3) {
754 return false;
755 }
756
757 // Java has a very distinctive curve list, but IcedTea patches it to a more
758 // standard [P-256, P-384, P-521]. Additionally check the extension
David Benjamin5a79ff52017-09-14 16:36:18 -0400759 // order. This may still flag other clients, but false positives only mean a
760 // loss of resumption. Any client new enough to support one of X25519,
761 // extended master secret, session tickets, or TLS 1.3 will be unaffected.
David Benjaminaba057a2017-09-11 15:21:43 -0400762 //
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.
David Benjamin5a79ff52017-09-14 16:36:18 -0400815 // 4. The server sends a certificate with a different (see below) SAN list
816 // than in the previous session.
David Benjaminaba057a2017-09-11 15:21:43 -0400817 //
818 // (Note the 3SHAKE mitigation is to reject certificates changes on
819 // renegotiation, while Java's logic applies to initial handshakes as well.)
820 //
David Benjamin5a79ff52017-09-14 16:36:18 -0400821 // The end result is long-lived Java clients break on certificate rotations
822 // where the SAN list changes too much. Older versions of Java break if the
823 // first DNS name of the two certificates is different. Newer ones will
824 // break if there is no intersection. The new logic mostly mitigates this,
825 // but this can still cause problems if switching to or from wildcards.
826 //
827 // Thus, fingerprint Java clients and decline all offered sessions. This
828 // avoids (2) while still introducing new sessions to clear any existing
829 // problematic sessions.
David Benjaminaba057a2017-09-11 15:21:43 -0400830 *out_session = nullptr;
831 *out_tickets_supported = tickets_supported;
832 *out_renew_ticket = false;
833 return ssl_hs_ok;
834 }
835
836 UniquePtr<SSL_SESSION> session;
837 bool renew_ticket = false;
David Benjaminef1b0092015-11-21 14:05:44 -0500838 if (tickets_supported && ticket_len > 0) {
Adam Langley4c341d02017-03-08 19:33:21 -0800839 switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
840 client_hello->session_id,
841 client_hello->session_id_len)) {
842 case ssl_ticket_aead_success:
843 break;
844 case ssl_ticket_aead_ignore_ticket:
David Benjamin37af90f2017-07-29 01:42:16 -0400845 assert(!session);
Adam Langley4c341d02017-03-08 19:33:21 -0800846 break;
847 case ssl_ticket_aead_error:
Steven Valdez398085b2017-08-29 13:25:56 -0400848 return ssl_hs_error;
Adam Langley4c341d02017-03-08 19:33:21 -0800849 case ssl_ticket_aead_retry:
Steven Valdez398085b2017-08-29 13:25:56 -0400850 return ssl_hs_pending_ticket;
David Benjamine3aa1d92015-06-16 15:34:50 -0400851 }
852 } else {
David Benjaminc11ea9422017-08-29 16:33:21 -0400853 // The client didn't send a ticket, so the session ID is a real ID.
Steven Valdez398085b2017-08-29 13:25:56 -0400854 enum ssl_hs_wait_t lookup_ret = ssl_lookup_session(
David Benjamin731058e2016-12-03 23:15:13 -0500855 ssl, &session, client_hello->session_id, client_hello->session_id_len);
Steven Valdez398085b2017-08-29 13:25:56 -0400856 if (lookup_ret != ssl_hs_ok) {
David Benjamine3aa1d92015-06-16 15:34:50 -0400857 return lookup_ret;
858 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800859 }
Adam Langley95c29f32014-06-20 12:00:00 -0700860
David Benjamin37af90f2017-07-29 01:42:16 -0400861 *out_session = std::move(session);
David Benjamin75f99142016-11-12 12:36:06 +0900862 *out_tickets_supported = tickets_supported;
863 *out_renew_ticket = renew_ticket;
Steven Valdez398085b2017-08-29 13:25:56 -0400864 return ssl_hs_ok;
Adam Langley95c29f32014-06-20 12:00:00 -0700865}
866
David Benjamin86e95b82017-07-18 16:34:25 -0400867static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
868 int ret = 0;
869
870 if (session != NULL && session->session_id_length != 0) {
871 if (lock) {
872 CRYPTO_MUTEX_lock_write(&ctx->lock);
873 }
874 SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
875 session);
876 if (found_session == session) {
877 ret = 1;
878 found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
879 SSL_SESSION_list_remove(ctx, session);
880 }
881
882 if (lock) {
883 CRYPTO_MUTEX_unlock_write(&ctx->lock);
884 }
885
886 if (ret) {
887 if (ctx->remove_session_cb != NULL) {
888 ctx->remove_session_cb(ctx, found_session);
889 }
890 SSL_SESSION_free(found_session);
891 }
892 }
893
894 return ret;
895}
896
897void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
898 if (ssl->session == session) {
899 return;
900 }
901
902 SSL_SESSION_free(ssl->session);
903 ssl->session = session;
904 if (session != NULL) {
905 SSL_SESSION_up_ref(session);
906 }
907}
908
David Benjaminc11ea9422017-08-29 16:33:21 -0400909// locked by SSL_CTX in the calling function
David Benjamin86e95b82017-07-18 16:34:25 -0400910static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
911 if (session->next == NULL || session->prev == NULL) {
912 return;
913 }
914
915 if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400916 // last element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400917 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400918 // only one element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400919 ctx->session_cache_head = NULL;
920 ctx->session_cache_tail = NULL;
921 } else {
922 ctx->session_cache_tail = session->prev;
923 session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
924 }
925 } else {
926 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
David Benjaminc11ea9422017-08-29 16:33:21 -0400927 // first element in list
David Benjamin86e95b82017-07-18 16:34:25 -0400928 ctx->session_cache_head = session->next;
929 session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
David Benjaminc11ea9422017-08-29 16:33:21 -0400930 } else { // middle of list
David Benjamin86e95b82017-07-18 16:34:25 -0400931 session->next->prev = session->prev;
932 session->prev->next = session->next;
933 }
934 }
935 session->prev = session->next = NULL;
936}
937
938static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
939 if (session->next != NULL && session->prev != NULL) {
940 SSL_SESSION_list_remove(ctx, session);
941 }
942
943 if (ctx->session_cache_head == NULL) {
944 ctx->session_cache_head = session;
945 ctx->session_cache_tail = session;
946 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
947 session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
948 } else {
949 session->next = ctx->session_cache_head;
950 session->next->prev = session;
951 session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
952 ctx->session_cache_head = session;
953 }
954}
955
956} // namespace bssl
957
958using namespace bssl;
959
960SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
David Benjamin31b0c9b2017-07-20 14:49:15 -0400961 return ssl_session_new(ctx->x509_method).release();
David Benjamin86e95b82017-07-18 16:34:25 -0400962}
963
964int SSL_SESSION_up_ref(SSL_SESSION *session) {
965 CRYPTO_refcount_inc(&session->references);
966 return 1;
967}
968
969void SSL_SESSION_free(SSL_SESSION *session) {
970 if (session == NULL ||
971 !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
972 return;
973 }
974
975 CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
976
977 OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
978 OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
979 sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
980 session->x509_method->session_clear(session);
David Benjamin86e95b82017-07-18 16:34:25 -0400981 OPENSSL_free(session->tlsext_tick);
David Benjamin8fc2dc02017-08-22 15:07:51 -0700982 CRYPTO_BUFFER_free(session->signed_cert_timestamp_list);
983 CRYPTO_BUFFER_free(session->ocsp_response);
David Benjamin86e95b82017-07-18 16:34:25 -0400984 OPENSSL_free(session->psk_identity);
985 OPENSSL_free(session->early_alpn);
David Benjamin86e95b82017-07-18 16:34:25 -0400986 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}