Respect SSL_OP_NO_TICKET in TLSv1.3
authorMatt Caswell <matt@openssl.org>
Wed, 13 Jun 2018 14:57:39 +0000 (15:57 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 26 Jun 2018 17:09:46 +0000 (18:09 +0100)
Implement support for stateful TLSv1.3 tickets, and use them if
SSL_OP_NO_TICKET is set.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6563)

13 files changed:
crypto/err/openssl.txt
include/openssl/sslerr.h
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/statem/extensions_srvr.c
ssl/statem/statem_srvr.c
test/handshake_helper.c
test/ssl-tests/10-resumption.conf
test/ssl-tests/11-dtls_resumption.conf
test/ssl-tests/protocol_version.pm
test/sslapitest.c

index e0580a8..e65a806 100644 (file)
@@ -1089,7 +1089,10 @@ SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list
 SSL_F_CIPHERSUITE_CB:622:ciphersuite_cb
 SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names
 SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs
+SSL_F_CONSTRUCT_STATEFUL_TICKET:636:construct_stateful_ticket
+SSL_F_CONSTRUCT_STATELESS_TICKET:637:construct_stateless_ticket
 SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash
+SSL_F_CREATE_TICKET_PREQUEL:638:create_ticket_prequel
 SSL_F_CT_MOVE_SCTS:345:ct_move_scts
 SSL_F_CT_STRICT:349:ct_strict
 SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add
index d7d58e5..b2c6c1e 100644 (file)
@@ -26,8 +26,10 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_CIPHERSUITE_CB                             622
 # define SSL_F_CONSTRUCT_CA_NAMES                         552
 # define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS                 553
+# define SSL_F_CONSTRUCT_STATEFUL_TICKET                  636
+# define SSL_F_CONSTRUCT_STATELESS_TICKET                 637
 # define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH              539
-# define SSL_F_CREATE_TICKET_PREQUEL                      636
+# define SSL_F_CREATE_TICKET_PREQUEL                      638
 # define SSL_F_CT_MOVE_SCTS                               345
 # define SSL_F_CT_STRICT                                  349
 # define SSL_F_CUSTOM_EXT_ADD                             554
index 6f6430e..03c5bf2 100644 (file)
@@ -24,6 +24,10 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0),
      "construct_key_exchange_tbs"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATEFUL_TICKET, 0),
+     "construct_stateful_ticket"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_STATELESS_TICKET, 0),
+     "construct_stateless_ticket"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, 0),
      "create_synthetic_message_hash"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_TICKET_PREQUEL, 0),
