Skip to content

Commit 4fb1ff7

Browse files
authored
QUIC: SSL_new_session_ticket() support (openssl#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.
1 parent af922d2 commit 4fb1ff7

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
@@ -2360,10 +2360,14 @@ int SSL_renegotiate_pending(const SSL *s)
23602360

23612361
int SSL_new_session_ticket(SSL *s)
23622362
{
2363-
if (SSL_in_init(s) || SSL_IS_FIRST_HANDSHAKE(s) || !s->server
2363+
/* If we are in init because we're sending tickets, okay to send more. */
2364+
if ((SSL_in_init(s) && s->ext.extra_tickets_expected == 0)
2365+
|| SSL_IS_FIRST_HANDSHAKE(s) || !s->server
23642366
|| !SSL_IS_TLS13(s))
23652367
return 0;
23662368
s->ext.extra_tickets_expected++;
2369+
if (s->rlayer.wbuf[0].left == 0 && !SSL_in_init(s))
2370+
ossl_statem_set_in_init(s, 1);
23672371
return 1;
23682372
}
23692373

test/sslapitest.c

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

2486+
/* Once more, but with SSL_do_handshake() to drive the ticket generation */
2487+
c = '4';
2488+
new_called = 0;
2489+
if (!TEST_true(SSL_new_session_ticket(serverssl))
2490+
|| !TEST_true(SSL_new_session_ticket(serverssl))
2491+
|| !TEST_true(SSL_do_handshake(serverssl))
2492+
|| !TEST_int_eq(2, new_called)
2493+
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
2494+
|| !TEST_int_eq(4, new_called))
2495+
goto end;
2496+
24862497
/*
24872498
* Use the always-retry BIO to exercise the logic that forces ticket
24882499
* generation to wait until a record boundary.
24892500
*/
2490-
c = '4';
2501+
c = '5';
24912502
new_called = 0;
24922503
tmp = SSL_get_wbio(serverssl);
24932504
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
@@ -2503,9 +2514,14 @@ static int test_extra_tickets(int idx)
25032514
/* Restore a BIO that will let the write succeed */
25042515
SSL_set0_wbio(serverssl, tmp);
25052516
tmp = NULL;
2506-
/* These calls should just queue the request and not send anything. */
2517+
/*
2518+
* These calls should just queue the request and not send anything
2519+
* even if we explicitly try to hit the state machine.
2520+
*/
25072521
if (!TEST_true(SSL_new_session_ticket(serverssl))
25082522
|| !TEST_true(SSL_new_session_ticket(serverssl))
2523+
|| !TEST_int_eq(0, new_called)
2524+
|| !TEST_true(SSL_do_handshake(serverssl))
25092525
|| !TEST_int_eq(0, new_called))
25102526
goto end;
25112527
/* Re-do the write; still no tickets sent */
@@ -2518,8 +2534,12 @@ static int test_extra_tickets(int idx)
25182534
|| !TEST_int_eq(c, buf[0])
25192535
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
25202536
goto end;
2537+
/* Even trying to hit the state machine now will still not send tickets */
2538+
if (!TEST_true(SSL_do_handshake(serverssl))
2539+
|| !TEST_int_eq(0, new_called))
2540+
goto end;
25212541
/* Now the *next* write should send the tickets */
2522-
c = '5';
2542+
c = '6';
25232543
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
25242544
|| !TEST_size_t_eq(1, nbytes)
25252545
|| !TEST_int_eq(2, new_called)

0 commit comments

Comments
 (0)