Coverage Report

Created: 2026-06-15 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/ssl/ssl_session.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
// Copyright 2005 Nokia. All rights reserved.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
//     https://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
16
#include <openssl/ssl.h>
17
18
#include <assert.h>
19
#include <stdlib.h>
20
#include <string.h>
21
22
#include <utility>
23
24
#include <openssl/cipher.h>
25
#include <openssl/err.h>
26
#include <openssl/evp.h>
27
#include <openssl/hmac.h>
28
#include <openssl/mem.h>
29
#include <openssl/pool.h>
30
#include <openssl/rand.h>
31
32
#include "../crypto/internal.h"
33
#include "internal.h"
34
35
36
BSSL_NAMESPACE_BEGIN
37
38
// The address of this is a magic value, a pointer to which is returned by
39
// SSL_magic_pending_session_ptr(). It allows a session callback to indicate
40
// that it needs to asynchronously fetch session information.
41
static const char g_pending_session_magic = 0;
42
43
static ExDataClass g_ex_data_class(/*with_app_data=*/true);
44
45
static void SSL_SESSION_list_remove(SSLContext *ctx, SSL_SESSION *session);
46
static void SSL_SESSION_list_add(SSLContext *ctx, SSL_SESSION *session);
47
48
241k
UniquePtr<SSL_SESSION> ssl_session_new(const SSL_X509_METHOD *x509_method) {
49
241k
  return MakeUnique<SSL_SESSION>(x509_method);
50
241k
}
51
52
74.5k
uint32_t ssl_hash_session_id(Span<const uint8_t> session_id) {
53
  // Take the first four bytes of `session_id`. Session IDs are generated by the
54
  // server randomly, so we can assume even using the first four bytes results
55
  // in a good distribution.
56
74.5k
  uint8_t tmp_storage[sizeof(uint32_t)];
57
74.5k
  if (session_id.size() < sizeof(tmp_storage)) {
58
26.5k
    OPENSSL_memset(tmp_storage, 0, sizeof(tmp_storage));
59
26.5k
    OPENSSL_memcpy(tmp_storage, session_id.data(), session_id.size());
60
26.5k
    session_id = tmp_storage;
61
26.5k
  }
62
63
74.5k
  uint32_t hash = ((uint32_t)session_id[0]) | ((uint32_t)session_id[1] << 8) |
64
74.5k
                  ((uint32_t)session_id[2] << 16) |
65
74.5k
                  ((uint32_t)session_id[3] << 24);
66
67
74.5k
  return hash;
68
74.5k
}
69
70
UniquePtr<SSL_SESSION> SSL_SESSION_dup(const SSL_SESSION *session,
71
48.1k
                                       int dup_flags) {
72
48.1k
  UniquePtr<SSL_SESSION> new_session = ssl_session_new(session->x509_method);
73
48.1k
  if (!new_session) {
74
0
    return nullptr;
75
0
  }
76
77
48.1k
  new_session->is_server = session->is_server;
78
48.1k
  new_session->ssl_version = session->ssl_version;
79
48.1k
  new_session->is_quic = session->is_quic;
80
48.1k
  new_session->sid_ctx = session->sid_ctx;
81
82
  // Copy the key material.
83
48.1k
  new_session->secret = session->secret;
84
48.1k
  new_session->cipher = session->cipher;
85
86
  // Copy authentication state.
87
48.1k
  if (session->psk_identity != nullptr) {
88
40
    new_session->psk_identity.reset(
89
40
        OPENSSL_strdup(session->psk_identity.get()));
90
40
    if (new_session->psk_identity == nullptr) {
91
0
      return nullptr;
92
0
    }
93
40
  }
94
48.1k
  new_session->peer_cert_type = session->peer_cert_type;
95
48.1k
  if (session->certs != nullptr) {
96
46.3k
    new_session->certs.reset(sk_CRYPTO_BUFFER_deep_copy(
97
46.3k
        session->certs.get(), CRYPTO_BUFFER_dup_ref, CRYPTO_BUFFER_free));
98
46.3k
    if (new_session->certs == nullptr) {
99
0
      return nullptr;
100
0
    }
101
46.3k
  }
102
48.1k
  if (session->peer_raw_public_key != nullptr) {
103
0
    new_session->peer_raw_public_key = UpRef(session->peer_raw_public_key);
104
0
  }
105
106
48.1k
  if (!session->x509_method->session_dup(new_session.get(), session)) {
107
0
    return nullptr;
108
0
  }
109
110
48.1k
  new_session->verify_result = session->verify_result;
111
112
48.1k
  new_session->ocsp_response = UpRef(session->ocsp_response);
113
48.1k
  new_session->signed_cert_timestamp_list =
114
48.1k
      UpRef(session->signed_cert_timestamp_list);
115
116
48.1k
  OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
117
48.1k
                 SHA256_DIGEST_LENGTH);
118
48.1k
  new_session->peer_sha256_valid = session->peer_sha256_valid;
119
120
48.1k
  new_session->peer_signature_algorithm = session->peer_signature_algorithm;
121
122
48.1k
  new_session->timeout = session->timeout;
123
48.1k
  new_session->auth_timeout = session->auth_timeout;
124
48.1k
  new_session->time = session->time;
125
126
  // Copy non-authentication connection properties.
127
48.1k
  if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
128
47.7k
    new_session->session_id = session->session_id;
129
47.7k
    new_session->group_id = session->group_id;
130
47.7k
    new_session->original_handshake_hash = session->original_handshake_hash;
131
47.7k
    new_session->ticket_lifetime_hint = session->ticket_lifetime_hint;
132
47.7k
    new_session->ticket_age_add = session->ticket_age_add;
133
47.7k
    new_session->ticket_max_early_data = session->ticket_max_early_data;
134
47.7k
    new_session->extended_master_secret = session->extended_master_secret;
135
47.7k
    new_session->has_application_settings = session->has_application_settings;
136
137
47.7k
    if (!new_session->early_alpn.CopyFrom(session->early_alpn) ||
138
47.7k
        !new_session->quic_early_data_context.CopyFrom(
139
47.7k
            session->quic_early_data_context) ||
140
47.7k
        !new_session->local_application_settings.CopyFrom(
141
47.7k
            session->local_application_settings) ||
142
47.7k
        !new_session->peer_application_settings.CopyFrom(
143
47.7k
            session->peer_application_settings)) {
144
0
      return nullptr;
145
0
    }
146
47.7k
  }
147
148
  // Copy the ticket.
