Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -41744,6 +41744,13 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
return BUFFER_E;
}

/* The two-key rotation can only honor a hint below half the key lifetime.
* Refuse to issue a ticket whose advertised lifetime it cannot cover. */
if (enc && 2 * ctx->ticketHint >= WOLFSSL_TICKET_KEY_LIFETIME) {
Comment thread
dgarske marked this conversation as resolved.
Outdated
WOLFSSL_MSG("Ticket hint exceeds half the ticket key lifetime");
return WOLFSSL_TICKET_RET_FATAL;
Comment thread
dgarske marked this conversation as resolved.
Outdated
}

/* Check we have setup the RNG, name and primary key. */
if (keyCtx->expirary[0] == 0) {
#ifndef SINGLE_THREADED
Expand Down
71 changes: 71 additions & 0 deletions tests/api/test_ssl_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,77 @@ int test_wolfSSL_CTX_set_TicketHint_ext(void)
return EXPECT_RESULT();
}

#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) \
&& defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) \
&& !defined(NO_WOLFSSL_SERVER)
/* Trivial custom ticket encryption callback: it has no key-lifetime constraint,
* so it must be able to issue a ticket for any hint. */
static int test_TicketHint_custom_encCb(WOLFSSL* ssl,
Comment thread
dgarske marked this conversation as resolved.
byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ],
byte mac[WOLFSSL_TICKET_MAC_SZ], int enc, byte* ticket, int inLen,
int* outLen, void* userCtx)
{
int i;
(void)ssl;
(void)userCtx;
if (enc) {
XMEMSET(key_name, 0x2A, WOLFSSL_TICKET_NAME_SZ);
XMEMSET(iv, 0x2A, WOLFSSL_TICKET_IV_SZ);
XMEMSET(mac, 0x2A, WOLFSSL_TICKET_MAC_SZ);
}
for (i = 0; i < inLen; i++)
ticket[i] = (byte)(ticket[i] ^ 0xA5);
*outLen = inLen;
return WOLFSSL_TICKET_RET_OK;
}

/* Drive one TLS 1.3 handshake, returning the handshake result. */
static int test_TicketHint_handshake(int hint, int customCb)
{
struct test_memio_ctx test_ctx;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
int ret;

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
if (test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method) != 0) {
ret = -1;
goto done;
}
if (customCb)
wolfSSL_CTX_set_TicketEncCb(ctx_s, test_TicketHint_custom_encCb);
wolfSSL_CTX_set_TicketHint(ctx_s, hint);

ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
done:
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
return ret;
}
#endif

/* The default ticket encryption callback must refuse to issue a ticket when the
* hint exceeds half the key lifetime, but a custom callback has no such limit. */
int test_wolfSSL_CTX_set_TicketHint_default_cb_limit(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) \
&& defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) \
&& !defined(NO_WOLFSSL_SERVER)
/* Default callback: a hint below the limit is honored. */
ExpectIntEQ(test_TicketHint_handshake(WOLFSSL_TICKET_KEY_LIFETIME / 2 - 1, 0),
0);
/* Default callback: a hint at/above the limit fails the handshake. */
ExpectIntNE(test_TicketHint_handshake(WOLFSSL_TICKET_KEY_LIFETIME / 2, 0), 0);
/* Custom callback: the same oversized hint is fine. */
ExpectIntEQ(test_TicketHint_handshake(WOLFSSL_TICKET_KEY_LIFETIME / 2, 1), 0);
#endif
return EXPECT_RESULT();
}

int test_wolfSSL_tlsext_max_fragment_length_ext(void)
{
EXPECT_DECLS;
Expand Down
3 changes: 3 additions & 0 deletions tests/api/test_ssl_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int test_wolfSSL_CTX_num_tickets_ext(void);
int test_wolfSSL_set1_groups_ext(void);
int test_wolfSSL_set1_groups_list_ext(void);
int test_wolfSSL_CTX_set_TicketHint_ext(void);
int test_wolfSSL_CTX_set_TicketHint_default_cb_limit(void);
int test_wolfSSL_tlsext_max_fragment_length_ext(void);
int test_wolfSSL_DisableExtendedMasterSecret_ext(void);
int test_wolfSSL_set_tlsext_host_name_ext(void);
Expand Down Expand Up @@ -57,6 +58,8 @@ int test_wolfSSL_CTX_set_alpn_protos_inval_ext(void);
TEST_DECL_GROUP("ssl_ext", test_wolfSSL_set1_groups_ext), \
TEST_DECL_GROUP("ssl_ext", test_wolfSSL_set1_groups_list_ext), \
TEST_DECL_GROUP("ssl_ext", test_wolfSSL_CTX_set_TicketHint_ext), \
TEST_DECL_GROUP("ssl_ext", \
test_wolfSSL_CTX_set_TicketHint_default_cb_limit), \
TEST_DECL_GROUP("ssl_ext", \
test_wolfSSL_tlsext_max_fragment_length_ext), \
TEST_DECL_GROUP("ssl_ext", \
Expand Down
34 changes: 31 additions & 3 deletions tests/api/test_tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -5729,12 +5729,38 @@ int test_tls13_short_session_ticket(void)
}


#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
/* Custom ticket encryption callback with no key-lifetime limit, so the server
* issues a ticket for any hint (the default callback refuses a hint of at least
* half the key lifetime). */
static int test_tls13_max_lifetime_ticketEncCb(WOLFSSL* ssl,
byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ],
byte mac[WOLFSSL_TICKET_MAC_SZ], int enc, byte* ticket, int inLen,
int* outLen, void* userCtx)
{
int i;
(void)ssl;
(void)userCtx;
if (enc) {
XMEMSET(key_name, 0x2A, WOLFSSL_TICKET_NAME_SZ);
XMEMSET(iv, 0x2A, WOLFSSL_TICKET_IV_SZ);
XMEMSET(mac, 0x2A, WOLFSSL_TICKET_MAC_SZ);
}
for (i = 0; i < inLen; i++)
ticket[i] = (byte)(ticket[i] ^ 0xA5);
*outLen = inLen;
return WOLFSSL_TICKET_RET_OK;
}
#endif

/* RFC 8446 Section 4.6.1: a NewSessionTicket lifetime greater than
* MAX_LIFETIME (604800 seconds, 7 days) must be rejected. The public
* wolfSSL_CTX_set_TicketHint setter clamps the value, so write the
* out-of-range hint directly into the server CTX to force the server to
* encode an over-limit lifetime onto the wire and confirm the client's
* DoTls13NewSessionTicket bound check fires. */
* out-of-range hint directly into the server CTX. A custom encryption callback
* is installed so the default callback's key-lifetime limit does not block
* issuance, forcing the server to encode the over-limit lifetime onto the wire
* and confirming the client's DoTls13NewSessionTicket bound check fires. */
int test_tls13_new_session_ticket_max_lifetime(void)
{
EXPECT_DECLS;
Expand All @@ -5749,6 +5775,8 @@ int test_tls13_new_session_ticket_max_lifetime(void)
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

wolfSSL_CTX_set_TicketEncCb(ctx_s, test_tls13_max_lifetime_ticketEncCb);

/* Bypass the public-API clamp at 604800. */
if (EXPECT_SUCCESS()) {
ctx_s->ticketHint = MAX_LIFETIME + 1;
Expand Down
Loading