index 22f729c..6ced147 100644 (file)
@@ -3369,18 +3369,21 @@ void ssl_update_cache(SSL *s, int mode)
         && (!s->hit || SSL_IS_TLS13(s))) {
         /*
          * Add the session to the internal cache. In server side TLSv1.3 we
-         * normally don't do this because its a full stateless ticket with only
-         * a dummy session id so there is no reason to cache it, unless:
+         * normally don't do this because by default it's a full stateless ticket
+         * with only a dummy session id so there is no reason to cache it,
+         * unless:
          * - we are doing early_data, in which case we cache so that we can
          *   detect replays
          * - the application has set a remove_session_cb so needs to know about
          *   session timeout events
+         * - SSL_OP_NO_TICKET is set in which case it is a stateful ticket
          */
         if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0
                 && (!SSL_IS_TLS13(s)
                     || !s->server
                     || s->max_early_data > 0
-                    || s->session_ctx->remove_session_cb != NULL))
+                    || s->session_ctx->remove_session_cb != NULL
+                    || (s->options & SSL_OP_NO_TICKET) != 0))
             SSL_CTX_add_session(s->session_ctx, s->session);
 
         /*
index 86c250b..a4d1376 100644 (file)
@@ -2212,6 +2212,8 @@ void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
 __owur int ssl_generate_session_id(SSL *s, SSL_SESSION *ss);
 __owur int ssl_get_new_session(SSL *s, int session);
+__owur SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
+                                         size_t sess_id_len);
 __owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello);
 __owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 __owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
index fde4187..628b9f0 100644 (file)
@@ -12,6 +12,7 @@
 #include <openssl/rand.h>
 #include <openssl/engine.h>
 #include "internal/refcount.h"
+#include "internal/cryptlib.h"
 #include "ssl_locl.h"
 #include "statem/statem_locl.h"
 
@@ -452,6 +453,73 @@ int ssl_get_new_session(SSL *s, int session)
     return 1;
 }
 
+SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
+                                  size_t sess_id_len)
+{
+    SSL_SESSION *ret = NULL;
+    int discard;
+
+    if ((s->session_ctx->session_cache_mode
+         & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) {
+        SSL_SESSION data;
+
+        data.ssl_version = s->version;
+        if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH))
+            return NULL;
+
+        memcpy(data.session_id, sess_id, sess_id_len);
+        data.session_id_length = sess_id_len;
+
+        CRYPTO_THREAD_read_lock(s->session_ctx->lock);
+        ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
+        if (ret != NULL) {
+            /* don't allow other threads to steal it: */
+            SSL_SESSION_up_ref(ret);
+        }
+        CRYPTO_THREAD_unlock(s->session_ctx->lock);
+        if (ret == NULL)
+            CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
+                              s->session_ctx->lock);
+    }
+
+    if (ret == NULL && s->session_ctx->get_session_cb != NULL) {
+        int copy = 1;
+
+        ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, &copy);
+
+        if (ret != NULL) {
+            CRYPTO_atomic_add(&s->session_ctx->stats.sess_cb_hit, 1, &discard,
+                              s->session_ctx->lock);
+
+            /*
+             * 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)
+                SSL_SESSION_up_ref(ret);
+
+            /*
+             * Add the externally cached session to the internal cache as
+             * well if and only if we are supposed to.
+             */
+            if ((s->session_ctx->session_cache_mode &
+                 SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) {
+                /*
+                 * Either return value of SSL_CTX_add_session should not
+                 * interrupt the session resumption process. The return
+                 * value is intentionally ignored.
+                 */
+                (void)SSL_CTX_add_session(s->session_ctx, ret);
+            }
+        }
+    }
+
+    return ret;
+}
+
 /*-
  * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
  * connection. It is only called by servers.
@@ -504,8 +572,11 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
             goto err;
         case SSL_TICKET_NONE:
         case SSL_TICKET_EMPTY:
-            if (hello->session_id_len > 0)
+            if (hello->session_id_len > 0) {
                 try_session_cache = 1;
+                ret = lookup_sess_in_cache(s, hello->session_id,
+                                           hello->session_id_len);
+            }
             break;
         case SSL_TICKET_NO_DECRYPT:
         case SSL_TICKET_SUCCESS:
@@ -514,67 +585,6 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
         }
     }
 
-    if (try_session_cache &&
-        ret == NULL &&
-        !(s->session_ctx->session_cache_mode &
-          SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
-        SSL_SESSION data;
-
-        data.ssl_version = s->version;
-        memcpy(data.session_id, hello->session_id, hello->session_id_len);
-        data.session_id_length = hello->session_id_len;
-
-        CRYPTO_THREAD_read_lock(s->session_ctx->lock);
-        ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
-        if (ret != NULL) {
-            /* don't allow other threads to steal it: */
-            SSL_SESSION_up_ref(ret);
-        }
-        CRYPTO_THREAD_unlock(s->session_ctx->lock);
-        if (ret == NULL)
-            CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
-                              s->session_ctx->lock);
-    }
-
-    if (try_session_cache &&
-        ret == NULL && s->session_ctx->get_session_cb != NULL) {
-        int copy = 1;
-
-        ret = s->session_ctx->get_session_cb(s, hello->session_id,
-                                             hello->session_id_len,
-                                             &copy);
-
-        if (ret != NULL) {
-            CRYPTO_atomic_add(&s->session_ctx->stats.sess_cb_hit, 1, &discard,
-                              s->session_ctx->lock);
-
-            /*
-             * 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)
-                SSL_SESSION_up_ref(ret);
-
-            /*
-             * Add the externally cached session to the internal cache as
-             * well if and only if we are supposed to.
-             */
-            if (!
-                (s->session_ctx->session_cache_mode &
-                 SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
-                /*
-                 * Either return value of SSL_CTX_add_session should not
-                 * interrupt the session resumption process. The return
-                 * value is intentionally ignored.
-                 */
-                SSL_CTX_add_session(s->session_ctx, ret);
-            }
-        }
-    }
-
     if (ret == NULL)
         goto err;
 
index 7c756c0..48be044 100644 (file)
@@ -1009,6 +1009,33 @@ int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
     return 1;
 }
 