149
48.1k
  if (dup_flags & SSL_SESSION_INCLUDE_TICKET &&
150
38.9k
      !new_session->ticket.CopyFrom(session->ticket)) {
151
0
    return nullptr;
152
0
  }
153
154
  // The new_session does not get a copy of the ex_data.
155
156
48.1k
  new_session->not_resumable = true;
157
48.1k
  return new_session;
158
48.1k
}
159
160
47.1k
void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session) {
161
47.1k
  OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get());
162
163
  // To avoid overflows and underflows, if we've gone back in time, update the
164
  // time, but mark the session expired.
165
47.1k
  if (session->time > now.tv_sec) {
166
0
    session->time = now.tv_sec;
167
0
    session->timeout = 0;
168
0
    session->auth_timeout = 0;
169
0
    return;
170
0
  }
171
172
  // Adjust the session time and timeouts. If the session has already expired,
173
  // clamp the timeouts at zero.
174
47.1k
  uint64_t delta = now.tv_sec - session->time;
175
47.1k
  session->time = now.tv_sec;
176
47.1k
  if (session->timeout < delta) {
177
0
    session->timeout = 0;
178
47.1k
  } else {
179
47.1k
    session->timeout -= delta;
180
47.1k
  }
181
47.1k
  if (session->auth_timeout < delta) {
182
58
    session->auth_timeout = 0;
183
47.1k
  } else {
184
47.1k
    session->auth_timeout -= delta;
185
47.1k
  }
186
47.1k
}
187
188
void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
189
360
                               uint32_t timeout) {
190
  // Rebase the timestamp relative to the current time so `timeout` is measured
191
  // correctly.
192
360
  ssl_session_rebase_time(ssl, session);
193
194
360
  if (session->timeout > timeout) {
195
191
    return;
196
191
  }
197
198
169
  session->timeout = timeout;
199
169
  if (session->timeout > session->auth_timeout) {
200
71
    session->timeout = session->auth_timeout;
201
71
  }
202
169
}
203
204
213k
uint16_t ssl_session_protocol_version(const SSL_SESSION *session) {
205
213k
  uint16_t ret;
206
213k
  if (!ssl_protocol_version_from_wire(&ret, session->ssl_version)) {
207
    // An `SSL_SESSION` will never have an invalid version. This is enforced by
208
    // the parser.
209
0
    assert(0);
210
0
    return 0;
211
0
  }
212
213
213k
  return ret;
214
213k
}
215
216
145k
const EVP_MD *ssl_session_get_digest(const SSL_SESSION *session) {
217
145k
  return ssl_get_handshake_digest(ssl_session_protocol_version(session),
218
145k
                                  session->cipher);
219
145k
}
220
221
60.1k
bool ssl_get_new_session(SSL_HANDSHAKE *hs) {
222
60.1k
  SSL *const ssl = hs->ssl;
223
60.1k
  if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
224
0
    OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
225
0
    return false;
226
0
  }
227
228
60.1k
  UniquePtr<SSL_SESSION> session = ssl_session_new(ssl->ctx->x509_method);
229
60.1k
  if (session == nullptr) {
230
0
    return false;
231
0
  }
232
233
60.1k
  session->is_server = ssl->server;
234
60.1k
  session->ssl_version = ssl->s3->version;
235
60.1k
  session->is_quic = SSL_is_quic(ssl);
236
237
  // Fill in the time from the `SSL_CTX`'s clock.
238
60.1k
  OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get());
239
60.1k
  session->time = now.tv_sec;
240
241
60.1k
  uint16_t version = ssl_protocol_version(ssl);
242
60.1k
  if (version >= TLS1_3_VERSION) {
243
    // TLS 1.3 uses tickets as authenticators, so we are willing to use them for
244
    // longer.
245
6.55k
    session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
246
6.55k
    session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
247
53.6k
  } else {
248
    // TLS 1.2 resumption does not incorporate new key material, so we use a
249
    // much shorter timeout.
250
53.6k
    session->timeout = ssl->session_ctx->session_timeout;
251
53.6k
    session->auth_timeout = ssl->session_ctx->session_timeout;
252
53.6k
  }
253
254
60.1k
  if (!session->sid_ctx.TryCopyFrom(hs->config->cert->sid_ctx)) {
255
0
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
256
0
    return false;
257
0
  }
258
259
  // The session is marked not resumable until it is completely filled in.
260
60.1k
  session->not_resumable = true;
261
60.1k
  session->verify_result = X509_V_ERR_INVALID_CALL;
262
263
60.1k
  hs->new_session = std::move(session);
264
60.1k
  ssl_set_session(ssl, nullptr);
265
60.1k
  return true;
