1*1523ccfdSEnji Cooper /* 2*1523ccfdSEnji Cooper * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. 3*1523ccfdSEnji Cooper * 4*1523ccfdSEnji Cooper * Licensed under the Apache License 2.0 (the "License"). You may not use 5*1523ccfdSEnji Cooper * this file except in compliance with the License. You can obtain a copy 6*1523ccfdSEnji Cooper * in the file LICENSE in the source distribution or at 7*1523ccfdSEnji Cooper * https://www.openssl.org/source/license.html 8*1523ccfdSEnji Cooper */ 9*1523ccfdSEnji Cooper 10*1523ccfdSEnji Cooper #include <openssl/ssl.h> 11*1523ccfdSEnji Cooper #include "helpers/ssltestlib.h" 12*1523ccfdSEnji Cooper #include "testutil.h" 13*1523ccfdSEnji Cooper 14*1523ccfdSEnji Cooper struct stats { 15*1523ccfdSEnji Cooper unsigned int tickets; 16*1523ccfdSEnji Cooper }; 17*1523ccfdSEnji Cooper 18*1523ccfdSEnji Cooper static char *cert = NULL; 19*1523ccfdSEnji Cooper static char *pkey = NULL; 20*1523ccfdSEnji Cooper static int stats_idx = -1; 21*1523ccfdSEnji Cooper 22*1523ccfdSEnji Cooper static int stats_init(struct stats *stats) 23*1523ccfdSEnji Cooper { 24*1523ccfdSEnji Cooper memset(stats, 0, sizeof(*stats)); 25*1523ccfdSEnji Cooper return 1; 26*1523ccfdSEnji Cooper } 27*1523ccfdSEnji Cooper 28*1523ccfdSEnji Cooper static int sess_new_cb(SSL *ssl, SSL_SESSION *session) 29*1523ccfdSEnji Cooper { 30*1523ccfdSEnji Cooper struct stats *stats = SSL_get_ex_data(ssl, stats_idx); 31*1523ccfdSEnji Cooper if (stats == NULL) 32*1523ccfdSEnji Cooper return 0; 33*1523ccfdSEnji Cooper if (SSL_is_init_finished(ssl) == 0) 34*1523ccfdSEnji Cooper stats->tickets++; 35*1523ccfdSEnji Cooper return 0; 36*1523ccfdSEnji Cooper } 37*1523ccfdSEnji Cooper 38*1523ccfdSEnji Cooper static void handshake_finished(const SSL *ssl) 39*1523ccfdSEnji Cooper { 40*1523ccfdSEnji Cooper const char *endpoint = SSL_is_server(ssl) ? "server" : "client"; 41*1523ccfdSEnji Cooper if (SSL_session_reused(ssl)) 42*1523ccfdSEnji Cooper TEST_info("%s: Abbreviated handshake finished", endpoint); 43*1523ccfdSEnji Cooper else 44*1523ccfdSEnji Cooper TEST_info("%s: Full handshake finished", endpoint); 45*1523ccfdSEnji Cooper } 46*1523ccfdSEnji Cooper 47*1523ccfdSEnji Cooper static void info_cb(const SSL *ssl, int type, int val) 48*1523ccfdSEnji Cooper { 49*1523ccfdSEnji Cooper const char *endpoint = SSL_is_server(ssl) ? "server" : "client"; 50*1523ccfdSEnji Cooper 51*1523ccfdSEnji Cooper if (type & SSL_CB_ALERT) { 52*1523ccfdSEnji Cooper const char *dir = (type & SSL_CB_READ) ? "read" : "write"; 53*1523ccfdSEnji Cooper 54*1523ccfdSEnji Cooper TEST_info("%s: alert %s: %s : %s", endpoint, dir, 55*1523ccfdSEnji Cooper SSL_alert_type_string_long(val), 56*1523ccfdSEnji Cooper SSL_alert_desc_string_long(val)); 57*1523ccfdSEnji Cooper } 58*1523ccfdSEnji Cooper if (type & SSL_CB_HANDSHAKE_DONE) 59*1523ccfdSEnji Cooper handshake_finished(ssl); 60*1523ccfdSEnji Cooper } 61*1523ccfdSEnji Cooper 62*1523ccfdSEnji Cooper static int set_callbacks(SSL *ssl) 63*1523ccfdSEnji Cooper { 64*1523ccfdSEnji Cooper SSL_set_info_callback(ssl, info_cb); 65*1523ccfdSEnji Cooper return 1; 66*1523ccfdSEnji Cooper } 67*1523ccfdSEnji Cooper 68*1523ccfdSEnji Cooper static int set_shutdown(SSL *c, SSL *s) 69*1523ccfdSEnji Cooper { 70*1523ccfdSEnji Cooper SSL_set_shutdown(c, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 71*1523ccfdSEnji Cooper SSL_set_shutdown(s, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 72*1523ccfdSEnji Cooper return 1; 73*1523ccfdSEnji Cooper } 74*1523ccfdSEnji Cooper 75*1523ccfdSEnji Cooper static int enable_tickets(SSL_CTX *s, SSL_CTX *c) 76*1523ccfdSEnji Cooper { 77*1523ccfdSEnji Cooper unsigned int cf = SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE; 78*1523ccfdSEnji Cooper unsigned int sf = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL_STORE; 79*1523ccfdSEnji Cooper 80*1523ccfdSEnji Cooper SSL_CTX_set_session_cache_mode(s, sf); 81*1523ccfdSEnji Cooper SSL_CTX_set_session_cache_mode(c, cf); 82*1523ccfdSEnji Cooper SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); 83*1523ccfdSEnji Cooper 84*1523ccfdSEnji Cooper SSL_CTX_sess_set_new_cb(s, sess_new_cb); 85*1523ccfdSEnji Cooper SSL_CTX_sess_set_new_cb(c, sess_new_cb); 86*1523ccfdSEnji Cooper 87*1523ccfdSEnji Cooper return 1; 88*1523ccfdSEnji Cooper } 89*1523ccfdSEnji Cooper 90*1523ccfdSEnji Cooper /* 91*1523ccfdSEnji Cooper * Verify ticket regeneration after fallback to a full handshake. If session 92*1523ccfdSEnji Cooper * resumption fails due to a ciphersuite mismatch, it falls back to a full 93*1523ccfdSEnji Cooper * handshake. In that case, ensure a new session ticket is issued reflecting the 94*1523ccfdSEnji Cooper * negotiated ciphersuite. 95*1523ccfdSEnji Cooper */ 96*1523ccfdSEnji Cooper static int test_tls13_ticket_ciphersuite_mismatch(void) 97*1523ccfdSEnji Cooper { 98*1523ccfdSEnji Cooper struct stats stats1, stats2; 99*1523ccfdSEnji Cooper SSL_CTX *s_ctx = NULL, *c_ctx = NULL; 100*1523ccfdSEnji Cooper SSL *s_ssl = NULL, *c_ssl = NULL, *s = NULL, *c = NULL; 101*1523ccfdSEnji Cooper SSL_SESSION *sess = NULL; 102*1523ccfdSEnji Cooper int test; 103*1523ccfdSEnji Cooper 104*1523ccfdSEnji Cooper test = create_ssl_ctx_pair(NULL, TLS_server_method(), TLS_client_method(), 105*1523ccfdSEnji Cooper TLS1_3_VERSION, TLS1_3_VERSION, &s_ctx, &c_ctx, cert, pkey) 106*1523ccfdSEnji Cooper && TEST_true(SSL_CTX_set_ciphersuites(s_ctx, "TLS_AES_128_GCM_SHA256")) 107*1523ccfdSEnji Cooper && TEST_true(SSL_CTX_set_ciphersuites(c_ctx, "TLS_AES_128_GCM_SHA256")) 108*1523ccfdSEnji Cooper && TEST_true(enable_tickets(s_ctx, c_ctx)) 109*1523ccfdSEnji Cooper && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s, &c, NULL, NULL)) 110*1523ccfdSEnji Cooper && TEST_true(set_callbacks(c)) 111*1523ccfdSEnji Cooper && TEST_true(set_callbacks(s)) 112*1523ccfdSEnji Cooper && TEST_true(stats_init(&stats1)) 113*1523ccfdSEnji Cooper && TEST_true(SSL_set_ex_data(c, stats_idx, &stats1)) 114*1523ccfdSEnji Cooper && TEST_true(create_ssl_connection(s, c, SSL_ERROR_NONE)) 115*1523ccfdSEnji Cooper && TEST_uint_eq(stats1.tickets, 2) 116*1523ccfdSEnji Cooper && TEST_true(set_shutdown(c, s)) 117*1523ccfdSEnji Cooper && TEST_ptr(sess = SSL_get1_session(c)) 118*1523ccfdSEnji Cooper && TEST_true(SSL_CTX_set_ciphersuites(s_ctx, "TLS_AES_256_GCM_SHA384")) 119*1523ccfdSEnji Cooper && TEST_true(SSL_CTX_set_ciphersuites(c_ctx, "TLS_AES_256_GCM_SHA384")) 120*1523ccfdSEnji Cooper && TEST_true(create_ssl_objects(s_ctx, c_ctx, &s_ssl, &c_ssl, NULL, NULL)) 121*1523ccfdSEnji Cooper && TEST_true(SSL_set_session(c_ssl, sess)) 122*1523ccfdSEnji Cooper && TEST_true(set_callbacks(c_ssl)) 123*1523ccfdSEnji Cooper && TEST_true(set_callbacks(s_ssl)) 124*1523ccfdSEnji Cooper && TEST_true(stats_init(&stats2)) 125*1523ccfdSEnji Cooper && TEST_true(SSL_set_ex_data(c_ssl, stats_idx, &stats2)) 126*1523ccfdSEnji Cooper && TEST_true(create_ssl_connection(s_ssl, c_ssl, SSL_ERROR_NONE)) 127*1523ccfdSEnji Cooper && TEST_false(SSL_session_reused(c_ssl)) 128*1523ccfdSEnji Cooper && TEST_uint_eq(stats2.tickets, 2); 129*1523ccfdSEnji Cooper 130*1523ccfdSEnji Cooper SSL_SESSION_free(sess); 131*1523ccfdSEnji Cooper SSL_free(s_ssl); 132*1523ccfdSEnji Cooper SSL_free(c_ssl); 133*1523ccfdSEnji Cooper SSL_free(s); 134*1523ccfdSEnji Cooper SSL_free(c); 135*1523ccfdSEnji Cooper SSL_CTX_free(s_ctx); 136*1523ccfdSEnji Cooper SSL_CTX_free(c_ctx); 137*1523ccfdSEnji Cooper return test; 138*1523ccfdSEnji Cooper } 139*1523ccfdSEnji Cooper 140*1523ccfdSEnji Cooper OPT_TEST_DECLARE_USAGE("\n") 141*1523ccfdSEnji Cooper 142*1523ccfdSEnji Cooper int setup_tests(void) 143*1523ccfdSEnji Cooper { 144*1523ccfdSEnji Cooper if (!test_skip_common_options()) { 145*1523ccfdSEnji Cooper TEST_error("Error parsing test options\n"); 146*1523ccfdSEnji Cooper return 0; 147*1523ccfdSEnji Cooper } 148*1523ccfdSEnji Cooper 149*1523ccfdSEnji Cooper if (!TEST_ptr(cert = test_get_argument(0)) 150*1523ccfdSEnji Cooper || !TEST_ptr(pkey = test_get_argument(1))) 151*1523ccfdSEnji Cooper return 0; 152*1523ccfdSEnji Cooper 153*1523ccfdSEnji Cooper stats_idx = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 154*1523ccfdSEnji Cooper ADD_TEST(test_tls13_ticket_ciphersuite_mismatch); 155*1523ccfdSEnji Cooper 156*1523ccfdSEnji Cooper return 1; 157*1523ccfdSEnji Cooper } 158