+static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
+                                                 SSL_SESSION **sess)
+{
+    SSL_SESSION *tmpsess = NULL;
+
+    switch (PACKET_remaining(tick)) {
+        case 0:
+            return SSL_TICKET_EMPTY;
+
+        case SSL_MAX_SSL_SESSION_ID_LENGTH:
+            break;
+
+        default:
+            return SSL_TICKET_NO_DECRYPT;
+    }
+
+    tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
+                                   SSL_MAX_SSL_SESSION_ID_LENGTH);
+
+    if (tmpsess == NULL)
+        return SSL_TICKET_NO_DECRYPT;
+
+    s->ext.ticket_expected = 1;
+    *sess = tmpsess;
+    return SSL_TICKET_SUCCESS;
+}
+
 int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                        size_t chainidx)
 {
@@ -1132,9 +1159,12 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
             uint32_t ticket_age = 0, now, agesec, agems;
             int ret;
 
-            ret = tls_decrypt_ticket(s, PACKET_data(&identity),
-                                     PACKET_remaining(&identity), NULL, 0,
-                                     &sess);
+            if ((s->options & SSL_OP_NO_TICKET) != 0)
+                ret = tls_get_stateful_ticket(s, &identity, &sess);
+            else
+                ret = tls_decrypt_ticket(s, PACKET_data(&identity),
+                                         PACKET_remaining(&identity), NULL, 0,
+                                         &sess);
 
             if (ret == SSL_TICKET_EMPTY) {
                 SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
index a4a0ea2..ab16e63 100644 (file)
@@ -3799,29 +3799,29 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
      * long
      */
     if (slen_full == 0 || slen_full > 0xFF00) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     senc = OPENSSL_malloc(slen_full);
     if (senc == NULL) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+                 SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     ctx = EVP_CIPHER_CTX_new();
     hctx = HMAC_CTX_new();
     if (ctx == NULL || hctx == NULL) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     p = senc;
     if (!i2d_SSL_SESSION(s->session, &p)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -3831,23 +3831,23 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
     const_p = senc;
     sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
     if (sess == NULL) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     slen = i2d_SSL_SESSION(sess, NULL);
     if (slen == 0 || slen > slen_full) {
         /* shouldn't ever happen */
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         SSL_SESSION_free(sess);
         goto err;
     }
     p = senc;
     if (!i2d_SSL_SESSION(sess, &p)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         SSL_SESSION_free(sess);
         goto err;
     }
@@ -3868,7 +3868,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
             if (!WPACKET_put_bytes_u32(pkt, 0)
                     || !WPACKET_put_bytes_u16(pkt, 0)) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                         SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                         SSL_F_CONSTRUCT_STATELESS_TICKET,
                          ERR_R_INTERNAL_ERROR);
                 goto err;
             }
@@ -3878,8 +3878,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
             return 1;
         }
         if (ret < 0) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                     SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
                      SSL_R_CALLBACK_FAILED);
             goto err;
         }
