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);