Commit 3f72c613db for openssl.org
commit 3f72c613db19909ca190797082c5511fe6df7ad4
Author: Ryan Hooper <ryanh@openssl.foundation>
Date: Thu Sep 24 14:46:32 2026 -0400
DTLS: Expose dtls_listener_cookie_hmac() and add a regression test
Drop static from dtls_listener_cookie_hmac() and declare it in
ssl_local.h, alongside its sibling listener cookie callbacks, so it
can be exercised directly from test/dtlsssllistenertest.c.
Add test_dtls_listener_cookie_hmac_long_addr(), which sets a DTLS1.3
server connection's peer_addr to an AF_UNIX address with a sun_path
longer than 64 bytes. dtls_listener_cookie_hmac() currently sizes its
address scratch buffers with a hardcoded 64 instead of sizeof(BIO_ADDR),
so BIO_ADDR_rawaddress() overflows those stack buffers for such a peer.
Assisted-by: Claude:claude-sonnet-5
Reviewed-by: Frederik Wedel-Heinen <fwh.openssl@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Merge-date: Wed Sep 30 08:23:10 2026
Merged-from: https://github.com/openssl/openssl/pull/32982
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 8372d0927e..98c939ab9f 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -1596,7 +1596,7 @@ static OSSL_TIME dtls_listener_get_time_direct(DTLS_LISTENER *dl)
*
* Returns 1 on success, 0 on failure.
*/
-static int dtls_listener_cookie_hmac(SSL *ssl, uint64_t timestamp,
+int dtls_listener_cookie_hmac(SSL *ssl, uint64_t timestamp,
unsigned char *hmac_out)
{
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL_ONLY(ssl);
@@ -1604,8 +1604,8 @@ static int dtls_listener_cookie_hmac(SSL *ssl, uint64_t timestamp,
EVP_MAC_CTX *mctx = NULL;
OSSL_PARAM params[2];
/* 8 (timestamp) + 2 (port) + max address size */
- unsigned char data[8 + sizeof(uint16_t) + 64];
- unsigned char addr_buf[64];
+ unsigned char data[DTLS_LISTENER_COOKIE_TIMESTAMP_LEN + sizeof(uint16_t) + sizeof(BIO_ADDR)];
+ unsigned char addr_buf[sizeof(BIO_ADDR)];
size_t data_len = 0;
size_t addr_len = 0;
size_t hmac_len = DTLS_LISTENER_COOKIE_HMAC_LEN;
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 9d40fcb0f4..5632e05ead 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -3159,6 +3159,8 @@ int ossl_dtls_listener_gen_stateless_cookie_cb(SSL *ssl, unsigned char *cookie,
int ossl_dtls_listener_verify_stateless_cookie_cb(SSL *ssl,
const unsigned char *cookie,
size_t cookie_len);
+int dtls_listener_cookie_hmac(SSL *ssl, uint64_t timestamp,
+ unsigned char *hmac_out);
#endif /* !OPENSSL_NO_DTLS && !OPENSSL_NO_SOCK */
__owur int tls1_new(SSL *s);
diff --git a/test/dtlsssllistenertest.c b/test/dtlsssllistenertest.c
index e77867bdf8..16565ec318 100644
--- a/test/dtlsssllistenertest.c
+++ b/test/dtlsssllistenertest.c
@@ -1928,6 +1928,59 @@ err:
return success;
}
+#if !defined(OPENSSL_NO_UNIX_SOCK) && !defined(OPENSSL_NO_DTLS1_3)
+/*
+ * dtls_listener_cookie_hmac() used to size its address scratch buffers with
+ * a hardcoded 64 bytes instead of sizeof(BIO_ADDR). An AF_UNIX peer address,
+ * whose sun_path can be much longer than 64 bytes, overflowed those stack
+ * buffers. Exercise it with a peer_addr set to a long AF_UNIX path.
+ */
+static int test_dtls_listener_cookie_hmac_long_addr(void)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ SSL_CONNECTION *sc = NULL;
+ /* One byte short of sun_path's capacity: longer than the old 64-byte
+ * addr_buf/data buffers in dtls_listener_cookie_hmac(). */
+ char long_path[UNIX_PATH_MAX - 1];
+ unsigned char hmac_out[EVP_MAX_MD_SIZE];
+ int testresult = 0;
+
+ memset(long_path, 'a', sizeof(long_path) - 1);
+ long_path[sizeof(long_path) - 1] = '\0';
+
+ if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(),
+ DTLS_client_method(), DTLS1_3_VERSION, DTLS1_3_VERSION,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+ goto end;
+
+ if (!TEST_ptr(sc = SSL_CONNECTION_FROM_SSL(serverssl)))
+ goto end;
+
+ if (!TEST_true(BIO_ADDR_rawmake(&sc->d1->peer_addr, AF_UNIX,
+ long_path, strlen(long_path), 0)))
+ goto end;
+
+ if (!TEST_true(dtls_listener_cookie_hmac(serverssl, 0, hmac_out)))
+ goto end;
+
+ testresult = 1;
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ return testresult;
+}
+#endif /* !OPENSSL_NO_UNIX_SOCK && !OPENSSL_NO_DTLS1_3 */
+
/*
* Test SSL_new_listener with NULL context.
* Should return NULL and not crash.
@@ -5982,6 +6035,9 @@ int setup_tests(void)
/* Peer address tests */
ADD_TEST(test_dtls_get_peer_addr_no_peer);
ADD_TEST(test_dtls_get_peer_addr_listener);
+#if !defined(OPENSSL_NO_UNIX_SOCK) && !defined(OPENSSL_NO_DTLS1_3)
+ ADD_TEST(test_dtls_listener_cookie_hmac_long_addr);
+#endif
/* Error handling and edge case tests */
ADD_TEST(test_dtls_new_listener_null_ctx);