+#ifndef OPENSSL_NO_TLS1_3
+static SSL_SESSION *sesscache[6];
+static int do_cache;
+
+static int new_cachesession_cb(SSL *ssl, SSL_SESSION *sess)
+{
+ if (do_cache) {
+ sesscache[new_called] = sess;
+ } else {
+ /* We don't need the reference to the session, so free it */
+ SSL_SESSION_free(sess);
+ }
+ new_called++;
+
+ return 1;
+}
+
+static int post_handshake_verify(SSL *sssl, SSL *cssl)
+{
+ SSL_set_verify(sssl, SSL_VERIFY_PEER, NULL);
+ if (!TEST_true(SSL_verify_client_post_handshake(sssl)))
+ return 0;
+
+ /* Start handshake on the server and client */
+ if (!TEST_int_eq(SSL_do_handshake(sssl), 1)
+ || !TEST_int_le(SSL_read(cssl, NULL, 0), 0)
+ || !TEST_int_le(SSL_read(sssl, NULL, 0), 0)
+ || !TEST_true(create_ssl_connection(sssl, cssl,
+ SSL_ERROR_NONE)))
+ return 0;
+
+ return 1;
+}
+
+static int test_tickets(int idx)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ int testresult = 0, i;
+ size_t j;
+
+ /* idx is the test number, but also the number of tickets we want */
+
+ new_called = 0;
+ do_cache = 1;
+
+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
+ TLS1_VERSION, TLS_MAX_VERSION, &sctx,
+ &cctx, cert, privkey))
+ || !TEST_true(SSL_CTX_set_num_tickets(sctx, idx)))
+ goto end;
+
+ SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT
+ | SSL_SESS_CACHE_NO_INTERNAL_STORE);
+ SSL_CTX_sess_set_new_cb(cctx, new_cachesession_cb);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
+ &clientssl, NULL, NULL)))
+ goto end;
+
+ SSL_force_post_handshake_auth(clientssl);
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE))
+ /* Check we got the number of tickets we were expecting */
+ || !TEST_int_eq(idx, new_called))
+ goto end;
+
+ /* After a post-handshake authentication we should get new tickets issued */
+ if (!post_handshake_verify(serverssl, clientssl)
+ || !TEST_int_eq(idx * 2, new_called))
+ goto end;
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ /* Stop caching sessions - just count them */
+ do_cache = 0;
+
+ /* Test that we can resume with all the tickets we got given */
+ for (i = 0; i < idx * 2; i++) {
+ new_called = 0;
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
+ &clientssl, NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, sesscache[i])))
+ goto end;
+
+ SSL_force_post_handshake_auth(clientssl);
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE))
+ || !TEST_true(SSL_session_reused(clientssl))
+ /* Following a resumption we only get 1 ticket */
+ || !TEST_int_eq(new_called, 1))
+ goto end;
+
+ new_called = 0;
+ /* After a post-handshake authentication we should get 1 new ticket */
+ if (!post_handshake_verify(serverssl, clientssl)
+ || !TEST_int_eq(new_called, 1))
+ goto end;
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+ SSL_SESSION_free(sesscache[i]);
+ sesscache[i] = NULL;
+ }
+
+ testresult = 1;
+
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ for (j = 0; j < OSSL_NELEM(sesscache); j++) {
+ SSL_SESSION_free(sesscache[j]);
+ sesscache[j] = NULL;
+ }
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+#endif
+