@@ -3894,8 +3893,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
                 || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
                                  sizeof(tctx->ext.secure->tick_hmac_key),
                                  EVP_sha256(), NULL)) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                     SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
                      ERR_R_INTERNAL_ERROR);
             goto err;
         }
@@ -3933,14 +3931,14 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
             || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
             || macdata1 != macdata2) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+                 SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     /* Close the sub-packet created by create_ticket_prequel() */
     if (!WPACKET_close(pkt)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -3952,6 +3950,25 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
     return ok;
 }
 
+static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
+                                     unsigned char *tick_nonce)
+{
+    if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
+        /* SSLfatal() already called */
+        return 0;
+    }
+
+    if (!WPACKET_memcpy(pkt, s->session->session_id,
+                        s->session->session_id_length)
+            || !WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    return 1;
+}
+
 int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
 {
     SSL_CTX *tctx = s->session_ctx;
@@ -4065,7 +4082,13 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
         tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0)
         goto err;
 
-    if (!construct_stateless_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
+    if ((s->options & SSL_OP_NO_TICKET) != 0 && SSL_IS_TLS13(s)) {
+        if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
+            /* SSLfatal() already called */
+            goto err;
+        }
+    } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
+                                           tick_nonce)) {
         /* SSLfatal() already called */
         goto err;
     }
