Commit 1234697b33 for openssl.org
commit 1234697b33694bea6e7df35704b126108d1391ea
Author: Bob Beck <beck@openssl.org>
Date: Wed Sep 9 17:28:18 2026 -0600
Bring recent comments into line with the STYLE.md comment rules
Comments added by AI-assisted commits over the last three months
often narrate the change rather than describe the code: the
behaviour being replaced, the alternative not taken, or the bug the
test was written for. STYLE.md now says that a comment states what
the code does and the constraint it satisfies, and that the
reasoning behind a change does not belong in one.
Reword those comments to that standard.
Reviewed-by: Milan Broz <mbroz@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Merge-date: Fri Oct 2 08:06:12 2026
Merged-from: https://github.com/openssl/openssl/pull/32779
diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c
index 41491b92a1..8d4b782abc 100644
--- a/crypto/asn1/a_d2i_fp.c
+++ b/crypto/asn1/a_d2i_fp.c
@@ -149,9 +149,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
* truncated. Only a clean EOF at a top-level object boundary
* (i == 0, diff == 0, eos == 0) is the normal end of input:
* fail without queuing an error so that callers looping over
- * concatenated DER values (e.g. the libcrypto d2i_*_bio()
- * consumers in CPython's ssl module) terminate cleanly instead
- * of seeing a spurious ASN1_R_NOT_ENOUGH_DATA.
+ * concatenated DER values terminate cleanly.
*/
if (i < 0 || diff != 0 || eos != 0)
ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
diff --git a/crypto/mem.c b/crypto/mem.c
index f5286e4aa5..2bdbc2d11d 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -119,7 +119,7 @@ static void parseit(void)
/*
* Get the count (parsing stops at the '@' if present), and percentage.
- * Ignore an unparsable/overflowing count rather than acting on garbage.
+ * An unparsable or overflowing count is ignored.
* Validate that the count is followed by '@' or end-of-string.
*/
if (!ossl_strtol(md_failstring, &end, 10, &md_count)
diff --git a/crypto/property/property.c b/crypto/property/property.c
index 80f657f2be..81cb6a8d6d 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -1243,10 +1243,8 @@ static ossl_inline int ossl_method_store_cache_set_atomic(OSSL_METHOD_STORE *sto
*
* Only insert it if no NULL-provider entry exists yet for this nid and
* property query. The first provider to cache this nid owns that
- * entry, which matches the provider ossl_method_store_fetch would pick
- * by implementation order. Without this check, a later cache_set from
- * a different provider would overwrite it and change which provider an
- * "any provider" lookup resolves to.
+ * entry, which is the provider ossl_method_store_fetch picks by
+ * implementation order.
*/
if (ossl_method_store_atomic_find_in_list(sa, nid, NULL, prop_query) == NULL) {
p = QUERY_new(strlen(prop_query));
diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c
index d0c7c63551..5e2f6328ef 100644
--- a/crypto/rand/prov_seed.c
+++ b/crypto/rand/prov_seed.c
@@ -49,10 +49,8 @@ size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx,
if (ossl_rand_seed_source_strict(ctx)) {
/*
- * With strict seeding the seed source must be used, even when the
- * request arrives before anything instantiated it: create it now
- * and fail instead of silently substituting the operating system
- * entropy sources.
+ * With strict seeding the configured seed source must be used,
+ * even when the request arrives before anything instantiated it.
*/
rng = ossl_rand_get0_seed(ctx);
if (rng == NULL || !evp_rand_can_seed(rng)) {
diff --git a/demos/dtlsecho/main.c b/demos/dtlsecho/main.c
index e9856171f9..1b6b0b5b11 100644
--- a/demos/dtlsecho/main.c
+++ b/demos/dtlsecho/main.c
@@ -49,9 +49,9 @@ static SOCKET create_socket(void)
char port_str[6];
/*
- * Resolve the wildcard address for our port. Requesting AF_INET6 gives a
- * single socket that, BIO_listen will clear IPV6_V6ONLY below, and the
- * socket accepts both IPv6 and IPv4 clients.
+ * Resolve the wildcard address for our port. With AF_INET6 and
+ * IPV6_V6ONLY cleared by BIO_listen below, a single socket accepts both
+ * IPv6 and IPv4 clients.
*/
snprintf(port_str, sizeof(port_str), "%d", server_port);
if (!BIO_lookup_ex(NULL, port_str, BIO_LOOKUP_SERVER, AF_INET6,
diff --git a/demos/dtlslistenerecho/main.c b/demos/dtlslistenerecho/main.c
index bdaf445d2f..a208b7e20d 100644
--- a/demos/dtlslistenerecho/main.c
+++ b/demos/dtlslistenerecho/main.c
@@ -96,7 +96,7 @@ static SSL_CTX *create_context(bool isServer)
* invoked for each handshake flight to choose the next retransmit interval.
* timer_us holds the previous interval (0 on the first call). We start at 1s
* and double, but cap the backoff so a stalled handshake is abandoned in a
- * reasonable time rather than the library default of nearly 8 minutes.
+ * reasonable time.
*/
static unsigned int dtls_timer_cb(SSL *s, unsigned int timer_us)
{
@@ -255,8 +255,8 @@ static void handle_connection(struct connection_thread_args *conn_args)
}
/*
- * Wait for the socket to become ready rather than busy-looping. Size
- * the wait to the DTLS retransmit timer so we wake when a flight is
+ * Wait for the socket to become ready. Size the wait to the DTLS
+ * retransmit timer so the loop wakes when a flight is
* due for retransmission; fall back to a fixed interval if no timer is
* armed.
*/
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 7ca3725b5d..f0247525c5 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -579,11 +579,9 @@ int dtls1_handle_timeout(SSL_CONNECTION *s)
if (dtls1_check_timeout_num(s) < 0) {
/*
- * SSLfatal() already called, so the connection is finished. Stop the
- * timer rather than returning with next_timeout left in the past:
- * nothing will re-arm or clear it from here, so DTLSv1_get_timeout()
- * would report "due now" for ever and spin any caller which waits on
- * it.
+ * SSLfatal() already called, so the connection is finished. Nothing
+ * re-arms or clears the timer after this, and an expired timeout left
+ * in place makes DTLSv1_get_timeout() report it due for ever.
*/
dtls1_stop_timer(s);
return -1;
@@ -1441,10 +1439,9 @@ static void dtls_listener_packet_handler(DGRAM_URXE *urxe, void *arg)
/* Create new pending connection if needed */
if (conn_ssl == NULL) {
/*
- * Reject before allocating anything if we have reached the pending
- * connection limit. The LHASH item count is O(1), and this check does
- * not need a conn_ssl, so performing it first avoids creating and then
- * immediately freeing a connection when we are at capacity.
+ * Reject before allocating anything if the pending connection limit
+ * is reached. The LHASH item count is O(1) and the check does not
+ * need a conn_ssl.
*/
if (ossl_dgram_conn_lookup_num_items(dl->pending_conns) >= dl->max_pending_conns)
goto release;
@@ -2483,9 +2480,8 @@ SSL *ossl_dtls_accept_connection(SSL *ssl, uint64_t flags)
/*
* Wait only if the caller has not asked us not to and the listener is in
- * blocking mode. Note that the check for a network BIO below is deliberately
- * left ahead of this, so that asking to wait on a listener which has none
- * remains an error rather than silently returning nothing.
+ * blocking mode. A listener with no network BIO takes the blocking path,
+ * which reports the missing BIO as an error.
*/
if (!no_block && !ossl_dtls_blocking(ssl) && dl->net_rbio != NULL)
no_block = 1;
@@ -3122,11 +3118,7 @@ int ossl_dtls_set_blocking_mode(SSL *s, int blocking)
return 0;
}
- /*
- * Refuse to claim blocking we cannot deliver, as QUIC does. Checked before
- * anything is written, so that a call which fails leaves the mode alone
- * rather than reporting failure having already changed it.
- */
+ /* Blocking mode which cannot be delivered is refused, as in QUIC. */
if (blocking && !ossl_dtls_can_support_blocking(s)) {
ERR_raise(ERR_LIB_SSL, ERR_R_UNSUPPORTED);
return 0;
@@ -3220,27 +3212,16 @@ int ossl_dtls_conn_wait_for_datagram(SSL *s)
* connection which is in blocking mode.
*
* The socket is shared with every other connection and is always
- * non-blocking, so a send which cannot be completed has nowhere to wait. For
- * DTLS the record layer would otherwise discard the datagram - a reasonable
- * default for an unreliable transport, but not what an application which asked
- * for blocking writes expects.
+ * non-blocking, so a send which cannot be completed has nowhere else to wait.
*
* Only one wait is performed. The caller retries the send, and comes back here
- * if it still cannot proceed, so a wakeup which turns out not to leave room in
- * the socket buffer costs an extra attempt rather than a lost datagram.
- *
- * The retransmission timer deliberately does not shorten this wait, unlike the
- * one for a datagram above. There the wakeup is useful, because the wait can
- * service the timer itself; here it cannot. Servicing it would mean
- * retransmitting a flight from inside tls_retry_write_records(), which is
- * part-way through sending one and holds write buffer state that a
- * re-entrant do_dtls1_write() would clobber. Waking for a timer nothing then
- * services would be worse than not waking: the timeout stays expired, and an
- * expired timeout reads as a zero deadline, so every later wait would return
- * at once and the caller's retry loop would spin without sleeping. Waiting for
- * the socket alone is also what the send actually needs. Retransmission is not
- * the right response to a flight which has not finished going out, and once it
- * has, the state machine handles the timer as usual.
+ * if it still cannot proceed.
+ *
+ * The retransmission timer does not bound this wait. The timer cannot be
+ * serviced from here: the caller is inside tls_retry_write_records(), which
+ * holds write buffer state that do_dtls1_write() uses. A wait woken by a
+ * timer nothing services finds the timeout still expired, which reads as a
+ * zero deadline, and returns at once on every later call.
*
* Returns 1 if the send should be retried, or 0 if the wait could not be
* performed or the listener has failed.
diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c
index 5da8af882a..a249d6db12 100644
--- a/ssl/quic/quic_ackm.c
+++ b/ssl/quic/quic_ackm.c
@@ -1144,11 +1144,9 @@ int ossl_ackm_on_tx_ack_only_packet(OSSL_ACKM *ackm, OSSL_ACKM_TX_PKT *pkt)
return 0;
/*
- * A packet containing only an ACK frame must not be treated as
- * in-flight or ack-eliciting; if it were, ossl_ackm_on_tx_packet()
- * below would (correctly) perform bytes-in-flight/timer/CC bookkeeping
- * for a packet we are about to discard from history, which would be
- * incorrect.
+ * A packet containing only an ACK frame is not kept in history, so it
+ * must not be in-flight or ack-eliciting: ossl_ackm_on_tx_packet() below
+ * performs bytes-in-flight, timer and CC bookkeeping for such packets.
*/
if (pkt->is_inflight || pkt->is_ack_eliciting)
return 0;
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index dc62238211..8f363c093a 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -598,8 +598,7 @@ int ossl_quic_channel_set0_tls(QUIC_CHANNEL *ch, SSL *ssl)
{
/*
* Rebind the handshake layer first, so that a failure leaves the channel
- * entirely unmodified rather than with a TLS connection the handshake
- * layer does not know about.
+ * unmodified.
*/
if (!ossl_assert(ch != NULL && ssl != NULL && ch->tls == NULL)
|| !ossl_quic_tls_set0_ssl(ch->qtls, ssl))
diff --git a/ssl/record/methods/dtls_meth.c b/ssl/record/methods/dtls_meth.c
index f4dce6427e..68a5349894 100644
--- a/ssl/record/methods/dtls_meth.c
+++ b/ssl/record/methods/dtls_meth.c
@@ -325,9 +325,9 @@ static int dtls_rlayer_buffer_record(OSSL_RECORD_LAYER *rl, struct pqueue_st *qu
}
/*
- * Take a copy of just this record's on-wire bytes (header + ciphertext)
- * rather than the whole (much larger) read buffer. The live rl->rbuf is
- * left untouched and continues to be used for subsequent reads.
+ * Take a copy of just this record's on-wire bytes (header + ciphertext).
+ * rl->rbuf is left untouched and continues to be used for subsequent
+ * reads.
*/
rdata->packet_length = rl->packet_length;
rdata->packet = OPENSSL_memdup(rl->packet, rl->packet_length);
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index ef7b469b65..e3c7d7e7de 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1178,11 +1178,9 @@ static int rlayer_dtls_get_urxe_packet(void *cbarg, unsigned char **data,
/*
* Still nothing. In blocking mode this is where the caller waits: the
- * connection has no BIO of its own to block in, so returning here would
- * report SSL_ERROR_WANT_READ instead of blocking. Waiting inside this
- * callback keeps that out of the record layer and the state machine, which
- * see only a read which took a while, exactly as a blocking BIO would give
- * them.
+ * connection has no BIO of its own to block in. The record layer and the
+ * state machine see only a read which took a while, as with a blocking
+ * BIO.
*/
if (urxe == NULL && s->d1->listener != NULL
&& ossl_dtls_blocking(SSL_CONNECTION_GET_SSL(s))
@@ -1630,9 +1628,8 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
* For DTLS listener-created connections the peer address must be applied
* to every record layer as it is created (including the encrypted layers
* built during the handshake). SSL_set1_initial_peer_addr() only updates
- * the record layers that exist when it is called, so writes on a later
- * layer would otherwise fall back to BIO_write() on the shared listener
- * BIO instead of BIO_sendmmsg() to the peer.
+ * the record layers that exist when it is called. A layer without a peer
+ * address writes with BIO_write() on the shared listener BIO.
*/
#ifndef OPENSSL_NO_SOCK
if (SSL_CONNECTION_IS_DTLS(s)
diff --git a/ssl/rio/poll_builder.c b/ssl/rio/poll_builder.c
index 509c79918f..32d67744bb 100644
--- a/ssl/rio/poll_builder.c
+++ b/ssl/rio/poll_builder.c
@@ -156,12 +156,12 @@ int ossl_rio_poll_builder_poll(RIO_POLL_BUILDER *rpb, OSSL_TIME deadline)
/*
* Waiting with no file descriptors is legitimate: a DTLS connection whose
* BIO cannot provide a poll descriptor has no readiness to wait for, but
- * still has a retransmission deadline to wake for. Handle that here rather
- * than leaving it to the OS, because poll() treats an empty descriptor set
- * as a plain sleep whereas Windows' select() rejects it outright.
+ * still has a retransmission deadline to wake for. poll() treats an empty
+ * descriptor set as a plain sleep and Windows' select() rejects it, so
+ * the sleep is done here.
*
- * With no descriptors and no deadline nothing could ever wake us, so that
- * is a caller error rather than an indefinite sleep.
+ * With no descriptors and no deadline nothing can wake the wait; that is
+ * a caller error.
*/
if (rio_poll_builder_is_empty(rpb)) {
if (ossl_time_is_infinite(deadline))
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 6f1ba3cfe2..8dd8b63653 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -3374,17 +3374,11 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL_CONNECTION *s,
s->session->not_resumable = 0;
/*
- * Refresh the session's recollection of the negotiated ALPN protocol to
- * match this connection, rather than leaving it as whatever the session
- * (or the session it was duplicated from, on a resumption) previously
- * carried. Without this, a connection that resumes a session but
- * negotiates no ALPN (or a different one) leaves the stale protocol
- * name in place, and a later 0-RTT attempt against this ticket can
- * incorrectly trip the "inconsistent early data alpn" check -- or, if
- * the client happens to offer that same stale protocol again by
- * coincidence, incorrectly appear consistent. This mirrors, on the
- * client, the server-side fix for issue #11197 in
- * tls_construct_new_session_ticket().
+ * The session's ALPN protocol must match what this connection
+ * negotiated, including none. A resumed session carries the protocol
+ * from the handshake that created it, and a later 0-RTT attempt checks
+ * that ALPN is consistent with the session (GitHub issue #11197). The
+ * server side is in tls_construct_new_session_ticket().
*/
OPENSSL_free(s->session->ext.alpn_selected);
if (s->s3.alpn_selected != NULL) {
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 75dc8d5f50..ffb935873a 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -4857,12 +4857,11 @@ CON_FUNC_RETURN tls_construct_new_session_ticket(SSL_CONNECTION *s, WPACKET *pkt
s->session->ext.alpn_selected_len = s->s3.alpn_selected_len;
} else {
/*
- * No ALPN was negotiated on this handshake. If we resumed a
- * session that had previously negotiated ALPN, the stale value
- * must be cleared from the (copied) session before it is stored
- * in the new ticket. Otherwise a subsequent 0-RTT attempt using
- * that ticket would incorrectly assume an ALPN protocol had been
- * negotiated. See tls_handle_alpn().
+ * No ALPN was negotiated on this handshake. A resumed session
+ * carries the protocol from the handshake that created it, and
+ * a 0-RTT attempt using the new ticket checks that ALPN is
+ * consistent with the session, so clear it. See
+ * tls_handle_alpn().
*/
OPENSSL_free(s->session->ext.alpn_selected);
s->session->ext.alpn_selected = NULL;
diff --git a/test/cmp_extracerts_dos_test.c b/test/cmp_extracerts_dos_test.c
index edb2dc8c4a..50c9364abd 100644
--- a/test/cmp_extracerts_dos_test.c
+++ b/test/cmp_extracerts_dos_test.c
@@ -8,40 +8,13 @@
*/
/*
- * Regression test for: CMP server unauthenticated memory/CPU DoS via
- * cached extraCerts on failed protection checks.
+ * The extraCerts of a CMP message which fails its protection check must not
+ * remain in ctx->untrusted.
*
- * Root cause (crypto/cmp/cmp_vfy.c, ossl_cmp_msg_check_update(), current
- * master as of this writing):
- *
- * res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts, ...);
- * ...
- * res = OSSL_CMP_validate_msg(ctx, msg) || (cb...); // may be 0 (rejected)
- *
- * if (ctx->noCacheExtraCerts) // <-- rollback is
- * while (num_added-- > 0) // gated on this
- * X509_free(sk_X509_shift(ctx->untrusted)); // flag only, NOT
- * // on the
- * // validation
- * // result (res)
- *
- * if (!res) { ...; return 0; } // certs from a REJECTED msg are kept
- *
- * This test exercises ossl_cmp_msg_check_update() directly -- no sockets,
- * no HTTP server, no apps/cmp.c -- and asserts on the resulting size of
- * ctx->untrusted. It builds a genuinely PBM-protected OSSL_CMP_MSG using
- * the project's own internal message-creation function
- * (ossl_cmp_genm_new(), same one exercised in test/cmp_msg_test.c) so the
- * message is not hand-crafted to "look" rejectable -- it is rejected for a
- * real reason (the receiving ctx has no matching secret configured), the
- * same way OSSL_CMP_validate_msg() would reject any unauthenticated CMP
- * request in the field.
- *
- * Expected results:
- * - BEFORE the fix: untrusted_count_after == untrusted_count_before + N
- * (every rejected message's extraCerts persist)
- * - AFTER the fix: untrusted_count_after == untrusted_count_before
- * (rejected messages leave no residue)
+ * This test calls ossl_cmp_msg_check_update() directly and asserts on the
+ * resulting size of ctx->untrusted. The message is a PBM-protected
+ * OSSL_CMP_MSG built with ossl_cmp_genm_new(), rejected because the receiving
+ * ctx has no matching secret configured.
*/
#include "helpers/cmp_testlib.h"
@@ -75,20 +48,9 @@ static CMP_DOS_TEST_FIXTURE *set_up(const char *const test_case_name)
return NULL;
}
/*
- * Deliberately do NOT call OSSL_CMP_CTX_set1_secretValue() on the
- * server ctx. Per OSSL_CMP_validate_msg() (crypto/cmp/cmp_vfy.c):
- * case NID_id_PasswordBasedMAC:
- * if (ctx->secretValue == NULL) {
- * ossl_cmp_info(ctx, "no secret available for verifying..");
- * ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
- * return 0;
- * }
- * so every PBM-protected message this ctx receives is unconditionally
- * rejected -- a deterministic, content-independent rejection path that
- * models "missing or invalid protection" from the report's repro
- * steps, without needing to forge a bad MAC by hand.
- * ctx->noCacheExtraCerts is left at its default (0), exactly as in the
- * vulnerable deployment ("not setting -no_cache_extracerts").
+ * No secret is set on the server ctx, so OSSL_CMP_validate_msg() rejects
+ * every PBM-protected message it receives. noCacheExtraCerts is left at
+ * its default of 0.
*/
return fixture;
}
@@ -241,13 +203,7 @@ err:
return NULL;
}
-/*
- * Core assertion: N distinct rejected requests must not grow
- * server_ctx->untrusted at all.
- *
- * Before the fix this fails with e.g.:
- * ERROR: untrusted count after (25) != count before (0)
- */
+/* N distinct rejected requests must not grow server_ctx->untrusted. */
static int execute_no_unbounded_growth_test(CMP_DOS_TEST_FIXTURE *fixture)
{
OSSL_CMP_CTX *server_ctx = fixture->server_ctx;
@@ -293,9 +249,8 @@ static int execute_no_unbounded_growth_test(CMP_DOS_TEST_FIXTURE *fixture)
}
/*
- * Single-request variant of the same check, useful in isolation since it
- * pins down that even ONE rejected request leaves no residue -- ruling out
- * X509_ADD_FLAG_NO_DUP coincidentally masking the bug in the N-request test.
+ * Single-request variant of the same check. One rejected request cannot be
+ * masked by X509_ADD_FLAG_NO_DUP.
*/
static int execute_single_rejected_request_test(CMP_DOS_TEST_FIXTURE *fixture)
{
diff --git a/test/cmp_protect_test.c b/test/cmp_protect_test.c
index 80ce1fb758..513ee05ff7 100644
--- a/test/cmp_protect_test.c
+++ b/test/cmp_protect_test.c
@@ -187,13 +187,11 @@ static int test_cmp_calc_protection_pbmac(void)
}
/*
- * Regression test for the ossl_cmp_calc_protection() protectionAlg
- * type-confusion DoS: a PKIMessage whose protectionAlg has the
- * id-PasswordBasedMAC OID but carries a BOOLEAN parameter instead of the
- * expected PBMParameter SEQUENCE. X509_ALGOR_get0() then returns the boolean's
- * union member (0xff) via ppval; the unpatched code took the non-NULL ppval as
- * a valid ASN1_STRING * and dereferenced 0xff, crashing with a near-NULL
- * access. The fixed code must reject the malformed parameter and return NULL.
+ * ossl_cmp_calc_protection() must reject a PKIMessage whose protectionAlg has
+ * the id-PasswordBasedMAC OID but carries a BOOLEAN parameter in place of the
+ * PBMParameter SEQUENCE. For such a parameter X509_ALGOR_get0() returns the
+ * boolean's union member (0xff) via ppval, which is not an ASN1_STRING *
+ * (CVE-2026-63076).
*/
static int test_cmp_calc_protection_pbmac_bad_alg_param(void)
{
diff --git a/test/cmsapitest.c b/test/cmsapitest.c
index f30a0be8c6..35ffa79ca0 100644
--- a/test/cmsapitest.c
+++ b/test/cmsapitest.c
@@ -1372,18 +1372,16 @@ end:
#if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_X963KDF)
/*
- * Regression test for CVE-2026-63072: an 8-byte out-of-bounds heap write
- * reachable through CMS_decrypt() when a KeyAgreeRecipientInfo names an
- * id-aesNNN-wrap-pad key-wrap OID. CMS sizes the unwrap output buffer from
- * the cipher's length query (inlen - 8), but AES-WRAP-PAD unwrap cleanses
- * inlen bytes of it on every RFC 5649 integrity-failure path.
+ * CVE-2026-63072: CMS_decrypt() with a KeyAgreeRecipientInfo naming an
+ * id-aesNNN-wrap-pad key-wrap OID. AES-WRAP-PAD unwrap cleanses inlen bytes of
+ * the output buffer on every RFC 5649 integrity-failure path, and CMS sizes
+ * that buffer from the cipher's length query.
*
- * We build a valid ECDH KARI message (which uses non-padded id-aes256-wrap),
- * flip the single OID byte an attacker would flip on the wire to turn it into
- * id-aes256-wrap-pad (key length unchanged), and decrypt with the matching
- * private key. The unwrap must fail its integrity check without writing past
- * the CMS-allocated buffer; CMS_decrypt() must fail cleanly. Under a
- * memory-checking build (e.g. valgrind) the overflow is flagged directly.
+ * Build a valid ECDH KARI message (non-padded id-aes256-wrap), flip the single
+ * OID byte that turns it into id-aes256-wrap-pad (key length unchanged), and
+ * decrypt with the matching private key. The unwrap must fail its integrity
+ * check without writing past the CMS-allocated buffer and CMS_decrypt() must
+ * fail cleanly. Under a memory-checking build the overflow is flagged directly.
*/
static int test_kari_wrap_pad_unwrap_overflow(void)
{
@@ -1438,8 +1436,8 @@ static int test_kari_wrap_pad_unwrap_overflow(void)
goto end;
/*
- * The wrap-pad unwrap fails the AIV check; with the fix it does so without
- * writing past the CMS-allocated buffer. CMS_decrypt() must fail cleanly.
+ * The wrap-pad unwrap fails the AIV check without writing past the
+ * CMS-allocated buffer, and CMS_decrypt() must fail cleanly.
*/
if (!TEST_ptr(outbio = BIO_new(BIO_s_mem()))
|| !TEST_false(CMS_decrypt(cms2, eckey, eccert, NULL, outbio, 0)))
diff --git a/test/dtls_multithread_test.c b/test/dtls_multithread_test.c
index a478590fb8..066f68a853 100644
--- a/test/dtls_multithread_test.c
+++ b/test/dtls_multithread_test.c
@@ -731,11 +731,9 @@ static unsigned int blocking_accept_thread(void *arg)
* readiness rather than for a datagram, which is what this exercises - a
* client is only created once the accepting thread is already in the call.
*
- * Note that this cannot distinguish waiting from spinning: the accept returns
- * the connection either way, and the difference is CPU consumed rather than
- * anything observable through the API. It is a test that the blocking path
- * works at all, which was previously only covered for the failure case of
- * having no BIO set.
+ * This cannot distinguish waiting from spinning: the accept returns the
+ * connection either way, and the difference is not observable through the
+ * API.
*/
static int test_dtls_blocking_accept(void)
{
@@ -756,10 +754,7 @@ static int test_dtls_blocking_accept(void)
if (!TEST_true(create_listener(sctx, &listener, &server_addr, &server_fd)))
goto err;
- /*
- * This test needs the blocking accept, so ask for it rather than relying
- * on the default.
- */
+ /* This test needs the blocking accept. */
if (!TEST_true(SSL_set_blocking_mode(listener, 1)))
goto err;
@@ -923,10 +918,8 @@ static unsigned int blocking_read_thread(void *arg)
* assertion rather than as a hang.
*
* idx 0 blocks in the handshake as well as in the read. idx 1 handshakes in
- * non-blocking mode and only then switches the connection to blocking, which
- * leaves the read as the sole assertion the emulation has to satisfy - without
- * it, idx 0 fails at SSL_accept() and never reaches the read, so on its own it
- * would not tell us the read path works.
+ * non-blocking mode and only then switches the connection to blocking, so
+ * the read is the only thing relying on the emulation.
*
* Only the client is driven from this thread: the accepting thread ticks the
* listener itself, which is what lets a blocked connection make progress at
diff --git a/test/dtlsssllistenertest.c b/test/dtlsssllistenertest.c
index 16565ec318..8740ce8bf8 100644
--- a/test/dtlsssllistenertest.c
+++ b/test/dtlsssllistenertest.c
@@ -3808,15 +3808,9 @@ end:
/*
* Test DTLS 1.3 SSL Listener handshake message buffering.
*
- * This test verifies that when a DTLS 1.3 SSL Listener sends handshake
- * messages, multiple records are buffered into a single datagram
- * rather than being sent as separate datagrams.
- *
- * Expected behavior with buffering:
- * - At least one datagram contains multiple DTLS records
- *
- * Without buffering (the bug this tests for):
- * - Each record would be in its own datagram
+ * When a DTLS 1.3 SSL Listener sends handshake messages, multiple records
+ * are buffered into a single datagram: at least one datagram must contain
+ * multiple DTLS records.
*/
static int test_dtls13_listener_msg_buffering(void)
{
@@ -4133,12 +4127,11 @@ static int big_ch_ext_add_cb(SSL *s, unsigned int ext_type,
}
/*
- * Helper to create a DTLS client on a *connected* UDP socket. Unlike the
- * BIO_dgram_set_peer() helpers above (which use an unconnected socket and so
- * cause DTLS to fragment the ClientHello into sub-MTU datagrams), a connected
- * socket lets DTLS discover the large loopback path MTU and send the whole
- * ClientHello in a single datagram - which is what exercises the listener demux
- * receive-buffer sizing.
+ * Helper to create a DTLS client on a connected UDP socket. A connected socket
+ * lets DTLS discover the large loopback path MTU and send the whole
+ * ClientHello in a single datagram, which exercises the listener demux
+ * receive-buffer sizing; on an unconnected socket DTLS fragments it into
+ * sub-MTU datagrams.
*/
static int create_dtls_client_connected(SSL_CTX *cctx,
const BIO_ADDR *server_addr, SSL **clientssl, int *client_fd)
@@ -4952,48 +4945,19 @@ static int test_new_pending_cb_alternate(void)
* A thread waiting in SSL_poll() for SSL_POLL_EVENT_IC is blocked on the
* listener's network socket and on its notifier. Where another thread does the
* demuxing, that socket does not necessarily become readable on the waiter's
- * behalf, so the notifier is what has to wake it.
- *
- * Most of the time the bug this covers is masked. Every connection reaching
- * the accept queue got there because a datagram was demuxed into its receive
- * queue, and the packet handler has always signalled on that injection, so the
- * waiter is woken, ticks the listener itself during its readout, and finds the
- * connection. What is not covered by that is the window in which the injection
- * and the queue push straddle a waiter registering, because signalling is
- * conditional on there being a waiter at the time.
- *
- * The numbered steps below are that window - the interleaving of two threads
- * which the fix exists to handle. They are not what this test does, and are
- * given only so that what it does assert makes sense; see the end of this
- * comment for how it is actually checked.
+ * behalf, so the notifier is what wakes it. Signalling is conditional on a
+ * registered waiter, and the demux of a ClientHello and the push of the
+ * completed connection onto the accept queue are separate steps of a tick, so
+ * a waiter which registers between them is woken only by the push.
*
- * 1. Accept thread A polls the listener for SSL_POLL_EVENT_IC. Its readout
- * ticks the listener, finds nothing, and it decides to block. It is not
- * a registered waiter yet.
- * 2. Worker thread B polls one of its own connections, which also ticks the
- * listener. The pump reads a client's final ClientHello and injects it
- * into that pending connection's queue. There are no waiters, so nothing
- * is signalled.
- * 3. A enters the blocking section. Its re-check runs without ticking, so it
- * sees only the accept queue, which is still empty, and it blocks.
- * 4. B's tick reaches dtls_listener_drive_pending(), which completes the
- * connection against the buffered ClientHello and pushes it onto the
- * accept queue.
+ * The interleaving cannot be forced from outside the library, so this drives
+ * its essential part on one thread: pumping the demux directly performs the
+ * injection, the signal it raises is cleared, and the tick which follows can
+ * only signal by way of the queue push.
*
- * Without a signal at step 4, A sleeps on with a validated connection sitting
- * ready, until some unrelated datagram makes the socket readable again. B
- * consumed the only one in flight, and the client is now waiting on the
- * server, so on a quiet listener that is until the client retransmits.
- *
- * That interleaving cannot be forced from outside the library, so rather than
- * reproducing the steps above, this drives their essential part by hand and on
- * one thread: pumping the demux directly performs step 2, the signal it raises
- * is then cleared, and the tick which follows can only signal by way of step 4.
- * Asserting that it did is therefore asserting that a queue push signals.
- *
- * signalled_notifier is protected by the listener mutex in the library, which
- * has to assume concurrent access. This test is single threaded throughout, so
- * it reads the field directly without holding the mutex.
+ * signalled_notifier is protected by the listener mutex in the library. This
+ * test is single threaded throughout, so it reads the field directly without
+ * holding the mutex.
*/
static int test_dtls_notifier_signalled_on_accept_queue_push(void)
{
@@ -5118,60 +5082,26 @@ end:
/*
* Test that a blocking SSL_poll() on a listener enters a blocking section.
*
- * Unless it does, three things follow: the notifier is not in the poll set, so
- * it cannot wake this thread; cur_blocking_waiters is never incremented, and
- * since signalling is conditional on there being a waiter, no other thread
- * even attempts to signal; and there is no re-check after registering, so
- * readiness arising between the readout and the wait is lost.
- *
- * Polling the socket alone is not enough, though not because a wakeup can be
- * missed outright. poll() reports whatever is currently sitting in the socket
- * buffer and returns immediately if there is any, so a thread cannot miss a
- * datagram just by being outside poll() when it arrives. What it can miss is a
- * datagram another thread has already taken. With several threads polling the
- * one shared socket that happens constantly: an arriving datagram wakes all of
- * them, only one gets it, and the rest find nothing. Any of them can be the
- * one that takes it, because SSL_read() on a connection pumps the demux and
- * SSL_poll() on a connection ticks the whole listener.
+ * The blocking section puts the notifier in the poll set, registers this
+ * thread as a waiter so other threads signal it, and re-checks readiness after
+ * registering. Several threads poll the one shared socket; a datagram wakes all
+ * of them and one takes it, and that thread's tick can complete a pending
+ * connection and push it onto the accept queue. A thread watching the socket
+ * alone then sleeps with a connection on the queue.
*
- * 1. Accept thread A polls the listener for SSL_POLL_EVENT_IC. Its readout
- * ticks the listener, finds nothing, and it decides to block.
- * 2. A client's final ClientHello lands on the shared socket.
- * 3. Worker thread B, polling one of its own connections, ticks the listener
- * and is the one that takes the datagram. Its tick completes the pending
- * connection and pushes it onto the accept queue. Signalling is attempted,
- * but A never registered as a waiter, so nothing is signalled.
- * 4. A reaches its poll, watching the socket alone. B drained it, so it is
- * empty, and A sleeps with a validated connection sitting on the accept
- * queue.
+ * Entering a blocking section has no public observable. The last waiter out of
+ * a blocking section drains a raised notifier signal, so this raises one
+ * beforehand, polls briefly with nothing ready, and checks afterwards: drained
+ * means a blocking section was entered and left.
*
- * A's readout, back at step 1, would have found that connection had it run
- * after step 3 rather than before it. Registering as a waiter and re-checking
- * is what removes the dependency on that ordering.
+ * signalled_notifier is protected by the listener mutex in the library. This
+ * test is single threaded throughout, so it reads and writes the field
+ * directly without holding the mutex.
*
- * Note that the signal added for the step 3 queue push is itself conditional on
- * a registered waiter, so it does nothing for a thread polling the listener
- * until that thread registers. The two fixes are complementary.
- *
- * None of that has a public observable, and this deliberately does not time
- * the wait. Instead it relies on the last waiter out of a blocking section
- * draining a raised notifier signal: raise one beforehand, poll briefly with
- * nothing ready, and check afterwards. Drained means a blocking section was
- * entered and left, since only a leave drains it and only an enter can be left;
- * still standing means neither happened.
- *
- * signalled_notifier is protected by the listener mutex in the library, which
- * has to assume concurrent access. This test is single threaded throughout, so
- * it reads and writes the field directly without holding the mutex.
- *
- * Note what this does not cover. That the notifier is in the poll set, and so
- * can actually deliver a wakeup, is not checked: with a signal raised the poll
- * returns at once if the notifier is being watched and sleeps out its timeout
- * if it is not, and only timing separates those. A longer timeout would not
- * help, because the first iteration's leave drains the notifier and the next
- * one sleeps out the remainder either way. The re-check after registering is
- * not covered either, since readiness arriving between the readout and the
- * registration cannot be produced from a single thread.
+ * Not covered: that the notifier in the poll set delivers a wakeup (only
+ * timing separates that from sleeping out the timeout), and the re-check
+ * after registering (readiness arriving between the readout and the
+ * registration cannot be produced from a single thread).
*/
static int test_dtls_poll_listener_enters_blocking_section(void)
{
@@ -5376,8 +5306,7 @@ static int test_dtls_poll_conn_honours_retransmit_timer(void)
/*
* Install the short timeout before the server sends anything, so that it
- * is picked up when the retransmission timer is first started rather than
- * only on a later expiry.
+ * is picked up when the retransmission timer is first started.
*/
DTLS_set_timer_cb(serverssl, short_timer_cb);
@@ -5731,11 +5660,8 @@ end:
* Test that a rejected SSL_set_blocking_mode() leaves the mode alone.
*
* Whether blocking can be supported depends on the listener's BIO, so a
- * request can be refused now and be perfectly deliverable later. The refusal
- * must therefore not record the mode it refused to set: the effect only becomes
- * visible once a BIO which can supply a poll descriptor is in place, at which
- * point the listener would be found blocking on the strength of a call which
- * failed.
+ * request refused before a BIO which can supply a poll descriptor is in place
+ * must not be recorded, or the listener is found blocking once one is.
*/
static int test_dtls_blocking_mode_failed_set_is_inert(void)
{
@@ -5864,18 +5790,12 @@ static const BIO_METHOD *bio_f_failing_send_filter(void)
/*
* Test that a write on a blocking listener connection waits for the socket and
- * sends again, rather than reporting that it needs to be retried.
- *
- * A datagram which cannot be sent is normally dropped, which is reasonable for
- * an unreliable transport but is not what an application asking for blocking
- * writes expects: it gets no data sent and a WANT_WRITE it did not ask to have
- * to handle. The listener's socket is shared and always non-blocking, so there
- * is nothing for such a write to block in by itself.
+ * sends again. The listener's socket is shared and always non-blocking, so
+ * there is nothing for such a write to block in by itself.
*
* A loopback socket's send buffer does not fill, so a filter BIO supplies the
- * transient failure instead. Only one send is rejected: the retry then goes
- * through, and the client is read to confirm the datagram was really sent
- * rather than merely reported as sent.
+ * transient failure. Only one send is rejected: the retry then goes through,
+ * and the client is read to confirm the datagram was sent.
*
* The handshake runs with the listener non-blocking, so this test drives both
* ends from the one thread as the others here do, and only the connection is
@@ -5953,12 +5873,7 @@ static int test_dtls_blocking_write(void)
|| !TEST_size_t_eq(written, 3))
goto end;
- /*
- * The send really was rejected, and was retried rather than reported: the
- * count proves a second attempt was made, which is the whole behaviour
- * under test. Without it, a write which never reached the filter at all
- * would look the same as one which was retried.
- */
+ /* The count shows the send was rejected once and then retried. */
if (!TEST_int_eq(data.fails_remaining, 0)
|| !TEST_int_ge(data.sends, 2))
goto end;
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 385272faf5..e321619b46 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -4295,9 +4295,8 @@ static int test_RSA_verify_recover_empty_payload(void)
goto done;
/*
- * The actual recovery call is essential: a NULL output buffer would only
- * run the size-query path, which never decodes the signature and so would
- * not reproduce the regression.
+ * A NULL output buffer runs only the size-query path, which never decodes
+ * the signature.
*/
recovered_len = (size_t)recovered_cap;
if (!TEST_int_gt(EVP_PKEY_verify_recover(verify_ctx, recovered,
diff --git a/test/quic_tserver_test.c b/test/quic_tserver_test.c
index ac3d879e46..06c2174d81 100644
--- a/test/quic_tserver_test.c
+++ b/test/quic_tserver_test.c
@@ -366,7 +366,7 @@ static int do_test(int use_thread_assist, int use_fake_time, int use_inject)
/*
* The assist thread alone keeps the idle connection alive. It
* waits on real time internally, so advancing fake time can
- * outrun it. Rather than race it, wait until it has caught up:
+ * outrun it. Wait until it has caught up:
* the event timeout is computed against fake time, so once the
* next deadline is back in the future all events due up to now
* - including any keepalive - have been serviced.
diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c
index 529a254394..3f65cd4c17 100644
--- a/test/radix/quic_tests.c
+++ b/test/radix/quic_tests.c
@@ -484,16 +484,11 @@ DEF_FUNC(check_poll_abort_blocking)
/*
* C0 and Cb0 are streams of two independent client connections, and so
- * belong to two independent QUIC_REACTORs. The bug being tested for does
- * not actually require this: it reproduces just as well if all items
- * share one reactor. What needs two reactors is poll_abort_test_step_cb()
- * below, which forces Cb0 ready by ticking its reactor directly, on this
- * thread, while C0's blocking section is still open. Doing that on C0's
- * own (shared) reactor would deadlock: ossl_quic_reactor_tick() would see
- * a nonzero cur_blocking_waiters left over from C0 and call
- * rtor_notify_other_threads(), which waits on a condvar for some *other*
- * thread to clear the notifier signal - a thread that doesn't exist here.
- * Using Cb0's own, still-untouched reactor keeps that tick a no-op.
+ * belong to two independent QUIC_REACTORs. poll_abort_test_step_cb() below
+ * forces Cb0 ready by ticking its reactor directly, on this thread, while
+ * C0's blocking section is still open. Ticking a reactor with a nonzero
+ * cur_blocking_waiters calls rtor_notify_other_threads(), which waits for
+ * another thread to clear the notifier signal.
*/
REQUIRE_SSL_4(C, C0, Cb0, Lb0);
@@ -816,7 +811,7 @@ DEF_FUNC(check_flood_stats)
/*
* The flood is delivered over a real socket and processed by the
* connection's assist thread asynchronously, so give it a chance to
- * catch up rather than failing on the first observation.
+ * catch up.
*/
if (path_challenge_count < 16 || path_response_count < 1)
F_SPIN_AGAIN();
diff --git a/test/rand_test.c b/test/rand_test.c
index 3843afe446..e11dc12f92 100644
--- a/test/rand_test.c
+++ b/test/rand_test.c
@@ -398,10 +398,9 @@ static int provider_side_drbg_instantiate(EVP_RAND_CTX *rctx)
}
/*
- * Regression test for #25941: with strict seeding the configured seed
- * source must be instantiated on demand and used when a provider
- * requests seeding material before anything else created it, instead of
- * being silently replaced by the operating system entropy sources.
+ * With strict seeding the configured seed source must be instantiated on
+ * demand and used when a provider requests seeding material before
+ * anything else created it (#25941).
*/
static int test_rand_seed_source_strict(void)
{
diff --git a/test/recipes/20-test_app_s_client_msg.t b/test/recipes/20-test_app_s_client_msg.t
index 75d388efe8..7feebc0959 100644
--- a/test/recipes/20-test_app_s_client_msg.t
+++ b/test/recipes/20-test_app_s_client_msg.t
@@ -28,8 +28,8 @@ my $server_key = srctop_file("test", "certs", "serverkey.pem");
my $resultdir = result_dir();
# Each case exercises the s_client message callback (-msg) over a different
-# protocol version. Every record must be decoded; before the DTLSv1.2 fix such
-# records were logged as "Not TLS data or unknown version".
+# protocol version. Every record must be decoded; none may be logged as
+# "Not TLS data or unknown version".
my @cases = (
{ name => "TLSv1.2", flag => "-tls1_2", disabled => "tls1_2" },
{ name => "TLSv1.3", flag => "-tls1_3", disabled => "tls1_3" },
diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t
index 634ddbb6e3..41cfcee278 100644
--- a/test/recipes/80-test_cms.t
+++ b/test/recipes/80-test_cms.t
@@ -1075,9 +1075,7 @@ subtest "CMS parse authenticatedData authAttrs and unauthAttrs\n" => sub {
# BouncyCastle authenticatedData (HMAC-SHA256, KEK) carrying both an
# authenticated and an unauthenticated attribute. Per RFC 5652 these are
- # SET OF Attribute, so with the CMS_AuthenticatedData template fixed to use
- # X509_ATTRIBUTE they are rendered as attributes (object:/set:) rather than
- # as an X509_ALGOR (algorithm:/parameter:) they were misparsed into before.
+ # SET OF Attribute, and are rendered as attributes (object:/set:).
my $exit = 0;
my $dump = join "\n",
run(app(["openssl", "cms", @defaultprov, "-cmsout", "-noout",
diff --git a/test/statem_clnt_construct_test.c b/test/statem_clnt_construct_test.c
index 5452676ba0..31bc29c3c6 100644
--- a/test/statem_clnt_construct_test.c
+++ b/test/statem_clnt_construct_test.c
@@ -947,7 +947,7 @@ err:
#ifndef OSSL_NO_USABLE_TLS1_3
/*
* With middlebox compat on, the TLS 1.3 path changes the write keys; without a
- * negotiated cipher that fails rather than succeeding.
+ * negotiated cipher that fails.
*/
static int test_construct_cert_change_cipher_fail(void)
{
diff --git a/test/tls13tickettest.c b/test/tls13tickettest.c
index 300c6b2dbc..4fad87d93c 100644
--- a/test/tls13tickettest.c
+++ b/test/tls13tickettest.c
@@ -999,37 +999,25 @@ static int test_tls13_ticket_early_data_accepted(void)
*
* A session that negotiated ALPN is resumed on a connection that negotiates no
* ALPN at all (the client advertises none). The NewSessionTicket issued for the
- * resumed session must not retain the ALPN protocol from the original session;
- * otherwise a later 0-RTT attempt using that ticket would incorrectly assume
- * that protocol had been negotiated.
+ * resumed session must not carry the ALPN protocol from the original session
+ * (GitHub issue #11197).
*
- * Regression test for GitHub issue #11197: tls_construct_new_session_ticket()
- * copied s->s3.alpn_selected into the session only when an ALPN protocol was
- * negotiated, but failed to clear s->session->ext.alpn_selected when it wasn't.
+ * A third connection resumes the ALPN-cleared ticket and negotiates
+ * "goodalpn", the original session's protocol. The ticket carries no ALPN, so
+ * 0-RTT must be rejected: the client's SSL_write_early_data() succeeds (the
+ * data is sent before the server's response is known) and
+ * SSL_get_early_data_status() reports that the server did not accept it.
*
- * A third connection then resumes the now-ALPN-cleared ticket and negotiates
- * "goodalpn" again -- the same, non-empty protocol as the original session,
- * coincidentally. Since the ticket being resumed carries no ALPN, 0-RTT must
- * still be rejected: the client's SSL_write_early_data() appears to succeed
- * (the data is sent before the server's response is known), but a post hoc
- * SSL_get_early_data_status() check confirms the server never accepted it.
+ * A fourth connection resumes the same ticket again (anti-replay is disabled
+ * for this test) advertising no ALPN, consistent with the ticket, and 0-RTT
+ * must be accepted. This shows the rejection in connection 3 is specific to
+ * the ALPN mismatch.
*
- * A fourth connection resumes that same ALPN-cleared ticket a second time --
- * anti-replay is disabled for this test, so reusing it twice is not itself a
- * reason for rejection -- but this time advertises no ALPN, consistent with
- * what the ticket actually recorded. 0-RTT must now be accepted. Without this
- * case, the rejection asserted for connection 3 would be unfalsifiable: it
- * would look identical if early data were simply never being accepted here
- * for any reason at all.
- *
- * The fourth connection resumes from an independent SSL_SESSION_dup() copy
- * of the ticket (taken before connection 3 uses the original), rather than
- * the original SSL_SESSION object itself: completing a handshake from a
- * resumed session marks that SSL_SESSION object not-resumable on the client
- * side as a single-use safeguard, independent of (and in addition to) the
- * server's SSL_OP_NO_ANTI_REPLAY setting. Resuming the literal object a
- * second time would therefore quietly fall back to a full, non-PSK
- * handshake instead of testing the intended 0-RTT path.
+ * The fourth connection resumes from an SSL_SESSION_dup() copy taken before
+ * connection 3 uses the original. Completing a handshake from a resumed
+ * session marks that SSL_SESSION object not-resumable on the client side,
+ * independent of the server's SSL_OP_NO_ANTI_REPLAY setting, and resuming it
+ * again falls back to a full handshake.
*/
static int test_tls13_ticket_alpn_cleared(void)
{
@@ -1079,7 +1067,7 @@ static int test_tls13_ticket_alpn_cleared(void)
* Connection 2: resume the session, but the client advertises no ALPN
* this time so nothing is negotiated. The server issues a fresh
* NewSessionTicket for the resumed session; its stored ALPN must be
- * cleared rather than inheriting "goodalpn" from the original session.
+ * empty.
*/
&& TEST_true(tls_channel_init(c, s, &resumed))
&& TEST_true(SSL_set_session(resumed.c.ssl, sess))
@@ -1107,14 +1095,8 @@ static int test_tls13_ticket_alpn_cleared(void)
&& TEST_true(tls_shutdown(&resumed))
&& TEST_ptr(sess2 = SSL_get1_session(resumed.c.ssl))
/*
- * Connection 3 is about to resume sess2 and, since 0-RTT is attempted
- * on it, the client will mark sess2 not-resumable once that attempt
- * completes (this happens on any full handshake completed from a
- * resumed session, independent of the server's anti-replay setting --
- * it is a client-side single-use restriction on the SSL_SESSION
- * object itself). Take an independent copy now, while sess2 is still
- * untouched, so connection 4 below has its own unconsumed ticket to
- * resume from.
+ * Connection 3 resumes sess2, after which the client marks sess2
+ * not-resumable. Connection 4 resumes from this copy.
*/
&& TEST_ptr(sess2b = SSL_SESSION_dup(sess2))
/*
@@ -1146,13 +1128,9 @@ static int test_tls13_ticket_alpn_cleared(void)
SSL_EARLY_DATA_REJECTED)
&& TEST_true(tls_shutdown(&resumed2))
/*
- * Connection 4: resume the same ticket from connection 2 again, via
- * the untouched copy (sess2b) taken before connection 3 consumed
- * sess2 -- anti-replay is off, so a second use of that ticket is not
- * itself rejected -- but this time advertise no ALPN, matching what
- * the ticket recorded. 0-RTT must be accepted, proving connection 3
- * was rejected for the ALPN mismatch specifically, not because early
- * data never works.
+ * Connection 4: resume the same ticket again via the copy (sess2b),
+ * anti-replay being off, advertising no ALPN, matching the ticket.
+ * 0-RTT must be accepted.
*/
&& TEST_true(tls_channel_init(c, s, &resumed3))
&& TEST_true(SSL_set_session(resumed3.c.ssl, sess2b))
diff --git a/test/unit/crypto/bio/test_bss_dgram_win.c b/test/unit/crypto/bio/test_bss_dgram_win.c
index 080d91c4e2..abdbef4efc 100644
--- a/test/unit/crypto/bio/test_bss_dgram_win.c
+++ b/test/unit/crypto/bio/test_bss_dgram_win.c
@@ -401,8 +401,7 @@ static void test_win_get_send_timeout_converts_milliseconds(void **state)
/*
* GET_RECV_TIMER_EXP checks data->_errno == WSAETIMEDOUT on Windows
* (EAGAIN elsewhere), then consumes/clears it. WSAETIMEDOUT is treated
- * as fatal by BIO_dgram_non_fatal_error, so we set _errno directly
- * rather than driving it through a recvfrom retry that never sets it.
+ * as fatal by BIO_dgram_non_fatal_error, so set _errno directly.
*/
static void test_win_recv_timer_exp_consumes_errno(void **state)
{