|
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 |
@@ -5942,8 +5951,11 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, |
5942 | 5951 | #ifdef WOLFSSL_EARLY_DATA |
5943 | 5952 | if (ssl->earlyData != no_early_data) { |
5944 | 5953 | TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); |
5945 | | - if (ext == NULL || !ext->val) |
| 5954 | + if (ext == NULL || !ext->val) { |
| 5955 | + WOLFSSL_MSG("Early data rejected by server (no early_data " |
| 5956 | + "EncryptedExtensions response)"); |
5946 | 5957 | ssl->earlyData = no_early_data; |
| 5958 | + } |
5947 | 5959 | } |
5948 | 5960 |
|
5949 | 5961 | if (ssl->earlyData == no_early_data) { |
@@ -6427,18 +6439,6 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, |
6427 | 6439 | /* This PSK works, no need to try any more. */ |
6428 | 6440 | current->chosen = 1; |
6429 | 6441 | ext->resp = 1; |
6430 | | -#if defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) && \ |
6431 | | - !defined(NO_SESSION_CACHE) |
6432 | | - /* RFC 8446 section 8: accept 0-RTT for a given handshake at most |
6433 | | - * once. Evict the session from both the internal cache (under a |
6434 | | - * write lock) and any external cache (via ctx->rem_sess_cb) so |
6435 | | - * the same ClientHello cannot replay early data. Only when the |
6436 | | - * client offered 0-RTT on a session that permits it. */ |
6437 | | - if (ssl->earlyData != no_early_data && |
6438 | | - ssl->session->maxEarlyDataSz != 0) { |
6439 | | - (void)wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session); |
6440 | | - } |
6441 | | -#endif |
6442 | 6442 | break; |
6443 | 6443 | } |
6444 | 6444 |
|
@@ -6599,8 +6599,16 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, |
6599 | 6599 | * RFC 8773bis: early_data is not compatible with |
6600 | 6600 | * cert_with_extern_psk, so skip key derivation in that case. */ |
6601 | 6601 | if (ssl->earlyData != no_early_data && first |
| 6602 | + && ssl->options.maxEarlyDataSz > 0 |
6602 | 6603 | #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK |
6603 | 6604 | && !hasCertWithExternPsk |
| 6605 | + #endif |
| 6606 | + #if defined(HAVE_SESSION_TICKET) && !defined(NO_SESSION_CACHE) |
| 6607 | + /* RFC 8446 section 8: evict the session from the cache. |
| 6608 | + * Accept 0-RTT only when the eviction found the entry |
| 6609 | + * (single-use). */ |
| 6610 | + && wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session) |
| 6611 | + == 1 |
6604 | 6612 | #endif |
6605 | 6613 | ) { |
6606 | 6614 | extEarlyData->resp = 1; |
@@ -6663,6 +6671,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, |
6663 | 6671 | * combination in the ClientHello, but clear the response flag |
6664 | 6672 | * here as a defense-in-depth measure. */ |
6665 | 6673 | if (extEarlyData != NULL) { |
| 6674 | + WOLFSSL_MSG("Rejecting early data: " |
| 6675 | + "cert_with_extern_psk is not 0-RTT compatible"); |
6666 | 6676 | extEarlyData->resp = 0; |
6667 | 6677 | ssl->earlyData = no_early_data; |
6668 | 6678 | } |
@@ -15493,7 +15503,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) |
15493 | 15503 | #ifdef HAVE_SESSION_TICKET |
15494 | 15504 | #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED |
15495 | 15505 | if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 && |
15496 | | - ssl->ctx->ticketEncCb != NULL) { |
| 15506 | + ssl->ctx->ticketEncCb != NULL && |
| 15507 | + ssl->options.maxTicketTls13 > 0) { |
15497 | 15508 | if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { |
15498 | 15509 | WOLFSSL_ERROR(ssl->error); |
15499 | 15510 | return WOLFSSL_FATAL_ERROR; |
@@ -15634,6 +15645,11 @@ int wolfSSL_send_SessionTicket(WOLFSSL* ssl) |
15634 | 15645 | * A value of zero indicates no early data is to be sent by client using session |
15635 | 15646 | * tickets. |
15636 | 15647 | * |
| 15648 | + * The default value is zero: per RFC 8446 Appendix E.5, TLS implementations |
| 15649 | + * "MUST NOT enable 0-RTT (either sending or accepting) unless specifically |
| 15650 | + * requested by the application." Servers must explicitly opt in by calling |
| 15651 | + * this function (or the per-SSL equivalent) with a non-zero value. |
| 15652 | + * |
15637 | 15653 | * ctx The SSL/TLS CTX object. |
15638 | 15654 | * sz Maximum size of the early data. |
15639 | 15655 | * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and |
|
0 commit comments