266
60.1k
}
267
268
1.76k
bool ssl_ctx_rotate_ticket_encryption_key(SSLContext *ctx) {
269
1.76k
  OPENSSL_timeval now = ssl_ctx_get_current_time(ctx);
270
1.76k
  {
271
    // Avoid acquiring a write lock in the common case (i.e. a non-default key
272
    // is used or the default keys have not expired yet).
273
1.76k
    MutexReadLock lock(&ctx->lock);
274
1.76k
    if (ctx->ticket_key_current &&
275
1.76k
        (ctx->ticket_key_current->next_rotation_tv_sec == 0 ||
276
1.76k
         ctx->ticket_key_current->next_rotation_tv_sec > now.tv_sec) &&
277
1.76k
        (!ctx->ticket_key_prev ||
278
1.76k
         ctx->ticket_key_prev->next_rotation_tv_sec > now.tv_sec)) {
279
1.76k
      return true;
280
1.76k
    }
281
1.76k
  }
282
283
3
  MutexWriteLock lock(&ctx->lock);
284
3
  if (!ctx->ticket_key_current ||
285
0
      (ctx->ticket_key_current->next_rotation_tv_sec != 0 &&
286
3
       ctx->ticket_key_current->next_rotation_tv_sec <= now.tv_sec)) {
287
    // The current key has not been initialized or it is expired.
288
3
    auto new_key = bssl::MakeUnique<TicketKey>();
289
3
    if (!new_key) {
290
0
      return false;
291
0
    }
292
3
    RAND_bytes(new_key->name, 16);
293
3
    RAND_bytes(new_key->hmac_key, 16);
294
3
    RAND_bytes(new_key->aes_key, 16);
295
3
    new_key->next_rotation_tv_sec =
296
3
        now.tv_sec + SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
297
3
    if (ctx->ticket_key_current) {
298
      // The current key expired. Rotate it to prev and bump up its rotation
299
      // timestamp. Note that even with the new rotation time it may still be
300
      // expired and get dropped below.
301
0
      ctx->ticket_key_current->next_rotation_tv_sec +=
302
0
          SSL_DEFAULT_TICKET_KEY_ROTATION_INTERVAL;
303
0
      ctx->ticket_key_prev = std::move(ctx->ticket_key_current);
304
0
    }
305
3
    ctx->ticket_key_current = std::move(new_key);
306
3
  }
307
308
  // Drop an expired prev key.
309
3
  if (ctx->ticket_key_prev &&
310
0
      ctx->ticket_key_prev->next_rotation_tv_sec <= now.tv_sec) {
311
0
    ctx->ticket_key_prev.reset();
312
0
  }
313
314
3
  return true;
315
3
}
316
317
static int ssl_encrypt_ticket_with_cipher_ctx(SSL_HANDSHAKE *hs, CBB *out,
318
                                              const uint8_t *session_buf,
319
1.60k
                                              size_t session_len) {
320
1.60k
  ScopedEVP_CIPHER_CTX ctx;
321
1.60k
  ScopedHMAC_CTX hctx;
322
323
  // If the session is too long, decline to send a ticket.
324
1.60k
  static const size_t kMaxTicketOverhead =
325
1.60k
      16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
326
1.60k
  if (session_len > 0xffff - kMaxTicketOverhead) {
327
0
    return 1;
328
0
  }
329
330
  // Initialize HMAC and cipher contexts. If callback present it does all the
331
  // work otherwise use generated values from parent ctx.
332
1.60k
  SSLContext *tctx = hs->ssl->session_ctx.get();
333
1.60k
  uint8_t iv[EVP_MAX_IV_LENGTH];
334
1.60k
  uint8_t key_name[16];
335
1.60k
  if (tctx->ticket_key_cb != nullptr) {
336
0
    int ret = tctx->ticket_key_cb(hs->ssl, key_name, iv, ctx.get(), hctx.get(),
337
0
                                  1 /* encrypt */);
338
0
    if (ret < 0) {
339
0
      return 0;
340
0
    }
341
0
    if (ret == 0) {
342
      // The caller requested to send no ticket, so write nothing to `out`.
343
0
      return 1;
344
0
    }
345
1.60k
  } else {
346
    // Rotate ticket key if necessary.
347
1.60k
    if (!ssl_ctx_rotate_ticket_encryption_key(tctx)) {
348
0
      return 0;
349
0
    }
350
1.60k
    MutexReadLock lock(&tctx->lock);
351
1.60k
    if (!RAND_bytes(iv, 16) ||
352
1.60k
        !EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_cbc(), nullptr,
353
1.60k
                            tctx->ticket_key_current->aes_key, iv) ||
354
1.60k
        !HMAC_Init_ex(hctx.get(), tctx->ticket_key_current->hmac_key, 16,
355
1.60k
                      tlsext_tick_md(), nullptr)) {
356
0
      return 0;
357
0
    }
358
1.60k
    OPENSSL_memcpy(key_name, tctx->ticket_key_current->name, 16);
359
1.60k
  }
360
361
1.60k
  uint8_t *ptr;
362
1.60k
  if (!CBB_add_bytes(out, key_name, 16) ||
363
1.60k
      !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(ctx.get())) ||
364
1.60k
      !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) {
365
0
    return 0;
366
0
  }
367
368
1.60k
  size_t total = 0;
369
1.60k
  if (CRYPTO_fuzzer_mode_enabled()) {
370
1.44k
    OPENSSL_memcpy(ptr, session_buf, session_len);
371
1.44k
    total = session_len;
372
1.44k
  } else {
373
161
    size_t len;
374
161
    if (!EVP_EncryptUpdate_ex(ctx.get(), ptr + total, &len,
375
161
                              session_len + EVP_MAX_BLOCK_LENGTH - total,
376
161
                              session_buf, session_len)) {
377
0
      return 0;
378
0
    }
379
161
    total += len;
380
161
    if (!EVP_EncryptFinal_ex2(ctx.get(), ptr + total, &len,
381
161
                              session_len + EVP_MAX_BLOCK_LENGTH - total)) {
382
0
      return 0;
383
0
    }
384
161
    total += len;
385
161
  }
386
1.60k
  if (!CBB_did_write(out, total)) {
387
0
    return 0;
388
0
  }
389
390
1.60k
  unsigned hlen;
391
1.60k
  if (!HMAC_Update(hctx.get(), CBB_data(out), CBB_len(out)) ||  //
392
1.60k
      !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) ||               //
393
1.60k
      !HMAC_Final(hctx.get(), ptr, &hlen) ||                    //
394
1.60k
      !CBB_did_write(out, hlen)) {
395
0
    return 0;
396
0
  }
397
398
1.60k
  return 1;
399
1.60k
}
400
401
static int ssl_encrypt_ticket_with_method(SSL_HANDSHAKE *hs, CBB *out,
402
                                          const uint8_t *session_buf,
403
0
                                          size_t session_len) {
404
0
  SSL *const ssl = hs->ssl;
405
0
  const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
406
0
  const size_t max_overhead = method->max_overhead(ssl);
407
0
  const size_t max_out = session_len + max_overhead;
408
0
  if (max_out < max_overhead) {
409
0
    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
410
0
    return 0;
411
0
  }
412
413
0
  uint8_t *ptr;
414
0
  if (!CBB_reserve(out, &ptr, max_out)) {
415
0
    return 0;
416
0
  }
417
418
0
  size_t out_len;
419
0
  if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
420
0
    OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
421
0
    return 0;
422
0
  }
423
424
0
  if (!CBB_did_write(out, out_len)) {
425
0
    return 0;
426
0
  }
427
428
0
  return 1;
