Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit 274b61d

Browse files
kaduktmshort
authored andcommitted
QUIC: SSL_new_session_ticket() support (#26)
* Let SSL_new_session_ticket() work immediately The initial implementation always deferred the generation of the requested ticket(s) until the next application write, but this means that the ticket cannot be written at all until there is application data ready to write. In some scenarios this application data may never arrive or may take a long time to arrive, so (when already at a record boundary) allow the application to explicitly call SSL_do_handshake() after SSL_new_session_ticket() to force an immediate write, even when there is no application data available. The default behavior remains to defer the generation of the ticket and coalesce the network traffic for the ticket and application data. * Test new SSL_new_session_ticket() functionality Now that we can become "in init" directly after the call, test the various scenarios where explicit SSL_do_handshake() calls can come into play. * Update SSL_new_session_ticket() manual for triggered send Document the recently added functionality. (cherry picked from commit 4fb1ff7)
1 parent 5923fb1 commit 274b61d

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

doc/man3/SSL_CTX_set_num_tickets.pod

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,22 @@ sent.
4545
To issue tickets after other events (such as application-layer changes),
4646
SSL_new_session_ticket() is used by a server application to request that a new
4747
ticket be sent when it is safe to do so. New tickets are only allowed to be
48-
sent in this manner after the initial handshake has completed, and only for TLS
49-
1.3 connections. The ticket generation and transmission are delayed until the
50-
server is starting a new write operation, so that it is bundled with other
51-
application data being written and properly aligned to a record boundary.
52-
SSL_new_session_ticket() can be called more than once to request additional
53-
tickets be sent; all such requests are queued and written together when it is
54-
safe to do so. Note that a successful return from SSL_new_session_ticket()
55-
indicates only that the request to send a ticket was processed, not that the
56-
ticket itself was sent. To be notified when the ticket itself is sent, a
57-
new-session callback can be registered with L<SSL_CTX_sess_set_new_cb(3)> that
58-
will be invoked as the ticket or tickets are generated.
48+
sent in this manner after the initial handshake has completed, and only for
49+
TLS 1.3 connections. By default, the ticket generation and transmission are
50+
delayed until the server is starting a new write operation, so that it is
51+
bundled with other application data being written and properly aligned to a
52+
record boundary. If the connection was at a record boundary when
53+
SSL_new_session_ticket() was called, the ticket can be sent immediately
54+
(without waiting for the next application write) by calling
55+
SSL_do_handshake(). SSL_new_session_ticket() can be called more than once to
56+
request additional tickets be sent; all such requests are queued and written
57+
together when it is safe to do so and triggered by SSL_write() or
58+
SSL_do_handshake(). Note that a successful return from
59+
SSL_new_session_ticket() indicates only that the request to send a ticket was
60+
processed, not that the ticket itself was sent. To be notified when the
61+
ticket itself is sent, a new-session callback can be registered with
62+
L<SSL_CTX_sess_set_new_cb(3)> that will be invoked as the ticket or tickets
63+
are generated.
5964

6065
SSL_CTX_get_num_tickets() and SSL_get_num_tickets() return the number of
6166
tickets set by a previous call to SSL_CTX_set_num_tickets() or

ssl/ssl_lib.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2220,10 +2220,14 @@ int SSL_renegotiate_pending(const SSL *s)
22202220

22212221
int SSL_new_session_ticket(SSL *s)
22222222
{
2223-
if (SSL_in_init(s) || SSL_IS_FIRST_HANDSHAKE(s) || !s->server
2223+
/* If we are in init because we're sending tickets, okay to send more. */
2224+
if ((SSL_in_init(s) && s->ext.extra_tickets_expected == 0)
2225+
|| SSL_IS_FIRST_HANDSHAKE(s) || !s->server
22242226
|| !SSL_IS_TLS13(s))
22252227
return 0;
22262228
s->ext.extra_tickets_expected++;
2229+
if (s->rlayer.wbuf[0].left == 0 && !SSL_in_init(s))
2230+
ossl_statem_set_in_init(s, 1);
22272231
return 1;
22282232
}
22292233

test/sslapitest.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,11 +1707,22 @@ static int test_extra_tickets(int idx)
17071707
|| !TEST_int_eq(4, new_called))
17081708
goto end;
17091709

1710+
/* Once more, but with SSL_do_handshake() to drive the ticket generation */
1711+
c = '4';
1712+
new_called = 0;
1713+
if (!TEST_true(SSL_new_session_ticket(serverssl))
1714+
|| !TEST_true(SSL_new_session_ticket(serverssl))
1715+
|| !TEST_true(SSL_do_handshake(serverssl))
1716+
|| !TEST_int_eq(2, new_called)
1717+
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
1718+
|| !TEST_int_eq(4, new_called))
1719+
goto end;
1720+
17101721
/*
17111722
* Use the always-retry BIO to exercise the logic that forces ticket
17121723
* generation to wait until a record boundary.
17131724
*/
1714-
c = '4';
1725+
c = '5';
17151726
new_called = 0;
17161727
tmp = SSL_get_wbio(serverssl);
17171728
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
@@ -1727,9 +1738,14 @@ static int test_extra_tickets(int idx)
17271738
/* Restore a BIO that will let the write succeed */
17281739
SSL_set0_wbio(serverssl, tmp);
17291740
tmp = NULL;
1730-
/* These calls should just queue the request and not send anything. */
1741+
/*
1742+
* These calls should just queue the request and not send anything
1743+
* even if we explicitly try to hit the state machine.
1744+
*/
17311745
if (!TEST_true(SSL_new_session_ticket(serverssl))
17321746
|| !TEST_true(SSL_new_session_ticket(serverssl))
1747+
|| !TEST_int_eq(0, new_called)
1748+
|| !TEST_true(SSL_do_handshake(serverssl))
17331749
|| !TEST_int_eq(0, new_called))
17341750
goto end;
17351751
/* Re-do the write; still no tickets sent */
@@ -1742,8 +1758,12 @@ static int test_extra_tickets(int idx)
17421758
|| !TEST_int_eq(c, buf[0])
17431759
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
17441760
goto end;
1761+
/* Even trying to hit the state machine now will still not send tickets */
1762+
if (!TEST_true(SSL_do_handshake(serverssl))
1763+
|| !TEST_int_eq(0, new_called))
1764+
goto end;
17451765
/* Now the *next* write should send the tickets */
1746-
c = '5';
1766+
c = '6';
17471767
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
17481768
|| !TEST_size_t_eq(1, nbytes)
17491769
|| !TEST_int_eq(2, new_called)

0 commit comments

Comments
 (0)