1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright 2005 Nokia. All rights reserved. 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci#if defined(__TANDEM) && defined(_SPT_MODEL_) 12e1051a39Sopenharmony_ci# include <spthread.h> 13e1051a39Sopenharmony_ci# include <spt_extensions.h> /* timeval */ 14e1051a39Sopenharmony_ci#endif 15e1051a39Sopenharmony_ci#include <stdio.h> 16e1051a39Sopenharmony_ci#include <openssl/rand.h> 17e1051a39Sopenharmony_ci#include <openssl/engine.h> 18e1051a39Sopenharmony_ci#include "internal/refcount.h" 19e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 20e1051a39Sopenharmony_ci#include "ssl_local.h" 21e1051a39Sopenharmony_ci#include "statem/statem_local.h" 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_cistatic void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); 24e1051a39Sopenharmony_cistatic void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); 25e1051a39Sopenharmony_cistatic int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ciDEFINE_STACK_OF(SSL_SESSION) 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci__owur static int sess_timedout(time_t t, SSL_SESSION *ss) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci /* if timeout overflowed, it can never timeout! */ 32e1051a39Sopenharmony_ci if (ss->timeout_ovf) 33e1051a39Sopenharmony_ci return 0; 34e1051a39Sopenharmony_ci return t > ss->calc_timeout; 35e1051a39Sopenharmony_ci} 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci/* 38e1051a39Sopenharmony_ci * Returns -1/0/+1 as other XXXcmp-type functions 39e1051a39Sopenharmony_ci * Takes overflow of calculated timeout into consideration 40e1051a39Sopenharmony_ci */ 41e1051a39Sopenharmony_ci__owur static int timeoutcmp(SSL_SESSION *a, SSL_SESSION *b) 42e1051a39Sopenharmony_ci{ 43e1051a39Sopenharmony_ci /* if only one overflowed, then it is greater */ 44e1051a39Sopenharmony_ci if (a->timeout_ovf && !b->timeout_ovf) 45e1051a39Sopenharmony_ci return 1; 46e1051a39Sopenharmony_ci if (!a->timeout_ovf && b->timeout_ovf) 47e1051a39Sopenharmony_ci return -1; 48e1051a39Sopenharmony_ci /* No overflow, or both overflowed, so straight compare is safe */ 49e1051a39Sopenharmony_ci if (a->calc_timeout < b->calc_timeout) 50e1051a39Sopenharmony_ci return -1; 51e1051a39Sopenharmony_ci if (a->calc_timeout > b->calc_timeout) 52e1051a39Sopenharmony_ci return 1; 53e1051a39Sopenharmony_ci return 0; 54e1051a39Sopenharmony_ci} 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci#ifdef __DJGPP__ /* time_t is unsigned on djgpp, it's signed anywhere else */ 57e1051a39Sopenharmony_ci# define TMAX(_type_) ((time_t)-1) 58e1051a39Sopenharmony_ci#else 59e1051a39Sopenharmony_ci# define TMAX(_type_) ((time_t)(((_type_)-1) >> 1)) 60e1051a39Sopenharmony_ci#endif 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci#define CALCULATE_TIMEOUT(_ss_, _type_) do { \ 63e1051a39Sopenharmony_ci _type_ overflow; \ 64e1051a39Sopenharmony_ci time_t tmax = TMAX(_type_); \ 65e1051a39Sopenharmony_ci overflow = (_type_)tmax - (_type_)(_ss_)->time; \ 66e1051a39Sopenharmony_ci if ((_ss_)->timeout > (time_t)overflow) { \ 67e1051a39Sopenharmony_ci (_ss_)->timeout_ovf = 1; \ 68e1051a39Sopenharmony_ci (_ss_)->calc_timeout = (_ss_)->timeout - (time_t)overflow; \ 69e1051a39Sopenharmony_ci } else { \ 70e1051a39Sopenharmony_ci (_ss_)->timeout_ovf = 0; \ 71e1051a39Sopenharmony_ci (_ss_)->calc_timeout = (_ss_)->time + (_ss_)->timeout; \ 72e1051a39Sopenharmony_ci } \ 73e1051a39Sopenharmony_ci } while (0) 74e1051a39Sopenharmony_ci/* 75e1051a39Sopenharmony_ci * Calculates effective timeout, saving overflow state 76e1051a39Sopenharmony_ci * Locking must be done by the caller of this function 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_civoid ssl_session_calculate_timeout(SSL_SESSION *ss) 79e1051a39Sopenharmony_ci{ 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci if (sizeof(time_t) == 8) 82e1051a39Sopenharmony_ci CALCULATE_TIMEOUT(ss, uint64_t); 83e1051a39Sopenharmony_ci else 84e1051a39Sopenharmony_ci CALCULATE_TIMEOUT(ss, uint32_t); 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci /* 87e1051a39Sopenharmony_ci * N.B. Realistic overflow can only occur in our lifetimes on a 88e1051a39Sopenharmony_ci * 32-bit machine in January 2038. 89e1051a39Sopenharmony_ci * However, There are no controls to limit the |timeout| 90e1051a39Sopenharmony_ci * value, except to keep it positive. 91e1051a39Sopenharmony_ci */ 92e1051a39Sopenharmony_ci} 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci/* 95e1051a39Sopenharmony_ci * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, 96e1051a39Sopenharmony_ci * unlike in earlier protocol versions, the session ticket may not have been 97e1051a39Sopenharmony_ci * sent yet even though a handshake has finished. The session ticket data could 98e1051a39Sopenharmony_ci * come in sometime later...or even change if multiple session ticket messages 99e1051a39Sopenharmony_ci * are sent from the server. The preferred way for applications to obtain 100e1051a39Sopenharmony_ci * a resumable session is to use SSL_CTX_sess_set_new_cb(). 101e1051a39Sopenharmony_ci */ 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ciSSL_SESSION *SSL_get_session(const SSL *ssl) 104e1051a39Sopenharmony_ci/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ 105e1051a39Sopenharmony_ci{ 106e1051a39Sopenharmony_ci return ssl->session; 107e1051a39Sopenharmony_ci} 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ciSSL_SESSION *SSL_get1_session(SSL *ssl) 110e1051a39Sopenharmony_ci/* variant of SSL_get_session: caller really gets something */ 111e1051a39Sopenharmony_ci{ 112e1051a39Sopenharmony_ci SSL_SESSION *sess; 113e1051a39Sopenharmony_ci /* 114e1051a39Sopenharmony_ci * Need to lock this all up rather than just use CRYPTO_add so that 115e1051a39Sopenharmony_ci * somebody doesn't free ssl->session between when we check it's non-null 116e1051a39Sopenharmony_ci * and when we up the reference count. 117e1051a39Sopenharmony_ci */ 118e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(ssl->lock)) 119e1051a39Sopenharmony_ci return NULL; 120e1051a39Sopenharmony_ci sess = ssl->session; 121e1051a39Sopenharmony_ci if (sess) 122e1051a39Sopenharmony_ci SSL_SESSION_up_ref(sess); 123e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ssl->lock); 124e1051a39Sopenharmony_ci return sess; 125e1051a39Sopenharmony_ci} 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ciint SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci return CRYPTO_set_ex_data(&s->ex_data, idx, arg); 130e1051a39Sopenharmony_ci} 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_civoid *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) 133e1051a39Sopenharmony_ci{ 134e1051a39Sopenharmony_ci return CRYPTO_get_ex_data(&s->ex_data, idx); 135e1051a39Sopenharmony_ci} 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ciSSL_SESSION *SSL_SESSION_new(void) 138e1051a39Sopenharmony_ci{ 139e1051a39Sopenharmony_ci SSL_SESSION *ss; 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) 142e1051a39Sopenharmony_ci return NULL; 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci ss = OPENSSL_zalloc(sizeof(*ss)); 145e1051a39Sopenharmony_ci if (ss == NULL) { 146e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 147e1051a39Sopenharmony_ci return NULL; 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ 151e1051a39Sopenharmony_ci ss->references = 1; 152e1051a39Sopenharmony_ci ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ 153e1051a39Sopenharmony_ci ss->time = time(NULL); 154e1051a39Sopenharmony_ci ssl_session_calculate_timeout(ss); 155e1051a39Sopenharmony_ci ss->lock = CRYPTO_THREAD_lock_new(); 156e1051a39Sopenharmony_ci if (ss->lock == NULL) { 157e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 158e1051a39Sopenharmony_ci OPENSSL_free(ss); 159e1051a39Sopenharmony_ci return NULL; 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { 163e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(ss->lock); 164e1051a39Sopenharmony_ci OPENSSL_free(ss); 165e1051a39Sopenharmony_ci return NULL; 166e1051a39Sopenharmony_ci } 167e1051a39Sopenharmony_ci return ss; 168e1051a39Sopenharmony_ci} 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci/* 171e1051a39Sopenharmony_ci * Create a new SSL_SESSION and duplicate the contents of |src| into it. If 172e1051a39Sopenharmony_ci * ticket == 0 then no ticket information is duplicated, otherwise it is. 173e1051a39Sopenharmony_ci */ 174e1051a39Sopenharmony_cistatic SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket) 175e1051a39Sopenharmony_ci{ 176e1051a39Sopenharmony_ci SSL_SESSION *dest; 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci dest = OPENSSL_malloc(sizeof(*dest)); 179e1051a39Sopenharmony_ci if (dest == NULL) { 180e1051a39Sopenharmony_ci goto err; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci memcpy(dest, src, sizeof(*dest)); 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci /* 185e1051a39Sopenharmony_ci * Set the various pointers to NULL so that we can call SSL_SESSION_free in 186e1051a39Sopenharmony_ci * the case of an error whilst halfway through constructing dest 187e1051a39Sopenharmony_ci */ 188e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_PSK 189e1051a39Sopenharmony_ci dest->psk_identity_hint = NULL; 190e1051a39Sopenharmony_ci dest->psk_identity = NULL; 191e1051a39Sopenharmony_ci#endif 192e1051a39Sopenharmony_ci dest->ext.hostname = NULL; 193e1051a39Sopenharmony_ci dest->ext.tick = NULL; 194e1051a39Sopenharmony_ci dest->ext.alpn_selected = NULL; 195e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SRP 196e1051a39Sopenharmony_ci dest->srp_username = NULL; 197e1051a39Sopenharmony_ci#endif 198e1051a39Sopenharmony_ci dest->peer_chain = NULL; 199e1051a39Sopenharmony_ci dest->peer = NULL; 200e1051a39Sopenharmony_ci dest->ticket_appdata = NULL; 201e1051a39Sopenharmony_ci memset(&dest->ex_data, 0, sizeof(dest->ex_data)); 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci /* As the copy is not in the cache, we remove the associated pointers */ 204e1051a39Sopenharmony_ci dest->prev = NULL; 205e1051a39Sopenharmony_ci dest->next = NULL; 206e1051a39Sopenharmony_ci dest->owner = NULL; 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci dest->references = 1; 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci dest->lock = CRYPTO_THREAD_lock_new(); 211e1051a39Sopenharmony_ci if (dest->lock == NULL) 212e1051a39Sopenharmony_ci goto err; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) 215e1051a39Sopenharmony_ci goto err; 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if (src->peer != NULL) { 218e1051a39Sopenharmony_ci if (!X509_up_ref(src->peer)) 219e1051a39Sopenharmony_ci goto err; 220e1051a39Sopenharmony_ci dest->peer = src->peer; 221e1051a39Sopenharmony_ci } 222e1051a39Sopenharmony_ci 223e1051a39Sopenharmony_ci if (src->peer_chain != NULL) { 224e1051a39Sopenharmony_ci dest->peer_chain = X509_chain_up_ref(src->peer_chain); 225e1051a39Sopenharmony_ci if (dest->peer_chain == NULL) 226e1051a39Sopenharmony_ci goto err; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_PSK 229e1051a39Sopenharmony_ci if (src->psk_identity_hint) { 230e1051a39Sopenharmony_ci dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint); 231e1051a39Sopenharmony_ci if (dest->psk_identity_hint == NULL) { 232e1051a39Sopenharmony_ci goto err; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci if (src->psk_identity) { 236e1051a39Sopenharmony_ci dest->psk_identity = OPENSSL_strdup(src->psk_identity); 237e1051a39Sopenharmony_ci if (dest->psk_identity == NULL) { 238e1051a39Sopenharmony_ci goto err; 239e1051a39Sopenharmony_ci } 240e1051a39Sopenharmony_ci } 241e1051a39Sopenharmony_ci#endif 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, 244e1051a39Sopenharmony_ci &dest->ex_data, &src->ex_data)) { 245e1051a39Sopenharmony_ci goto err; 246e1051a39Sopenharmony_ci } 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci if (src->ext.hostname) { 249e1051a39Sopenharmony_ci dest->ext.hostname = OPENSSL_strdup(src->ext.hostname); 250e1051a39Sopenharmony_ci if (dest->ext.hostname == NULL) { 251e1051a39Sopenharmony_ci goto err; 252e1051a39Sopenharmony_ci } 253e1051a39Sopenharmony_ci } 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci if (ticket != 0 && src->ext.tick != NULL) { 256e1051a39Sopenharmony_ci dest->ext.tick = 257e1051a39Sopenharmony_ci OPENSSL_memdup(src->ext.tick, src->ext.ticklen); 258e1051a39Sopenharmony_ci if (dest->ext.tick == NULL) 259e1051a39Sopenharmony_ci goto err; 260e1051a39Sopenharmony_ci } else { 261e1051a39Sopenharmony_ci dest->ext.tick_lifetime_hint = 0; 262e1051a39Sopenharmony_ci dest->ext.ticklen = 0; 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci if (src->ext.alpn_selected != NULL) { 266e1051a39Sopenharmony_ci dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected, 267e1051a39Sopenharmony_ci src->ext.alpn_selected_len); 268e1051a39Sopenharmony_ci if (dest->ext.alpn_selected == NULL) 269e1051a39Sopenharmony_ci goto err; 270e1051a39Sopenharmony_ci } 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SRP 273e1051a39Sopenharmony_ci if (src->srp_username) { 274e1051a39Sopenharmony_ci dest->srp_username = OPENSSL_strdup(src->srp_username); 275e1051a39Sopenharmony_ci if (dest->srp_username == NULL) { 276e1051a39Sopenharmony_ci goto err; 277e1051a39Sopenharmony_ci } 278e1051a39Sopenharmony_ci } 279e1051a39Sopenharmony_ci#endif 280e1051a39Sopenharmony_ci 281e1051a39Sopenharmony_ci if (src->ticket_appdata != NULL) { 282e1051a39Sopenharmony_ci dest->ticket_appdata = 283e1051a39Sopenharmony_ci OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); 284e1051a39Sopenharmony_ci if (dest->ticket_appdata == NULL) 285e1051a39Sopenharmony_ci goto err; 286e1051a39Sopenharmony_ci } 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci return dest; 289e1051a39Sopenharmony_ci err: 290e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 291e1051a39Sopenharmony_ci SSL_SESSION_free(dest); 292e1051a39Sopenharmony_ci return NULL; 293e1051a39Sopenharmony_ci} 294e1051a39Sopenharmony_ci 295e1051a39Sopenharmony_ciSSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) 296e1051a39Sopenharmony_ci{ 297e1051a39Sopenharmony_ci return ssl_session_dup_intern(src, 1); 298e1051a39Sopenharmony_ci} 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_ci/* 301e1051a39Sopenharmony_ci * Used internally when duplicating a session which might be already shared. 302e1051a39Sopenharmony_ci * We will have resumed the original session. Subsequently we might have marked 303e1051a39Sopenharmony_ci * it as non-resumable (e.g. in another thread) - but this copy should be ok to 304e1051a39Sopenharmony_ci * resume from. 305e1051a39Sopenharmony_ci */ 306e1051a39Sopenharmony_ciSSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) 307e1051a39Sopenharmony_ci{ 308e1051a39Sopenharmony_ci SSL_SESSION *sess = ssl_session_dup_intern(src, ticket); 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_ci if (sess != NULL) 311e1051a39Sopenharmony_ci sess->not_resumable = 0; 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ci return sess; 314e1051a39Sopenharmony_ci} 315e1051a39Sopenharmony_ci 316e1051a39Sopenharmony_ciconst unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) 317e1051a39Sopenharmony_ci{ 318e1051a39Sopenharmony_ci if (len) 319e1051a39Sopenharmony_ci *len = (unsigned int)s->session_id_length; 320e1051a39Sopenharmony_ci return s->session_id; 321e1051a39Sopenharmony_ci} 322e1051a39Sopenharmony_ciconst unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, 323e1051a39Sopenharmony_ci unsigned int *len) 324e1051a39Sopenharmony_ci{ 325e1051a39Sopenharmony_ci if (len != NULL) 326e1051a39Sopenharmony_ci *len = (unsigned int)s->sid_ctx_length; 327e1051a39Sopenharmony_ci return s->sid_ctx; 328e1051a39Sopenharmony_ci} 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ciunsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) 331e1051a39Sopenharmony_ci{ 332e1051a39Sopenharmony_ci return s->compress_meth; 333e1051a39Sopenharmony_ci} 334e1051a39Sopenharmony_ci 335e1051a39Sopenharmony_ci/* 336e1051a39Sopenharmony_ci * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling 337e1051a39Sopenharmony_ci * the ID with random junk repeatedly until we have no conflict is going to 338e1051a39Sopenharmony_ci * complete in one iteration pretty much "most" of the time (btw: 339e1051a39Sopenharmony_ci * understatement). So, if it takes us 10 iterations and we still can't avoid 340e1051a39Sopenharmony_ci * a conflict - well that's a reasonable point to call it quits. Either the 341e1051a39Sopenharmony_ci * RAND code is broken or someone is trying to open roughly very close to 342e1051a39Sopenharmony_ci * 2^256 SSL sessions to our server. How you might store that many sessions 343e1051a39Sopenharmony_ci * is perhaps a more interesting question ... 344e1051a39Sopenharmony_ci */ 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci#define MAX_SESS_ID_ATTEMPTS 10 347e1051a39Sopenharmony_cistatic int def_generate_session_id(SSL *ssl, unsigned char *id, 348e1051a39Sopenharmony_ci unsigned int *id_len) 349e1051a39Sopenharmony_ci{ 350e1051a39Sopenharmony_ci unsigned int retry = 0; 351e1051a39Sopenharmony_ci do 352e1051a39Sopenharmony_ci if (RAND_bytes_ex(ssl->ctx->libctx, id, *id_len, 0) <= 0) 353e1051a39Sopenharmony_ci return 0; 354e1051a39Sopenharmony_ci while (SSL_has_matching_session_id(ssl, id, *id_len) && 355e1051a39Sopenharmony_ci (++retry < MAX_SESS_ID_ATTEMPTS)) ; 356e1051a39Sopenharmony_ci if (retry < MAX_SESS_ID_ATTEMPTS) 357e1051a39Sopenharmony_ci return 1; 358e1051a39Sopenharmony_ci /* else - woops a session_id match */ 359e1051a39Sopenharmony_ci /* 360e1051a39Sopenharmony_ci * XXX We should also check the external cache -- but the probability of 361e1051a39Sopenharmony_ci * a collision is negligible, and we could not prevent the concurrent 362e1051a39Sopenharmony_ci * creation of sessions with identical IDs since we currently don't have 363e1051a39Sopenharmony_ci * means to atomically check whether a session ID already exists and make 364e1051a39Sopenharmony_ci * a reservation for it if it does not (this problem applies to the 365e1051a39Sopenharmony_ci * internal cache as well). 366e1051a39Sopenharmony_ci */ 367e1051a39Sopenharmony_ci return 0; 368e1051a39Sopenharmony_ci} 369e1051a39Sopenharmony_ci 370e1051a39Sopenharmony_ciint ssl_generate_session_id(SSL *s, SSL_SESSION *ss) 371e1051a39Sopenharmony_ci{ 372e1051a39Sopenharmony_ci unsigned int tmp; 373e1051a39Sopenharmony_ci GEN_SESSION_CB cb = def_generate_session_id; 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci switch (s->version) { 376e1051a39Sopenharmony_ci case SSL3_VERSION: 377e1051a39Sopenharmony_ci case TLS1_VERSION: 378e1051a39Sopenharmony_ci case TLS1_1_VERSION: 379e1051a39Sopenharmony_ci case TLS1_2_VERSION: 380e1051a39Sopenharmony_ci case TLS1_3_VERSION: 381e1051a39Sopenharmony_ci case DTLS1_BAD_VER: 382e1051a39Sopenharmony_ci case DTLS1_VERSION: 383e1051a39Sopenharmony_ci case DTLS1_2_VERSION: 384e1051a39Sopenharmony_ci ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; 385e1051a39Sopenharmony_ci break; 386e1051a39Sopenharmony_ci default: 387e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNSUPPORTED_SSL_VERSION); 388e1051a39Sopenharmony_ci return 0; 389e1051a39Sopenharmony_ci } 390e1051a39Sopenharmony_ci 391e1051a39Sopenharmony_ci /*- 392e1051a39Sopenharmony_ci * If RFC5077 ticket, use empty session ID (as server). 393e1051a39Sopenharmony_ci * Note that: 394e1051a39Sopenharmony_ci * (a) ssl_get_prev_session() does lookahead into the 395e1051a39Sopenharmony_ci * ClientHello extensions to find the session ticket. 396e1051a39Sopenharmony_ci * When ssl_get_prev_session() fails, statem_srvr.c calls 397e1051a39Sopenharmony_ci * ssl_get_new_session() in tls_process_client_hello(). 398e1051a39Sopenharmony_ci * At that point, it has not yet parsed the extensions, 399e1051a39Sopenharmony_ci * however, because of the lookahead, it already knows 400e1051a39Sopenharmony_ci * whether a ticket is expected or not. 401e1051a39Sopenharmony_ci * 402e1051a39Sopenharmony_ci * (b) statem_clnt.c calls ssl_get_new_session() before parsing 403e1051a39Sopenharmony_ci * ServerHello extensions, and before recording the session 404e1051a39Sopenharmony_ci * ID received from the server, so this block is a noop. 405e1051a39Sopenharmony_ci */ 406e1051a39Sopenharmony_ci if (s->ext.ticket_expected) { 407e1051a39Sopenharmony_ci ss->session_id_length = 0; 408e1051a39Sopenharmony_ci return 1; 409e1051a39Sopenharmony_ci } 410e1051a39Sopenharmony_ci 411e1051a39Sopenharmony_ci /* Choose which callback will set the session ID */ 412e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(s->lock)) 413e1051a39Sopenharmony_ci return 0; 414e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock)) { 415e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->lock); 416e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, 417e1051a39Sopenharmony_ci SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); 418e1051a39Sopenharmony_ci return 0; 419e1051a39Sopenharmony_ci } 420e1051a39Sopenharmony_ci if (s->generate_session_id) 421e1051a39Sopenharmony_ci cb = s->generate_session_id; 422e1051a39Sopenharmony_ci else if (s->session_ctx->generate_session_id) 423e1051a39Sopenharmony_ci cb = s->session_ctx->generate_session_id; 424e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->session_ctx->lock); 425e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->lock); 426e1051a39Sopenharmony_ci /* Choose a session ID */ 427e1051a39Sopenharmony_ci memset(ss->session_id, 0, ss->session_id_length); 428e1051a39Sopenharmony_ci tmp = (int)ss->session_id_length; 429e1051a39Sopenharmony_ci if (!cb(s, ss->session_id, &tmp)) { 430e1051a39Sopenharmony_ci /* The callback failed */ 431e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, 432e1051a39Sopenharmony_ci SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); 433e1051a39Sopenharmony_ci return 0; 434e1051a39Sopenharmony_ci } 435e1051a39Sopenharmony_ci /* 436e1051a39Sopenharmony_ci * Don't allow the callback to set the session length to zero. nor 437e1051a39Sopenharmony_ci * set it higher than it was. 438e1051a39Sopenharmony_ci */ 439e1051a39Sopenharmony_ci if (tmp == 0 || tmp > ss->session_id_length) { 440e1051a39Sopenharmony_ci /* The callback set an illegal length */ 441e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, 442e1051a39Sopenharmony_ci SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); 443e1051a39Sopenharmony_ci return 0; 444e1051a39Sopenharmony_ci } 445e1051a39Sopenharmony_ci ss->session_id_length = tmp; 446e1051a39Sopenharmony_ci /* Finally, check for a conflict */ 447e1051a39Sopenharmony_ci if (SSL_has_matching_session_id(s, ss->session_id, 448e1051a39Sopenharmony_ci (unsigned int)ss->session_id_length)) { 449e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_SSL_SESSION_ID_CONFLICT); 450e1051a39Sopenharmony_ci return 0; 451e1051a39Sopenharmony_ci } 452e1051a39Sopenharmony_ci 453e1051a39Sopenharmony_ci return 1; 454e1051a39Sopenharmony_ci} 455e1051a39Sopenharmony_ci 456e1051a39Sopenharmony_ciint ssl_get_new_session(SSL *s, int session) 457e1051a39Sopenharmony_ci{ 458e1051a39Sopenharmony_ci /* This gets used by clients and servers. */ 459e1051a39Sopenharmony_ci 460e1051a39Sopenharmony_ci SSL_SESSION *ss = NULL; 461e1051a39Sopenharmony_ci 462e1051a39Sopenharmony_ci if ((ss = SSL_SESSION_new()) == NULL) { 463e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); 464e1051a39Sopenharmony_ci return 0; 465e1051a39Sopenharmony_ci } 466e1051a39Sopenharmony_ci 467e1051a39Sopenharmony_ci /* If the context has a default timeout, use it */ 468e1051a39Sopenharmony_ci if (s->session_ctx->session_timeout == 0) 469e1051a39Sopenharmony_ci ss->timeout = SSL_get_default_timeout(s); 470e1051a39Sopenharmony_ci else 471e1051a39Sopenharmony_ci ss->timeout = s->session_ctx->session_timeout; 472e1051a39Sopenharmony_ci ssl_session_calculate_timeout(ss); 473e1051a39Sopenharmony_ci 474e1051a39Sopenharmony_ci SSL_SESSION_free(s->session); 475e1051a39Sopenharmony_ci s->session = NULL; 476e1051a39Sopenharmony_ci 477e1051a39Sopenharmony_ci if (session) { 478e1051a39Sopenharmony_ci if (SSL_IS_TLS13(s)) { 479e1051a39Sopenharmony_ci /* 480e1051a39Sopenharmony_ci * We generate the session id while constructing the 481e1051a39Sopenharmony_ci * NewSessionTicket in TLSv1.3. 482e1051a39Sopenharmony_ci */ 483e1051a39Sopenharmony_ci ss->session_id_length = 0; 484e1051a39Sopenharmony_ci } else if (!ssl_generate_session_id(s, ss)) { 485e1051a39Sopenharmony_ci /* SSLfatal() already called */ 486e1051a39Sopenharmony_ci SSL_SESSION_free(ss); 487e1051a39Sopenharmony_ci return 0; 488e1051a39Sopenharmony_ci } 489e1051a39Sopenharmony_ci 490e1051a39Sopenharmony_ci } else { 491e1051a39Sopenharmony_ci ss->session_id_length = 0; 492e1051a39Sopenharmony_ci } 493e1051a39Sopenharmony_ci 494e1051a39Sopenharmony_ci if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { 495e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); 496e1051a39Sopenharmony_ci SSL_SESSION_free(ss); 497e1051a39Sopenharmony_ci return 0; 498e1051a39Sopenharmony_ci } 499e1051a39Sopenharmony_ci memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); 500e1051a39Sopenharmony_ci ss->sid_ctx_length = s->sid_ctx_length; 501e1051a39Sopenharmony_ci s->session = ss; 502e1051a39Sopenharmony_ci ss->ssl_version = s->version; 503e1051a39Sopenharmony_ci ss->verify_result = X509_V_OK; 504e1051a39Sopenharmony_ci 505e1051a39Sopenharmony_ci /* If client supports extended master secret set it in session */ 506e1051a39Sopenharmony_ci if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) 507e1051a39Sopenharmony_ci ss->flags |= SSL_SESS_FLAG_EXTMS; 508e1051a39Sopenharmony_ci 509e1051a39Sopenharmony_ci return 1; 510e1051a39Sopenharmony_ci} 511e1051a39Sopenharmony_ci 512e1051a39Sopenharmony_ciSSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, 513e1051a39Sopenharmony_ci size_t sess_id_len) 514e1051a39Sopenharmony_ci{ 515e1051a39Sopenharmony_ci SSL_SESSION *ret = NULL; 516e1051a39Sopenharmony_ci 517e1051a39Sopenharmony_ci if ((s->session_ctx->session_cache_mode 518e1051a39Sopenharmony_ci & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { 519e1051a39Sopenharmony_ci SSL_SESSION data; 520e1051a39Sopenharmony_ci 521e1051a39Sopenharmony_ci data.ssl_version = s->version; 522e1051a39Sopenharmony_ci if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH)) 523e1051a39Sopenharmony_ci return NULL; 524e1051a39Sopenharmony_ci 525e1051a39Sopenharmony_ci memcpy(data.session_id, sess_id, sess_id_len); 526e1051a39Sopenharmony_ci data.session_id_length = sess_id_len; 527e1051a39Sopenharmony_ci 528e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(s->session_ctx->lock)) 529e1051a39Sopenharmony_ci return NULL; 530e1051a39Sopenharmony_ci ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); 531e1051a39Sopenharmony_ci if (ret != NULL) { 532e1051a39Sopenharmony_ci /* don't allow other threads to steal it: */ 533e1051a39Sopenharmony_ci SSL_SESSION_up_ref(ret); 534e1051a39Sopenharmony_ci } 535e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->session_ctx->lock); 536e1051a39Sopenharmony_ci if (ret == NULL) 537e1051a39Sopenharmony_ci ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_miss); 538e1051a39Sopenharmony_ci } 539e1051a39Sopenharmony_ci 540e1051a39Sopenharmony_ci if (ret == NULL && s->session_ctx->get_session_cb != NULL) { 541e1051a39Sopenharmony_ci int copy = 1; 542e1051a39Sopenharmony_ci 543e1051a39Sopenharmony_ci ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); 544e1051a39Sopenharmony_ci 545e1051a39Sopenharmony_ci if (ret != NULL) { 546e1051a39Sopenharmony_ci if (ret->not_resumable) { 547e1051a39Sopenharmony_ci /* If its not resumable then ignore this session */ 548e1051a39Sopenharmony_ci if (!copy) 549e1051a39Sopenharmony_ci SSL_SESSION_free(ret); 550e1051a39Sopenharmony_ci return NULL; 551e1051a39Sopenharmony_ci } 552e1051a39Sopenharmony_ci ssl_tsan_counter(s->session_ctx, 553e1051a39Sopenharmony_ci &s->session_ctx->stats.sess_cb_hit); 554e1051a39Sopenharmony_ci 555e1051a39Sopenharmony_ci /* 556e1051a39Sopenharmony_ci * Increment reference count now if the session callback asks us 557e1051a39Sopenharmony_ci * to do so (note that if the session structures returned by the 558e1051a39Sopenharmony_ci * callback are shared between threads, it must handle the 559e1051a39Sopenharmony_ci * reference count itself [i.e. copy == 0], or things won't be 560e1051a39Sopenharmony_ci * thread-safe). 561e1051a39Sopenharmony_ci */ 562e1051a39Sopenharmony_ci if (copy) 563e1051a39Sopenharmony_ci SSL_SESSION_up_ref(ret); 564e1051a39Sopenharmony_ci 565e1051a39Sopenharmony_ci /* 566e1051a39Sopenharmony_ci * Add the externally cached session to the internal cache as 567e1051a39Sopenharmony_ci * well if and only if we are supposed to. 568e1051a39Sopenharmony_ci */ 569e1051a39Sopenharmony_ci if ((s->session_ctx->session_cache_mode & 570e1051a39Sopenharmony_ci SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { 571e1051a39Sopenharmony_ci /* 572e1051a39Sopenharmony_ci * Either return value of SSL_CTX_add_session should not 573e1051a39Sopenharmony_ci * interrupt the session resumption process. The return 574e1051a39Sopenharmony_ci * value is intentionally ignored. 575e1051a39Sopenharmony_ci */ 576e1051a39Sopenharmony_ci (void)SSL_CTX_add_session(s->session_ctx, ret); 577e1051a39Sopenharmony_ci } 578e1051a39Sopenharmony_ci } 579e1051a39Sopenharmony_ci } 580e1051a39Sopenharmony_ci 581e1051a39Sopenharmony_ci return ret; 582e1051a39Sopenharmony_ci} 583e1051a39Sopenharmony_ci 584e1051a39Sopenharmony_ci/*- 585e1051a39Sopenharmony_ci * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this 586e1051a39Sopenharmony_ci * connection. It is only called by servers. 587e1051a39Sopenharmony_ci * 588e1051a39Sopenharmony_ci * hello: The parsed ClientHello data 589e1051a39Sopenharmony_ci * 590e1051a39Sopenharmony_ci * Returns: 591e1051a39Sopenharmony_ci * -1: fatal error 592e1051a39Sopenharmony_ci * 0: no session found 593e1051a39Sopenharmony_ci * 1: a session may have been found. 594e1051a39Sopenharmony_ci * 595e1051a39Sopenharmony_ci * Side effects: 596e1051a39Sopenharmony_ci * - If a session is found then s->session is pointed at it (after freeing an 597e1051a39Sopenharmony_ci * existing session if need be) and s->verify_result is set from the session. 598e1051a39Sopenharmony_ci * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 599e1051a39Sopenharmony_ci * if the server should issue a new session ticket (to 0 otherwise). 600e1051a39Sopenharmony_ci */ 601e1051a39Sopenharmony_ciint ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) 602e1051a39Sopenharmony_ci{ 603e1051a39Sopenharmony_ci /* This is used only by servers. */ 604e1051a39Sopenharmony_ci 605e1051a39Sopenharmony_ci SSL_SESSION *ret = NULL; 606e1051a39Sopenharmony_ci int fatal = 0; 607e1051a39Sopenharmony_ci int try_session_cache = 0; 608e1051a39Sopenharmony_ci SSL_TICKET_STATUS r; 609e1051a39Sopenharmony_ci 610e1051a39Sopenharmony_ci if (SSL_IS_TLS13(s)) { 611e1051a39Sopenharmony_ci /* 612e1051a39Sopenharmony_ci * By default we will send a new ticket. This can be overridden in the 613e1051a39Sopenharmony_ci * ticket processing. 614e1051a39Sopenharmony_ci */ 615e1051a39Sopenharmony_ci s->ext.ticket_expected = 1; 616e1051a39Sopenharmony_ci if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, 617e1051a39Sopenharmony_ci SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, 618e1051a39Sopenharmony_ci NULL, 0) 619e1051a39Sopenharmony_ci || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, 620e1051a39Sopenharmony_ci hello->pre_proc_exts, NULL, 0)) 621e1051a39Sopenharmony_ci return -1; 622e1051a39Sopenharmony_ci 623e1051a39Sopenharmony_ci ret = s->session; 624e1051a39Sopenharmony_ci } else { 625e1051a39Sopenharmony_ci /* sets s->ext.ticket_expected */ 626e1051a39Sopenharmony_ci r = tls_get_ticket_from_client(s, hello, &ret); 627e1051a39Sopenharmony_ci switch (r) { 628e1051a39Sopenharmony_ci case SSL_TICKET_FATAL_ERR_MALLOC: 629e1051a39Sopenharmony_ci case SSL_TICKET_FATAL_ERR_OTHER: 630e1051a39Sopenharmony_ci fatal = 1; 631e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); 632e1051a39Sopenharmony_ci goto err; 633e1051a39Sopenharmony_ci case SSL_TICKET_NONE: 634e1051a39Sopenharmony_ci case SSL_TICKET_EMPTY: 635e1051a39Sopenharmony_ci if (hello->session_id_len > 0) { 636e1051a39Sopenharmony_ci try_session_cache = 1; 637e1051a39Sopenharmony_ci ret = lookup_sess_in_cache(s, hello->session_id, 638e1051a39Sopenharmony_ci hello->session_id_len); 639e1051a39Sopenharmony_ci } 640e1051a39Sopenharmony_ci break; 641e1051a39Sopenharmony_ci case SSL_TICKET_NO_DECRYPT: 642e1051a39Sopenharmony_ci case SSL_TICKET_SUCCESS: 643e1051a39Sopenharmony_ci case SSL_TICKET_SUCCESS_RENEW: 644e1051a39Sopenharmony_ci break; 645e1051a39Sopenharmony_ci } 646e1051a39Sopenharmony_ci } 647e1051a39Sopenharmony_ci 648e1051a39Sopenharmony_ci if (ret == NULL) 649e1051a39Sopenharmony_ci goto err; 650e1051a39Sopenharmony_ci 651e1051a39Sopenharmony_ci /* Now ret is non-NULL and we own one of its reference counts. */ 652e1051a39Sopenharmony_ci 653e1051a39Sopenharmony_ci /* Check TLS version consistency */ 654e1051a39Sopenharmony_ci if (ret->ssl_version != s->version) 655e1051a39Sopenharmony_ci goto err; 656e1051a39Sopenharmony_ci 657e1051a39Sopenharmony_ci if (ret->sid_ctx_length != s->sid_ctx_length 658e1051a39Sopenharmony_ci || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { 659e1051a39Sopenharmony_ci /* 660e1051a39Sopenharmony_ci * We have the session requested by the client, but we don't want to 661e1051a39Sopenharmony_ci * use it in this context. 662e1051a39Sopenharmony_ci */ 663e1051a39Sopenharmony_ci goto err; /* treat like cache miss */ 664e1051a39Sopenharmony_ci } 665e1051a39Sopenharmony_ci 666e1051a39Sopenharmony_ci if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { 667e1051a39Sopenharmony_ci /* 668e1051a39Sopenharmony_ci * We can't be sure if this session is being used out of context, 669e1051a39Sopenharmony_ci * which is especially important for SSL_VERIFY_PEER. The application 670e1051a39Sopenharmony_ci * should have used SSL[_CTX]_set_session_id_context. For this error 671e1051a39Sopenharmony_ci * case, we generate an error instead of treating the event like a 672e1051a39Sopenharmony_ci * cache miss (otherwise it would be easy for applications to 673e1051a39Sopenharmony_ci * effectively disable the session cache by accident without anyone 674e1051a39Sopenharmony_ci * noticing). 675e1051a39Sopenharmony_ci */ 676e1051a39Sopenharmony_ci 677e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_INTERNAL_ERROR, 678e1051a39Sopenharmony_ci SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); 679e1051a39Sopenharmony_ci fatal = 1; 680e1051a39Sopenharmony_ci goto err; 681e1051a39Sopenharmony_ci } 682e1051a39Sopenharmony_ci 683e1051a39Sopenharmony_ci if (sess_timedout(time(NULL), ret)) { 684e1051a39Sopenharmony_ci ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_timeout); 685e1051a39Sopenharmony_ci if (try_session_cache) { 686e1051a39Sopenharmony_ci /* session was from the cache, so remove it */ 687e1051a39Sopenharmony_ci SSL_CTX_remove_session(s->session_ctx, ret); 688e1051a39Sopenharmony_ci } 689e1051a39Sopenharmony_ci goto err; 690e1051a39Sopenharmony_ci } 691e1051a39Sopenharmony_ci 692e1051a39Sopenharmony_ci /* Check extended master secret extension consistency */ 693e1051a39Sopenharmony_ci if (ret->flags & SSL_SESS_FLAG_EXTMS) { 694e1051a39Sopenharmony_ci /* If old session includes extms, but new does not: abort handshake */ 695e1051a39Sopenharmony_ci if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)) { 696e1051a39Sopenharmony_ci SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_INCONSISTENT_EXTMS); 697e1051a39Sopenharmony_ci fatal = 1; 698e1051a39Sopenharmony_ci goto err; 699e1051a39Sopenharmony_ci } 700e1051a39Sopenharmony_ci } else if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) { 701e1051a39Sopenharmony_ci /* If new session includes extms, but old does not: do not resume */ 702e1051a39Sopenharmony_ci goto err; 703e1051a39Sopenharmony_ci } 704e1051a39Sopenharmony_ci 705e1051a39Sopenharmony_ci if (!SSL_IS_TLS13(s)) { 706e1051a39Sopenharmony_ci /* We already did this for TLS1.3 */ 707e1051a39Sopenharmony_ci SSL_SESSION_free(s->session); 708e1051a39Sopenharmony_ci s->session = ret; 709e1051a39Sopenharmony_ci } 710e1051a39Sopenharmony_ci 711e1051a39Sopenharmony_ci ssl_tsan_counter(s->session_ctx, &s->session_ctx->stats.sess_hit); 712e1051a39Sopenharmony_ci s->verify_result = s->session->verify_result; 713e1051a39Sopenharmony_ci return 1; 714e1051a39Sopenharmony_ci 715e1051a39Sopenharmony_ci err: 716e1051a39Sopenharmony_ci if (ret != NULL) { 717e1051a39Sopenharmony_ci SSL_SESSION_free(ret); 718e1051a39Sopenharmony_ci /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ 719e1051a39Sopenharmony_ci if (SSL_IS_TLS13(s)) 720e1051a39Sopenharmony_ci s->session = NULL; 721e1051a39Sopenharmony_ci 722e1051a39Sopenharmony_ci if (!try_session_cache) { 723e1051a39Sopenharmony_ci /* 724e1051a39Sopenharmony_ci * The session was from a ticket, so we should issue a ticket for 725e1051a39Sopenharmony_ci * the new session 726e1051a39Sopenharmony_ci */ 727e1051a39Sopenharmony_ci s->ext.ticket_expected = 1; 728e1051a39Sopenharmony_ci } 729e1051a39Sopenharmony_ci } 730e1051a39Sopenharmony_ci if (fatal) 731e1051a39Sopenharmony_ci return -1; 732e1051a39Sopenharmony_ci 733e1051a39Sopenharmony_ci return 0; 734e1051a39Sopenharmony_ci} 735e1051a39Sopenharmony_ci 736e1051a39Sopenharmony_ciint SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) 737e1051a39Sopenharmony_ci{ 738e1051a39Sopenharmony_ci int ret = 0; 739e1051a39Sopenharmony_ci SSL_SESSION *s; 740e1051a39Sopenharmony_ci 741e1051a39Sopenharmony_ci /* 742e1051a39Sopenharmony_ci * add just 1 reference count for the SSL_CTX's session cache even though 743e1051a39Sopenharmony_ci * it has two ways of access: each session is in a doubly linked list and 744e1051a39Sopenharmony_ci * an lhash 745e1051a39Sopenharmony_ci */ 746e1051a39Sopenharmony_ci SSL_SESSION_up_ref(c); 747e1051a39Sopenharmony_ci /* 748e1051a39Sopenharmony_ci * if session c is in already in cache, we take back the increment later 749e1051a39Sopenharmony_ci */ 750e1051a39Sopenharmony_ci 751e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(ctx->lock)) { 752e1051a39Sopenharmony_ci SSL_SESSION_free(c); 753e1051a39Sopenharmony_ci return 0; 754e1051a39Sopenharmony_ci } 755e1051a39Sopenharmony_ci s = lh_SSL_SESSION_insert(ctx->sessions, c); 756e1051a39Sopenharmony_ci 757e1051a39Sopenharmony_ci /* 758e1051a39Sopenharmony_ci * s != NULL iff we already had a session with the given PID. In this 759e1051a39Sopenharmony_ci * case, s == c should hold (then we did not really modify 760e1051a39Sopenharmony_ci * ctx->sessions), or we're in trouble. 761e1051a39Sopenharmony_ci */ 762e1051a39Sopenharmony_ci if (s != NULL && s != c) { 763e1051a39Sopenharmony_ci /* We *are* in trouble ... */ 764e1051a39Sopenharmony_ci SSL_SESSION_list_remove(ctx, s); 765e1051a39Sopenharmony_ci SSL_SESSION_free(s); 766e1051a39Sopenharmony_ci /* 767e1051a39Sopenharmony_ci * ... so pretend the other session did not exist in cache (we cannot 768e1051a39Sopenharmony_ci * handle two SSL_SESSION structures with identical session ID in the 769e1051a39Sopenharmony_ci * same cache, which could happen e.g. when two threads concurrently 770e1051a39Sopenharmony_ci * obtain the same session from an external cache) 771e1051a39Sopenharmony_ci */ 772e1051a39Sopenharmony_ci s = NULL; 773e1051a39Sopenharmony_ci } else if (s == NULL && 774e1051a39Sopenharmony_ci lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { 775e1051a39Sopenharmony_ci /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ 776e1051a39Sopenharmony_ci 777e1051a39Sopenharmony_ci /* 778e1051a39Sopenharmony_ci * ... so take back the extra reference and also don't add 779e1051a39Sopenharmony_ci * the session to the SSL_SESSION_list at this time 780e1051a39Sopenharmony_ci */ 781e1051a39Sopenharmony_ci s = c; 782e1051a39Sopenharmony_ci } 783e1051a39Sopenharmony_ci 784e1051a39Sopenharmony_ci /* Adjust last used time, and add back into the cache at the appropriate spot */ 785e1051a39Sopenharmony_ci if (ctx->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) { 786e1051a39Sopenharmony_ci c->time = time(NULL); 787e1051a39Sopenharmony_ci ssl_session_calculate_timeout(c); 788e1051a39Sopenharmony_ci } 789e1051a39Sopenharmony_ci 790e1051a39Sopenharmony_ci if (s == NULL) { 791e1051a39Sopenharmony_ci /* 792e1051a39Sopenharmony_ci * new cache entry -- remove old ones if cache has become too large 793e1051a39Sopenharmony_ci * delete cache entry *before* add, so we don't remove the one we're adding! 794e1051a39Sopenharmony_ci */ 795e1051a39Sopenharmony_ci 796e1051a39Sopenharmony_ci ret = 1; 797e1051a39Sopenharmony_ci 798e1051a39Sopenharmony_ci if (SSL_CTX_sess_get_cache_size(ctx) > 0) { 799e1051a39Sopenharmony_ci while (SSL_CTX_sess_number(ctx) >= SSL_CTX_sess_get_cache_size(ctx)) { 800e1051a39Sopenharmony_ci if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) 801e1051a39Sopenharmony_ci break; 802e1051a39Sopenharmony_ci else 803e1051a39Sopenharmony_ci ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full); 804e1051a39Sopenharmony_ci } 805e1051a39Sopenharmony_ci } 806e1051a39Sopenharmony_ci } 807e1051a39Sopenharmony_ci 808e1051a39Sopenharmony_ci SSL_SESSION_list_add(ctx, c); 809e1051a39Sopenharmony_ci 810e1051a39Sopenharmony_ci if (s != NULL) { 811e1051a39Sopenharmony_ci /* 812e1051a39Sopenharmony_ci * existing cache entry -- decrement previously incremented reference 813e1051a39Sopenharmony_ci * count because it already takes into account the cache 814e1051a39Sopenharmony_ci */ 815e1051a39Sopenharmony_ci 816e1051a39Sopenharmony_ci SSL_SESSION_free(s); /* s == c */ 817e1051a39Sopenharmony_ci ret = 0; 818e1051a39Sopenharmony_ci } 819e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 820e1051a39Sopenharmony_ci return ret; 821e1051a39Sopenharmony_ci} 822e1051a39Sopenharmony_ci 823e1051a39Sopenharmony_ciint SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) 824e1051a39Sopenharmony_ci{ 825e1051a39Sopenharmony_ci return remove_session_lock(ctx, c, 1); 826e1051a39Sopenharmony_ci} 827e1051a39Sopenharmony_ci 828e1051a39Sopenharmony_cistatic int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) 829e1051a39Sopenharmony_ci{ 830e1051a39Sopenharmony_ci SSL_SESSION *r; 831e1051a39Sopenharmony_ci int ret = 0; 832e1051a39Sopenharmony_ci 833e1051a39Sopenharmony_ci if ((c != NULL) && (c->session_id_length != 0)) { 834e1051a39Sopenharmony_ci if (lck) { 835e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(ctx->lock)) 836e1051a39Sopenharmony_ci return 0; 837e1051a39Sopenharmony_ci } 838e1051a39Sopenharmony_ci if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { 839e1051a39Sopenharmony_ci ret = 1; 840e1051a39Sopenharmony_ci r = lh_SSL_SESSION_delete(ctx->sessions, r); 841e1051a39Sopenharmony_ci SSL_SESSION_list_remove(ctx, r); 842e1051a39Sopenharmony_ci } 843e1051a39Sopenharmony_ci c->not_resumable = 1; 844e1051a39Sopenharmony_ci 845e1051a39Sopenharmony_ci if (lck) 846e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 847e1051a39Sopenharmony_ci 848e1051a39Sopenharmony_ci if (ctx->remove_session_cb != NULL) 849e1051a39Sopenharmony_ci ctx->remove_session_cb(ctx, c); 850e1051a39Sopenharmony_ci 851e1051a39Sopenharmony_ci if (ret) 852e1051a39Sopenharmony_ci SSL_SESSION_free(r); 853e1051a39Sopenharmony_ci } 854e1051a39Sopenharmony_ci return ret; 855e1051a39Sopenharmony_ci} 856e1051a39Sopenharmony_ci 857e1051a39Sopenharmony_civoid SSL_SESSION_free(SSL_SESSION *ss) 858e1051a39Sopenharmony_ci{ 859e1051a39Sopenharmony_ci int i; 860e1051a39Sopenharmony_ci 861e1051a39Sopenharmony_ci if (ss == NULL) 862e1051a39Sopenharmony_ci return; 863e1051a39Sopenharmony_ci CRYPTO_DOWN_REF(&ss->references, &i, ss->lock); 864e1051a39Sopenharmony_ci REF_PRINT_COUNT("SSL_SESSION", ss); 865e1051a39Sopenharmony_ci if (i > 0) 866e1051a39Sopenharmony_ci return; 867e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 0); 868e1051a39Sopenharmony_ci 869e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); 870e1051a39Sopenharmony_ci 871e1051a39Sopenharmony_ci OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key)); 872e1051a39Sopenharmony_ci OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id)); 873e1051a39Sopenharmony_ci X509_free(ss->peer); 874e1051a39Sopenharmony_ci sk_X509_pop_free(ss->peer_chain, X509_free); 875e1051a39Sopenharmony_ci OPENSSL_free(ss->ext.hostname); 876e1051a39Sopenharmony_ci OPENSSL_free(ss->ext.tick); 877e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_PSK 878e1051a39Sopenharmony_ci OPENSSL_free(ss->psk_identity_hint); 879e1051a39Sopenharmony_ci OPENSSL_free(ss->psk_identity); 880e1051a39Sopenharmony_ci#endif 881e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SRP 882e1051a39Sopenharmony_ci OPENSSL_free(ss->srp_username); 883e1051a39Sopenharmony_ci#endif 884e1051a39Sopenharmony_ci OPENSSL_free(ss->ext.alpn_selected); 885e1051a39Sopenharmony_ci OPENSSL_free(ss->ticket_appdata); 886e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(ss->lock); 887e1051a39Sopenharmony_ci OPENSSL_clear_free(ss, sizeof(*ss)); 888e1051a39Sopenharmony_ci} 889e1051a39Sopenharmony_ci 890e1051a39Sopenharmony_ciint SSL_SESSION_up_ref(SSL_SESSION *ss) 891e1051a39Sopenharmony_ci{ 892e1051a39Sopenharmony_ci int i; 893e1051a39Sopenharmony_ci 894e1051a39Sopenharmony_ci if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0) 895e1051a39Sopenharmony_ci return 0; 896e1051a39Sopenharmony_ci 897e1051a39Sopenharmony_ci REF_PRINT_COUNT("SSL_SESSION", ss); 898e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 2); 899e1051a39Sopenharmony_ci return ((i > 1) ? 1 : 0); 900e1051a39Sopenharmony_ci} 901e1051a39Sopenharmony_ci 902e1051a39Sopenharmony_ciint SSL_set_session(SSL *s, SSL_SESSION *session) 903e1051a39Sopenharmony_ci{ 904e1051a39Sopenharmony_ci ssl_clear_bad_session(s); 905e1051a39Sopenharmony_ci if (s->ctx->method != s->method) { 906e1051a39Sopenharmony_ci if (!SSL_set_ssl_method(s, s->ctx->method)) 907e1051a39Sopenharmony_ci return 0; 908e1051a39Sopenharmony_ci } 909e1051a39Sopenharmony_ci 910e1051a39Sopenharmony_ci if (session != NULL) { 911e1051a39Sopenharmony_ci SSL_SESSION_up_ref(session); 912e1051a39Sopenharmony_ci s->verify_result = session->verify_result; 913e1051a39Sopenharmony_ci } 914e1051a39Sopenharmony_ci SSL_SESSION_free(s->session); 915e1051a39Sopenharmony_ci s->session = session; 916e1051a39Sopenharmony_ci 917e1051a39Sopenharmony_ci return 1; 918e1051a39Sopenharmony_ci} 919e1051a39Sopenharmony_ci 920e1051a39Sopenharmony_ciint SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, 921e1051a39Sopenharmony_ci unsigned int sid_len) 922e1051a39Sopenharmony_ci{ 923e1051a39Sopenharmony_ci if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { 924e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_TOO_LONG); 925e1051a39Sopenharmony_ci return 0; 926e1051a39Sopenharmony_ci } 927e1051a39Sopenharmony_ci s->session_id_length = sid_len; 928e1051a39Sopenharmony_ci if (sid != s->session_id) 929e1051a39Sopenharmony_ci memcpy(s->session_id, sid, sid_len); 930e1051a39Sopenharmony_ci return 1; 931e1051a39Sopenharmony_ci} 932e1051a39Sopenharmony_ci 933e1051a39Sopenharmony_cilong SSL_SESSION_set_timeout(SSL_SESSION *s, long t) 934e1051a39Sopenharmony_ci{ 935e1051a39Sopenharmony_ci time_t new_timeout = (time_t)t; 936e1051a39Sopenharmony_ci 937e1051a39Sopenharmony_ci if (s == NULL || t < 0) 938e1051a39Sopenharmony_ci return 0; 939e1051a39Sopenharmony_ci if (s->owner != NULL) { 940e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(s->owner->lock)) 941e1051a39Sopenharmony_ci return 0; 942e1051a39Sopenharmony_ci s->timeout = new_timeout; 943e1051a39Sopenharmony_ci ssl_session_calculate_timeout(s); 944e1051a39Sopenharmony_ci SSL_SESSION_list_add(s->owner, s); 945e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->owner->lock); 946e1051a39Sopenharmony_ci } else { 947e1051a39Sopenharmony_ci s->timeout = new_timeout; 948e1051a39Sopenharmony_ci ssl_session_calculate_timeout(s); 949e1051a39Sopenharmony_ci } 950e1051a39Sopenharmony_ci return 1; 951e1051a39Sopenharmony_ci} 952e1051a39Sopenharmony_ci 953e1051a39Sopenharmony_cilong SSL_SESSION_get_timeout(const SSL_SESSION *s) 954e1051a39Sopenharmony_ci{ 955e1051a39Sopenharmony_ci if (s == NULL) 956e1051a39Sopenharmony_ci return 0; 957e1051a39Sopenharmony_ci return (long)s->timeout; 958e1051a39Sopenharmony_ci} 959e1051a39Sopenharmony_ci 960e1051a39Sopenharmony_cilong SSL_SESSION_get_time(const SSL_SESSION *s) 961e1051a39Sopenharmony_ci{ 962e1051a39Sopenharmony_ci if (s == NULL) 963e1051a39Sopenharmony_ci return 0; 964e1051a39Sopenharmony_ci return (long)s->time; 965e1051a39Sopenharmony_ci} 966e1051a39Sopenharmony_ci 967e1051a39Sopenharmony_cilong SSL_SESSION_set_time(SSL_SESSION *s, long t) 968e1051a39Sopenharmony_ci{ 969e1051a39Sopenharmony_ci time_t new_time = (time_t)t; 970e1051a39Sopenharmony_ci 971e1051a39Sopenharmony_ci if (s == NULL) 972e1051a39Sopenharmony_ci return 0; 973e1051a39Sopenharmony_ci if (s->owner != NULL) { 974e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(s->owner->lock)) 975e1051a39Sopenharmony_ci return 0; 976e1051a39Sopenharmony_ci s->time = new_time; 977e1051a39Sopenharmony_ci ssl_session_calculate_timeout(s); 978e1051a39Sopenharmony_ci SSL_SESSION_list_add(s->owner, s); 979e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->owner->lock); 980e1051a39Sopenharmony_ci } else { 981e1051a39Sopenharmony_ci s->time = new_time; 982e1051a39Sopenharmony_ci ssl_session_calculate_timeout(s); 983e1051a39Sopenharmony_ci } 984e1051a39Sopenharmony_ci return t; 985e1051a39Sopenharmony_ci} 986e1051a39Sopenharmony_ci 987e1051a39Sopenharmony_ciint SSL_SESSION_get_protocol_version(const SSL_SESSION *s) 988e1051a39Sopenharmony_ci{ 989e1051a39Sopenharmony_ci return s->ssl_version; 990e1051a39Sopenharmony_ci} 991e1051a39Sopenharmony_ci 992e1051a39Sopenharmony_ciint SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version) 993e1051a39Sopenharmony_ci{ 994e1051a39Sopenharmony_ci s->ssl_version = version; 995e1051a39Sopenharmony_ci return 1; 996e1051a39Sopenharmony_ci} 997e1051a39Sopenharmony_ci 998e1051a39Sopenharmony_ciconst SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s) 999e1051a39Sopenharmony_ci{ 1000e1051a39Sopenharmony_ci return s->cipher; 1001e1051a39Sopenharmony_ci} 1002e1051a39Sopenharmony_ci 1003e1051a39Sopenharmony_ciint SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher) 1004e1051a39Sopenharmony_ci{ 1005e1051a39Sopenharmony_ci s->cipher = cipher; 1006e1051a39Sopenharmony_ci return 1; 1007e1051a39Sopenharmony_ci} 1008e1051a39Sopenharmony_ci 1009e1051a39Sopenharmony_ciconst char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) 1010e1051a39Sopenharmony_ci{ 1011e1051a39Sopenharmony_ci return s->ext.hostname; 1012e1051a39Sopenharmony_ci} 1013e1051a39Sopenharmony_ci 1014e1051a39Sopenharmony_ciint SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname) 1015e1051a39Sopenharmony_ci{ 1016e1051a39Sopenharmony_ci OPENSSL_free(s->ext.hostname); 1017e1051a39Sopenharmony_ci if (hostname == NULL) { 1018e1051a39Sopenharmony_ci s->ext.hostname = NULL; 1019e1051a39Sopenharmony_ci return 1; 1020e1051a39Sopenharmony_ci } 1021e1051a39Sopenharmony_ci s->ext.hostname = OPENSSL_strdup(hostname); 1022e1051a39Sopenharmony_ci 1023e1051a39Sopenharmony_ci return s->ext.hostname != NULL; 1024e1051a39Sopenharmony_ci} 1025e1051a39Sopenharmony_ci 1026e1051a39Sopenharmony_ciint SSL_SESSION_has_ticket(const SSL_SESSION *s) 1027e1051a39Sopenharmony_ci{ 1028e1051a39Sopenharmony_ci return (s->ext.ticklen > 0) ? 1 : 0; 1029e1051a39Sopenharmony_ci} 1030e1051a39Sopenharmony_ci 1031e1051a39Sopenharmony_ciunsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) 1032e1051a39Sopenharmony_ci{ 1033e1051a39Sopenharmony_ci return s->ext.tick_lifetime_hint; 1034e1051a39Sopenharmony_ci} 1035e1051a39Sopenharmony_ci 1036e1051a39Sopenharmony_civoid SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, 1037e1051a39Sopenharmony_ci size_t *len) 1038e1051a39Sopenharmony_ci{ 1039e1051a39Sopenharmony_ci *len = s->ext.ticklen; 1040e1051a39Sopenharmony_ci if (tick != NULL) 1041e1051a39Sopenharmony_ci *tick = s->ext.tick; 1042e1051a39Sopenharmony_ci} 1043e1051a39Sopenharmony_ci 1044e1051a39Sopenharmony_ciuint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) 1045e1051a39Sopenharmony_ci{ 1046e1051a39Sopenharmony_ci return s->ext.max_early_data; 1047e1051a39Sopenharmony_ci} 1048e1051a39Sopenharmony_ci 1049e1051a39Sopenharmony_ciint SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) 1050e1051a39Sopenharmony_ci{ 1051e1051a39Sopenharmony_ci s->ext.max_early_data = max_early_data; 1052e1051a39Sopenharmony_ci 1053e1051a39Sopenharmony_ci return 1; 1054e1051a39Sopenharmony_ci} 1055e1051a39Sopenharmony_ci 1056e1051a39Sopenharmony_civoid SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, 1057e1051a39Sopenharmony_ci const unsigned char **alpn, 1058e1051a39Sopenharmony_ci size_t *len) 1059e1051a39Sopenharmony_ci{ 1060e1051a39Sopenharmony_ci *alpn = s->ext.alpn_selected; 1061e1051a39Sopenharmony_ci *len = s->ext.alpn_selected_len; 1062e1051a39Sopenharmony_ci} 1063e1051a39Sopenharmony_ci 1064e1051a39Sopenharmony_ciint SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn, 1065e1051a39Sopenharmony_ci size_t len) 1066e1051a39Sopenharmony_ci{ 1067e1051a39Sopenharmony_ci OPENSSL_free(s->ext.alpn_selected); 1068e1051a39Sopenharmony_ci if (alpn == NULL || len == 0) { 1069e1051a39Sopenharmony_ci s->ext.alpn_selected = NULL; 1070e1051a39Sopenharmony_ci s->ext.alpn_selected_len = 0; 1071e1051a39Sopenharmony_ci return 1; 1072e1051a39Sopenharmony_ci } 1073e1051a39Sopenharmony_ci s->ext.alpn_selected = OPENSSL_memdup(alpn, len); 1074e1051a39Sopenharmony_ci if (s->ext.alpn_selected == NULL) { 1075e1051a39Sopenharmony_ci s->ext.alpn_selected_len = 0; 1076e1051a39Sopenharmony_ci return 0; 1077e1051a39Sopenharmony_ci } 1078e1051a39Sopenharmony_ci s->ext.alpn_selected_len = len; 1079e1051a39Sopenharmony_ci 1080e1051a39Sopenharmony_ci return 1; 1081e1051a39Sopenharmony_ci} 1082e1051a39Sopenharmony_ci 1083e1051a39Sopenharmony_ciX509 *SSL_SESSION_get0_peer(SSL_SESSION *s) 1084e1051a39Sopenharmony_ci{ 1085e1051a39Sopenharmony_ci return s->peer; 1086e1051a39Sopenharmony_ci} 1087e1051a39Sopenharmony_ci 1088e1051a39Sopenharmony_ciint SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, 1089e1051a39Sopenharmony_ci unsigned int sid_ctx_len) 1090e1051a39Sopenharmony_ci{ 1091e1051a39Sopenharmony_ci if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { 1092e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); 1093e1051a39Sopenharmony_ci return 0; 1094e1051a39Sopenharmony_ci } 1095e1051a39Sopenharmony_ci s->sid_ctx_length = sid_ctx_len; 1096e1051a39Sopenharmony_ci if (sid_ctx != s->sid_ctx) 1097e1051a39Sopenharmony_ci memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); 1098e1051a39Sopenharmony_ci 1099e1051a39Sopenharmony_ci return 1; 1100e1051a39Sopenharmony_ci} 1101e1051a39Sopenharmony_ci 1102e1051a39Sopenharmony_ciint SSL_SESSION_is_resumable(const SSL_SESSION *s) 1103e1051a39Sopenharmony_ci{ 1104e1051a39Sopenharmony_ci /* 1105e1051a39Sopenharmony_ci * In the case of EAP-FAST, we can have a pre-shared "ticket" without a 1106e1051a39Sopenharmony_ci * session ID. 1107e1051a39Sopenharmony_ci */ 1108e1051a39Sopenharmony_ci return !s->not_resumable 1109e1051a39Sopenharmony_ci && (s->session_id_length > 0 || s->ext.ticklen > 0); 1110e1051a39Sopenharmony_ci} 1111e1051a39Sopenharmony_ci 1112e1051a39Sopenharmony_cilong SSL_CTX_set_timeout(SSL_CTX *s, long t) 1113e1051a39Sopenharmony_ci{ 1114e1051a39Sopenharmony_ci long l; 1115e1051a39Sopenharmony_ci if (s == NULL) 1116e1051a39Sopenharmony_ci return 0; 1117e1051a39Sopenharmony_ci l = s->session_timeout; 1118e1051a39Sopenharmony_ci s->session_timeout = t; 1119e1051a39Sopenharmony_ci return l; 1120e1051a39Sopenharmony_ci} 1121e1051a39Sopenharmony_ci 1122e1051a39Sopenharmony_cilong SSL_CTX_get_timeout(const SSL_CTX *s) 1123e1051a39Sopenharmony_ci{ 1124e1051a39Sopenharmony_ci if (s == NULL) 1125e1051a39Sopenharmony_ci return 0; 1126e1051a39Sopenharmony_ci return s->session_timeout; 1127e1051a39Sopenharmony_ci} 1128e1051a39Sopenharmony_ci 1129e1051a39Sopenharmony_ciint SSL_set_session_secret_cb(SSL *s, 1130e1051a39Sopenharmony_ci tls_session_secret_cb_fn tls_session_secret_cb, 1131e1051a39Sopenharmony_ci void *arg) 1132e1051a39Sopenharmony_ci{ 1133e1051a39Sopenharmony_ci if (s == NULL) 1134e1051a39Sopenharmony_ci return 0; 1135e1051a39Sopenharmony_ci s->ext.session_secret_cb = tls_session_secret_cb; 1136e1051a39Sopenharmony_ci s->ext.session_secret_cb_arg = arg; 1137e1051a39Sopenharmony_ci return 1; 1138e1051a39Sopenharmony_ci} 1139e1051a39Sopenharmony_ci 1140e1051a39Sopenharmony_ciint SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, 1141e1051a39Sopenharmony_ci void *arg) 1142e1051a39Sopenharmony_ci{ 1143e1051a39Sopenharmony_ci if (s == NULL) 1144e1051a39Sopenharmony_ci return 0; 1145e1051a39Sopenharmony_ci s->ext.session_ticket_cb = cb; 1146e1051a39Sopenharmony_ci s->ext.session_ticket_cb_arg = arg; 1147e1051a39Sopenharmony_ci return 1; 1148e1051a39Sopenharmony_ci} 1149e1051a39Sopenharmony_ci 1150e1051a39Sopenharmony_ciint SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) 1151e1051a39Sopenharmony_ci{ 1152e1051a39Sopenharmony_ci if (s->version >= TLS1_VERSION) { 1153e1051a39Sopenharmony_ci OPENSSL_free(s->ext.session_ticket); 1154e1051a39Sopenharmony_ci s->ext.session_ticket = NULL; 1155e1051a39Sopenharmony_ci s->ext.session_ticket = 1156e1051a39Sopenharmony_ci OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); 1157e1051a39Sopenharmony_ci if (s->ext.session_ticket == NULL) { 1158e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); 1159e1051a39Sopenharmony_ci return 0; 1160e1051a39Sopenharmony_ci } 1161e1051a39Sopenharmony_ci 1162e1051a39Sopenharmony_ci if (ext_data != NULL) { 1163e1051a39Sopenharmony_ci s->ext.session_ticket->length = ext_len; 1164e1051a39Sopenharmony_ci s->ext.session_ticket->data = s->ext.session_ticket + 1; 1165e1051a39Sopenharmony_ci memcpy(s->ext.session_ticket->data, ext_data, ext_len); 1166e1051a39Sopenharmony_ci } else { 1167e1051a39Sopenharmony_ci s->ext.session_ticket->length = 0; 1168e1051a39Sopenharmony_ci s->ext.session_ticket->data = NULL; 1169e1051a39Sopenharmony_ci } 1170e1051a39Sopenharmony_ci 1171e1051a39Sopenharmony_ci return 1; 1172e1051a39Sopenharmony_ci } 1173e1051a39Sopenharmony_ci 1174e1051a39Sopenharmony_ci return 0; 1175e1051a39Sopenharmony_ci} 1176e1051a39Sopenharmony_ci 1177e1051a39Sopenharmony_civoid SSL_CTX_flush_sessions(SSL_CTX *s, long t) 1178e1051a39Sopenharmony_ci{ 1179e1051a39Sopenharmony_ci STACK_OF(SSL_SESSION) *sk; 1180e1051a39Sopenharmony_ci SSL_SESSION *current; 1181e1051a39Sopenharmony_ci unsigned long i; 1182e1051a39Sopenharmony_ci 1183e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(s->lock)) 1184e1051a39Sopenharmony_ci return; 1185e1051a39Sopenharmony_ci 1186e1051a39Sopenharmony_ci sk = sk_SSL_SESSION_new_null(); 1187e1051a39Sopenharmony_ci i = lh_SSL_SESSION_get_down_load(s->sessions); 1188e1051a39Sopenharmony_ci lh_SSL_SESSION_set_down_load(s->sessions, 0); 1189e1051a39Sopenharmony_ci 1190e1051a39Sopenharmony_ci /* 1191e1051a39Sopenharmony_ci * Iterate over the list from the back (oldest), and stop 1192e1051a39Sopenharmony_ci * when a session can no longer be removed. 1193e1051a39Sopenharmony_ci * Add the session to a temporary list to be freed outside 1194e1051a39Sopenharmony_ci * the SSL_CTX lock. 1195e1051a39Sopenharmony_ci * But still do the remove_session_cb() within the lock. 1196e1051a39Sopenharmony_ci */ 1197e1051a39Sopenharmony_ci while (s->session_cache_tail != NULL) { 1198e1051a39Sopenharmony_ci current = s->session_cache_tail; 1199e1051a39Sopenharmony_ci if (t == 0 || sess_timedout((time_t)t, current)) { 1200e1051a39Sopenharmony_ci lh_SSL_SESSION_delete(s->sessions, current); 1201e1051a39Sopenharmony_ci SSL_SESSION_list_remove(s, current); 1202e1051a39Sopenharmony_ci current->not_resumable = 1; 1203e1051a39Sopenharmony_ci if (s->remove_session_cb != NULL) 1204e1051a39Sopenharmony_ci s->remove_session_cb(s, current); 1205e1051a39Sopenharmony_ci /* 1206e1051a39Sopenharmony_ci * Throw the session on a stack, it's entirely plausible 1207e1051a39Sopenharmony_ci * that while freeing outside the critical section, the 1208e1051a39Sopenharmony_ci * session could be re-added, so avoid using the next/prev 1209e1051a39Sopenharmony_ci * pointers. If the stack failed to create, or the session 1210e1051a39Sopenharmony_ci * couldn't be put on the stack, just free it here 1211e1051a39Sopenharmony_ci */ 1212e1051a39Sopenharmony_ci if (sk == NULL || !sk_SSL_SESSION_push(sk, current)) 1213e1051a39Sopenharmony_ci SSL_SESSION_free(current); 1214e1051a39Sopenharmony_ci } else { 1215e1051a39Sopenharmony_ci break; 1216e1051a39Sopenharmony_ci } 1217e1051a39Sopenharmony_ci } 1218e1051a39Sopenharmony_ci 1219e1051a39Sopenharmony_ci lh_SSL_SESSION_set_down_load(s->sessions, i); 1220e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(s->lock); 1221e1051a39Sopenharmony_ci 1222e1051a39Sopenharmony_ci sk_SSL_SESSION_pop_free(sk, SSL_SESSION_free); 1223e1051a39Sopenharmony_ci} 1224e1051a39Sopenharmony_ci 1225e1051a39Sopenharmony_ciint ssl_clear_bad_session(SSL *s) 1226e1051a39Sopenharmony_ci{ 1227e1051a39Sopenharmony_ci if ((s->session != NULL) && 1228e1051a39Sopenharmony_ci !(s->shutdown & SSL_SENT_SHUTDOWN) && 1229e1051a39Sopenharmony_ci !(SSL_in_init(s) || SSL_in_before(s))) { 1230e1051a39Sopenharmony_ci SSL_CTX_remove_session(s->session_ctx, s->session); 1231e1051a39Sopenharmony_ci return 1; 1232e1051a39Sopenharmony_ci } else 1233e1051a39Sopenharmony_ci return 0; 1234e1051a39Sopenharmony_ci} 1235e1051a39Sopenharmony_ci 1236e1051a39Sopenharmony_ci/* locked by SSL_CTX in the calling function */ 1237e1051a39Sopenharmony_cistatic void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) 1238e1051a39Sopenharmony_ci{ 1239e1051a39Sopenharmony_ci if ((s->next == NULL) || (s->prev == NULL)) 1240e1051a39Sopenharmony_ci return; 1241e1051a39Sopenharmony_ci 1242e1051a39Sopenharmony_ci if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { 1243e1051a39Sopenharmony_ci /* last element in list */ 1244e1051a39Sopenharmony_ci if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 1245e1051a39Sopenharmony_ci /* only one element in list */ 1246e1051a39Sopenharmony_ci ctx->session_cache_head = NULL; 1247e1051a39Sopenharmony_ci ctx->session_cache_tail = NULL; 1248e1051a39Sopenharmony_ci } else { 1249e1051a39Sopenharmony_ci ctx->session_cache_tail = s->prev; 1250e1051a39Sopenharmony_ci s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); 1251e1051a39Sopenharmony_ci } 1252e1051a39Sopenharmony_ci } else { 1253e1051a39Sopenharmony_ci if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 1254e1051a39Sopenharmony_ci /* first element in list */ 1255e1051a39Sopenharmony_ci ctx->session_cache_head = s->next; 1256e1051a39Sopenharmony_ci s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); 1257e1051a39Sopenharmony_ci } else { 1258e1051a39Sopenharmony_ci /* middle of list */ 1259e1051a39Sopenharmony_ci s->next->prev = s->prev; 1260e1051a39Sopenharmony_ci s->prev->next = s->next; 1261e1051a39Sopenharmony_ci } 1262e1051a39Sopenharmony_ci } 1263e1051a39Sopenharmony_ci s->prev = s->next = NULL; 1264e1051a39Sopenharmony_ci s->owner = NULL; 1265e1051a39Sopenharmony_ci} 1266e1051a39Sopenharmony_ci 1267e1051a39Sopenharmony_cistatic void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) 1268e1051a39Sopenharmony_ci{ 1269e1051a39Sopenharmony_ci SSL_SESSION *next; 1270e1051a39Sopenharmony_ci 1271e1051a39Sopenharmony_ci if ((s->next != NULL) && (s->prev != NULL)) 1272e1051a39Sopenharmony_ci SSL_SESSION_list_remove(ctx, s); 1273e1051a39Sopenharmony_ci 1274e1051a39Sopenharmony_ci if (ctx->session_cache_head == NULL) { 1275e1051a39Sopenharmony_ci ctx->session_cache_head = s; 1276e1051a39Sopenharmony_ci ctx->session_cache_tail = s; 1277e1051a39Sopenharmony_ci s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 1278e1051a39Sopenharmony_ci s->next = (SSL_SESSION *)&(ctx->session_cache_tail); 1279e1051a39Sopenharmony_ci } else { 1280e1051a39Sopenharmony_ci if (timeoutcmp(s, ctx->session_cache_head) >= 0) { 1281e1051a39Sopenharmony_ci /* 1282e1051a39Sopenharmony_ci * if we timeout after (or the same time as) the first 1283e1051a39Sopenharmony_ci * session, put us first - usual case 1284e1051a39Sopenharmony_ci */ 1285e1051a39Sopenharmony_ci s->next = ctx->session_cache_head; 1286e1051a39Sopenharmony_ci s->next->prev = s; 1287e1051a39Sopenharmony_ci s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 1288e1051a39Sopenharmony_ci ctx->session_cache_head = s; 1289e1051a39Sopenharmony_ci } else if (timeoutcmp(s, ctx->session_cache_tail) < 0) { 1290e1051a39Sopenharmony_ci /* if we timeout before the last session, put us last */ 1291e1051a39Sopenharmony_ci s->prev = ctx->session_cache_tail; 1292e1051a39Sopenharmony_ci s->prev->next = s; 1293e1051a39Sopenharmony_ci s->next = (SSL_SESSION *)&(ctx->session_cache_tail); 1294e1051a39Sopenharmony_ci ctx->session_cache_tail = s; 1295e1051a39Sopenharmony_ci } else { 1296e1051a39Sopenharmony_ci /* 1297e1051a39Sopenharmony_ci * we timeout somewhere in-between - if there is only 1298e1051a39Sopenharmony_ci * one session in the cache it will be caught above 1299e1051a39Sopenharmony_ci */ 1300e1051a39Sopenharmony_ci next = ctx->session_cache_head->next; 1301e1051a39Sopenharmony_ci while (next != (SSL_SESSION*)&(ctx->session_cache_tail)) { 1302e1051a39Sopenharmony_ci if (timeoutcmp(s, next) >= 0) { 1303e1051a39Sopenharmony_ci s->next = next; 1304e1051a39Sopenharmony_ci s->prev = next->prev; 1305e1051a39Sopenharmony_ci next->prev->next = s; 1306e1051a39Sopenharmony_ci next->prev = s; 1307e1051a39Sopenharmony_ci break; 1308e1051a39Sopenharmony_ci } 1309e1051a39Sopenharmony_ci next = next->next; 1310e1051a39Sopenharmony_ci } 1311e1051a39Sopenharmony_ci } 1312e1051a39Sopenharmony_ci } 1313e1051a39Sopenharmony_ci s->owner = ctx; 1314e1051a39Sopenharmony_ci} 1315e1051a39Sopenharmony_ci 1316e1051a39Sopenharmony_civoid SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, 1317e1051a39Sopenharmony_ci int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) 1318e1051a39Sopenharmony_ci{ 1319e1051a39Sopenharmony_ci ctx->new_session_cb = cb; 1320e1051a39Sopenharmony_ci} 1321e1051a39Sopenharmony_ci 1322e1051a39Sopenharmony_ciint (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { 1323e1051a39Sopenharmony_ci return ctx->new_session_cb; 1324e1051a39Sopenharmony_ci} 1325e1051a39Sopenharmony_ci 1326e1051a39Sopenharmony_civoid SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, 1327e1051a39Sopenharmony_ci void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) 1328e1051a39Sopenharmony_ci{ 1329e1051a39Sopenharmony_ci ctx->remove_session_cb = cb; 1330e1051a39Sopenharmony_ci} 1331e1051a39Sopenharmony_ci 1332e1051a39Sopenharmony_civoid (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, 1333e1051a39Sopenharmony_ci SSL_SESSION *sess) { 1334e1051a39Sopenharmony_ci return ctx->remove_session_cb; 1335e1051a39Sopenharmony_ci} 1336e1051a39Sopenharmony_ci 1337e1051a39Sopenharmony_civoid SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, 1338e1051a39Sopenharmony_ci SSL_SESSION *(*cb) (struct ssl_st *ssl, 1339e1051a39Sopenharmony_ci const unsigned char *data, 1340e1051a39Sopenharmony_ci int len, int *copy)) 1341e1051a39Sopenharmony_ci{ 1342e1051a39Sopenharmony_ci ctx->get_session_cb = cb; 1343e1051a39Sopenharmony_ci} 1344e1051a39Sopenharmony_ci 1345e1051a39Sopenharmony_ciSSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, 1346e1051a39Sopenharmony_ci const unsigned char 1347e1051a39Sopenharmony_ci *data, int len, 1348e1051a39Sopenharmony_ci int *copy) { 1349e1051a39Sopenharmony_ci return ctx->get_session_cb; 1350e1051a39Sopenharmony_ci} 1351e1051a39Sopenharmony_ci 1352e1051a39Sopenharmony_civoid SSL_CTX_set_info_callback(SSL_CTX *ctx, 1353e1051a39Sopenharmony_ci void (*cb) (const SSL *ssl, int type, int val)) 1354e1051a39Sopenharmony_ci{ 1355e1051a39Sopenharmony_ci ctx->info_callback = cb; 1356e1051a39Sopenharmony_ci} 1357e1051a39Sopenharmony_ci 1358e1051a39Sopenharmony_civoid (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, 1359e1051a39Sopenharmony_ci int val) { 1360e1051a39Sopenharmony_ci return ctx->info_callback; 1361e1051a39Sopenharmony_ci} 1362e1051a39Sopenharmony_ci 1363e1051a39Sopenharmony_civoid SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, 1364e1051a39Sopenharmony_ci int (*cb) (SSL *ssl, X509 **x509, 1365e1051a39Sopenharmony_ci EVP_PKEY **pkey)) 1366e1051a39Sopenharmony_ci{ 1367e1051a39Sopenharmony_ci ctx->client_cert_cb = cb; 1368e1051a39Sopenharmony_ci} 1369e1051a39Sopenharmony_ci 1370e1051a39Sopenharmony_ciint (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, 1371e1051a39Sopenharmony_ci EVP_PKEY **pkey) { 1372e1051a39Sopenharmony_ci return ctx->client_cert_cb; 1373e1051a39Sopenharmony_ci} 1374e1051a39Sopenharmony_ci 1375e1051a39Sopenharmony_civoid SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, 1376e1051a39Sopenharmony_ci int (*cb) (SSL *ssl, 1377e1051a39Sopenharmony_ci unsigned char *cookie, 1378e1051a39Sopenharmony_ci unsigned int *cookie_len)) 1379e1051a39Sopenharmony_ci{ 1380e1051a39Sopenharmony_ci ctx->app_gen_cookie_cb = cb; 1381e1051a39Sopenharmony_ci} 1382e1051a39Sopenharmony_ci 1383e1051a39Sopenharmony_civoid SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, 1384e1051a39Sopenharmony_ci int (*cb) (SSL *ssl, 1385e1051a39Sopenharmony_ci const unsigned char *cookie, 1386e1051a39Sopenharmony_ci unsigned int cookie_len)) 1387e1051a39Sopenharmony_ci{ 1388e1051a39Sopenharmony_ci ctx->app_verify_cookie_cb = cb; 1389e1051a39Sopenharmony_ci} 1390e1051a39Sopenharmony_ci 1391e1051a39Sopenharmony_ciint SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) 1392e1051a39Sopenharmony_ci{ 1393e1051a39Sopenharmony_ci OPENSSL_free(ss->ticket_appdata); 1394e1051a39Sopenharmony_ci ss->ticket_appdata_len = 0; 1395e1051a39Sopenharmony_ci if (data == NULL || len == 0) { 1396e1051a39Sopenharmony_ci ss->ticket_appdata = NULL; 1397e1051a39Sopenharmony_ci return 1; 1398e1051a39Sopenharmony_ci } 1399e1051a39Sopenharmony_ci ss->ticket_appdata = OPENSSL_memdup(data, len); 1400e1051a39Sopenharmony_ci if (ss->ticket_appdata != NULL) { 1401e1051a39Sopenharmony_ci ss->ticket_appdata_len = len; 1402e1051a39Sopenharmony_ci return 1; 1403e1051a39Sopenharmony_ci } 1404e1051a39Sopenharmony_ci return 0; 1405e1051a39Sopenharmony_ci} 1406e1051a39Sopenharmony_ci 1407e1051a39Sopenharmony_ciint SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) 1408e1051a39Sopenharmony_ci{ 1409e1051a39Sopenharmony_ci *data = ss->ticket_appdata; 1410e1051a39Sopenharmony_ci *len = ss->ticket_appdata_len; 1411e1051a39Sopenharmony_ci return 1; 1412e1051a39Sopenharmony_ci} 1413e1051a39Sopenharmony_ci 1414e1051a39Sopenharmony_civoid SSL_CTX_set_stateless_cookie_generate_cb( 1415e1051a39Sopenharmony_ci SSL_CTX *ctx, 1416e1051a39Sopenharmony_ci int (*cb) (SSL *ssl, 1417e1051a39Sopenharmony_ci unsigned char *cookie, 1418e1051a39Sopenharmony_ci size_t *cookie_len)) 1419e1051a39Sopenharmony_ci{ 1420e1051a39Sopenharmony_ci ctx->gen_stateless_cookie_cb = cb; 1421e1051a39Sopenharmony_ci} 1422e1051a39Sopenharmony_ci 1423e1051a39Sopenharmony_civoid SSL_CTX_set_stateless_cookie_verify_cb( 1424e1051a39Sopenharmony_ci SSL_CTX *ctx, 1425e1051a39Sopenharmony_ci int (*cb) (SSL *ssl, 1426e1051a39Sopenharmony_ci const unsigned char *cookie, 1427e1051a39Sopenharmony_ci size_t cookie_len)) 1428e1051a39Sopenharmony_ci{ 1429e1051a39Sopenharmony_ci ctx->verify_stateless_cookie_cb = cb; 1430e1051a39Sopenharmony_ci} 1431e1051a39Sopenharmony_ci 1432e1051a39Sopenharmony_ciIMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) 1433