429
0
}
430
431
bool ssl_encrypt_ticket(SSL_HANDSHAKE *hs, CBB *out,
432
1.60k
                        const SSL_SESSION *session) {
433
  // Serialize the SSL_SESSION to be encoded into the ticket.
434
1.60k
  uint8_t *session_buf = nullptr;
435
1.60k
  size_t session_len;
436
1.60k
  if (!SSL_SESSION_to_bytes_for_ticket(session, &session_buf, &session_len)) {
437
0
    return false;
438
0
  }
439
1.60k
  bssl::UniquePtr<uint8_t> free_session_buf(session_buf);
440
441
1.60k
  if (hs->ssl->session_ctx->ticket_aead_method) {
442
0
    return ssl_encrypt_ticket_with_method(hs, out, session_buf, session_len);
443
1.60k
  } else {
444
1.60k
    return ssl_encrypt_ticket_with_cipher_ctx(hs, out, session_buf,
445
1.60k
                                              session_len);
446
1.60k
  }
447
1.60k
}
448
449
47.4k
SSLSessionType ssl_session_get_type(const SSL_SESSION *session) {
450
47.4k
  if (session->not_resumable) {
451
37.0k
    return SSLSessionType::kNotResumable;
452
37.0k
  }
453
10.3k
  if (ssl_session_protocol_version(session) >= TLS1_3_VERSION) {
454
4.47k
    return session->ticket.empty() ? SSLSessionType::kNotResumable
455
4.47k
                                   : SSLSessionType::kPreSharedKey;
456
4.47k
  }
457
5.84k
  if (!session->ticket.empty()) {
458
1.63k
    return SSLSessionType::kTicket;
459
1.63k
  }
460
4.21k
  if (!session->session_id.empty()) {
461
3.96k
    return SSLSessionType::kID;
462
3.96k
  }
463
248
  return SSLSessionType::kNotResumable;
464
4.21k
}
465
466
bool ssl_session_is_context_valid(const SSL_HANDSHAKE *hs,
467
1.35k
                                  const SSL_SESSION *session) {
468
1.35k
  return session != nullptr &&
469
1.35k
         Span(session->sid_ctx) == hs->config->cert->sid_ctx;
470
1.35k
}
471
472
2.97k
bool ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
473
2.97k
  if (session == nullptr) {
474
0
    return false;
475
0
  }
476
477
2.97k
  OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get());
478
479
  // Reject tickets from the future to avoid underflow.
480
2.97k
  if (now.tv_sec < session->time) {
481
95
    return false;
482
95
  }
483
484
2.88k
  return session->timeout > now.tv_sec - session->time;
485
2.97k
}
486
487
bool ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
488
909
                              const SSL_SESSION *session) {
489
909
  const SSL *const ssl = hs->ssl;
490
909
  return ssl_session_is_context_valid(hs, session) &&
491
         // The session must have been created by the same type of end point as
492
         // we're now using it with.
493
906
         ssl->server == session->is_server &&
494
         // The session must not be expired.
495
903
         ssl_session_is_time_valid(ssl, session) &&
496
         // Only resume if the session's version matches the negotiated
497
         // version.
498
881
         ssl->s3->version == session->ssl_version &&
499
         // Only resume if the session's cipher matches the negotiated one. This
500
         // is stricter than necessary for TLS 1.3, which allows cross-cipher
501
         // resumption if the PRF hashes match. We require an exact match for
502
         // simplicity. If loosening this, the 0-RTT accept logic must be
503
         // updated to check the cipher.
504
818
         hs->new_cipher == session->cipher &&
505
         // If the session contains a client certificate/RPK (either the full
506
         // certificate/RPK or just the hash) then require that the form of the
507
         // certificate/RPK matches the current configuration.
508
812
         (!ssl_session_has_peer_cred(session) ||
509
12
          session->peer_sha256_valid ==
510
12
              hs->config->retain_only_sha256_of_client_certs) &&
511
         // Only resume if the underlying transport protocol hasn't changed.
512
         // This is to prevent cross-protocol resumption between QUIC and TCP.
513
809
         SSL_is_quic(ssl) == int{session->is_quic};
514
909
}
515
516
// ssl_lookup_session looks up `session_id` in the session cache and sets
517
// `*out_session` to an `SSL_SESSION` object if found.
518
static enum ssl_hs_wait_t ssl_lookup_session(
519
    SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session,
520
6.93k
    Span<const uint8_t> session_id) {
521
6.93k
  SSL *const ssl = hs->ssl;
522
6.93k
  out_session->reset();
523
524
6.93k
  if (session_id.empty() || session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
525
5.84k
    return ssl_hs_ok;
526
5.84k
  }
527
528
1.09k
  UniquePtr<SSL_SESSION> session;
529
  // Try the internal cache, if it exists.
530
1.09k
  if (!(ssl->session_ctx->session_cache_mode &
531
1.09k
        SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
532
1.09k
    uint32_t hash = ssl_hash_session_id(session_id);
533
1.09k
    auto cmp = [](const void *key, const SSL_SESSION *sess) -> int {
534
1.04k
      Span<const uint8_t> key_id =
535
1.04k
          *reinterpret_cast<const Span<const uint8_t> *>(key);
536
1.04k
      return key_id == sess->session_id ? 0 : 1;
537
1.04k
    };
538
1.09k
    MutexReadLock lock(&ssl->session_ctx->lock);
539
    // `lh_SSL_SESSION_retrieve_key` returns a non-owning pointer.
540
1.09k
    session = UpRef(lh_SSL_SESSION_retrieve_key(ssl->session_ctx->sessions,
541
1.09k
                                                &session_id, hash, cmp));
542
    // TODO(davidben): This should probably move it to the front of the list.
543
1.09k
  }
544
545
  // Fall back to the external cache, if it exists.
546
1.09k
  if (!session && ssl->session_ctx->get_session_cb != nullptr) {
547
0
    int copy = 1;
548
0
    session.reset(ssl->session_ctx->get_session_cb(ssl, session_id.data(),
549
0
                                                   session_id.size(), &copy));
550
0
    if (!session) {
551
0
      return ssl_hs_ok;
552
0
    }
553
554
0
    if (session.get() == SSL_magic_pending_session_ptr()) {
555
0
      session.release();  // This pointer is not actually owned.
556
0
      return ssl_hs_pending_session;
557
0
    }
558
559
    // Increment reference count now if the session callback asks us to do so
560
    // (note that if the session structures returned by the callback are shared
561
    // between threads, it must handle the reference count itself [i.e. copy ==
562
    // 0], or things won't be thread-safe).
563
0
    if (copy) {
564
0
      SSL_SESSION_up_ref(session.get());
565
0
    }
566
567
    // Add the externally cached session to the internal cache if necessary.
568
0
    if (!(ssl->session_ctx->session_cache_mode &
569
0
          SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
570
0
      SSL_CTX_add_session(ssl->session_ctx.get(), session.get());
571
0
    }
572
0
  }
573
574
1.09k
  if (session && !ssl_session_is_time_valid(ssl, session.get())) {
575
    // The session was from the cache, so remove it.
576
91
    SSL_CTX_remove_session(ssl->session_ctx.get(), session.get());
577
91
    session.reset();
578
91
  }
579
580
1.09k
  *out_session = std::move(session);
581
1.09k
  return ssl_hs_ok;
582
1.09k
}
583
584
enum ssl_hs_wait_t ssl_get_prev_session(SSL_HANDSHAKE *hs,
585
                                        UniquePtr<SSL_SESSION> *out_session,
586
                                        bool *out_tickets_supported,
587
                                        bool *out_renew_ticket,
588
7.85k
                                        const SSL_CLIENT_HELLO *client_hello) {
589
  // This is used only by servers.
590
7.85k
  assert(hs->ssl->server);
591
7.85k
  UniquePtr<SSL_SESSION> session;
592
7.85k
  bool renew_ticket = false;
593
594
  // If tickets are disabled, always behave as if no tickets are present.
595
7.85k
  CBS ticket;
596
7.85k
  const bool tickets_supported =
597
7.85k
      !(SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) &&
598
7.85k
      ssl_client_hello_get_extension(client_hello, &ticket,
599
7.85k
                                     TLSEXT_TYPE_session_ticket);
600
7.85k
  if (tickets_supported && CBS_len(&ticket) != 0) {
601
913
    switch (ssl_process_ticket(
602
913
        hs, &session, &renew_ticket, ticket,
603
913
        Span(client_hello->session_id, client_hello->session_id_len),
604
913
        /*save_ticket=*/false)) {
605
324
      case ssl_ticket_aead_success:
606
324
        break;
607
589
      case ssl_ticket_aead_ignore_ticket:
608
589
        assert(!session);
609
589
        break;
610
589
      case ssl_ticket_aead_error:
611
0
        return ssl_hs_error;
612
0
      case ssl_ticket_aead_retry:
613
0
        return ssl_hs_pending_ticket;
614
913
    }
615
6.93k
  } else {
616
    // The client didn't send a ticket, so the session ID is a real ID.
617
6.93k
    enum ssl_hs_wait_t lookup_ret = ssl_lookup_session(
618
6.93k
        hs, &session,
619
6.93k
        Span(client_hello->session_id, client_hello->session_id_len));
620
6.93k
    if (lookup_ret != ssl_hs_ok) {
621
0
      return lookup_ret;
622
0
    }
623
6.93k
  }
624
625
7.85k
  *out_session = std::move(session);
626
7.85k
  *out_tickets_supported = tickets_supported;
627
7.85k
  *out_renew_ticket = renew_ticket;
628
7.85k
  return ssl_hs_ok;
629
7.85k
}
630
631
91
static bool remove_session(SSLContext *ctx, SSL_SESSION *session, bool lock) {
632
91
  if (session == nullptr || session->session_id.empty()) {
633
0
    return false;
634
0
  }
635
636
91
  if (lock) {
637
91
    ctx->lock.LockWrite();
638
91
  }
639
640
91
  SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions, session);
641
91
  bool found = found_session == session;
642
91
  if (found) {
643
91
    found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
644
91
    SSL_SESSION_list_remove(ctx, session);
645
91
  }
646
647
91
  if (lock) {
648
91
    ctx->lock.UnlockWrite();
649
91
  }
650
651
91
  if (found) {
652
    // TODO(https://crbug.com/boringssl/251): Callbacks should not be called
653
    // under a lock.
654
91
    if (ctx->remove_session_cb != nullptr) {
655
0
      ctx->remove_session_cb(ctx, found_session);
656
0
    }
657
91
    SSL_SESSION_free(found_session);
658
91
  }
659
660
91
  return found;
661
91
}
662
663
168k
void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
664
168k
  if (ssl->session.get() == session) {
665
113k
    return;
666
113k
  }
667
668
55.2k
  ssl->session = UpRef(session);
669
55.2k
}
670
671
// locked by SSL_CTX in the calling function
672
61.3k
static void SSL_SESSION_list_remove(SSLContext *ctx, SSL_SESSION *session) {
673
61.3k
  if (session->next == nullptr || session->prev == nullptr) {
674
0
    return;
675
0
  }
676
677
61.3k
  if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
678
    // last element in list
679
21.0k
    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
680
      // only one element in list
681
14.8k
      ctx->session_cache_head = nullptr;
682
14.8k
      ctx->session_cache_tail = nullptr;
683
14.8k
    } else {
684
6.19k
      ctx->session_cache_tail = session->prev;
685
6.19k
      session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
686
6.19k
    }
