[Bug 3983] New: UMAC corruption for messages >1024 bytes due to strict-aliasing violation

bugzilla-daemon at mindrot.org bugzilla-daemon at mindrot.org
Sat Jul 25 00:33:57 AEST 2026


https://bugzilla.mindrot.org/show_bug.cgi?id=3983

            Bug ID: 3983
           Summary: UMAC corruption for messages >1024 bytes due to
                    strict-aliasing violation
           Product: Portable OpenSSH
           Version: 9.6p1
          Hardware: Other
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P5
         Component: ssh
          Assignee: unassigned-bugs at mindrot.org
          Reporter: talaberp at gmail.com

Hi,

I have run into a strange issue. If for SSH connection UMAC is
negotiated I got `Corrupted MAC on input` when I try to send a few KB
of data.
I managed to narrow down the issue that above 1024 bytes of data passed
for umac calculation, the issue occurs, but only in case the compiler
uses optimization. This limit comes from `L1_KEY_LEN` in umac.c which
decides to pass code execution on "long message path" towards
poly_hash() instead of "short path" using ip_short() in uhash_final.
The problem was on "long path" as `UINT64 poly_key_8[STREAMS];` already
contained corrupted data, because `endian_convert()` called earlier by
`uhash_init()` used a code which violates strict-aliasing rule when
manipulating poly_key_8: a U64[] data via an U32* pointer.
When compiled in debug mode, without optimization it was fine.
Otherwise, it caused the issue, unless `-fno-strict-aliasing` was
passed as well, which fixed the violation above. Switching this code
part to use memcpy instead fixed the issue for me:
```
[umac.c#L556](https://github.com/openssh/openssh-portable/blob/master/umac.c#L556)
     } else if (bpw == 8) {
-        UINT32 *p = (UINT32 *)buf;
-        UINT32 t;
+        UINT8 *p = (UINT8 *)buf;
+        UINT32 hi, lo;
         do {
-            t = LOAD_UINT32_REVERSED(p+1);
-            p[1] = LOAD_UINT32_REVERSED(p);
-            p[0] = t;
-            p += 2;
+            hi = LOAD_UINT32_REVERSED(p);
+            lo = LOAD_UINT32_REVERSED(p + 4);
+            memcpy(p, &lo, sizeof(lo));
+            memcpy(p + 4, &hi, sizeof(hi));
+            p += 8;
         } while (--iters);
     }
```
Since OpenSSH uses `-fno-strict-aliasing` by default, issue remained
hidden for a while.
[configure.ac#L218](https://github.com/openssh/openssh-portable/blob/master/configure.ac#L218)

The fix applies to both the umac-64* and umac-128* processing paths,
though when I was testing it, it was not triggered for umac-64*.

BR,
Peter

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


More information about the openssh-bugs mailing list