From 1cdfc764ac57133e4a0561697161b17383f5a06e Mon Sep 17 00:00:00 2001
From: matt335672 <30179339+matt335672@users.noreply.github.com>
Date: Tue, 10 Mar 2026 20:33:15 +0000
Subject: [PATCH] security: Check HMAC on non-FIPS slowpath input

CVE-2026-32105: Add a check that the HMAC signature supplied with a
non-FIPS slowpath input PDU matches the calculated signature.

(cherry picked from commit 759104912c64b33b2442ed788c1806e36d028db0)
---
 libxrdp/xrdp_sec.c | 104 +++++++++++++++++++++++++++++++--------------
 1 file changed, 71 insertions(+), 33 deletions(-)

--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -1325,7 +1325,10 @@ xrdp_sec_fips_sign(struct xrdp_sec *self
 }
 
 /*****************************************************************************/
-/* Check a FIPS hash is valid */
+/* Check a FIPS hash is valid
+ *
+ * Result is boolean (i.e. != 0 is OK)
+ * */
 static int
 xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len,
                         char *data, int data_len)
@@ -1345,6 +1348,66 @@ xrdp_sec_fips_check_sig(struct xrdp_sec
 }
 
 /*****************************************************************************/
+/* Generate a MAC hash (5.3.6.1), using a combination of SHA1 and MD5
+ *
+ * Salted MAC is not currently supported */
+static void
+xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len,
+              char *data, int data_len)
+{
+    char shasig[20];
+    char md5sig[16];
+    char lenhdr[4];
+    void *sha1_info;
+    void *md5_info;
+
+    buf_out_uint32(lenhdr, data_len);
+    sha1_info = ssl_sha1_info_create();
+    md5_info = ssl_md5_info_create();
+    ssl_sha1_clear(sha1_info);
+    ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len);
+    ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40);
+    ssl_sha1_transform(sha1_info, lenhdr, 4);
+    ssl_sha1_transform(sha1_info, data, data_len);
+    ssl_sha1_complete(sha1_info, shasig);
+    ssl_md5_clear(md5_info);
+    ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len);
+    ssl_md5_transform(md5_info, (char *)g_pad_92, 48);
+    ssl_md5_transform(md5_info, shasig, 20);
+    ssl_md5_complete(md5_info, md5sig);
+    g_memcpy(out, md5sig, out_len);
+    ssl_sha1_info_delete(sha1_info);
+    ssl_md5_info_delete(md5_info);
+}
+
+/*****************************************************************************/
+/* Check a non-FIPS hash is valid
+ *
+ * Salted MAC is not currently supported
+ *
+ * Result is boolean (i.e. != 0 is OK) */
+static int
+xrdp_sec_check_sig(struct xrdp_sec *self, const char *sig, int sig_len,
+                   char *data, int data_len)
+{
+    char computed[8];
+    int rv = 0;
+    if (sig_len > (int)sizeof(computed))
+    {
+        LOG(LOG_LEVEL_ERROR,
+            "xrdp_sec_check_sig() Buffer overflow (got %d expected %d)",
+            sig_len, (int)sizeof(computed));
+    }
+    else
+    {
+        xrdp_sec_sign(self, computed, sig_len, data, data_len);
+        rv = (memcmp(computed, sig, sig_len) == 0);
+    }
+
+    return rv;
+}
+
+/*****************************************************************************/
 static void
 xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2)
 {
@@ -1664,10 +1727,16 @@ xrdp_sec_recv(struct xrdp_sec *self, str
                 return 1;
             }
             /* TS_SECURITY_HEADER1 */
-            in_uint8s(s, 8); /* signature(8) */
+            in_uint8p(s, data_signature, 8);
             LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER1 "
                       "dataSignature (ignored)");
             xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p));
+            if (!xrdp_sec_check_sig(self, data_signature, 8,
+                                    s->p, (int)(s->end - s->p)))
+            {
+                LOG(LOG_LEVEL_ERROR, "MAC checksum error for non-FIPS PDU");
+                return 1;
+            }
         }
     }
 
@@ -1764,37 +1833,6 @@ xrdp_sec_recv(struct xrdp_sec *self, str
 }
 
 /*****************************************************************************/
-/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
-static void
-xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len,
-              char *data, int data_len)
-{
-    char shasig[20];
-    char md5sig[16];
-    char lenhdr[4];
-    void *sha1_info;
-    void *md5_info;
-
-    buf_out_uint32(lenhdr, data_len);
-    sha1_info = ssl_sha1_info_create();
-    md5_info = ssl_md5_info_create();
-    ssl_sha1_clear(sha1_info);
-    ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len);
-    ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40);
-    ssl_sha1_transform(sha1_info, lenhdr, 4);
-    ssl_sha1_transform(sha1_info, data, data_len);
-    ssl_sha1_complete(sha1_info, shasig);
-    ssl_md5_clear(md5_info);
-    ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len);
-    ssl_md5_transform(md5_info, (char *)g_pad_92, 48);
-    ssl_md5_transform(md5_info, shasig, 20);
-    ssl_md5_complete(md5_info, md5sig);
-    g_memcpy(out, md5sig, out_len);
-    ssl_sha1_info_delete(sha1_info);
-    ssl_md5_info_delete(md5_info);
-}
-
-/*****************************************************************************/
 /* returns error */
 int
 xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