687
40.3k
  } else {
688
40.3k
    if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
689
      // first element in list
690
21.3k
      ctx->session_cache_head = session->next;
691
21.3k
      session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
692
21.3k
    } else {  // middle of list
693
18.9k
      session->next->prev = session->prev;
694
18.9k
      session->prev->next = session->next;
695
18.9k
    }
696
40.3k
  }
697
61.3k
  session->prev = session->next = nullptr;
698
61.3k
}
699
700
61.3k
static void SSL_SESSION_list_add(SSLContext *ctx, SSL_SESSION *session) {
701
61.3k
  if (session->next != nullptr && session->prev != nullptr) {
702
0
    SSL_SESSION_list_remove(ctx, session);
703
0
  }
704
705
61.3k
  if (ctx->session_cache_head == nullptr) {
706
14.8k
    ctx->session_cache_head = session;
707
14.8k
    ctx->session_cache_tail = session;
708
14.8k
    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
709
14.8k
    session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
710
46.4k
  } else {
711
46.4k
    session->next = ctx->session_cache_head;
712
46.4k
    session->next->prev = session;
713
46.4k
    session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
714
46.4k
    ctx->session_cache_head = session;
715
46.4k
  }
716
61.3k
}
717
718
static bool add_session_locked(SSLContext *ctx,
719
61.3k
                               UniquePtr<SSL_SESSION> session) {
720
61.3k
  SSL_SESSION *new_session = session.get();
721
61.3k
  SSL_SESSION *old_session;
722
61.3k
  if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, new_session)) {
723
0
    return false;
724
0
  }
725
  // `ctx->sessions` took ownership of `new_session` and gave us back a
726
  // reference to `old_session`. (`old_session` may be the same as
727
  // `new_session`, in which case we traded identical references with
728
  // `ctx->sessions`.)
729
61.3k
  session.release();
730
61.3k
  session.reset(old_session);
731
732
61.3k
  if (old_session != nullptr) {
733
49.3k
    if (old_session == new_session) {
734
      // `session` was already in the cache. There are no linked list pointers
735
      // to update.
736
0
      return false;
737
0
    }
738
739
    // There was a session ID collision. `old_session` was replaced with
740
    // `session` in the hash table, so `old_session` must be removed from the
741
    // linked list to match.
742
49.3k
    SSL_SESSION_list_remove(ctx, old_session);
743
49.3k
  }
744
745
  // This does not increment the reference count. Although `session` is inserted
746
  // into two structures (a doubly-linked list and the hash table), `ctx` only
747
  // takes one reference.
748
61.3k
  SSL_SESSION_list_add(ctx, new_session);
