[openssl] master update
kaduk at mit.edu
kaduk at mit.edu
Wed May 19 21:57:14 UTC 2021
The branch master has been updated
via 6e495312fda0e669d105172c1ac8a8c0bf52da6d (commit)
via a0bbcb42a94cc6bc4f72d567c5e701b4cecf5be6 (commit)
via 7c73fefe38f4fce9437b1d24d90dd5aa411c7e28 (commit)
from e34e91d7e575a2f69119601f2d34655cb6816148 (commit)
- Log -----------------------------------------------------------------
commit 6e495312fda0e669d105172c1ac8a8c0bf52da6d
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date: Thu Apr 8 18:41:46 2021 -0700
Update SSL_new_session_ticket() manual for triggered send
Document the recently added functionality.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14817)
commit a0bbcb42a94cc6bc4f72d567c5e701b4cecf5be6
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date: Thu Apr 8 17:09:18 2021 -0700
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.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14817)
commit 7c73fefe38f4fce9437b1d24d90dd5aa411c7e28
Author: Benjamin Kaduk <bkaduk at akamai.com>
Date: Fri Apr 2 10:04:24 2021 -0700
Let SSL_new_session_ticket() enter init immediately
The initial implementation always deferred the generation of the
requested ticket(s) until the next application write, but this
is not a great fit for what it actually does, architecturally wise.
A request to send a session ticket means entering back into the
handshake state machine (or "in init", as it's known in the
implementation). The state machine transition is not something that
only occurs at an application-data write, and in general could occur at
any time. The only constraint is that we can't enter "init" while in
the middle of writing application data. In such cases we will need to
wait until the next TLS record boundary to enter the state machine,
as is currently done.
However, there is no reason why we cannot enter the handshake state
machine immediately in SSL_new_session_ticket() if there are no
application writes pending. Doing so provides a cleaner API surface to
the application, as then calling SSL_do_handshake() suffices to drive
the actual ticket generation. In the previous state of affairs a dummy
zero-length SSL_write() would be needed to trigger the ticket
generation, which is a logical mismatch in the type of operation being
performed.
This commit should only change whether SSL_do_handshake() vs zero-length
SSL_write() is needed to immediately generate a ticket after the
SSL_new_session_ticket() call -- the default behavior is still to defer
the actual write until there is other application data to write, unless
the application requests otherwise.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14817)
-----------------------------------------------------------------------
Summary of changes:
doc/man3/SSL_CTX_set_num_tickets.pod | 27 ++++++++++++++++-----------
ssl/ssl_lib.c | 6 +++++-
test/sslapitest.c | 26 +++++++++++++++++++++++---
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/doc/man3/SSL_CTX_set_num_tickets.pod b/doc/man3/SSL_CTX_set_num_tickets.pod
index aa673bd8d0..7ab62d3ad3 100644
--- a/doc/man3/SSL_CTX_set_num_tickets.pod
+++ b/doc/man3/SSL_CTX_set_num_tickets.pod
@@ -45,17 +45,22 @@ sent.
To issue tickets after other events (such as application-layer changes),
SSL_new_session_ticket() is used by a server application to request that a new
ticket be sent when it is safe to do so. New tickets are only allowed to be
-sent in this manner after the initial handshake has completed, and only for TLS
-1.3 connections. The ticket generation and transmission are delayed until the
-server is starting a new write operation, so that it is bundled with other
-application data being written and properly aligned to a record boundary.
-SSL_new_session_ticket() can be called more than once to request additional
-tickets be sent; all such requests are queued and written together when it is
-safe to do so. Note that a successful return from SSL_new_session_ticket()
-indicates only that the request to send a ticket was processed, not that the
-ticket itself was sent. To be notified when the ticket itself is sent, a
-new-session callback can be registered with L<SSL_CTX_sess_set_new_cb(3)> that
-will be invoked as the ticket or tickets are generated.
+sent in this manner after the initial handshake has completed, and only for
+TLS 1.3 connections. By default, the ticket generation and transmission are
+delayed until the server is starting a new write operation, so that it is
+bundled with other application data being written and properly aligned to a
+record boundary. If the connection was at a record boundary when
+SSL_new_session_ticket() was called, the ticket can be sent immediately
+(without waiting for the next application write) by calling
+SSL_do_handshake(). SSL_new_session_ticket() can be called more than once to
+request additional tickets be sent; all such requests are queued and written
+together when it is safe to do so and triggered by SSL_write() or
+SSL_do_handshake(). Note that a successful return from
+SSL_new_session_ticket() indicates only that the request to send a ticket was
+processed, not that the ticket itself was sent. To be notified when the
+ticket itself is sent, a new-session callback can be registered with
+L<SSL_CTX_sess_set_new_cb(3)> that will be invoked as the ticket or tickets
+are generated.
SSL_CTX_get_num_tickets() and SSL_get_num_tickets() return the number of
tickets set by a previous call to SSL_CTX_set_num_tickets() or
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index ff13442e3b..f35eaf07c5 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2327,10 +2327,14 @@ int SSL_renegotiate_pending(const SSL *s)
int SSL_new_session_ticket(SSL *s)
{
- if (SSL_in_init(s) || SSL_IS_FIRST_HANDSHAKE(s) || !s->server
+ /* If we are in init because we're sending tickets, okay to send more. */
+ if ((SSL_in_init(s) && s->ext.extra_tickets_expected == 0)
+ || SSL_IS_FIRST_HANDSHAKE(s) || !s->server
|| !SSL_IS_TLS13(s))
return 0;
s->ext.extra_tickets_expected++;
+ if (s->rlayer.wbuf[0].left == 0 && !SSL_in_init(s))
+ ossl_statem_set_in_init(s, 1);
return 1;
}
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 0a7295c5cb..28e9852dbb 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -2516,11 +2516,22 @@ static int test_extra_tickets(int idx)
|| !TEST_int_eq(4, new_called))
goto end;
+ /* Once more, but with SSL_do_handshake() to drive the ticket generation */
+ c = '4';
+ new_called = 0;
+ if (!TEST_true(SSL_new_session_ticket(serverssl))
+ || !TEST_true(SSL_new_session_ticket(serverssl))
+ || !TEST_true(SSL_do_handshake(serverssl))
+ || !TEST_int_eq(2, new_called)
+ || !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes))
+ || !TEST_int_eq(4, new_called))
+ goto end;
+
/*
* Use the always-retry BIO to exercise the logic that forces ticket
* generation to wait until a record boundary.
*/
- c = '4';
+ c = '5';
new_called = 0;
tmp = SSL_get_wbio(serverssl);
if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
@@ -2536,9 +2547,14 @@ static int test_extra_tickets(int idx)
/* Restore a BIO that will let the write succeed */
SSL_set0_wbio(serverssl, tmp);
tmp = NULL;
- /* These calls should just queue the request and not send anything. */
+ /*
+ * These calls should just queue the request and not send anything
+ * even if we explicitly try to hit the state machine.
+ */
if (!TEST_true(SSL_new_session_ticket(serverssl))
|| !TEST_true(SSL_new_session_ticket(serverssl))
+ || !TEST_int_eq(0, new_called)
+ || !TEST_true(SSL_do_handshake(serverssl))
|| !TEST_int_eq(0, new_called))
goto end;
/* Re-do the write; still no tickets sent */
@@ -2551,8 +2567,12 @@ static int test_extra_tickets(int idx)
|| !TEST_int_eq(c, buf[0])
|| !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &nbytes)))
goto end;
+ /* Even trying to hit the state machine now will still not send tickets */
+ if (!TEST_true(SSL_do_handshake(serverssl))
+ || !TEST_int_eq(0, new_called))
+ goto end;
/* Now the *next* write should send the tickets */
- c = '5';
+ c = '6';
if (!TEST_true(SSL_write_ex(serverssl, &c, 1, &nbytes))
|| !TEST_size_t_eq(1, nbytes)
|| !TEST_int_eq(2, new_called)
More information about the openssl-commits
mailing list