index 3ebf64d..c40a0e7 100644 (file)
@@ -1396,7 +1396,8 @@ static int create_sctp_socks(int *ssock, int *csock)
 static HANDSHAKE_RESULT *do_handshake_internal(
     SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx,
     const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra,
-    SSL_SESSION *session_in, SSL_SESSION **session_out)
+    SSL_SESSION *session_in, SSL_SESSION *serv_sess_in,
+    SSL_SESSION **session_out, SSL_SESSION **serv_sess_out)
 {
     PEER server, client;
     BIO *client_to_server = NULL, *server_to_client = NULL;
@@ -1452,10 +1453,14 @@ static HANDSHAKE_RESULT *do_handshake_internal(
 
     configure_handshake_ssl(server.ssl, client.ssl, extra);
     if (session_in != NULL) {
+        SSL_SESSION_get_id(serv_sess_in, &sess_id_len);
         /* In case we're testing resumption without tickets. */
-        if (!TEST_true(SSL_CTX_add_session(server_ctx, session_in))
+        if ((sess_id_len > 0
+                    && !TEST_true(SSL_CTX_add_session(server_ctx,
+                                                      serv_sess_in)))
                 || !TEST_true(SSL_set_session(client.ssl, session_in)))
             goto err;
+        sess_id_len = 0;
     }
 
     ret->result = SSL_TEST_INTERNAL_ERROR;
@@ -1657,6 +1662,16 @@ static HANDSHAKE_RESULT *do_handshake_internal(
 
     if (session_out != NULL)
         *session_out = SSL_get1_session(client.ssl);
+    if (serv_sess_out != NULL) {
+        SSL_SESSION *tmp = SSL_get_session(server.ssl);
+
+        /*
+         * We create a fresh copy that is not in the server session ctx linked
+         * list.
+         */
+        if (tmp != NULL)
+            *serv_sess_out = SSL_SESSION_dup(tmp);
+    }
 
     if (SSL_get_server_tmp_key(client.ssl, &tmp_key)) {
         ret->tmp_key_type = pkey_type(tmp_key);
@@ -1699,11 +1714,11 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
                                const SSL_TEST_CTX *test_ctx)
 {
     HANDSHAKE_RESULT *result;
-    SSL_SESSION *session = NULL;
+    SSL_SESSION *session = NULL, *serv_sess = NULL;
 
     result = do_handshake_internal(server_ctx, server2_ctx, client_ctx,
                                    test_ctx, &test_ctx->extra,
-                                   NULL, &session);
+                                   NULL, NULL, &session, &serv_sess);
     if (result == NULL
             || test_ctx->handshake_mode != SSL_TEST_HANDSHAKE_RESUME
             || result->result == SSL_TEST_INTERNAL_ERROR)
@@ -1718,8 +1733,9 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
     /* We don't support SNI on second handshake yet, so server2_ctx is NULL. */
     result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx,
                                    test_ctx, &test_ctx->resume_extra,
-                                   session, NULL);
+                                   session, serv_sess, NULL, NULL);
  end:
     SSL_SESSION_free(session);
+    SSL_SESSION_free(serv_sess);
     return result;
 }
index 73955de..73de974 100644 (file)
@@ -90,6 +90,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [0-resumption-client]
@@ -126,6 +127,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [1-resumption-client]
@@ -162,6 +164,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [2-resumption-client]
@@ -198,6 +201,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [3-resumption-client]
@@ -234,6 +238,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [4-resumption-client]
@@ -270,6 +275,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [5-resumption-client]
@@ -306,6 +312,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [6-resumption-client]
@@ -342,6 +349,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [7-resumption-client]
@@ -378,6 +386,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [8-resumption-client]
@@ -414,6 +423,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [9-resumption-client]
@@ -450,6 +460,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [10-resumption-client]
@@ -486,6 +497,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [11-resumption-client]
@@ -522,6 +534,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [12-resumption-client]
@@ -558,6 +571,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [13-resumption-client]
@@ -594,6 +608,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [14-resumption-client]
@@ -630,6 +645,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [15-resumption-client]
@@ -666,6 +682,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [16-resumption-client]
@@ -702,6 +719,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [17-resumption-client]
@@ -738,6 +756,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [18-resumption-client]
@@ -774,6 +793,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [19-resumption-client]
@@ -810,6 +830,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [20-resumption-client]
@@ -846,6 +867,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [21-resumption-client]
@@ -882,6 +904,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [22-resumption-client]
@@ -918,6 +941,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [23-resumption-client]
@@ -954,6 +978,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [24-resumption-client]
@@ -990,6 +1015,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [25-resumption-client]
@@ -1026,6 +1052,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [26-resumption-client]
@@ -1062,6 +1089,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [27-resumption-client]
@@ -1098,6 +1126,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [28-resumption-client]
@@ -1134,6 +1163,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [29-resumption-client]
@@ -1170,6 +1200,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [30-resumption-client]
@@ -1206,6 +1237,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = TLSv1.3
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [31-resumption-client]
index ceed959..a981fa5 100644 (file)
@@ -41,6 +41,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [0-resumption-client]
@@ -78,6 +79,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [1-resumption-client]
@@ -115,6 +117,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [2-resumption-client]
@@ -152,6 +155,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [3-resumption-client]
@@ -189,6 +193,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [4-resumption-client]
@@ -226,6 +231,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [5-resumption-client]
@@ -263,6 +269,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1.2
+Options = SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [6-resumption-client]
@@ -300,6 +307,7 @@ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
 CipherString = DEFAULT
 MaxProtocol = DTLSv1.2
+Options = -SessionTicket
 PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
 
 [7-resumption-client]
index 215f9e8..943719e 100644 (file)
@@ -210,6 +210,7 @@ sub generate_resumption_tests {
                         },
                         "resume_server" => {
                             "MaxProtocol" => $protocols[$resume_protocol],
+                            "Options" => $ticket,
                         },
                         "test" => {
                             "ExpectedProtocol" => $protocols[$resume_protocol],
index 9b0237e..61619a3 100644 (file)
@@ -1062,7 +1062,8 @@ static int execute_test_session(int maxprot, int use_int_cache,
     sess2 = NULL;
 
     SSL_CTX_set_max_proto_version(sctx, maxprot);
-    SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
+    if (maxprot == TLS1_2_VERSION)
+        SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
     new_called = remove_called = get_called = 0;
     if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
                                       NULL, NULL))