749
750
  // Enforce any cache size limits.
751
61.3k
  if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
752
61.3k
    while (lh_SSL_SESSION_num_items(ctx->sessions) >
753
61.3k
           SSL_CTX_sess_get_cache_size(ctx)) {
754
0
      if (!remove_session(ctx, ctx->session_cache_tail,
755
0
                          /*lock=*/false)) {
756
0
        break;
757
0
      }
758
0
    }
759
61.3k
  }
760
761
61.3k
  return true;
762
61.3k
}
763
764
41.9k
void ssl_update_cache(SSL *ssl) {
765
41.9k
  SSLContext *ctx = ssl->session_ctx.get();
766
41.9k
  SSL_SESSION *session = ssl->s3->established_session.get();
767
41.9k
  int mode = SSL_is_server(ssl) ? SSL_SESS_CACHE_SERVER : SSL_SESS_CACHE_CLIENT;
768
41.9k
  if (!SSL_SESSION_is_resumable(session) ||
769
41.7k
      (ctx->session_cache_mode & mode) != mode) {
770
41.7k
    return;
771
41.7k
  }
772
773
  // Clients never use the internal session cache.
774
151
  if (ssl->server &&
775
151
      !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
776
151
    UniquePtr<SSL_SESSION> ref = UpRef(session);
777
151
    bool remove_expired_sessions = false;
778
151
    {
779
151
      MutexWriteLock lock(&ctx->lock);
780
151
      add_session_locked(ctx, std::move(ref));
781
782
151
      if (!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
783
        // Automatically flush the internal session cache every 255 connections.
784
151
        ctx->handshakes_since_cache_flush++;
785
151
        if (ctx->handshakes_since_cache_flush >= 255) {
786
0
          remove_expired_sessions = true;
787
0
          ctx->handshakes_since_cache_flush = 0;
788
0
        }
789
151
      }
790
151
    }
791
792
151
    if (remove_expired_sessions) {
793
      // `SSL_CTX_flush_sessions` takes the lock we just released. We could
794
      // merge the critical sections, but we'd then call user code under a
795
      // lock, or compute `now` earlier, even when not flushing.
796
0
      OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get());
797
0
      SSL_CTX_flush_sessions(ctx, now.tv_sec);
798
0
    }
799
151
  }
800
801
151
  if (ctx->new_session_cb != nullptr) {
802
0
    UniquePtr<SSL_SESSION> ref = UpRef(session);
803
0
    if (ctx->new_session_cb(ssl, ref.get())) {
804
      // `new_session_cb`'s return value signals whether it took ownership.
805
0
      ref.release();
806
0
    }
807
0
  }
808
151
}
809
810
129k
bool ssl_session_has_peer_cred(const SSL_SESSION *session) {
811
129k
  return sk_CRYPTO_BUFFER_num(SSL_SESSION_get0_peer_certificates(session)) >
812
129k
             0 ||
813
4.10k
         SSL_SESSION_get0_peer_rpk(session) != nullptr ||
814
4.10k
         session->peer_sha256_valid;
815
129k
}
816
817
BSSL_NAMESPACE_END
818
819
using namespace bssl;
820
821
ssl_session_st::ssl_session_st(const SSL_X509_METHOD *method)
822
241k
    : RefCounted(CheckSubClass()),
823
241k
      x509_method(method),
824
241k
      extended_master_secret(false),
825
241k
      peer_sha256_valid(false),
826
241k
      not_resumable(false),
827
241k
      ticket_age_add_valid(false),
828
241k
      is_server(false),
829
241k
      is_quic(false),
830
241k
      has_application_settings(false),
831
241k
      is_resumable_across_names(false) {
832
241k
  CRYPTO_new_ex_data(&ex_data);
833
241k
  time = ::time(nullptr);
834
241k
}
835
836
241k
ssl_session_st::~ssl_session_st() {
837
241k
  CRYPTO_free_ex_data(&g_ex_data_class, &ex_data);
838
241k
  x509_method->session_clear(this);
839
241k
}
840
841
0
SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
842
0
  return ssl_session_new(FromOpaque(ctx)->x509_method).release();
843
0
}
844
845
116k
int SSL_SESSION_up_ref(SSL_SESSION *session) {
846
116k
  session->UpRefInternal();
847
116k
  return 1;
848
116k
}
849
850
358k
void SSL_SESSION_free(SSL_SESSION *session) {
851
358k
  if (session == nullptr) {
852
0
    return;
853
0
  }
854
358k
  session->DecRefInternal();
855
358k
}
856
857
const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
858
0
                                  unsigned *out_len) {
859
0
  if (out_len != nullptr) {
860
0
    *out_len = session->session_id.size();
861
0
  }
862
0
  return session->session_id.data();
863
0
}
864
865
int SSL_SESSION_set1_id(SSL_SESSION *session, const uint8_t *sid,
866
0
                        size_t sid_len) {
867
0
  if (!session->session_id.TryCopyFrom(Span(sid, sid_len))) {
868
0
    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_TOO_LONG);
869
0
    return 0;
870
0
  }
871
872
0
  return 1;
873
0
}
874
875
0
uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
876
0
  return session->timeout;
877
0
}
878
879
0
uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
880
0
  if (session == nullptr) {
881
    // NULL should crash, but silently accept it here for compatibility.
882
0
    return 0;
883
0
  }
884
0
  return session->time;
885
0
}
886
887
0
X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
888
0
  return session->x509_peer;
889
0
}
890
891
const STACK_OF(CRYPTO_BUFFER) *SSL_SESSION_get0_peer_certificates(
892
129k
    const SSL_SESSION *session) {
893
129k
  return session->certs.get();
894
129k
}
895
896
4.10k
EVP_PKEY *SSL_SESSION_get0_peer_rpk(const SSL_SESSION *session) {
897
4.10k
  return session->peer_raw_public_key.get();
898
4.10k
}
899
900
void SSL_SESSION_get0_signed_cert_timestamp_list(const SSL_SESSION *session,
901
                                                 const uint8_t **out,
902
0
                                                 size_t *out_len) {
903
0
  if (session->signed_cert_timestamp_list) {
904
0
    *out = CRYPTO_BUFFER_data(session->signed_cert_timestamp_list.get());
905
0
    *out_len = CRYPTO_BUFFER_len(session->signed_cert_timestamp_list.get());
906
0
  } else {
907
0
    *out = nullptr;
908
0
    *out_len = 0;
909
0
  }
910
0
}
911
912
void SSL_SESSION_get0_ocsp_response(const SSL_SESSION *session,
913
0
                                    const uint8_t **out, size_t *out_len) {
914
0
  if (session->ocsp_response) {
915
0
    *out = CRYPTO_BUFFER_data(session->ocsp_response.get());
916
0
    *out_len = CRYPTO_BUFFER_len(session->ocsp_response.get());
917
0
  } else {
918
0
    *out = nullptr;
919
0
    *out_len = 0;
920
0
  }
921
0
}
922
923
size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
924
0
                                  size_t max_out) {
925
0
  if (max_out == 0) {
926
0
    return session->secret.size();
927
0
  }
928
0
  if (max_out > session->secret.size()) {
929
0
    max_out = session->secret.size();
930
0
  }
931
0
  OPENSSL_memcpy(out, session->secret.data(), max_out);
932
0
  return max_out;
933
0
}
934
935
0
uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
936
0
  if (session == nullptr) {
937
0
    return 0;
938
0
  }
