Reformat the rest of ssl/. Change-Id: I7dc264f7e29b3ba8be4c717583467edf71bf8dd9
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index cbfdb9a..117e53c 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c
@@ -152,224 +152,218 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s); static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); -SSL_SESSION *SSL_magic_pending_session_ptr(void) - { - return (SSL_SESSION*) &g_pending_session_magic; - } - -SSL_SESSION *SSL_get_session(const SSL *ssl) -/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ - { - return(ssl->session); - } - -SSL_SESSION *SSL_get1_session(SSL *ssl) -/* variant of SSL_get_session: caller really gets something */ - { - SSL_SESSION *sess; - /* Need to lock this all up rather than just use CRYPTO_add so that - * somebody doesn't free ssl->session between when we check it's - * non-null and when we up the reference count. */ - CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); - sess = ssl->session; - if(sess) - sess->references++; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); - return(sess); - } - -int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) - { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, - new_func, dup_func, free_func); - } - -int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) - { - return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); - } - -void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) - { - return(CRYPTO_get_ex_data(&s->ex_data,idx)); - } - -SSL_SESSION *SSL_SESSION_new(void) - { - SSL_SESSION *ss; - - ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); - if (ss == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_SESSION_new, ERR_R_MALLOC_FAILURE); - return(0); - } - memset(ss,0,sizeof(SSL_SESSION)); - - ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ - ss->references=1; - ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT; - ss->time=(unsigned long)time(NULL); - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); - return(ss); - } - -const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) - { - if(len) - *len = s->session_id_length; - return s->session_id; - } - -/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 - * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly - * until we have no conflict is going to complete in one iteration pretty much - * "most" of the time (btw: understatement). So, if it takes us 10 iterations - * and we still can't avoid a conflict - well that's a reasonable point to call - * it quits. Either the RAND code is broken or someone is trying to open roughly - * very close to 2^128 (or 2^256) SSL sessions to our server. How you might - * store that many sessions is perhaps a more interesting question ... */ - -#define MAX_SESS_ID_ATTEMPTS 10 -static int def_generate_session_id(const SSL *ssl, unsigned char *id, - unsigned int *id_len) -{ - unsigned int retry = 0; - do - { - if (!RAND_bytes(id, *id_len)) - return 0; - } - while(SSL_has_matching_session_id(ssl, id, *id_len) && - (++retry < MAX_SESS_ID_ATTEMPTS)); - if(retry < MAX_SESS_ID_ATTEMPTS) - return 1; - /* else - woops a session_id match */ - /* XXX We should also check the external cache -- - * but the probability of a collision is negligible, and - * we could not prevent the concurrent creation of sessions - * with identical IDs since we currently don't have means - * to atomically check whether a session ID already exists - * and make a reservation for it if it does not - * (this problem applies to the internal cache as well). - */ - return 0; +SSL_SESSION *SSL_magic_pending_session_ptr(void) { + return (SSL_SESSION *)&g_pending_session_magic; } -int ssl_get_new_session(SSL *s, int session) - { - /* This gets used by clients and servers. */ +SSL_SESSION *SSL_get_session(const SSL *ssl) +{ + /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ + return ssl->session; +} - unsigned int tmp; - SSL_SESSION *ss=NULL; - GEN_SESSION_CB cb = def_generate_session_id; +SSL_SESSION *SSL_get1_session(SSL *ssl) { + /* variant of SSL_get_session: caller really gets something */ + SSL_SESSION *sess; + /* Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's + * non-null and when we up the reference count. */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); + sess = ssl->session; + if (sess) { + sess->references++; + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); - if (s->mode & SSL_MODE_NO_SESSION_CREATION) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SESSION_MAY_NOT_BE_CREATED); - return 0; - } + return sess; +} - if ((ss=SSL_SESSION_new()) == NULL) return(0); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, + new_func, dup_func, free_func); +} - /* If the context has a default timeout, use it over the default. */ - if (s->initial_ctx->session_timeout != 0) - ss->timeout=s->initial_ctx->session_timeout; +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) { + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} - if (s->session != NULL) - { - SSL_SESSION_free(s->session); - s->session=NULL; - } +void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) { + return CRYPTO_get_ex_data(&s->ex_data, idx); +} - if (session) - { - if (s->version == SSL3_VERSION || - s->version == TLS1_VERSION || - s->version == TLS1_1_VERSION || - s->version == TLS1_2_VERSION || - s->version == DTLS1_VERSION || - s->version == DTLS1_2_VERSION) - { - ss->ssl_version = s->version; - ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; - } - else - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_UNSUPPORTED_SSL_VERSION); - SSL_SESSION_free(ss); - return(0); - } - /* If RFC4507 ticket use empty session ID */ - if (s->tlsext_ticket_expected) - { - ss->session_id_length = 0; - goto sess_id_done; - } - /* Choose which callback will set the session ID */ - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - if(s->generate_session_id) - cb = s->generate_session_id; - else if(s->initial_ctx->generate_session_id) - cb = s->initial_ctx->generate_session_id; - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - /* Choose a session ID */ - tmp = ss->session_id_length; - if(!cb(s, ss->session_id, &tmp)) - { - /* The callback failed */ - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); - SSL_SESSION_free(ss); - return(0); - } - /* Don't allow the callback to set the session length to zero. - * nor set it higher than it was. */ - if(!tmp || (tmp > ss->session_id_length)) - { - /* The callback set an illegal length */ - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); - SSL_SESSION_free(ss); - return(0); - } - ss->session_id_length = tmp; - /* Finally, check for a conflict */ - if(SSL_has_matching_session_id(s, ss->session_id, - ss->session_id_length)) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_CONFLICT); - SSL_SESSION_free(ss); - return(0); - } - sess_id_done: - if (s->tlsext_hostname) { - ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); - if (ss->tlsext_hostname == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); - SSL_SESSION_free(ss); - return 0; - } - } - } - else - { - ss->session_id_length=0; - } +SSL_SESSION *SSL_SESSION_new(void) { + SSL_SESSION *ss; - if (s->sid_ctx_length > sizeof ss->sid_ctx) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); - SSL_SESSION_free(ss); - return 0; - } - memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); - ss->sid_ctx_length=s->sid_ctx_length; - s->session=ss; - ss->ssl_version=s->version; - ss->verify_result = X509_V_OK; + ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); + if (ss == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_SESSION_new, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(ss, 0, sizeof(SSL_SESSION)); - return(1); - } + ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ + ss->references = 1; + ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT; + ss->time = (unsigned long)time(NULL); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + return ss; +} + +const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { + if (len) { + *len = s->session_id_length; + } + return s->session_id; +} + +/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. + * SSLv3/TLSv1 has 32 bytes (256 bits). As such, filling the ID with random + * gunk repeatedly until we have no conflict is going to complete in one + * iteration pretty much "most" of the time (btw: understatement). So, if it + * takes us 10 iterations and we still can't avoid a conflict - well that's a + * reasonable point to call it quits. Either the RAND code is broken or someone + * is trying to open roughly very close to 2^128 (or 2^256) SSL sessions to our + * server. How you might store that many sessions is perhaps a more interesting + * question ... */ +static int def_generate_session_id(const SSL *ssl, uint8_t *id, + unsigned int *id_len) { + static const unsigned kMaxAttempts = 10; + unsigned int retry = 0; + do { + if (!RAND_bytes(id, *id_len)) { + return 0; + } + } while (SSL_has_matching_session_id(ssl, id, *id_len) && + (++retry < kMaxAttempts)); + + if (retry < kMaxAttempts) { + return 1; + } + + /* else - woops a session_id match */ + /* XXX We should also check the external cache -- but the probability of a + * collision is negligible, and we could not prevent the concurrent creation + * of sessions with identical IDs since we currently don't have means to + * atomically check whether a session ID already exists and make a + * reservation for it if it does not (this problem applies to the internal + * cache as well). */ + return 0; +} + +int ssl_get_new_session(SSL *s, int session) { + /* This gets used by clients and servers. */ + + unsigned int tmp; + SSL_SESSION *ss = NULL; + GEN_SESSION_CB cb = def_generate_session_id; + + if (s->mode & SSL_MODE_NO_SESSION_CREATION) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SESSION_MAY_NOT_BE_CREATED); + return 0; + } + + ss = SSL_SESSION_new(); + if (ss == NULL) { + return 0; + } + + /* If the context has a default timeout, use it over the default. */ + if (s->initial_ctx->session_timeout != 0) { + ss->timeout = s->initial_ctx->session_timeout; + } + + if (s->session != NULL) { + SSL_SESSION_free(s->session); + s->session = NULL; + } + + if (session) { + if (s->version == SSL3_VERSION || s->version == TLS1_VERSION || + s->version == TLS1_1_VERSION || s->version == TLS1_2_VERSION || + s->version == DTLS1_VERSION || s->version == DTLS1_2_VERSION) { + ss->ssl_version = s->version; + ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + } else { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_UNSUPPORTED_SSL_VERSION); + SSL_SESSION_free(ss); + return 0; + } + + /* If RFC4507 ticket use empty session ID */ + if (s->tlsext_ticket_expected) { + ss->session_id_length = 0; + goto sess_id_done; + } + + /* Choose which callback will set the session ID */ + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + if (s->generate_session_id) { + cb = s->generate_session_id; + } else if (s->initial_ctx->generate_session_id) { + cb = s->initial_ctx->generate_session_id; + } + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + /* Choose a session ID */ + tmp = ss->session_id_length; + if (!cb(s, ss->session_id, &tmp)) { + /* The callback failed */ + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); + SSL_SESSION_free(ss); + return 0; + } + + /* Don't allow the callback to set the session length to zero. nor set it + * higher than it was. */ + if (!tmp || tmp > ss->session_id_length) { + /* The callback set an illegal length */ + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); + SSL_SESSION_free(ss); + return 0; + } + + ss->session_id_length = tmp; + /* Finally, check for a conflict */ + if (SSL_has_matching_session_id(s, ss->session_id, ss->session_id_length)) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_CONFLICT); + SSL_SESSION_free(ss); + return 0; + } + + sess_id_done: + if (s->tlsext_hostname) { + ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); + if (ss->tlsext_hostname == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + } + } else { + ss->session_id_length = 0; + } + + if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + + memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); + ss->sid_ctx_length = s->sid_ctx_length; + s->session = ss; + ss->ssl_version = s->version; + ss->verify_result = X509_V_OK; + + return 1; +} /* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this * connection. It is only called by servers. @@ -385,561 +379,542 @@ * - If a session is found then s->session is pointed at it (after freeing an * existing session if need be) and s->verify_result is set from the session. * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1 - * if the server should issue a new session ticket (to 0 otherwise). - */ -int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx) - { - /* This is used only by servers. */ + * if the server should issue a new session ticket (to 0 otherwise). */ +int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx) { + /* This is used only by servers. */ + SSL_SESSION *ret = NULL; + int fatal = 0; + int try_session_cache = 1; + int r; - SSL_SESSION *ret=NULL; - int fatal = 0; - int try_session_cache = 1; - int r; + if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + goto err; + } - if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) - goto err; + if (ctx->session_id_len == 0) { + try_session_cache = 0; + } - if (ctx->session_id_len == 0) - try_session_cache = 0; + r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */ + switch (r) { + case -1: /* Error during processing */ + fatal = 1; + goto err; - r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */ - switch (r) - { - case -1: /* Error during processing */ - fatal = 1; - goto err; - case 0: /* No ticket found */ - case 1: /* Zero length ticket found */ - break; /* Ok to carry on processing session id. */ - case 2: /* Ticket found but not decrypted. */ - case 3: /* Ticket decrypted, *ret has been set. */ - try_session_cache = 0; - break; - default: - abort(); - } + case 0: /* No ticket found */ + case 1: /* Zero length ticket found */ + break; /* Ok to carry on processing session id. */ - if (try_session_cache && - ret == NULL && - !(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) - { - SSL_SESSION data; - data.ssl_version=s->version; - data.session_id_length=ctx->session_id_len; - if (ctx->session_id_len == 0) - return 0; - memcpy(data.session_id,ctx->session_id,ctx->session_id_len); - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - ret=lh_SSL_SESSION_retrieve(s->initial_ctx->sessions,&data); - if (ret != NULL) - { - /* don't allow other threads to steal it: */ - CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); - } - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - if (ret == NULL) - s->initial_ctx->stats.sess_miss++; - } + case 2: /* Ticket found but not decrypted. */ + case 3: /* Ticket decrypted, *ret has been set. */ + try_session_cache = 0; + break; - if (try_session_cache && - ret == NULL && - s->initial_ctx->get_session_cb != NULL) - { - int copy=1; - - if ((ret=s->initial_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,©))) - { - if (ret == SSL_magic_pending_session_ptr()) - { - /* This is a magic value which indicates that - * the callback needs to unwind the stack and - * figure out the session asynchronously. */ - return PENDING_SESSION; - } - s->initial_ctx->stats.sess_cb_hit++; + default: + abort(); + } - /* Increment reference count now if the session callback - * asks us to do so (note that if the session structures - * returned by the callback are shared between threads, - * it must handle the reference count itself [i.e. copy == 0], - * or things won't be thread-safe). */ - if (copy) - CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); + if (try_session_cache && ret == NULL && + !(s->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { + SSL_SESSION data; + data.ssl_version = s->version; + data.session_id_length = ctx->session_id_len; + if (ctx->session_id_len == 0) { + return 0; + } + memcpy(data.session_id, ctx->session_id, ctx->session_id_len); + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + ret = lh_SSL_SESSION_retrieve(s->initial_ctx->sessions, &data); + if (ret != NULL) { + /* don't allow other threads to steal it: */ + CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + } + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + if (ret == NULL) { + s->initial_ctx->stats.sess_miss++; + } + } - /* Add the externally cached session to the internal - * cache as well if and only if we are supposed to. */ - if(!(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE)) - /* The following should not return 1, otherwise, - * things are very strange */ - SSL_CTX_add_session(s->initial_ctx,ret); - } - } + if (try_session_cache && ret == NULL && + s->initial_ctx->get_session_cb != NULL) { + int copy = 1; - if (ret == NULL) - goto err; + ret = s->initial_ctx->get_session_cb(s, (uint8_t *)ctx->session_id, + ctx->session_id_len, ©); + if (ret != NULL) { + if (ret == SSL_magic_pending_session_ptr()) { + /* This is a magic value which indicates that the callback needs to + * unwind the stack and figure out the session asynchronously. */ + return PENDING_SESSION; + } + s->initial_ctx->stats.sess_cb_hit++; - /* Now ret is non-NULL and we own one of its reference counts. */ + /* Increment reference count now if the session callback asks us to do so + * (note that if the session structures returned by the callback are + * shared between threads, it must handle the reference count itself + * [i.e. copy == 0], or things won't be thread-safe). */ + if (copy) { + CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + } - if (ret->sid_ctx_length != s->sid_ctx_length - || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) - { - /* We have the session requested by the client, but we don't - * want to use it in this context. */ - goto err; /* treat like cache miss */ - } - - if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) - { - /* We can't be sure if this session is being used out of - * context, which is especially important for SSL_VERIFY_PEER. - * The application should have used SSL[_CTX]_set_session_id_context. - * - * For this error case, we generate an error instead of treating - * the event like a cache miss (otherwise it would be easy for - * applications to effectively disable the session cache by - * accident without anyone noticing). - */ - - OPENSSL_PUT_ERROR(SSL, ssl_get_prev_session, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); - fatal = 1; - goto err; - } + /* Add the externally cached session to the internal cache as well if and + * only if we are supposed to. */ + if (!(s->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE)) { + /* The following should not return 1, otherwise, things are very + * strange */ + SSL_CTX_add_session(s->initial_ctx, ret); + } + } + } - if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */ - { - s->initial_ctx->stats.sess_timeout++; - if (try_session_cache) - { - /* session was from the cache, so remove it */ - SSL_CTX_remove_session(s->initial_ctx,ret); - } - goto err; - } + if (ret == NULL) { + goto err; + } - s->initial_ctx->stats.sess_hit++; + /* Now ret is non-NULL and we own one of its reference counts. */ - if (s->session != NULL) - SSL_SESSION_free(s->session); - s->session=ret; - s->verify_result = s->session->verify_result; - return 1; + if (ret->sid_ctx_length != s->sid_ctx_length || + memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { + /* We have the session requested by the client, but we don't want to use it + * in this context. */ + goto err; /* treat like cache miss */ + } - err: - if (ret != NULL) - { - SSL_SESSION_free(ret); - if (!try_session_cache) - { - /* The session was from a ticket, so we should - * issue a ticket for the new session */ - s->tlsext_ticket_expected = 1; - } - } - if (fatal) - return -1; - else - return 0; - } + if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { + /* We can't be sure if this session is being used out of context, which is + * especially important for SSL_VERIFY_PEER. The application should have + * used SSL[_CTX]_set_session_id_context. + * + * For this error case, we generate an error instead of treating the event + * like a cache miss (otherwise it would be easy for applications to + * effectively disable the session cache by accident without anyone + * noticing). */ + OPENSSL_PUT_ERROR(SSL, ssl_get_prev_session, + SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + fatal = 1; + goto err; + } -int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) - { - int ret=0; - SSL_SESSION *s; + if (ret->timeout < (long)(time(NULL) - ret->time)) { + /* timeout */ + s->initial_ctx->stats.sess_timeout++; + if (try_session_cache) { + /* session was from the cache, so remove it */ + SSL_CTX_remove_session(s->initial_ctx, ret); + } + goto err; + } - /* add just 1 reference count for the SSL_CTX's session cache - * even though it has two ways of access: each session is in a - * doubly linked list and an lhash */ - CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); - /* if session c is in already in cache, we take back the increment later */ + s->initial_ctx->stats.sess_hit++; - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - if (!lh_SSL_SESSION_insert(ctx->sessions,&s,c)) { - return 0; - } - - /* s != NULL iff we already had a session with the given PID. - * In this case, s == c should hold (then we did not really modify - * ctx->sessions), or we're in trouble. */ - if (s != NULL && s != c) - { - /* We *are* in trouble ... */ - SSL_SESSION_list_remove(ctx,s); - SSL_SESSION_free(s); - /* ... so pretend the other session did not exist in cache - * (we cannot handle two SSL_SESSION structures with identical - * session ID in the same cache, which could happen e.g. when - * two threads concurrently obtain the same session from an external - * cache) */ - s = NULL; - } + if (s->session != NULL) { + SSL_SESSION_free(s->session); + } + s->session = ret; + s->verify_result = s->session->verify_result; + return 1; - /* Put at the head of the queue unless it is already in the cache */ - if (s == NULL) - SSL_SESSION_list_add(ctx,c); - - if (s != NULL) - { - /* existing cache entry -- decrement previously incremented reference - * count because it already takes into account the cache */ - - SSL_SESSION_free(s); /* s == c */ - ret=0; - } - else - { - /* new cache entry -- remove old ones if cache has become too large */ - - ret=1; - - if (SSL_CTX_sess_get_cache_size(ctx) > 0) - { - while (SSL_CTX_sess_number(ctx) > - SSL_CTX_sess_get_cache_size(ctx)) - { - if (!remove_session_lock(ctx, - ctx->session_cache_tail, 0)) - break; - else - ctx->stats.sess_cache_full++; - } - } - } - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - return(ret); - } - -int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) -{ - return remove_session_lock(ctx, c, 1); +err: + if (ret != NULL) { + SSL_SESSION_free(ret); + if (!try_session_cache) { + /* The session was from a ticket, so we should + * issue a ticket for the new session */ + s->tlsext_ticket_expected = 1; + } + } + if (fatal) { + return -1; + } + return 0; } -static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) - { - SSL_SESSION *r; - int ret=0; +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { + int ret = 0; + SSL_SESSION *s; - if ((c != NULL) && (c->session_id_length != 0)) - { - if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - if ((r = lh_SSL_SESSION_retrieve(ctx->sessions,c)) == c) - { - ret=1; - r=lh_SSL_SESSION_delete(ctx->sessions,c); - SSL_SESSION_list_remove(ctx,c); - } + /* add just 1 reference count for the SSL_CTX's session cache even though it + * has two ways of access: each session is in a doubly linked list and an + * lhash */ + CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION); + /* if session c is in already in cache, we take back the increment later */ - if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) { + return 0; + } - if (ret) - { - r->not_resumable=1; - if (ctx->remove_session_cb != NULL) - ctx->remove_session_cb(ctx,r); - SSL_SESSION_free(r); - } - } - else - ret=0; - return(ret); - } + /* s != NULL iff we already had a session with the given PID. In this case, s + * == c should hold (then we did not really modify ctx->sessions), or we're + * in trouble. */ + if (s != NULL && s != c) { + /* We *are* in trouble ... */ + SSL_SESSION_list_remove(ctx, s); + SSL_SESSION_free(s); + /* ... so pretend the other session did not exist in cache (we cannot + * handle two SSL_SESSION structures with identical session ID in the same + * cache, which could happen e.g. when two threads concurrently obtain the + * same session from an external cache) */ + s = NULL; + } -void SSL_SESSION_free(SSL_SESSION *ss) - { - int i; + /* Put at the head of the queue unless it is already in the cache */ + if (s == NULL) { + SSL_SESSION_list_add(ctx, c); + } - if(ss == NULL) - return; + if (s != NULL) { + /* existing cache entry -- decrement previously incremented reference count + * because it already takes into account the cache */ + SSL_SESSION_free(s); /* s == c */ + ret = 0; + } else { + /* new cache entry -- remove old ones if cache has become too large */ + ret = 1; - i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); -#ifdef REF_PRINT - REF_PRINT("SSL_SESSION",ss); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"SSL_SESSION_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + if (SSL_CTX_sess_get_cache_size(ctx) > 0) { + while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { + if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { + break; + } + ctx->stats.sess_cache_full++; + } + } + } - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return ret; +} - OPENSSL_cleanse(ss->master_key,sizeof ss->master_key); - OPENSSL_cleanse(ss->session_id,sizeof ss->session_id); - if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); - if (ss->peer != NULL) X509_free(ss->peer); - if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname); - if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick); - if (ss->tlsext_signed_cert_timestamp_list != NULL) - OPENSSL_free(ss->tlsext_signed_cert_timestamp_list); - if (ss->ocsp_response != NULL) - OPENSSL_free(ss->ocsp_response); - if (ss->psk_identity != NULL) - OPENSSL_free(ss->psk_identity); - OPENSSL_cleanse(ss,sizeof(*ss)); - OPENSSL_free(ss); - } +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) { + return remove_session_lock(ctx, c, 1); +} -int SSL_set_session(SSL *s, SSL_SESSION *session) - { - if (s->session == session) - return 1; +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) { + SSL_SESSION *r; + int ret = 0; - if (s->session != NULL) - SSL_SESSION_free(s->session); - s->session = session; - if (session != NULL) - { - CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); - s->verify_result = session->verify_result; - } - return 1; - } + if (c != NULL && c->session_id_length != 0) { + if (lock) { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + } + r = lh_SSL_SESSION_retrieve(ctx->sessions, c); + if (r == c) { + ret = 1; + r = lh_SSL_SESSION_delete(ctx->sessions, c); + SSL_SESSION_list_remove(ctx, c); + } -long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) - { - if (s == NULL) return(0); - s->timeout=t; - return(1); - } + if (lock) { + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } -long SSL_SESSION_get_timeout(const SSL_SESSION *s) - { - if (s == NULL) return(0); - return(s->timeout); - } + if (ret) { + r->not_resumable = 1; + if (ctx->remove_session_cb != NULL) { + ctx->remove_session_cb(ctx, r); + } + SSL_SESSION_free(r); + } + } -long SSL_SESSION_get_time(const SSL_SESSION *s) - { - if (s == NULL) return(0); - return(s->time); - } + return ret; +} -long SSL_SESSION_set_time(SSL_SESSION *s, long t) - { - if (s == NULL) return(0); - s->time=t; - return(t); - } +void SSL_SESSION_free(SSL_SESSION *ss) { + int i; -X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) - { - return s->peer; - } + if (ss == NULL) { + return; + } -int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx, - unsigned int sid_ctx_len) - { - if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) - { - OPENSSL_PUT_ERROR(SSL, SSL_SESSION_set1_id_context, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); - return 0; - } - s->sid_ctx_length=sid_ctx_len; - memcpy(s->sid_ctx,sid_ctx,sid_ctx_len); + i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION); + if (i > 0) { + return; + } - return 1; - } + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); -long SSL_CTX_set_timeout(SSL_CTX *s, long t) - { - long l; - if (s == NULL) return(0); - l=s->session_timeout; - s->session_timeout=t; - return(l); - } + OPENSSL_cleanse(ss->master_key, sizeof ss->master_key); + OPENSSL_cleanse(ss->session_id, sizeof ss->session_id); + if (ss->sess_cert != NULL) { + ssl_sess_cert_free(ss->sess_cert); + } + if (ss->peer != NULL) { + X509_free(ss->peer); + } + if (ss->tlsext_hostname != NULL) { + OPENSSL_free(ss->tlsext_hostname); + } + if (ss->tlsext_tick != NULL) { + OPENSSL_free(ss->tlsext_tick); + } + if (ss->tlsext_signed_cert_timestamp_list != NULL) { + OPENSSL_free(ss->tlsext_signed_cert_timestamp_list); + } + if (ss->ocsp_response != NULL) { + OPENSSL_free(ss->ocsp_response); + } + if (ss->psk_identity != NULL) { + OPENSSL_free(ss->psk_identity); + } + OPENSSL_cleanse(ss, sizeof(*ss)); + OPENSSL_free(ss); +} -long SSL_CTX_get_timeout(const SSL_CTX *s) - { - if (s == NULL) return(0); - return(s->session_timeout); - } +int SSL_set_session(SSL *s, SSL_SESSION *session) { + if (s->session == session) { + return 1; + } -typedef struct timeout_param_st - { - SSL_CTX *ctx; - long time; - LHASH_OF(SSL_SESSION) *cache; - } TIMEOUT_PARAM; + if (s->session != NULL) { + SSL_SESSION_free(s->session); + } + s->session = session; + if (session != NULL) { + CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); + s->verify_result = session->verify_result; + } -static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) - { - TIMEOUT_PARAM *param = void_param; + return 1; +} - if ((param->time == 0) || (param->time > (sess->time+sess->timeout))) /* timeout */ - { - /* The reason we don't call SSL_CTX_remove_session() is to - * save on locking overhead */ - (void)lh_SSL_SESSION_delete(param->cache,sess); - SSL_SESSION_list_remove(param->ctx,sess); - sess->not_resumable=1; - if (param->ctx->remove_session_cb != NULL) - param->ctx->remove_session_cb(param->ctx,sess); - SSL_SESSION_free(sess); - } - } +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) { + if (s == NULL) { + return 0; + } -void SSL_CTX_flush_sessions(SSL_CTX *s, long t) - { - TIMEOUT_PARAM tp; + s->timeout = t; + return 1; +} - tp.ctx=s; - tp.cache=s->sessions; - if (tp.cache == NULL) return; - tp.time=t; - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - } +long SSL_SESSION_get_timeout(const SSL_SESSION *s) { + if (s == NULL) { + return 0; + } -int ssl_clear_bad_session(SSL *s) - { - if (s->session != NULL && - !(s->shutdown & SSL_SENT_SHUTDOWN) && - !SSL_in_init(s)) - { - SSL_CTX_remove_session(s->ctx,s->session); - return(1); - } - else - return(0); - } + return s->timeout; +} + +long SSL_SESSION_get_time(const SSL_SESSION *s) { + if (s == NULL) { + return 0; + } + + return s->time; +} + +long SSL_SESSION_set_time(SSL_SESSION *s, long t) { + if (s == NULL) { + return 0; + } + + s->time = t; + return t; +} + +X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; } + +int SSL_SESSION_set1_id_context(SSL_SESSION *s, const uint8_t *sid_ctx, + unsigned int sid_ctx_len) { + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_SESSION_set1_id_context, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + + s->sid_ctx_length = sid_ctx_len; + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +long SSL_CTX_set_timeout(SSL_CTX *s, long t) { + long l; + if (s == NULL) { + return 0; + } + + l = s->session_timeout; + s->session_timeout = t; + return l; +} + +long SSL_CTX_get_timeout(const SSL_CTX *s) { + if (s == NULL) { + return 0; + } + + return s->session_timeout; +} + +typedef struct timeout_param_st { + SSL_CTX *ctx; + long time; + LHASH_OF(SSL_SESSION) * cache; +} TIMEOUT_PARAM; + +static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) { + TIMEOUT_PARAM *param = void_param; + + if (param->time == 0 || + param->time > (sess->time + sess->timeout)) { + /* timeout */ + /* The reason we don't call SSL_CTX_remove_session() is to + * save on locking overhead */ + lh_SSL_SESSION_delete(param->cache, sess); + SSL_SESSION_list_remove(param->ctx, sess); + sess->not_resumable = 1; + if (param->ctx->remove_session_cb != NULL) { + param->ctx->remove_session_cb(param->ctx, sess); + } + SSL_SESSION_free(sess); + } +} + +void SSL_CTX_flush_sessions(SSL_CTX *s, long t) { + TIMEOUT_PARAM tp; + + tp.ctx = s; + tp.cache = s->sessions; + if (tp.cache == NULL) { + return; + } + tp.time = t; + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +} + +int ssl_clear_bad_session(SSL *s) { + if (s->session != NULL && !(s->shutdown & SSL_SENT_SHUTDOWN) && + !SSL_in_init(s)) { + SSL_CTX_remove_session(s->ctx, s->session); + return 1; + } + + return 0; +} /* locked by SSL_CTX in the calling function */ -static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) - { - if ((s->next == NULL) || (s->prev == NULL)) return; +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) { + if (s->next == NULL || s->prev == NULL) { + return; + } - if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) - { /* last element in list */ - if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) - { /* only one element in list */ - ctx->session_cache_head=NULL; - ctx->session_cache_tail=NULL; - } - else - { - ctx->session_cache_tail=s->prev; - s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail); - } - } - else - { - if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) - { /* first element in list */ - ctx->session_cache_head=s->next; - s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head); - } - else - { /* middle of list */ - s->next->prev=s->prev; - s->prev->next=s->next; - } - } - s->prev=s->next=NULL; - } + if (s->next == (SSL_SESSION *)&ctx->session_cache_tail) { + /* last element in list */ + if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* only one element in list */ + ctx->session_cache_head = NULL; + ctx->session_cache_tail = NULL; + } else { + ctx->session_cache_tail = s->prev; + s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } + } else { + if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* first element in list */ + ctx->session_cache_head = s->next; + s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); + } else { /* middle of list */ + s->next->prev = s->prev; + s->prev->next = s->next; + } + } + s->prev = s->next = NULL; +} -static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) - { - if ((s->next != NULL) && (s->prev != NULL)) - SSL_SESSION_list_remove(ctx,s); +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) { + if (s->next != NULL && s->prev != NULL) { + SSL_SESSION_list_remove(ctx, s); + } - if (ctx->session_cache_head == NULL) - { - ctx->session_cache_head=s; - ctx->session_cache_tail=s; - s->prev=(SSL_SESSION *)&(ctx->session_cache_head); - s->next=(SSL_SESSION *)&(ctx->session_cache_tail); - } - else - { - s->next=ctx->session_cache_head; - s->next->prev=s; - s->prev=(SSL_SESSION *)&(ctx->session_cache_head); - ctx->session_cache_head=s; - } - } + if (ctx->session_cache_head == NULL) { + ctx->session_cache_head = s; + ctx->session_cache_tail = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + s->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } else { + s->next = ctx->session_cache_head; + s->next->prev = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + ctx->session_cache_head = s; + } +} void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, - int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess)) - { - ctx->new_session_cb=cb; - } + int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) { + ctx->new_session_cb = cb; +} -int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) - { - return ctx->new_session_cb; - } +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) { + return ctx->new_session_cb; +} void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, - void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess)) - { - ctx->remove_session_cb=cb; - } + void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) { + ctx->remove_session_cb = cb; +} -void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess) - { - return ctx->remove_session_cb; - } +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx, + SSL_SESSION *sess) { + return ctx->remove_session_cb; +} void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, - SSL_SESSION *(*cb)(struct ssl_st *ssl, - unsigned char *data,int len,int *copy)) - { - ctx->get_session_cb=cb; - } + SSL_SESSION *(*cb)(struct ssl_st *ssl, + uint8_t *data, int len, + int *copy)) { + ctx->get_session_cb = cb; +} -SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, - unsigned char *data,int len,int *copy) - { - return ctx->get_session_cb; - } +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, uint8_t *data, + int len, int *copy) { + return ctx->get_session_cb; +} -void SSL_CTX_set_info_callback(SSL_CTX *ctx, - void (*cb)(const SSL *ssl,int type,int val)) - { - ctx->info_callback=cb; - } +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, int type, int val)) { + ctx->info_callback = cb; +} -void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val) - { - return ctx->info_callback; - } +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, + int val) { + return ctx->info_callback; +} -void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)) - { - ctx->client_cert_cb=cb; - } +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509, + EVP_PKEY **pkey)) { + ctx->client_cert_cb = cb; +} -int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey) - { - return ctx->client_cert_cb; - } +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, + EVP_PKEY **pkey) { + return ctx->client_cert_cb; +} void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, uint8_t *cookie, size_t *cookie_len)) - { - ctx->app_gen_cookie_cb=cb; - } + int (*cb)(SSL *ssl, uint8_t *cookie, + size_t *cookie_len)) { + ctx->app_gen_cookie_cb = cb; +} void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, const uint8_t *cookie, size_t cookie_len)) - { - ctx->app_verify_cookie_cb=cb; - } + int (*cb)(SSL *ssl, const uint8_t *cookie, + size_t cookie_len)) { + ctx->app_verify_cookie_cb = cb; +} void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx, - void (*cb)(SSL *ssl, EVP_PKEY **pkey)) - { - ctx->channel_id_cb=cb; - } + void (*cb)(SSL *ssl, EVP_PKEY **pkey)) { + ctx->channel_id_cb = cb; +} -void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL * ssl, EVP_PKEY **pkey) - { - return ctx->channel_id_cb; - } +void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) { + return ctx->channel_id_cb; +} IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)