xref: /freebsd/crypto/openssl/test/tls13tickettest.c (revision 1523ccfd9c8c254f7928143d31c305384b05fd11)
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