939
940
0
  session->time = time;
941
0
  return time;
942
0
}
943
944
0
uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
945
0
  if (session == nullptr) {
946
0
    return 0;
947
0
  }
948
949
0
  session->timeout = timeout;
950
0
  session->auth_timeout = timeout;
951
0
  return 1;
952
0
}
953
954
const uint8_t *SSL_SESSION_get0_id_context(const SSL_SESSION *session,
955
0
                                           unsigned *out_len) {
956
0
  if (out_len != nullptr) {
957
0
    *out_len = session->sid_ctx.size();
958
0
  }
959
0
  return session->sid_ctx.data();
960
0
}
961
962
int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
963
0
                                size_t sid_ctx_len) {
964
0
  if (!session->sid_ctx.TryCopyFrom(Span(sid_ctx, sid_ctx_len))) {
965
0
    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
966
0
    return 0;
967
0
  }
968
969
0
  return 1;
970
0
}
971
972
0
int SSL_SESSION_should_be_single_use(const SSL_SESSION *session) {
973
0
  return ssl_session_protocol_version(session) >= TLS1_3_VERSION;
974
0
}
975
976
41.9k
int SSL_SESSION_is_resumable(const SSL_SESSION *session) {
977
41.9k
  return ssl_session_get_type(session) != SSLSessionType::kNotResumable;
978
41.9k
}
979
980
0
int SSL_SESSION_has_ticket(const SSL_SESSION *session) {
981
0
  return !session->ticket.empty();
982
0
}
983
984
void SSL_SESSION_get0_ticket(const SSL_SESSION *session,
985
0
                             const uint8_t **out_ticket, size_t *out_len) {
986
0
  if (out_ticket != nullptr) {
987
0
    *out_ticket = session->ticket.data();
988
0
  }
989
0
  *out_len = session->ticket.size();
990
0
}
991
992
int SSL_SESSION_set_ticket(SSL_SESSION *session, const uint8_t *ticket,
993
0
                           size_t ticket_len) {
994
0
  return session->ticket.CopyFrom(Span(ticket, ticket_len));
995
0
}
996
997
0
uint32_t SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session) {
998
0
  return session->ticket_lifetime_hint;
999
0
}
1000
1001
0
const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *session) {
1002
0
  return session->cipher;
1003
0
}
1004
1005
0
int SSL_SESSION_has_peer_sha256(const SSL_SESSION *session) {
1006
0
  return session->peer_sha256_valid;
1007
0
}
1008
1009
void SSL_SESSION_get0_peer_sha256(const SSL_SESSION *session,
1010
0
                                  const uint8_t **out_ptr, size_t *out_len) {
1011
0
  if (session->peer_sha256_valid) {
1012
0
    *out_ptr = session->peer_sha256;
1013
0
    *out_len = sizeof(session->peer_sha256);
1014
0
  } else {
1015
0
    *out_ptr = nullptr;
1016
0
    *out_len = 0;
1017
0
  }
1018
0
}
1019
1020
0
int SSL_SESSION_is_resumable_across_names(const SSL_SESSION *session) {
1021
0
  return session->is_resumable_across_names;
1022
0
}
1023
1024
0
int SSL_SESSION_early_data_capable(const SSL_SESSION *session) {
1025
0
  return ssl_session_protocol_version(session) >= TLS1_3_VERSION &&
1026
0
         session->ticket_max_early_data != 0;
1027
0
}
1028
1029
0
SSL_SESSION *SSL_SESSION_copy_without_early_data(SSL_SESSION *session) {
1030
0
  if (!SSL_SESSION_early_data_capable(session)) {
1031
0
    return UpRef(session).release();
1032
0
  }
1033
1034
0
  bssl::UniquePtr<SSL_SESSION> copy =
1035
0
      SSL_SESSION_dup(session, SSL_SESSION_DUP_ALL);
1036
0
  if (!copy) {
1037
0
    return nullptr;
1038
0
  }
1039
1040
0
  copy->ticket_max_early_data = 0;
1041
  // Copied sessions are non-resumable until they're completely filled in.
1042
0
  copy->not_resumable = session->not_resumable;
1043
0
  assert(!SSL_SESSION_early_data_capable(copy.get()));
1044
0
  return copy.release();
1045
0
}
1046
1047
0
SSL_SESSION *SSL_magic_pending_session_ptr() {
1048
0
  return (SSL_SESSION *)&g_pending_session_magic;
1049
0
}
1050
1051
37.1k
SSL_SESSION *SSL_get_session(const SSL *ssl) {
1052
  // Once the initially handshake completes, we return the most recently
1053
  // established session. In particular, if there is a pending renegotiation, we
1054
  // do not return information about it until it completes.
1055
  //
1056
  // Code in the handshake must either use `hs->new_session` (if updating a
1057
  // partial session) or `ssl_handshake_session` (if trying to query properties
1058
  // consistently across TLS 1.2 resumption and other handshakes).
1059
37.1k
  if (ssl->s3->established_session != nullptr) {
1060
37.1k
    return ssl->s3->established_session.get();
1061
37.1k
  }
1062
1063
  // Otherwise, we must be in the initial handshake.
1064
0
  SSL_HANDSHAKE *hs = ssl->s3->hs.get();
1065
0
  assert(hs != nullptr);
1066
0
  assert(!ssl->s3->initial_handshake_complete);
1067
1068
  // Return the 0-RTT session, if in the 0-RTT state. While the handshake has
1069
  // not actually completed, the public accessors all report properties as if
1070
  // it has.
1071
0
  if (hs->early_session) {
1072
0
    return hs->early_session.get();
1073
0
  }
1074
1075
  // Otherwise, return the partial session.
1076
0
  return (SSL_SESSION *)ssl_handshake_session(hs);
1077
0
}
1078
1079
0
SSL_SESSION *SSL_get1_session(SSL *ssl) {
1080
0
  SSL_SESSION *ret = SSL_get_session(ssl);
1081
0
  if (ret != nullptr) {
1082
0
    SSL_SESSION_up_ref(ret);
1083
0
  }
1084
0
  return ret;
1085
0
}
1086
1087
int SSL_SESSION_get_ex_new_index(long argl, void *argp,
1088
                                 CRYPTO_EX_unused *unused,
1089
                                 CRYPTO_EX_dup *dup_unused,
1090
0
                                 CRYPTO_EX_free *free_func) {
1091
0
  return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func);
