|
61 | 61 | * |
62 | 62 | * TLS 1.3 Session Tickets: |
63 | 63 | * WOLFSSL_TICKET_HAVE_ID: Session tickets include ID default: off |
| 64 | + * Forced on when WOLFSSL_EARLY_DATA is set. |
64 | 65 | * WOLFSSL_TICKET_NONCE_MALLOC: Dynamically allocate ticket nonce default: off |
65 | 66 | * |
66 | 67 | * TLS 1.3 Key Exchange: |
|
81 | 82 |
|
82 | 83 | #if !defined(NO_TLS) && defined(WOLFSSL_TLS13) |
83 | 84 |
|
| 85 | +/* 0-RTT anti-replay eviction needs the session cache. */ |
| 86 | +#if defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) && \ |
| 87 | + defined(NO_SESSION_CACHE) && !defined(NO_WOLFSSL_SERVER) && \ |
| 88 | + !defined(WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY) |
| 89 | +#error "WOLFSSL_EARLY_DATA with tickets requires !NO_SESSION_CACHE, or " \ |
| 90 | + "define WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY to opt out." |
| 91 | +#endif |
| 92 | + |
84 | 93 | #ifndef WOLFCRYPT_ONLY |
85 | 94 |
|
86 | 95 | #ifdef HAVE_ERRNO_H |
@@ -5901,8 +5910,11 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, |
5901 | 5910 | #ifdef WOLFSSL_EARLY_DATA |
5902 | 5911 | if (ssl->earlyData != no_early_data) { |
5903 | 5912 | TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); |
5904 | | - if (ext == NULL || !ext->val) |
| 5913 | + if (ext == NULL || !ext->val) { |
| 5914 | + WOLFSSL_MSG("Early data rejected by server (no early_data " |
| 5915 | + "EncryptedExtensions response)"); |
5905 | 5916 | ssl->earlyData = no_early_data; |
| 5917 | + } |
5906 | 5918 | } |
5907 | 5919 |
|
5908 | 5920 | if (ssl->earlyData == no_early_data) { |
@@ -6377,18 +6389,6 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, |
6377 | 6389 | /* This PSK works, no need to try any more. */ |
6378 | 6390 | current->chosen = 1; |
6379 | 6391 | ext->resp = 1; |
6380 | | -#if defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) && \ |
6381 | | - !defined(NO_SESSION_CACHE) |
6382 | | - /* RFC 8446 section 8: accept 0-RTT for a given handshake at most |
6383 | | - * once. Evict the session from both the internal cache (under a |
6384 | | - * write lock) and any external cache (via ctx->rem_sess_cb) so |
6385 | | - * the same ClientHello cannot replay early data. Only when the |
6386 | | - * client offered 0-RTT on a session that permits it. */ |
6387 | | - if (ssl->earlyData != no_early_data && |
6388 | | - ssl->session->maxEarlyDataSz != 0) { |
6389 | | - (void)wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session); |
6390 | | - } |
6391 | | -#endif |
6392 | 6392 | break; |
6393 | 6393 | } |
6394 | 6394 |
|
@@ -6549,8 +6549,16 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, |
6549 | 6549 | * RFC 8773bis: early_data is not compatible with |
6550 | 6550 | * cert_with_extern_psk, so skip key derivation in that case. */ |
6551 | 6551 | if (ssl->earlyData != no_early_data && first |
| 6552 | + && ssl->options.maxEarlyDataSz > 0 |
6552 | 6553 | #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK |
6553 | 6554 | && !hasCertWithExternPsk |
| 6555 | + #endif |
| 6556 | + #if defined(HAVE_SESSION_TICKET) && !defined(NO_SESSION_CACHE) |
| 6557 | + /* RFC 8446 section 8: evict the session from the cache. |
| 6558 | + * Accept 0-RTT only when the eviction found the entry |
| 6559 | + * (single-use). */ |
| 6560 | + && wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session) |
| 6561 | + == 1 |
6554 | 6562 | #endif |
6555 | 6563 | ) { |
6556 | 6564 | extEarlyData->resp = 1; |
@@ -6613,6 +6621,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, |
6613 | 6621 | * combination in the ClientHello, but clear the response flag |
6614 | 6622 | * here as a defense-in-depth measure. */ |
6615 | 6623 | if (extEarlyData != NULL) { |
| 6624 | + WOLFSSL_MSG("Rejecting early data: " |
| 6625 | + "cert_with_extern_psk is not 0-RTT compatible"); |
6616 | 6626 | extEarlyData->resp = 0; |
6617 | 6627 | ssl->earlyData = no_early_data; |
6618 | 6628 | } |
@@ -15388,7 +15398,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) |
15388 | 15398 | #ifdef HAVE_SESSION_TICKET |
15389 | 15399 | #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED |
15390 | 15400 | if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 && |
15391 | | - ssl->ctx->ticketEncCb != NULL) { |
| 15401 | + ssl->ctx->ticketEncCb != NULL && |
| 15402 | + ssl->options.maxTicketTls13 > 0) { |
15392 | 15403 | if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { |
15393 | 15404 | WOLFSSL_ERROR(ssl->error); |
15394 | 15405 | return WOLFSSL_FATAL_ERROR; |
@@ -15529,6 +15540,11 @@ int wolfSSL_send_SessionTicket(WOLFSSL* ssl) |
15529 | 15540 | * A value of zero indicates no early data is to be sent by client using session |
15530 | 15541 | * tickets. |
15531 | 15542 | * |
| 15543 | + * The default value is zero: per RFC 8446 Appendix E.5, TLS implementations |
| 15544 | + * "MUST NOT enable 0-RTT (either sending or accepting) unless specifically |
| 15545 | + * requested by the application." Servers must explicitly opt in by calling |
| 15546 | + * this function (or the per-SSL equivalent) with a non-zero value. |
| 15547 | + * |
15532 | 15548 | * ctx The SSL/TLS CTX object. |
15533 | 15549 | * sz Maximum size of the early data. |
15534 | 15550 | * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and |
|
0 commit comments