Commit a24fbf403a for openssl.org

commit a24fbf403a891ec026847f70bef1fd582b1e9601
Author: slontis <shane.lontis@oracle.com>
Date:   Wed Mar 18 10:16:44 2026 +1100

    SLH-DSA: Fix Integer overflow in msg_encode leading to buffer overflow

    Reported by Zehua Qiao and me@snkth.com

    An encode message buffer M = 00 || CXT_LEN || CTX || MSG was being
    allocated followed by memcpy's into the buffer for CTX and MSG.
    If len(MSG) was close to size_t the allocated buffer would be
    overwritten.

    The fix uses WPACKET to perform the message encoding M = 00 || CXT_LEN || CTX || MSG

    Although ML_DSA does a similiar operation, SLH-DSA has to buffer the
    encoding because the encoded message is processed multiple times for
    PRF_MSG and H_MSG. FOr ML_DSA the encoded message can just be hashed.

    Fixes: 2f9e152d86a7 "Add SLH_DSA signature verification."

    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Matt Caswell <matt@openssl.foundation>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    MergeDate: Sun Mar 22 00:15:47 2026
    (Merged from https://github.com/openssl/openssl/pull/30477)

diff --git a/crypto/slh_dsa/slh_dsa.c b/crypto/slh_dsa/slh_dsa.c
index 36d0a61531..6519e8640f 100644
--- a/crypto/slh_dsa/slh_dsa.c
+++ b/crypto/slh_dsa/slh_dsa.c
@@ -232,6 +232,7 @@ static uint8_t *msg_encode(const uint8_t *msg, size_t msg_len,
     const uint8_t *ctx, size_t ctx_len, int encode,
     uint8_t *tmp, size_t tmp_len, size_t *out_len)
 {
+    WPACKET pkt;
     uint8_t *encoded = NULL;
     size_t encoded_len;

@@ -240,11 +241,14 @@ static uint8_t *msg_encode(const uint8_t *msg, size_t msg_len,
         *out_len = msg_len;
         return (uint8_t *)msg;
     }
+
     if (ctx_len > SLH_DSA_MAX_CONTEXT_STRING_LEN)
         return NULL;

     /* Pure encoding */
     encoded_len = 1 + 1 + ctx_len + msg_len;
+    if (encoded_len < msg_len) /* Check for overflow */
+        return NULL;
     *out_len = encoded_len;
     if (encoded_len <= tmp_len) {
         encoded = tmp;
@@ -253,10 +257,17 @@ static uint8_t *msg_encode(const uint8_t *msg, size_t msg_len,
         if (encoded == NULL)
             return NULL;
     }
-    encoded[0] = 0;
-    encoded[1] = (uint8_t)ctx_len;
-    memcpy(&encoded[2], ctx, ctx_len);
-    memcpy(&encoded[2 + ctx_len], msg, msg_len);
+    if (!WPACKET_init_static_len(&pkt, encoded, encoded_len, 0)
+        || !WPACKET_put_bytes_u8(&pkt, 0)
+        || !WPACKET_put_bytes_u8(&pkt, (uint8_t)ctx_len)
+        || !WPACKET_memcpy(&pkt, ctx, ctx_len)
+        || !WPACKET_memcpy(&pkt, msg, msg_len)
+        || !WPACKET_finish(&pkt)) {
+        if (encoded != tmp)
+            OPENSSL_free(encoded);
+        encoded = NULL;
+        WPACKET_cleanup(&pkt);
+    }
     return encoded;
 }