1e71b7053SJung-uk Kim /* 2*c3c73b4fSJung-uk Kim * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 31f13597dSJung-uk Kim * Copyright 2005 Nokia. All rights reserved. 41f13597dSJung-uk Kim * 5e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 6e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 7e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 8e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 91f13597dSJung-uk Kim */ 1074664626SKris Kennaway 1174664626SKris Kennaway #include <stdio.h> 1274664626SKris Kennaway #include <openssl/rand.h> 13db522d3aSSimon L. B. Nielsen #include <openssl/engine.h> 14e71b7053SJung-uk Kim #include "internal/refcount.h" 15e71b7053SJung-uk Kim #include "internal/cryptlib.h" 1617f01e99SJung-uk Kim #include "ssl_local.h" 1717f01e99SJung-uk Kim #include "statem/statem_local.h" 1874664626SKris Kennaway 1974664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); 2074664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); 2174664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); 2274664626SKris Kennaway 23e71b7053SJung-uk Kim /* 24e71b7053SJung-uk Kim * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, 25e71b7053SJung-uk Kim * unlike in earlier protocol versions, the session ticket may not have been 26e71b7053SJung-uk Kim * sent yet even though a handshake has finished. The session ticket data could 27e71b7053SJung-uk Kim * come in sometime later...or even change if multiple session ticket messages 28e71b7053SJung-uk Kim * are sent from the server. The preferred way for applications to obtain 29e71b7053SJung-uk Kim * a resumable session is to use SSL_CTX_sess_set_new_cb(). 30e71b7053SJung-uk Kim */ 31e71b7053SJung-uk Kim 323b4e3dcbSSimon L. B. Nielsen SSL_SESSION *SSL_get_session(const SSL *ssl) 33f579bf8eSKris Kennaway /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ 3474664626SKris Kennaway { 35e71b7053SJung-uk Kim return ssl->session; 3674664626SKris Kennaway } 3774664626SKris Kennaway 38f579bf8eSKris Kennaway SSL_SESSION *SSL_get1_session(SSL *ssl) 39f579bf8eSKris Kennaway /* variant of SSL_get_session: caller really gets something */ 40f579bf8eSKris Kennaway { 41f579bf8eSKris Kennaway SSL_SESSION *sess; 426f9291ceSJung-uk Kim /* 436f9291ceSJung-uk Kim * Need to lock this all up rather than just use CRYPTO_add so that 446f9291ceSJung-uk Kim * somebody doesn't free ssl->session between when we check it's non-null 456f9291ceSJung-uk Kim * and when we up the reference count. 466f9291ceSJung-uk Kim */ 47e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(ssl->lock); 48f579bf8eSKris Kennaway sess = ssl->session; 49f579bf8eSKris Kennaway if (sess) 50e71b7053SJung-uk Kim SSL_SESSION_up_ref(sess); 51e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ssl->lock); 52e71b7053SJung-uk Kim return sess; 5374664626SKris Kennaway } 5474664626SKris Kennaway 5574664626SKris Kennaway int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) 5674664626SKris Kennaway { 57e71b7053SJung-uk Kim return CRYPTO_set_ex_data(&s->ex_data, idx, arg); 5874664626SKris Kennaway } 5974664626SKris Kennaway 603b4e3dcbSSimon L. B. Nielsen void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) 6174664626SKris Kennaway { 62e71b7053SJung-uk Kim return CRYPTO_get_ex_data(&s->ex_data, idx); 6374664626SKris Kennaway } 6474664626SKris Kennaway 6574664626SKris Kennaway SSL_SESSION *SSL_SESSION_new(void) 6674664626SKris Kennaway { 6774664626SKris Kennaway SSL_SESSION *ss; 6874664626SKris Kennaway 69e71b7053SJung-uk Kim if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) 70e71b7053SJung-uk Kim return NULL; 71e71b7053SJung-uk Kim 72e71b7053SJung-uk Kim ss = OPENSSL_zalloc(sizeof(*ss)); 736f9291ceSJung-uk Kim if (ss == NULL) { 7474664626SKris Kennaway SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); 75e71b7053SJung-uk Kim return NULL; 7674664626SKris Kennaway } 7774664626SKris Kennaway 78f579bf8eSKris Kennaway ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ 7974664626SKris Kennaway ss->references = 1; 8074664626SKris Kennaway ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ 813b4e3dcbSSimon L. B. Nielsen ss->time = (unsigned long)time(NULL); 82e71b7053SJung-uk Kim ss->lock = CRYPTO_THREAD_lock_new(); 83e71b7053SJung-uk Kim if (ss->lock == NULL) { 84e71b7053SJung-uk Kim SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); 85e71b7053SJung-uk Kim OPENSSL_free(ss); 86e71b7053SJung-uk Kim return NULL; 87e71b7053SJung-uk Kim } 88e71b7053SJung-uk Kim 89e71b7053SJung-uk Kim if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { 90e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(ss->lock); 91e71b7053SJung-uk Kim OPENSSL_free(ss); 92e71b7053SJung-uk Kim return NULL; 93e71b7053SJung-uk Kim } 94e71b7053SJung-uk Kim return ss; 95e71b7053SJung-uk Kim } 96e71b7053SJung-uk Kim 97e71b7053SJung-uk Kim SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src) 98e71b7053SJung-uk Kim { 99e71b7053SJung-uk Kim return ssl_session_dup(src, 1); 10074664626SKris Kennaway } 10174664626SKris Kennaway 102ed6b93beSJung-uk Kim /* 103ed6b93beSJung-uk Kim * Create a new SSL_SESSION and duplicate the contents of |src| into it. If 104ed6b93beSJung-uk Kim * ticket == 0 then no ticket information is duplicated, otherwise it is. 105ed6b93beSJung-uk Kim */ 106ed6b93beSJung-uk Kim SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) 107ed6b93beSJung-uk Kim { 108ed6b93beSJung-uk Kim SSL_SESSION *dest; 109ed6b93beSJung-uk Kim 110*c3c73b4fSJung-uk Kim dest = OPENSSL_malloc(sizeof(*dest)); 111ed6b93beSJung-uk Kim if (dest == NULL) { 112ed6b93beSJung-uk Kim goto err; 113ed6b93beSJung-uk Kim } 114ed6b93beSJung-uk Kim memcpy(dest, src, sizeof(*dest)); 115ed6b93beSJung-uk Kim 116ed6b93beSJung-uk Kim /* 117ed6b93beSJung-uk Kim * Set the various pointers to NULL so that we can call SSL_SESSION_free in 118ed6b93beSJung-uk Kim * the case of an error whilst halfway through constructing dest 119ed6b93beSJung-uk Kim */ 120ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK 121ed6b93beSJung-uk Kim dest->psk_identity_hint = NULL; 122ed6b93beSJung-uk Kim dest->psk_identity = NULL; 123ed6b93beSJung-uk Kim #endif 124e71b7053SJung-uk Kim dest->ext.hostname = NULL; 125e71b7053SJung-uk Kim dest->ext.tick = NULL; 126e71b7053SJung-uk Kim dest->ext.alpn_selected = NULL; 127ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP 128ed6b93beSJung-uk Kim dest->srp_username = NULL; 129ed6b93beSJung-uk Kim #endif 130e71b7053SJung-uk Kim dest->peer_chain = NULL; 131e71b7053SJung-uk Kim dest->peer = NULL; 132e71b7053SJung-uk Kim dest->ticket_appdata = NULL; 133e71b7053SJung-uk Kim memset(&dest->ex_data, 0, sizeof(dest->ex_data)); 134ed6b93beSJung-uk Kim 135ed6b93beSJung-uk Kim /* We deliberately don't copy the prev and next pointers */ 136ed6b93beSJung-uk Kim dest->prev = NULL; 137ed6b93beSJung-uk Kim dest->next = NULL; 138ed6b93beSJung-uk Kim 139ed6b93beSJung-uk Kim dest->references = 1; 140ed6b93beSJung-uk Kim 141e71b7053SJung-uk Kim dest->lock = CRYPTO_THREAD_lock_new(); 142e71b7053SJung-uk Kim if (dest->lock == NULL) 143e71b7053SJung-uk Kim goto err; 144ed6b93beSJung-uk Kim 14547902a71SJung-uk Kim if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) 14647902a71SJung-uk Kim goto err; 14747902a71SJung-uk Kim 148e71b7053SJung-uk Kim if (src->peer != NULL) { 149e71b7053SJung-uk Kim if (!X509_up_ref(src->peer)) 150e71b7053SJung-uk Kim goto err; 151e71b7053SJung-uk Kim dest->peer = src->peer; 152e71b7053SJung-uk Kim } 153e71b7053SJung-uk Kim 154e71b7053SJung-uk Kim if (src->peer_chain != NULL) { 155e71b7053SJung-uk Kim dest->peer_chain = X509_chain_up_ref(src->peer_chain); 156e71b7053SJung-uk Kim if (dest->peer_chain == NULL) 157e71b7053SJung-uk Kim goto err; 158e71b7053SJung-uk Kim } 159ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK 160ed6b93beSJung-uk Kim if (src->psk_identity_hint) { 161e71b7053SJung-uk Kim dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint); 162ed6b93beSJung-uk Kim if (dest->psk_identity_hint == NULL) { 163ed6b93beSJung-uk Kim goto err; 164ed6b93beSJung-uk Kim } 165ed6b93beSJung-uk Kim } 166ed6b93beSJung-uk Kim if (src->psk_identity) { 167e71b7053SJung-uk Kim dest->psk_identity = OPENSSL_strdup(src->psk_identity); 168ed6b93beSJung-uk Kim if (dest->psk_identity == NULL) { 169ed6b93beSJung-uk Kim goto err; 170ed6b93beSJung-uk Kim } 171ed6b93beSJung-uk Kim } 172ed6b93beSJung-uk Kim #endif 173ed6b93beSJung-uk Kim 174ed6b93beSJung-uk Kim if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, 175ed6b93beSJung-uk Kim &dest->ex_data, &src->ex_data)) { 176ed6b93beSJung-uk Kim goto err; 177ed6b93beSJung-uk Kim } 178ed6b93beSJung-uk Kim 179e71b7053SJung-uk Kim if (src->ext.hostname) { 180e71b7053SJung-uk Kim dest->ext.hostname = OPENSSL_strdup(src->ext.hostname); 181e71b7053SJung-uk Kim if (dest->ext.hostname == NULL) { 182ed6b93beSJung-uk Kim goto err; 183ed6b93beSJung-uk Kim } 184ed6b93beSJung-uk Kim } 185ed6b93beSJung-uk Kim 186e71b7053SJung-uk Kim if (ticket != 0 && src->ext.tick != NULL) { 187e71b7053SJung-uk Kim dest->ext.tick = 188e71b7053SJung-uk Kim OPENSSL_memdup(src->ext.tick, src->ext.ticklen); 189e71b7053SJung-uk Kim if (dest->ext.tick == NULL) 190ed6b93beSJung-uk Kim goto err; 191ed6b93beSJung-uk Kim } else { 192e71b7053SJung-uk Kim dest->ext.tick_lifetime_hint = 0; 193e71b7053SJung-uk Kim dest->ext.ticklen = 0; 194ed6b93beSJung-uk Kim } 195e71b7053SJung-uk Kim 196e71b7053SJung-uk Kim if (src->ext.alpn_selected != NULL) { 197e71b7053SJung-uk Kim dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected, 198e71b7053SJung-uk Kim src->ext.alpn_selected_len); 199e71b7053SJung-uk Kim if (dest->ext.alpn_selected == NULL) 200e71b7053SJung-uk Kim goto err; 201e71b7053SJung-uk Kim } 202ed6b93beSJung-uk Kim 203ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP 204ed6b93beSJung-uk Kim if (src->srp_username) { 205e71b7053SJung-uk Kim dest->srp_username = OPENSSL_strdup(src->srp_username); 206ed6b93beSJung-uk Kim if (dest->srp_username == NULL) { 207ed6b93beSJung-uk Kim goto err; 208ed6b93beSJung-uk Kim } 209ed6b93beSJung-uk Kim } 210ed6b93beSJung-uk Kim #endif 211ed6b93beSJung-uk Kim 212e71b7053SJung-uk Kim if (src->ticket_appdata != NULL) { 213e71b7053SJung-uk Kim dest->ticket_appdata = 214e71b7053SJung-uk Kim OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); 215e71b7053SJung-uk Kim if (dest->ticket_appdata == NULL) 216e71b7053SJung-uk Kim goto err; 217e71b7053SJung-uk Kim } 218e71b7053SJung-uk Kim 219ed6b93beSJung-uk Kim return dest; 220ed6b93beSJung-uk Kim err: 221ed6b93beSJung-uk Kim SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); 222ed6b93beSJung-uk Kim SSL_SESSION_free(dest); 223ed6b93beSJung-uk Kim return NULL; 224ed6b93beSJung-uk Kim } 225ed6b93beSJung-uk Kim 226e71b7053SJung-uk Kim const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) 2273b4e3dcbSSimon L. B. Nielsen { 2283b4e3dcbSSimon L. B. Nielsen if (len) 229e71b7053SJung-uk Kim *len = (unsigned int)s->session_id_length; 2303b4e3dcbSSimon L. B. Nielsen return s->session_id; 2313b4e3dcbSSimon L. B. Nielsen } 232e71b7053SJung-uk Kim const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, 233e71b7053SJung-uk Kim unsigned int *len) 234e71b7053SJung-uk Kim { 235e71b7053SJung-uk Kim if (len != NULL) 236e71b7053SJung-uk Kim *len = (unsigned int)s->sid_ctx_length; 237e71b7053SJung-uk Kim return s->sid_ctx; 238e71b7053SJung-uk Kim } 2393b4e3dcbSSimon L. B. Nielsen 2401f13597dSJung-uk Kim unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) 2411f13597dSJung-uk Kim { 2421f13597dSJung-uk Kim return s->compress_meth; 2431f13597dSJung-uk Kim } 2441f13597dSJung-uk Kim 2456f9291ceSJung-uk Kim /* 246e71b7053SJung-uk Kim * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling 247e71b7053SJung-uk Kim * the ID with random junk repeatedly until we have no conflict is going to 248e71b7053SJung-uk Kim * complete in one iteration pretty much "most" of the time (btw: 249e71b7053SJung-uk Kim * understatement). So, if it takes us 10 iterations and we still can't avoid 250e71b7053SJung-uk Kim * a conflict - well that's a reasonable point to call it quits. Either the 251e71b7053SJung-uk Kim * RAND code is broken or someone is trying to open roughly very close to 252e71b7053SJung-uk Kim * 2^256 SSL sessions to our server. How you might store that many sessions 253e71b7053SJung-uk Kim * is perhaps a more interesting question ... 2546f9291ceSJung-uk Kim */ 2555c87c606SMark Murray 2565c87c606SMark Murray #define MAX_SESS_ID_ATTEMPTS 10 257e71b7053SJung-uk Kim static int def_generate_session_id(SSL *ssl, unsigned char *id, 2585c87c606SMark Murray unsigned int *id_len) 2595c87c606SMark Murray { 2605c87c606SMark Murray unsigned int retry = 0; 2615c87c606SMark Murray do 262aeb5019cSJung-uk Kim if (RAND_bytes(id, *id_len) <= 0) 2636be8ae07SJacques Vidrine return 0; 2645c87c606SMark Murray while (SSL_has_matching_session_id(ssl, id, *id_len) && 2655c87c606SMark Murray (++retry < MAX_SESS_ID_ATTEMPTS)) ; 2665c87c606SMark Murray if (retry < MAX_SESS_ID_ATTEMPTS) 2675c87c606SMark Murray return 1; 2685c87c606SMark Murray /* else - woops a session_id match */ 2696f9291ceSJung-uk Kim /* 2706f9291ceSJung-uk Kim * XXX We should also check the external cache -- but the probability of 2716f9291ceSJung-uk Kim * a collision is negligible, and we could not prevent the concurrent 2726f9291ceSJung-uk Kim * creation of sessions with identical IDs since we currently don't have 2736f9291ceSJung-uk Kim * means to atomically check whether a session ID already exists and make 2746f9291ceSJung-uk Kim * a reservation for it if it does not (this problem applies to the 2756f9291ceSJung-uk Kim * internal cache as well). 2765c87c606SMark Murray */ 2775c87c606SMark Murray return 0; 2785c87c606SMark Murray } 2795c87c606SMark Murray 280e71b7053SJung-uk Kim int ssl_generate_session_id(SSL *s, SSL_SESSION *ss) 281e71b7053SJung-uk Kim { 282e71b7053SJung-uk Kim unsigned int tmp; 283e71b7053SJung-uk Kim GEN_SESSION_CB cb = def_generate_session_id; 284e71b7053SJung-uk Kim 285e71b7053SJung-uk Kim switch (s->version) { 286e71b7053SJung-uk Kim case SSL3_VERSION: 287e71b7053SJung-uk Kim case TLS1_VERSION: 288e71b7053SJung-uk Kim case TLS1_1_VERSION: 289e71b7053SJung-uk Kim case TLS1_2_VERSION: 290e71b7053SJung-uk Kim case TLS1_3_VERSION: 291e71b7053SJung-uk Kim case DTLS1_BAD_VER: 292e71b7053SJung-uk Kim case DTLS1_VERSION: 293e71b7053SJung-uk Kim case DTLS1_2_VERSION: 294e71b7053SJung-uk Kim ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; 295e71b7053SJung-uk Kim break; 296e71b7053SJung-uk Kim default: 297e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 298e71b7053SJung-uk Kim SSL_R_UNSUPPORTED_SSL_VERSION); 299e71b7053SJung-uk Kim return 0; 300e71b7053SJung-uk Kim } 301e71b7053SJung-uk Kim 302e71b7053SJung-uk Kim /*- 303e71b7053SJung-uk Kim * If RFC5077 ticket, use empty session ID (as server). 304e71b7053SJung-uk Kim * Note that: 305e71b7053SJung-uk Kim * (a) ssl_get_prev_session() does lookahead into the 306e71b7053SJung-uk Kim * ClientHello extensions to find the session ticket. 307e71b7053SJung-uk Kim * When ssl_get_prev_session() fails, statem_srvr.c calls 308e71b7053SJung-uk Kim * ssl_get_new_session() in tls_process_client_hello(). 309e71b7053SJung-uk Kim * At that point, it has not yet parsed the extensions, 310e71b7053SJung-uk Kim * however, because of the lookahead, it already knows 311e71b7053SJung-uk Kim * whether a ticket is expected or not. 312e71b7053SJung-uk Kim * 313e71b7053SJung-uk Kim * (b) statem_clnt.c calls ssl_get_new_session() before parsing 314e71b7053SJung-uk Kim * ServerHello extensions, and before recording the session 315e71b7053SJung-uk Kim * ID received from the server, so this block is a noop. 316e71b7053SJung-uk Kim */ 317e71b7053SJung-uk Kim if (s->ext.ticket_expected) { 318e71b7053SJung-uk Kim ss->session_id_length = 0; 319e71b7053SJung-uk Kim return 1; 320e71b7053SJung-uk Kim } 321e71b7053SJung-uk Kim 322e71b7053SJung-uk Kim /* Choose which callback will set the session ID */ 323e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->lock); 324e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->session_ctx->lock); 325e71b7053SJung-uk Kim if (s->generate_session_id) 326e71b7053SJung-uk Kim cb = s->generate_session_id; 327e71b7053SJung-uk Kim else if (s->session_ctx->generate_session_id) 328e71b7053SJung-uk Kim cb = s->session_ctx->generate_session_id; 329e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->session_ctx->lock); 330e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->lock); 331e71b7053SJung-uk Kim /* Choose a session ID */ 332e71b7053SJung-uk Kim memset(ss->session_id, 0, ss->session_id_length); 333e71b7053SJung-uk Kim tmp = (int)ss->session_id_length; 334e71b7053SJung-uk Kim if (!cb(s, ss->session_id, &tmp)) { 335e71b7053SJung-uk Kim /* The callback failed */ 336e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 337e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); 338e71b7053SJung-uk Kim return 0; 339e71b7053SJung-uk Kim } 340e71b7053SJung-uk Kim /* 341e71b7053SJung-uk Kim * Don't allow the callback to set the session length to zero. nor 342e71b7053SJung-uk Kim * set it higher than it was. 343e71b7053SJung-uk Kim */ 344e71b7053SJung-uk Kim if (tmp == 0 || tmp > ss->session_id_length) { 345e71b7053SJung-uk Kim /* The callback set an illegal length */ 346e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 347e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); 348e71b7053SJung-uk Kim return 0; 349e71b7053SJung-uk Kim } 350e71b7053SJung-uk Kim ss->session_id_length = tmp; 351e71b7053SJung-uk Kim /* Finally, check for a conflict */ 352e71b7053SJung-uk Kim if (SSL_has_matching_session_id(s, ss->session_id, 353e71b7053SJung-uk Kim (unsigned int)ss->session_id_length)) { 354e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 355e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_CONFLICT); 356e71b7053SJung-uk Kim return 0; 357e71b7053SJung-uk Kim } 358e71b7053SJung-uk Kim 359e71b7053SJung-uk Kim return 1; 360e71b7053SJung-uk Kim } 361e71b7053SJung-uk Kim 36274664626SKris Kennaway int ssl_get_new_session(SSL *s, int session) 36374664626SKris Kennaway { 36474664626SKris Kennaway /* This gets used by clients and servers. */ 36574664626SKris Kennaway 36674664626SKris Kennaway SSL_SESSION *ss = NULL; 36774664626SKris Kennaway 368e71b7053SJung-uk Kim if ((ss = SSL_SESSION_new()) == NULL) { 369e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, 370e71b7053SJung-uk Kim ERR_R_MALLOC_FAILURE); 371e71b7053SJung-uk Kim return 0; 372e71b7053SJung-uk Kim } 37374664626SKris Kennaway 37474664626SKris Kennaway /* If the context has a default timeout, use it */ 3751f13597dSJung-uk Kim if (s->session_ctx->session_timeout == 0) 37674664626SKris Kennaway ss->timeout = SSL_get_default_timeout(s); 37774664626SKris Kennaway else 3781f13597dSJung-uk Kim ss->timeout = s->session_ctx->session_timeout; 37974664626SKris Kennaway 38074664626SKris Kennaway SSL_SESSION_free(s->session); 38174664626SKris Kennaway s->session = NULL; 38274664626SKris Kennaway 3836f9291ceSJung-uk Kim if (session) { 384e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) { 3856f9291ceSJung-uk Kim /* 386e71b7053SJung-uk Kim * We generate the session id while constructing the 387e71b7053SJung-uk Kim * NewSessionTicket in TLSv1.3. 3886f9291ceSJung-uk Kim */ 389e71b7053SJung-uk Kim ss->session_id_length = 0; 390e71b7053SJung-uk Kim } else if (!ssl_generate_session_id(s, ss)) { 391e71b7053SJung-uk Kim /* SSLfatal() already called */ 392db522d3aSSimon L. B. Nielsen SSL_SESSION_free(ss); 393db522d3aSSimon L. B. Nielsen return 0; 394db522d3aSSimon L. B. Nielsen } 395e71b7053SJung-uk Kim 3966f9291ceSJung-uk Kim } else { 39774664626SKris Kennaway ss->session_id_length = 0; 39874664626SKris Kennaway } 39974664626SKris Kennaway 400dee36b4fSJung-uk Kim if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { 401e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, 402e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 40348454956SJacques Vidrine SSL_SESSION_free(ss); 40448454956SJacques Vidrine return 0; 40548454956SJacques Vidrine } 40674664626SKris Kennaway memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); 40774664626SKris Kennaway ss->sid_ctx_length = s->sid_ctx_length; 40874664626SKris Kennaway s->session = ss; 40974664626SKris Kennaway ss->ssl_version = s->version; 410f579bf8eSKris Kennaway ss->verify_result = X509_V_OK; 41174664626SKris Kennaway 412e71b7053SJung-uk Kim /* If client supports extended master secret set it in session */ 413e71b7053SJung-uk Kim if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) 414e71b7053SJung-uk Kim ss->flags |= SSL_SESS_FLAG_EXTMS; 415e71b7053SJung-uk Kim 416e71b7053SJung-uk Kim return 1; 41774664626SKris Kennaway } 41874664626SKris Kennaway 419e71b7053SJung-uk Kim SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, 420e71b7053SJung-uk Kim size_t sess_id_len) 42174664626SKris Kennaway { 422db522d3aSSimon L. B. Nielsen SSL_SESSION *ret = NULL; 42374664626SKris Kennaway 424e71b7053SJung-uk Kim if ((s->session_ctx->session_cache_mode 425e71b7053SJung-uk Kim & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { 426db522d3aSSimon L. B. Nielsen SSL_SESSION data; 427e71b7053SJung-uk Kim 428db522d3aSSimon L. B. Nielsen data.ssl_version = s->version; 429e71b7053SJung-uk Kim if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH)) 430e71b7053SJung-uk Kim return NULL; 431e71b7053SJung-uk Kim 432e71b7053SJung-uk Kim memcpy(data.session_id, sess_id, sess_id_len); 433e71b7053SJung-uk Kim data.session_id_length = sess_id_len; 434e71b7053SJung-uk Kim 435e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->session_ctx->lock); 4361f13597dSJung-uk Kim ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); 4376f9291ceSJung-uk Kim if (ret != NULL) { 43874664626SKris Kennaway /* don't allow other threads to steal it: */ 439e71b7053SJung-uk Kim SSL_SESSION_up_ref(ret); 4401f13597dSJung-uk Kim } 441e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->session_ctx->lock); 4421f13597dSJung-uk Kim if (ret == NULL) 443e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_miss); 44474664626SKris Kennaway } 44574664626SKris Kennaway 446e71b7053SJung-uk Kim if (ret == NULL && s->session_ctx->get_session_cb != NULL) { 44774664626SKris Kennaway int copy = 1; 44874664626SKris Kennaway 449e71b7053SJung-uk Kim ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); 450e71b7053SJung-uk Kim 451e71b7053SJung-uk Kim if (ret != NULL) { 452e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_cb_hit); 45374664626SKris Kennaway 4546f9291ceSJung-uk Kim /* 4556f9291ceSJung-uk Kim * Increment reference count now if the session callback asks us 4566f9291ceSJung-uk Kim * to do so (note that if the session structures returned by the 4576f9291ceSJung-uk Kim * callback are shared between threads, it must handle the 4586f9291ceSJung-uk Kim * reference count itself [i.e. copy == 0], or things won't be 4596f9291ceSJung-uk Kim * thread-safe). 4606f9291ceSJung-uk Kim */ 46174664626SKris Kennaway if (copy) 462e71b7053SJung-uk Kim SSL_SESSION_up_ref(ret); 46374664626SKris Kennaway 4646f9291ceSJung-uk Kim /* 4656f9291ceSJung-uk Kim * Add the externally cached session to the internal cache as 4666f9291ceSJung-uk Kim * well if and only if we are supposed to. 4676f9291ceSJung-uk Kim */ 468e71b7053SJung-uk Kim if ((s->session_ctx->session_cache_mode & 469e71b7053SJung-uk Kim SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { 4706f9291ceSJung-uk Kim /* 471e71b7053SJung-uk Kim * Either return value of SSL_CTX_add_session should not 472e71b7053SJung-uk Kim * interrupt the session resumption process. The return 473e71b7053SJung-uk Kim * value is intentionally ignored. 4746f9291ceSJung-uk Kim */ 475e71b7053SJung-uk Kim (void)SSL_CTX_add_session(s->session_ctx, ret); 476e71b7053SJung-uk Kim } 477e71b7053SJung-uk Kim } 478e71b7053SJung-uk Kim } 479e71b7053SJung-uk Kim 480e71b7053SJung-uk Kim return ret; 481e71b7053SJung-uk Kim } 482e71b7053SJung-uk Kim 483e71b7053SJung-uk Kim /*- 484e71b7053SJung-uk Kim * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this 485e71b7053SJung-uk Kim * connection. It is only called by servers. 486e71b7053SJung-uk Kim * 487e71b7053SJung-uk Kim * hello: The parsed ClientHello data 488e71b7053SJung-uk Kim * 489e71b7053SJung-uk Kim * Returns: 490e71b7053SJung-uk Kim * -1: fatal error 491e71b7053SJung-uk Kim * 0: no session found 492e71b7053SJung-uk Kim * 1: a session may have been found. 493e71b7053SJung-uk Kim * 494e71b7053SJung-uk Kim * Side effects: 495e71b7053SJung-uk Kim * - If a session is found then s->session is pointed at it (after freeing an 496e71b7053SJung-uk Kim * existing session if need be) and s->verify_result is set from the session. 497e71b7053SJung-uk Kim * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 498e71b7053SJung-uk Kim * if the server should issue a new session ticket (to 0 otherwise). 499e71b7053SJung-uk Kim */ 500e71b7053SJung-uk Kim int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) 501e71b7053SJung-uk Kim { 502e71b7053SJung-uk Kim /* This is used only by servers. */ 503e71b7053SJung-uk Kim 504e71b7053SJung-uk Kim SSL_SESSION *ret = NULL; 505e71b7053SJung-uk Kim int fatal = 0; 506e71b7053SJung-uk Kim int try_session_cache = 0; 507e71b7053SJung-uk Kim SSL_TICKET_STATUS r; 508e71b7053SJung-uk Kim 509e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) { 510e71b7053SJung-uk Kim /* 511e71b7053SJung-uk Kim * By default we will send a new ticket. This can be overridden in the 512e71b7053SJung-uk Kim * ticket processing. 513e71b7053SJung-uk Kim */ 514e71b7053SJung-uk Kim s->ext.ticket_expected = 1; 515e71b7053SJung-uk Kim if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, 516e71b7053SJung-uk Kim SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, 517e71b7053SJung-uk Kim NULL, 0) 518e71b7053SJung-uk Kim || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, 519e71b7053SJung-uk Kim hello->pre_proc_exts, NULL, 0)) 520e71b7053SJung-uk Kim return -1; 521e71b7053SJung-uk Kim 522e71b7053SJung-uk Kim ret = s->session; 523e71b7053SJung-uk Kim } else { 524e71b7053SJung-uk Kim /* sets s->ext.ticket_expected */ 525e71b7053SJung-uk Kim r = tls_get_ticket_from_client(s, hello, &ret); 526e71b7053SJung-uk Kim switch (r) { 527e71b7053SJung-uk Kim case SSL_TICKET_FATAL_ERR_MALLOC: 528e71b7053SJung-uk Kim case SSL_TICKET_FATAL_ERR_OTHER: 529e71b7053SJung-uk Kim fatal = 1; 530e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, 531e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 532e71b7053SJung-uk Kim goto err; 533e71b7053SJung-uk Kim case SSL_TICKET_NONE: 534e71b7053SJung-uk Kim case SSL_TICKET_EMPTY: 535e71b7053SJung-uk Kim if (hello->session_id_len > 0) { 536e71b7053SJung-uk Kim try_session_cache = 1; 537e71b7053SJung-uk Kim ret = lookup_sess_in_cache(s, hello->session_id, 538e71b7053SJung-uk Kim hello->session_id_len); 539e71b7053SJung-uk Kim } 540e71b7053SJung-uk Kim break; 541e71b7053SJung-uk Kim case SSL_TICKET_NO_DECRYPT: 542e71b7053SJung-uk Kim case SSL_TICKET_SUCCESS: 543e71b7053SJung-uk Kim case SSL_TICKET_SUCCESS_RENEW: 544e71b7053SJung-uk Kim break; 54574664626SKris Kennaway } 54674664626SKris Kennaway } 54774664626SKris Kennaway 5481f13597dSJung-uk Kim if (ret == NULL) 5491f13597dSJung-uk Kim goto err; 5501f13597dSJung-uk Kim 5511f13597dSJung-uk Kim /* Now ret is non-NULL and we own one of its reference counts. */ 55274664626SKris Kennaway 553e71b7053SJung-uk Kim /* Check TLS version consistency */ 554e71b7053SJung-uk Kim if (ret->ssl_version != s->version) 555e71b7053SJung-uk Kim goto err; 556e71b7053SJung-uk Kim 557db522d3aSSimon L. B. Nielsen if (ret->sid_ctx_length != s->sid_ctx_length 5586f9291ceSJung-uk Kim || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { 5596f9291ceSJung-uk Kim /* 5606f9291ceSJung-uk Kim * We have the session requested by the client, but we don't want to 5616f9291ceSJung-uk Kim * use it in this context. 5626f9291ceSJung-uk Kim */ 56374664626SKris Kennaway goto err; /* treat like cache miss */ 56474664626SKris Kennaway } 565db522d3aSSimon L. B. Nielsen 5666f9291ceSJung-uk Kim if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { 5676f9291ceSJung-uk Kim /* 5686f9291ceSJung-uk Kim * We can't be sure if this session is being used out of context, 5696f9291ceSJung-uk Kim * which is especially important for SSL_VERIFY_PEER. The application 5706f9291ceSJung-uk Kim * should have used SSL[_CTX]_set_session_id_context. For this error 5716f9291ceSJung-uk Kim * case, we generate an error instead of treating the event like a 5726f9291ceSJung-uk Kim * cache miss (otherwise it would be easy for applications to 5736f9291ceSJung-uk Kim * effectively disable the session cache by accident without anyone 5746f9291ceSJung-uk Kim * noticing). 575db522d3aSSimon L. B. Nielsen */ 576db522d3aSSimon L. B. Nielsen 577e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, 5786f9291ceSJung-uk Kim SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); 579db522d3aSSimon L. B. Nielsen fatal = 1; 580db522d3aSSimon L. B. Nielsen goto err; 58174664626SKris Kennaway } 58274664626SKris Kennaway 5836f9291ceSJung-uk Kim if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ 584e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_timeout); 5856f9291ceSJung-uk Kim if (try_session_cache) { 5861f13597dSJung-uk Kim /* session was from the cache, so remove it */ 5871f13597dSJung-uk Kim SSL_CTX_remove_session(s->session_ctx, ret); 5881f13597dSJung-uk Kim } 58974664626SKris Kennaway goto err; 59074664626SKris Kennaway } 59174664626SKris Kennaway 592e71b7053SJung-uk Kim /* Check extended master secret extension consistency */ 593e71b7053SJung-uk Kim if (ret->flags & SSL_SESS_FLAG_EXTMS) { 594e71b7053SJung-uk Kim /* If old session includes extms, but new does not: abort handshake */ 595e71b7053SJung-uk Kim if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { 596e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION, 597e71b7053SJung-uk Kim SSL_R_INCONSISTENT_EXTMS); 598e71b7053SJung-uk Kim fatal = 1; 599e71b7053SJung-uk Kim goto err; 600e71b7053SJung-uk Kim } 601e71b7053SJung-uk Kim } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { 602e71b7053SJung-uk Kim /* If new session includes extms, but old does not: do not resume */ 603e71b7053SJung-uk Kim goto err; 604e71b7053SJung-uk Kim } 60574664626SKris Kennaway 606e71b7053SJung-uk Kim if (!SSL_IS_TLS13(s)) { 607e71b7053SJung-uk Kim /* We already did this for TLS1.3 */ 60874664626SKris Kennaway SSL_SESSION_free(s->session); 60974664626SKris Kennaway s->session = ret; 610e71b7053SJung-uk Kim } 611e71b7053SJung-uk Kim 612e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_hit); 613f579bf8eSKris Kennaway s->verify_result = s->session->verify_result; 6141f13597dSJung-uk Kim return 1; 61574664626SKris Kennaway 61674664626SKris Kennaway err: 6176f9291ceSJung-uk Kim if (ret != NULL) { 61874664626SKris Kennaway SSL_SESSION_free(ret); 619e71b7053SJung-uk Kim /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ 620e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) 621e71b7053SJung-uk Kim s->session = NULL; 622e71b7053SJung-uk Kim 6236f9291ceSJung-uk Kim if (!try_session_cache) { 6246f9291ceSJung-uk Kim /* 6256f9291ceSJung-uk Kim * The session was from a ticket, so we should issue a ticket for 6266f9291ceSJung-uk Kim * the new session 6276f9291ceSJung-uk Kim */ 628e71b7053SJung-uk Kim s->ext.ticket_expected = 1; 6291f13597dSJung-uk Kim } 6301f13597dSJung-uk Kim } 63174664626SKris Kennaway if (fatal) 63274664626SKris Kennaway return -1; 633e71b7053SJung-uk Kim 63474664626SKris Kennaway return 0; 63574664626SKris Kennaway } 63674664626SKris Kennaway 63774664626SKris Kennaway int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) 63874664626SKris Kennaway { 63974664626SKris Kennaway int ret = 0; 64074664626SKris Kennaway SSL_SESSION *s; 64174664626SKris Kennaway 6426f9291ceSJung-uk Kim /* 6436f9291ceSJung-uk Kim * add just 1 reference count for the SSL_CTX's session cache even though 6446f9291ceSJung-uk Kim * it has two ways of access: each session is in a doubly linked list and 6456f9291ceSJung-uk Kim * an lhash 6466f9291ceSJung-uk Kim */ 647e71b7053SJung-uk Kim SSL_SESSION_up_ref(c); 6486f9291ceSJung-uk Kim /* 6496f9291ceSJung-uk Kim * if session c is in already in cache, we take back the increment later 6506f9291ceSJung-uk Kim */ 65174664626SKris Kennaway 652e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(ctx->lock); 6531f13597dSJung-uk Kim s = lh_SSL_SESSION_insert(ctx->sessions, c); 65474664626SKris Kennaway 6556f9291ceSJung-uk Kim /* 6566f9291ceSJung-uk Kim * s != NULL iff we already had a session with the given PID. In this 6576f9291ceSJung-uk Kim * case, s == c should hold (then we did not really modify 6586f9291ceSJung-uk Kim * ctx->sessions), or we're in trouble. 6596f9291ceSJung-uk Kim */ 6606f9291ceSJung-uk Kim if (s != NULL && s != c) { 661f579bf8eSKris Kennaway /* We *are* in trouble ... */ 662f579bf8eSKris Kennaway SSL_SESSION_list_remove(ctx, s); 663f579bf8eSKris Kennaway SSL_SESSION_free(s); 6646f9291ceSJung-uk Kim /* 6656f9291ceSJung-uk Kim * ... so pretend the other session did not exist in cache (we cannot 6666f9291ceSJung-uk Kim * handle two SSL_SESSION structures with identical session ID in the 6676f9291ceSJung-uk Kim * same cache, which could happen e.g. when two threads concurrently 6686f9291ceSJung-uk Kim * obtain the same session from an external cache) 6696f9291ceSJung-uk Kim */ 670f579bf8eSKris Kennaway s = NULL; 6716cf8931aSJung-uk Kim } else if (s == NULL && 6726cf8931aSJung-uk Kim lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { 6736cf8931aSJung-uk Kim /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ 6746cf8931aSJung-uk Kim 6756cf8931aSJung-uk Kim /* 6766cf8931aSJung-uk Kim * ... so take back the extra reference and also don't add 6776cf8931aSJung-uk Kim * the session to the SSL_SESSION_list at this time 6786cf8931aSJung-uk Kim */ 6796cf8931aSJung-uk Kim s = c; 680f579bf8eSKris Kennaway } 681f579bf8eSKris Kennaway 682f579bf8eSKris Kennaway /* Put at the head of the queue unless it is already in the cache */ 68374664626SKris Kennaway if (s == NULL) 68474664626SKris Kennaway SSL_SESSION_list_add(ctx, c); 68574664626SKris Kennaway 6866f9291ceSJung-uk Kim if (s != NULL) { 6876f9291ceSJung-uk Kim /* 6886f9291ceSJung-uk Kim * existing cache entry -- decrement previously incremented reference 6896f9291ceSJung-uk Kim * count because it already takes into account the cache 6906f9291ceSJung-uk Kim */ 691f579bf8eSKris Kennaway 692f579bf8eSKris Kennaway SSL_SESSION_free(s); /* s == c */ 69374664626SKris Kennaway ret = 0; 6946f9291ceSJung-uk Kim } else { 6956f9291ceSJung-uk Kim /* 6966f9291ceSJung-uk Kim * new cache entry -- remove old ones if cache has become too large 6976f9291ceSJung-uk Kim */ 698f579bf8eSKris Kennaway 69974664626SKris Kennaway ret = 1; 70074664626SKris Kennaway 7016f9291ceSJung-uk Kim if (SSL_CTX_sess_get_cache_size(ctx) > 0) { 702e71b7053SJung-uk Kim while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { 7036f9291ceSJung-uk Kim if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) 70474664626SKris Kennaway break; 70574664626SKris Kennaway else 706e71b7053SJung-uk Kim tsan_counter(&ctx->stats.sess_cache_full); 70774664626SKris Kennaway } 70874664626SKris Kennaway } 70974664626SKris Kennaway } 710e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ctx->lock); 711e71b7053SJung-uk Kim return ret; 71274664626SKris Kennaway } 71374664626SKris Kennaway 71474664626SKris Kennaway int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) 71574664626SKris Kennaway { 71674664626SKris Kennaway return remove_session_lock(ctx, c, 1); 71774664626SKris Kennaway } 71874664626SKris Kennaway 71974664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) 72074664626SKris Kennaway { 72174664626SKris Kennaway SSL_SESSION *r; 72274664626SKris Kennaway int ret = 0; 72374664626SKris Kennaway 7246f9291ceSJung-uk Kim if ((c != NULL) && (c->session_id_length != 0)) { 7256f9291ceSJung-uk Kim if (lck) 726e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(ctx->lock); 727e71b7053SJung-uk Kim if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { 72874664626SKris Kennaway ret = 1; 729e71b7053SJung-uk Kim r = lh_SSL_SESSION_delete(ctx->sessions, r); 730e71b7053SJung-uk Kim SSL_SESSION_list_remove(ctx, r); 73174664626SKris Kennaway } 732e71b7053SJung-uk Kim c->not_resumable = 1; 73374664626SKris Kennaway 7346f9291ceSJung-uk Kim if (lck) 735e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ctx->lock); 73674664626SKris Kennaway 73774664626SKris Kennaway if (ctx->remove_session_cb != NULL) 738e71b7053SJung-uk Kim ctx->remove_session_cb(ctx, c); 739e71b7053SJung-uk Kim 740e71b7053SJung-uk Kim if (ret) 74174664626SKris Kennaway SSL_SESSION_free(r); 7426f9291ceSJung-uk Kim } else 74374664626SKris Kennaway ret = 0; 744e71b7053SJung-uk Kim return ret; 74574664626SKris Kennaway } 74674664626SKris Kennaway 74774664626SKris Kennaway void SSL_SESSION_free(SSL_SESSION *ss) 74874664626SKris Kennaway { 74974664626SKris Kennaway int i; 75074664626SKris Kennaway 75174664626SKris Kennaway if (ss == NULL) 75274664626SKris Kennaway return; 753e71b7053SJung-uk Kim CRYPTO_DOWN_REF(&ss->references, &i, ss->lock); 754e71b7053SJung-uk Kim REF_PRINT_COUNT("SSL_SESSION", ss); 7556f9291ceSJung-uk Kim if (i > 0) 7566f9291ceSJung-uk Kim return; 757e71b7053SJung-uk Kim REF_ASSERT_ISNT(i < 0); 75874664626SKris Kennaway 7595c87c606SMark Murray CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); 76074664626SKris Kennaway 761dee36b4fSJung-uk Kim OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key)); 762dee36b4fSJung-uk Kim OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id)); 7636f9291ceSJung-uk Kim X509_free(ss->peer); 764e71b7053SJung-uk Kim sk_X509_pop_free(ss->peer_chain, X509_free); 765e71b7053SJung-uk Kim OPENSSL_free(ss->ext.hostname); 766e71b7053SJung-uk Kim OPENSSL_free(ss->ext.tick); 7671f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK 7681f13597dSJung-uk Kim OPENSSL_free(ss->psk_identity_hint); 7691f13597dSJung-uk Kim OPENSSL_free(ss->psk_identity); 7701f13597dSJung-uk Kim #endif 7711f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 7721f13597dSJung-uk Kim OPENSSL_free(ss->srp_username); 773db522d3aSSimon L. B. Nielsen #endif 774e71b7053SJung-uk Kim OPENSSL_free(ss->ext.alpn_selected); 775e71b7053SJung-uk Kim OPENSSL_free(ss->ticket_appdata); 776e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(ss->lock); 777e71b7053SJung-uk Kim OPENSSL_clear_free(ss, sizeof(*ss)); 778e71b7053SJung-uk Kim } 779e71b7053SJung-uk Kim 780e71b7053SJung-uk Kim int SSL_SESSION_up_ref(SSL_SESSION *ss) 781e71b7053SJung-uk Kim { 782e71b7053SJung-uk Kim int i; 783e71b7053SJung-uk Kim 784e71b7053SJung-uk Kim if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0) 785e71b7053SJung-uk Kim return 0; 786e71b7053SJung-uk Kim 787e71b7053SJung-uk Kim REF_PRINT_COUNT("SSL_SESSION", ss); 788e71b7053SJung-uk Kim REF_ASSERT_ISNT(i < 2); 789e71b7053SJung-uk Kim return ((i > 1) ? 1 : 0); 79074664626SKris Kennaway } 79174664626SKris Kennaway 79274664626SKris Kennaway int SSL_set_session(SSL *s, SSL_SESSION *session) 79374664626SKris Kennaway { 794e71b7053SJung-uk Kim ssl_clear_bad_session(s); 795e71b7053SJung-uk Kim if (s->ctx->method != s->method) { 796e71b7053SJung-uk Kim if (!SSL_set_ssl_method(s, s->ctx->method)) 797aeb5019cSJung-uk Kim return 0; 798aeb5019cSJung-uk Kim } 7995c87c606SMark Murray 800e71b7053SJung-uk Kim if (session != NULL) { 801e71b7053SJung-uk Kim SSL_SESSION_up_ref(session); 802e71b7053SJung-uk Kim s->verify_result = session->verify_result; 803e71b7053SJung-uk Kim } 80474664626SKris Kennaway SSL_SESSION_free(s->session); 80574664626SKris Kennaway s->session = session; 806e71b7053SJung-uk Kim 807e71b7053SJung-uk Kim return 1; 80874664626SKris Kennaway } 80974664626SKris Kennaway 810e71b7053SJung-uk Kim int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, 811e71b7053SJung-uk Kim unsigned int sid_len) 812e71b7053SJung-uk Kim { 813e71b7053SJung-uk Kim if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { 814e71b7053SJung-uk Kim SSLerr(SSL_F_SSL_SESSION_SET1_ID, 815e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_TOO_LONG); 816e71b7053SJung-uk Kim return 0; 81774664626SKris Kennaway } 818e71b7053SJung-uk Kim s->session_id_length = sid_len; 819e71b7053SJung-uk Kim if (sid != s->session_id) 820e71b7053SJung-uk Kim memcpy(s->session_id, sid, sid_len); 821e71b7053SJung-uk Kim return 1; 82274664626SKris Kennaway } 82374664626SKris Kennaway 82474664626SKris Kennaway long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) 82574664626SKris Kennaway { 8266f9291ceSJung-uk Kim if (s == NULL) 827e71b7053SJung-uk Kim return 0; 82874664626SKris Kennaway s->timeout = t; 829e71b7053SJung-uk Kim return 1; 83074664626SKris Kennaway } 83174664626SKris Kennaway 8323b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_timeout(const SSL_SESSION *s) 83374664626SKris Kennaway { 8346f9291ceSJung-uk Kim if (s == NULL) 835e71b7053SJung-uk Kim return 0; 836e71b7053SJung-uk Kim return s->timeout; 83774664626SKris Kennaway } 83874664626SKris Kennaway 8393b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_time(const SSL_SESSION *s) 84074664626SKris Kennaway { 8416f9291ceSJung-uk Kim if (s == NULL) 842e71b7053SJung-uk Kim return 0; 843e71b7053SJung-uk Kim return s->time; 84474664626SKris Kennaway } 84574664626SKris Kennaway 84674664626SKris Kennaway long SSL_SESSION_set_time(SSL_SESSION *s, long t) 84774664626SKris Kennaway { 8486f9291ceSJung-uk Kim if (s == NULL) 849e71b7053SJung-uk Kim return 0; 85074664626SKris Kennaway s->time = t; 851e71b7053SJung-uk Kim return t; 852e71b7053SJung-uk Kim } 853e71b7053SJung-uk Kim 854e71b7053SJung-uk Kim int SSL_SESSION_get_protocol_version(const SSL_SESSION *s) 855e71b7053SJung-uk Kim { 856e71b7053SJung-uk Kim return s->ssl_version; 857e71b7053SJung-uk Kim } 858e71b7053SJung-uk Kim 859e71b7053SJung-uk Kim int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version) 860e71b7053SJung-uk Kim { 861e71b7053SJung-uk Kim s->ssl_version = version; 862e71b7053SJung-uk Kim return 1; 863e71b7053SJung-uk Kim } 864e71b7053SJung-uk Kim 865e71b7053SJung-uk Kim const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s) 866e71b7053SJung-uk Kim { 867e71b7053SJung-uk Kim return s->cipher; 868e71b7053SJung-uk Kim } 869e71b7053SJung-uk Kim 870e71b7053SJung-uk Kim int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher) 871e71b7053SJung-uk Kim { 872e71b7053SJung-uk Kim s->cipher = cipher; 873e71b7053SJung-uk Kim return 1; 874e71b7053SJung-uk Kim } 875e71b7053SJung-uk Kim 876e71b7053SJung-uk Kim const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) 877e71b7053SJung-uk Kim { 878e71b7053SJung-uk Kim return s->ext.hostname; 879e71b7053SJung-uk Kim } 880e71b7053SJung-uk Kim 881e71b7053SJung-uk Kim int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname) 882e71b7053SJung-uk Kim { 883e71b7053SJung-uk Kim OPENSSL_free(s->ext.hostname); 884e71b7053SJung-uk Kim if (hostname == NULL) { 885e71b7053SJung-uk Kim s->ext.hostname = NULL; 886e71b7053SJung-uk Kim return 1; 887e71b7053SJung-uk Kim } 888e71b7053SJung-uk Kim s->ext.hostname = OPENSSL_strdup(hostname); 889e71b7053SJung-uk Kim 890e71b7053SJung-uk Kim return s->ext.hostname != NULL; 891e71b7053SJung-uk Kim } 892e71b7053SJung-uk Kim 893e71b7053SJung-uk Kim int SSL_SESSION_has_ticket(const SSL_SESSION *s) 894e71b7053SJung-uk Kim { 895e71b7053SJung-uk Kim return (s->ext.ticklen > 0) ? 1 : 0; 896e71b7053SJung-uk Kim } 897e71b7053SJung-uk Kim 898e71b7053SJung-uk Kim unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) 899e71b7053SJung-uk Kim { 900e71b7053SJung-uk Kim return s->ext.tick_lifetime_hint; 901e71b7053SJung-uk Kim } 902e71b7053SJung-uk Kim 903e71b7053SJung-uk Kim void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, 904e71b7053SJung-uk Kim size_t *len) 905e71b7053SJung-uk Kim { 906e71b7053SJung-uk Kim *len = s->ext.ticklen; 907e71b7053SJung-uk Kim if (tick != NULL) 908e71b7053SJung-uk Kim *tick = s->ext.tick; 909e71b7053SJung-uk Kim } 910e71b7053SJung-uk Kim 911e71b7053SJung-uk Kim uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) 912e71b7053SJung-uk Kim { 913e71b7053SJung-uk Kim return s->ext.max_early_data; 914e71b7053SJung-uk Kim } 915e71b7053SJung-uk Kim 916e71b7053SJung-uk Kim int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) 917e71b7053SJung-uk Kim { 918e71b7053SJung-uk Kim s->ext.max_early_data = max_early_data; 919e71b7053SJung-uk Kim 920e71b7053SJung-uk Kim return 1; 921e71b7053SJung-uk Kim } 922e71b7053SJung-uk Kim 923e71b7053SJung-uk Kim void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, 924e71b7053SJung-uk Kim const unsigned char **alpn, 925e71b7053SJung-uk Kim size_t *len) 926e71b7053SJung-uk Kim { 927e71b7053SJung-uk Kim *alpn = s->ext.alpn_selected; 928e71b7053SJung-uk Kim *len = s->ext.alpn_selected_len; 929e71b7053SJung-uk Kim } 930e71b7053SJung-uk Kim 931e71b7053SJung-uk Kim int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn, 932e71b7053SJung-uk Kim size_t len) 933e71b7053SJung-uk Kim { 934e71b7053SJung-uk Kim OPENSSL_free(s->ext.alpn_selected); 935e71b7053SJung-uk Kim if (alpn == NULL || len == 0) { 936e71b7053SJung-uk Kim s->ext.alpn_selected = NULL; 937e71b7053SJung-uk Kim s->ext.alpn_selected_len = 0; 938e71b7053SJung-uk Kim return 1; 939e71b7053SJung-uk Kim } 940e71b7053SJung-uk Kim s->ext.alpn_selected = OPENSSL_memdup(alpn, len); 941e71b7053SJung-uk Kim if (s->ext.alpn_selected == NULL) { 942e71b7053SJung-uk Kim s->ext.alpn_selected_len = 0; 943e71b7053SJung-uk Kim return 0; 944e71b7053SJung-uk Kim } 945e71b7053SJung-uk Kim s->ext.alpn_selected_len = len; 946e71b7053SJung-uk Kim 947e71b7053SJung-uk Kim return 1; 94874664626SKris Kennaway } 94974664626SKris Kennaway 9501f13597dSJung-uk Kim X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) 9511f13597dSJung-uk Kim { 9521f13597dSJung-uk Kim return s->peer; 9531f13597dSJung-uk Kim } 9541f13597dSJung-uk Kim 9551f13597dSJung-uk Kim int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, 9561f13597dSJung-uk Kim unsigned int sid_ctx_len) 9571f13597dSJung-uk Kim { 9586f9291ceSJung-uk Kim if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { 9596f9291ceSJung-uk Kim SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT, 9606f9291ceSJung-uk Kim SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); 9611f13597dSJung-uk Kim return 0; 9621f13597dSJung-uk Kim } 9631f13597dSJung-uk Kim s->sid_ctx_length = sid_ctx_len; 964e71b7053SJung-uk Kim if (sid_ctx != s->sid_ctx) 9651f13597dSJung-uk Kim memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); 9661f13597dSJung-uk Kim 9671f13597dSJung-uk Kim return 1; 9681f13597dSJung-uk Kim } 9691f13597dSJung-uk Kim 970e71b7053SJung-uk Kim int SSL_SESSION_is_resumable(const SSL_SESSION *s) 971e71b7053SJung-uk Kim { 972e71b7053SJung-uk Kim /* 973e71b7053SJung-uk Kim * In the case of EAP-FAST, we can have a pre-shared "ticket" without a 974e71b7053SJung-uk Kim * session ID. 975e71b7053SJung-uk Kim */ 976e71b7053SJung-uk Kim return !s->not_resumable 977e71b7053SJung-uk Kim && (s->session_id_length > 0 || s->ext.ticklen > 0); 978e71b7053SJung-uk Kim } 979e71b7053SJung-uk Kim 98074664626SKris Kennaway long SSL_CTX_set_timeout(SSL_CTX *s, long t) 98174664626SKris Kennaway { 98274664626SKris Kennaway long l; 9836f9291ceSJung-uk Kim if (s == NULL) 984e71b7053SJung-uk Kim return 0; 98574664626SKris Kennaway l = s->session_timeout; 98674664626SKris Kennaway s->session_timeout = t; 987e71b7053SJung-uk Kim return l; 98874664626SKris Kennaway } 98974664626SKris Kennaway 9903b4e3dcbSSimon L. B. Nielsen long SSL_CTX_get_timeout(const SSL_CTX *s) 99174664626SKris Kennaway { 9926f9291ceSJung-uk Kim if (s == NULL) 993e71b7053SJung-uk Kim return 0; 994e71b7053SJung-uk Kim return s->session_timeout; 99574664626SKris Kennaway } 99674664626SKris Kennaway 9976f9291ceSJung-uk Kim int SSL_set_session_secret_cb(SSL *s, 998e71b7053SJung-uk Kim tls_session_secret_cb_fn tls_session_secret_cb, 9996f9291ceSJung-uk Kim void *arg) 10001f13597dSJung-uk Kim { 10016f9291ceSJung-uk Kim if (s == NULL) 1002e71b7053SJung-uk Kim return 0; 1003e71b7053SJung-uk Kim s->ext.session_secret_cb = tls_session_secret_cb; 1004e71b7053SJung-uk Kim s->ext.session_secret_cb_arg = arg; 1005e71b7053SJung-uk Kim return 1; 10061f13597dSJung-uk Kim } 10071f13597dSJung-uk Kim 10081f13597dSJung-uk Kim int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, 10091f13597dSJung-uk Kim void *arg) 10101f13597dSJung-uk Kim { 10116f9291ceSJung-uk Kim if (s == NULL) 1012e71b7053SJung-uk Kim return 0; 1013e71b7053SJung-uk Kim s->ext.session_ticket_cb = cb; 1014e71b7053SJung-uk Kim s->ext.session_ticket_cb_arg = arg; 1015e71b7053SJung-uk Kim return 1; 10161f13597dSJung-uk Kim } 10171f13597dSJung-uk Kim 10181f13597dSJung-uk Kim int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) 10191f13597dSJung-uk Kim { 10206f9291ceSJung-uk Kim if (s->version >= TLS1_VERSION) { 1021e71b7053SJung-uk Kim OPENSSL_free(s->ext.session_ticket); 1022e71b7053SJung-uk Kim s->ext.session_ticket = NULL; 1023e71b7053SJung-uk Kim s->ext.session_ticket = 10246f9291ceSJung-uk Kim OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); 1025e71b7053SJung-uk Kim if (s->ext.session_ticket == NULL) { 10261f13597dSJung-uk Kim SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); 10271f13597dSJung-uk Kim return 0; 10281f13597dSJung-uk Kim } 10291f13597dSJung-uk Kim 1030e71b7053SJung-uk Kim if (ext_data != NULL) { 1031e71b7053SJung-uk Kim s->ext.session_ticket->length = ext_len; 1032e71b7053SJung-uk Kim s->ext.session_ticket->data = s->ext.session_ticket + 1; 1033e71b7053SJung-uk Kim memcpy(s->ext.session_ticket->data, ext_data, ext_len); 10346f9291ceSJung-uk Kim } else { 1035e71b7053SJung-uk Kim s->ext.session_ticket->length = 0; 1036e71b7053SJung-uk Kim s->ext.session_ticket->data = NULL; 10371f13597dSJung-uk Kim } 10381f13597dSJung-uk Kim 10391f13597dSJung-uk Kim return 1; 10401f13597dSJung-uk Kim } 10411f13597dSJung-uk Kim 10421f13597dSJung-uk Kim return 0; 10431f13597dSJung-uk Kim } 10441f13597dSJung-uk Kim 10456f9291ceSJung-uk Kim typedef struct timeout_param_st { 104674664626SKris Kennaway SSL_CTX *ctx; 104774664626SKris Kennaway long time; 10481f13597dSJung-uk Kim LHASH_OF(SSL_SESSION) *cache; 104974664626SKris Kennaway } TIMEOUT_PARAM; 105074664626SKris Kennaway 1051e71b7053SJung-uk Kim static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p) 105274664626SKris Kennaway { 10536f9291ceSJung-uk Kim if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */ 10546f9291ceSJung-uk Kim /* 10556f9291ceSJung-uk Kim * The reason we don't call SSL_CTX_remove_session() is to save on 10566f9291ceSJung-uk Kim * locking overhead 10576f9291ceSJung-uk Kim */ 10581f13597dSJung-uk Kim (void)lh_SSL_SESSION_delete(p->cache, s); 105974664626SKris Kennaway SSL_SESSION_list_remove(p->ctx, s); 106074664626SKris Kennaway s->not_resumable = 1; 106174664626SKris Kennaway if (p->ctx->remove_session_cb != NULL) 106274664626SKris Kennaway p->ctx->remove_session_cb(p->ctx, s); 106374664626SKris Kennaway SSL_SESSION_free(s); 106474664626SKris Kennaway } 106574664626SKris Kennaway } 106674664626SKris Kennaway 1067e71b7053SJung-uk Kim IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM); 10685c87c606SMark Murray 106974664626SKris Kennaway void SSL_CTX_flush_sessions(SSL_CTX *s, long t) 107074664626SKris Kennaway { 107174664626SKris Kennaway unsigned long i; 107274664626SKris Kennaway TIMEOUT_PARAM tp; 107374664626SKris Kennaway 107474664626SKris Kennaway tp.ctx = s; 107574664626SKris Kennaway tp.cache = s->sessions; 10766f9291ceSJung-uk Kim if (tp.cache == NULL) 10776f9291ceSJung-uk Kim return; 107874664626SKris Kennaway tp.time = t; 1079e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(s->lock); 1080e71b7053SJung-uk Kim i = lh_SSL_SESSION_get_down_load(s->sessions); 1081e71b7053SJung-uk Kim lh_SSL_SESSION_set_down_load(s->sessions, 0); 1082e71b7053SJung-uk Kim lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); 1083e71b7053SJung-uk Kim lh_SSL_SESSION_set_down_load(s->sessions, i); 1084e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->lock); 108574664626SKris Kennaway } 108674664626SKris Kennaway 108774664626SKris Kennaway int ssl_clear_bad_session(SSL *s) 108874664626SKris Kennaway { 108974664626SKris Kennaway if ((s->session != NULL) && 109074664626SKris Kennaway !(s->shutdown & SSL_SENT_SHUTDOWN) && 10916f9291ceSJung-uk Kim !(SSL_in_init(s) || SSL_in_before(s))) { 1092aeb5019cSJung-uk Kim SSL_CTX_remove_session(s->session_ctx, s->session); 1093e71b7053SJung-uk Kim return 1; 10946f9291ceSJung-uk Kim } else 1095e71b7053SJung-uk Kim return 0; 109674664626SKris Kennaway } 109774664626SKris Kennaway 109874664626SKris Kennaway /* locked by SSL_CTX in the calling function */ 109974664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) 110074664626SKris Kennaway { 11016f9291ceSJung-uk Kim if ((s->next == NULL) || (s->prev == NULL)) 11026f9291ceSJung-uk Kim return; 110374664626SKris Kennaway 11046f9291ceSJung-uk Kim if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { 11056f9291ceSJung-uk Kim /* last element in list */ 11066f9291ceSJung-uk Kim if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 11076f9291ceSJung-uk Kim /* only one element in list */ 110874664626SKris Kennaway ctx->session_cache_head = NULL; 110974664626SKris Kennaway ctx->session_cache_tail = NULL; 11106f9291ceSJung-uk Kim } else { 111174664626SKris Kennaway ctx->session_cache_tail = s->prev; 111274664626SKris Kennaway s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); 111374664626SKris Kennaway } 11146f9291ceSJung-uk Kim } else { 11156f9291ceSJung-uk Kim if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 11166f9291ceSJung-uk Kim /* first element in list */ 111774664626SKris Kennaway ctx->session_cache_head = s->next; 111874664626SKris Kennaway s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); 11196f9291ceSJung-uk Kim } else { 11206f9291ceSJung-uk Kim /* middle of list */ 112174664626SKris Kennaway s->next->prev = s->prev; 112274664626SKris Kennaway s->prev->next = s->next; 112374664626SKris Kennaway } 112474664626SKris Kennaway } 112574664626SKris Kennaway s->prev = s->next = NULL; 112674664626SKris Kennaway } 112774664626SKris Kennaway 112874664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) 112974664626SKris Kennaway { 113074664626SKris Kennaway if ((s->next != NULL) && (s->prev != NULL)) 113174664626SKris Kennaway SSL_SESSION_list_remove(ctx, s); 113274664626SKris Kennaway 11336f9291ceSJung-uk Kim if (ctx->session_cache_head == NULL) { 113474664626SKris Kennaway ctx->session_cache_head = s; 113574664626SKris Kennaway ctx->session_cache_tail = s; 113674664626SKris Kennaway s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 113774664626SKris Kennaway s->next = (SSL_SESSION *)&(ctx->session_cache_tail); 11386f9291ceSJung-uk Kim } else { 113974664626SKris Kennaway s->next = ctx->session_cache_head; 114074664626SKris Kennaway s->next->prev = s; 114174664626SKris Kennaway s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 114274664626SKris Kennaway ctx->session_cache_head = s; 114374664626SKris Kennaway } 114474664626SKris Kennaway } 114574664626SKris Kennaway 11465471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, 1147e71b7053SJung-uk Kim int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) 11485471f83eSSimon L. B. Nielsen { 11495471f83eSSimon L. B. Nielsen ctx->new_session_cb = cb; 11505471f83eSSimon L. B. Nielsen } 11515471f83eSSimon L. B. Nielsen 11526f9291ceSJung-uk Kim int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { 11535471f83eSSimon L. B. Nielsen return ctx->new_session_cb; 11545471f83eSSimon L. B. Nielsen } 11555471f83eSSimon L. B. Nielsen 11565471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, 11575471f83eSSimon L. B. Nielsen void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) 11585471f83eSSimon L. B. Nielsen { 11595471f83eSSimon L. B. Nielsen ctx->remove_session_cb = cb; 11605471f83eSSimon L. B. Nielsen } 11615471f83eSSimon L. B. Nielsen 11626f9291ceSJung-uk Kim void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, 11636f9291ceSJung-uk Kim SSL_SESSION *sess) { 11645471f83eSSimon L. B. Nielsen return ctx->remove_session_cb; 11655471f83eSSimon L. B. Nielsen } 11665471f83eSSimon L. B. Nielsen 11675471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, 11685471f83eSSimon L. B. Nielsen SSL_SESSION *(*cb) (struct ssl_st *ssl, 1169e71b7053SJung-uk Kim const unsigned char *data, 1170e71b7053SJung-uk Kim int len, int *copy)) 11715471f83eSSimon L. B. Nielsen { 11725471f83eSSimon L. B. Nielsen ctx->get_session_cb = cb; 11735471f83eSSimon L. B. Nielsen } 11745471f83eSSimon L. B. Nielsen 11755471f83eSSimon L. B. Nielsen SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, 1176e71b7053SJung-uk Kim const unsigned char 1177e71b7053SJung-uk Kim *data, int len, 1178e71b7053SJung-uk Kim int *copy) { 11795471f83eSSimon L. B. Nielsen return ctx->get_session_cb; 11805471f83eSSimon L. B. Nielsen } 11815471f83eSSimon L. B. Nielsen 11825471f83eSSimon L. B. Nielsen void SSL_CTX_set_info_callback(SSL_CTX *ctx, 11835471f83eSSimon L. B. Nielsen void (*cb) (const SSL *ssl, int type, int val)) 11845471f83eSSimon L. B. Nielsen { 11855471f83eSSimon L. B. Nielsen ctx->info_callback = cb; 11865471f83eSSimon L. B. Nielsen } 11875471f83eSSimon L. B. Nielsen 11886f9291ceSJung-uk Kim void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, 11896f9291ceSJung-uk Kim int val) { 11905471f83eSSimon L. B. Nielsen return ctx->info_callback; 11915471f83eSSimon L. B. Nielsen } 11925471f83eSSimon L. B. Nielsen 11935471f83eSSimon L. B. Nielsen void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, 11946f9291ceSJung-uk Kim int (*cb) (SSL *ssl, X509 **x509, 11956f9291ceSJung-uk Kim EVP_PKEY **pkey)) 11965471f83eSSimon L. B. Nielsen { 11975471f83eSSimon L. B. Nielsen ctx->client_cert_cb = cb; 11985471f83eSSimon L. B. Nielsen } 11995471f83eSSimon L. B. Nielsen 12006f9291ceSJung-uk Kim int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, 12016f9291ceSJung-uk Kim EVP_PKEY **pkey) { 12025471f83eSSimon L. B. Nielsen return ctx->client_cert_cb; 12035471f83eSSimon L. B. Nielsen } 12045471f83eSSimon L. B. Nielsen 1205db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_ENGINE 1206db522d3aSSimon L. B. Nielsen int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) 1207db522d3aSSimon L. B. Nielsen { 12086f9291ceSJung-uk Kim if (!ENGINE_init(e)) { 1209db522d3aSSimon L. B. Nielsen SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB); 1210db522d3aSSimon L. B. Nielsen return 0; 1211db522d3aSSimon L. B. Nielsen } 12126f9291ceSJung-uk Kim if (!ENGINE_get_ssl_client_cert_function(e)) { 12136f9291ceSJung-uk Kim SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, 12146f9291ceSJung-uk Kim SSL_R_NO_CLIENT_CERT_METHOD); 1215db522d3aSSimon L. B. Nielsen ENGINE_finish(e); 1216db522d3aSSimon L. B. Nielsen return 0; 1217db522d3aSSimon L. B. Nielsen } 1218db522d3aSSimon L. B. Nielsen ctx->client_cert_engine = e; 1219db522d3aSSimon L. B. Nielsen return 1; 1220db522d3aSSimon L. B. Nielsen } 1221db522d3aSSimon L. B. Nielsen #endif 1222db522d3aSSimon L. B. Nielsen 12235471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, 12246f9291ceSJung-uk Kim int (*cb) (SSL *ssl, 12256f9291ceSJung-uk Kim unsigned char *cookie, 12266f9291ceSJung-uk Kim unsigned int *cookie_len)) 12275471f83eSSimon L. B. Nielsen { 12285471f83eSSimon L. B. Nielsen ctx->app_gen_cookie_cb = cb; 12295471f83eSSimon L. B. Nielsen } 12305471f83eSSimon L. B. Nielsen 12315471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, 1232e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1233e71b7053SJung-uk Kim const unsigned char *cookie, 12346f9291ceSJung-uk Kim unsigned int cookie_len)) 12355471f83eSSimon L. B. Nielsen { 12365471f83eSSimon L. B. Nielsen ctx->app_verify_cookie_cb = cb; 12375471f83eSSimon L. B. Nielsen } 12385471f83eSSimon L. B. Nielsen 1239e71b7053SJung-uk Kim int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) 1240e71b7053SJung-uk Kim { 1241e71b7053SJung-uk Kim OPENSSL_free(ss->ticket_appdata); 1242e71b7053SJung-uk Kim ss->ticket_appdata_len = 0; 1243e71b7053SJung-uk Kim if (data == NULL || len == 0) { 1244e71b7053SJung-uk Kim ss->ticket_appdata = NULL; 1245e71b7053SJung-uk Kim return 1; 1246e71b7053SJung-uk Kim } 1247e71b7053SJung-uk Kim ss->ticket_appdata = OPENSSL_memdup(data, len); 1248e71b7053SJung-uk Kim if (ss->ticket_appdata != NULL) { 1249e71b7053SJung-uk Kim ss->ticket_appdata_len = len; 1250e71b7053SJung-uk Kim return 1; 1251e71b7053SJung-uk Kim } 1252e71b7053SJung-uk Kim return 0; 1253e71b7053SJung-uk Kim } 1254e71b7053SJung-uk Kim 1255e71b7053SJung-uk Kim int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) 1256e71b7053SJung-uk Kim { 1257e71b7053SJung-uk Kim *data = ss->ticket_appdata; 1258e71b7053SJung-uk Kim *len = ss->ticket_appdata_len; 1259e71b7053SJung-uk Kim return 1; 1260e71b7053SJung-uk Kim } 1261e71b7053SJung-uk Kim 1262e71b7053SJung-uk Kim void SSL_CTX_set_stateless_cookie_generate_cb( 1263e71b7053SJung-uk Kim SSL_CTX *ctx, 1264e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1265e71b7053SJung-uk Kim unsigned char *cookie, 1266e71b7053SJung-uk Kim size_t *cookie_len)) 1267e71b7053SJung-uk Kim { 1268e71b7053SJung-uk Kim ctx->gen_stateless_cookie_cb = cb; 1269e71b7053SJung-uk Kim } 1270e71b7053SJung-uk Kim 1271e71b7053SJung-uk Kim void SSL_CTX_set_stateless_cookie_verify_cb( 1272e71b7053SJung-uk Kim SSL_CTX *ctx, 1273e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1274e71b7053SJung-uk Kim const unsigned char *cookie, 1275e71b7053SJung-uk Kim size_t cookie_len)) 1276e71b7053SJung-uk Kim { 1277e71b7053SJung-uk Kim ctx->verify_stateless_cookie_cb = cb; 1278e71b7053SJung-uk Kim } 1279e71b7053SJung-uk Kim 1280e71b7053SJung-uk Kim IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) 1281