1092
0
}
1093
1094
0
int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
1095
0
  return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
1096
0
}
1097
1098
0
void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
1099
0
  return CRYPTO_get_ex_data(&session->ex_data, idx);
1100
0
}
1101
1102
61.2k
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
1103
61.2k
  auto *ctx_impl = FromOpaque(ctx);
1104
61.2k
  UniquePtr<SSL_SESSION> owned_session = UpRef(session);
1105
61.2k
  MutexWriteLock lock(&ctx_impl->lock);
1106
61.2k
  return add_session_locked(ctx_impl, std::move(owned_session));
1107
61.2k
}
1108
1109
91
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) {
1110
91
  return remove_session(FromOpaque(ctx), session, /*lock=*/true);
1111
91
}
1112
1113
54.1k
int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
1114
  // SSL_set_session may only be called before the handshake has started.
1115
54.1k
  if (ssl->s3->initial_handshake_complete ||  //
1116
54.1k
      ssl->s3->hs == nullptr ||               //
1117
54.1k
      ssl->s3->hs->state != 0) {
1118
0
    abort();
1119
0
  }
1120
1121
54.1k
  ssl_set_session(ssl, session);
1122
54.1k
  return 1;
1123
54.1k
}
1124
1125
0
uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
1126
0
  if (ctx == nullptr) {
1127
0
    return 0;
1128
0
  }
1129
1130
  // Historically, zero was treated as `SSL_DEFAULT_SESSION_TIMEOUT`.
1131
0
  if (timeout == 0) {
1132
0
    timeout = SSL_DEFAULT_SESSION_TIMEOUT;
1133
0
  }
1134
1135
0
  return std::exchange(FromOpaque(ctx)->session_timeout, timeout);
1136
0
}
1137
1138
0
uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx) {
1139
0
  if (ctx == nullptr) {
1140
0
    return 0;
1141
0
  }
1142
1143
0
  return FromOpaque(ctx)->session_timeout;
1144
0
}
1145
1146
0
void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, uint32_t timeout) {
1147
0
  FromOpaque(ctx)->session_psk_dhe_timeout = timeout;
1148
0
}
1149
1150
typedef struct timeout_param_st {
1151
  SSLContext *ctx;
1152
  uint64_t time;
1153
  LHASH_OF(SSL_SESSION) *cache;
1154
} TIMEOUT_PARAM;
1155
1156
11.9k
static void timeout_doall_arg(SSL_SESSION *session, void *void_param) {
1157
11.9k
  TIMEOUT_PARAM *param = reinterpret_cast<TIMEOUT_PARAM *>(void_param);
1158
1159
11.9k
  if (param->time == 0 ||                                  //
1160
0
      session->time + session->timeout < session->time ||  //
1161
11.9k
      param->time > (session->time + session->timeout)) {
1162
    // TODO(davidben): This can probably just call `remove_session`.
1163
11.9k
    (void)lh_SSL_SESSION_delete(param->cache, session);
1164
11.9k
    SSL_SESSION_list_remove(param->ctx, session);
1165
    // TODO(https://crbug.com/boringssl/251): Callbacks should not be called
1166
    // under a lock.
1167
11.9k
    if (param->ctx->remove_session_cb != nullptr) {
1168
0
      param->ctx->remove_session_cb(param->ctx, session);
1169
0
    }
1170
11.9k
    SSL_SESSION_free(session);
1171
11.9k
  }
1172
11.9k
}
1173
1174
65.3k
void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time) {
1175
65.3k
  auto *ctx_impl = FromOpaque(ctx);
1176
65.3k
  TIMEOUT_PARAM tp;
1177
65.3k
  tp.ctx = ctx_impl;
1178
65.3k
  tp.cache = ctx_impl->sessions;
1179
65.3k
  if (tp.cache == nullptr) {
1180
0
    return;
1181
0
  }
1182
65.3k
  tp.time = time;
1183
65.3k
  MutexWriteLock lock(&ctx_impl->lock);
1184
65.3k
  lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
1185
65.3k
}
1186
1187
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
1188
0
                             int (*cb)(SSL *ssl, SSL_SESSION *session)) {
1189
0
  FromOpaque(ctx)->new_session_cb = cb;
1190
0
}
1191
1192
0
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) {
1193
0
  return FromOpaque(ctx)->new_session_cb;
1194
0
}
1195
1196
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
1197
                                void (*cb)(SSL_CTX *ctx,
1198
0
                                           SSL_SESSION *session)) {
1199
0
  FromOpaque(ctx)->remove_session_cb = cb;
1200
0
}
1201
1202
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
1203
0
                                                 SSL_SESSION *session) {
1204
0
  return FromOpaque(ctx)->remove_session_cb;
1205
0
}
1206
1207
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
1208
                             SSL_SESSION *(*cb)(SSL *ssl, const uint8_t *id,
1209
0
                                                int id_len, int *out_copy)) {
1210
0
  FromOpaque(ctx)->get_session_cb = cb;
1211
0
}
1212
1213
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
1214
                                                      const uint8_t *id,
1215
                                                      int id_len,
1216
0
                                                      int *out_copy) {
1217
0
  return FromOpaque(ctx)->get_session_cb;
1218
0
}
1219
1220
0
void SSL_CTX_set_resumption_across_names_enabled(SSL_CTX *ctx, int enabled) {
1221
0
  FromOpaque(ctx)->resumption_across_names_enabled = !!enabled;
1222
0
}
1223
1224
0
void SSL_set_resumption_across_names_enabled(SSL *ssl, int enabled) {
1225
0
  ssl->resumption_across_names_enabled = !!enabled;
1226
0
}
1227
1228
void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,
1229
0
                                                        int type, int value)) {
1230
0
  FromOpaque(ctx)->info_callback = cb;
1231
0
}
1232
1233
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type,
1234
0
                                                int value) {
1235
0
  return FromOpaque(ctx)->info_callback;
1236
0
}