[PATCH 3/7] gost28147: fix out-of-bounds read in IMIT MAC verify

Jussi Kivilinna jussi.kivilinna at iki.fi
Fri Jul 24 20:48:02 CEST 2026


* cipher/gost28147.c (gost_imit_verify): Reject tag longer than MAC.
* tests/basic.c (check_mac_gost_imit_verify_len): New.
(check_mac): Call check_mac_gost_imit_verify_len.
--

gost_imit_verify built 8-byte MAC in stack buffer but compared caller
supplied number of bytes without bounding it. Verify request longer
than 8 bytes read past buffer into adjacent stack storage. Reject
length above MAC size with GPG_ERR_INV_LENGTH, as HMAC verify does.
Shorter lengths still verify for truncated tags.

Reported-by: JEAN Jeremy <Jeremy.Jean at ssi.gouv.fr>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/gost28147.c |  3 +++
 tests/basic.c      | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index f094d5ba..10383c23 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
@@ -485,6 +485,9 @@ gost_imit_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
 {
   unsigned char tbuf[8];
 
+  if (buflen > sizeof(tbuf))
+    return GPG_ERR_INV_LENGTH;
+
   gost_imit_finish (h);
 
   buf_put_le32 (tbuf+0, h->u.imit.n1);
diff --git a/tests/basic.c b/tests/basic.c
index b62a9a90..0dceebd7 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -16159,6 +16159,68 @@ out:
   gcry_mac_close (hd);
 }
 
+#if USE_GOST28147
+static void
+check_mac_gost_imit_verify_len (void)
+{
+  static const char key[32] _GCRY_GCC_ATTR_NONSTRING =
+    "\x9d\x05\xb7\x9e\x90\xca\xd0\x0a\x2c\xda\xd2\x2e\xf4\xe8\x6f\x5c"
+    "\xf5\xdc\x37\x68\x19\x85\xb3\xbf\xaa\x18\xc1\xc3\x05\x0a\x91\xa2";
+  static const char data[16] _GCRY_GCC_ATTR_NONSTRING =
+    "\xb5\xa1\xf0\xe3\xce\x2f\x02\x1d\x67\x61\x94\x34\x5c\x41\xe3\x6e";
+  static const size_t bad_lens[] = { 9, 16, 64, 4096 };
+  unsigned char tag[8];
+  unsigned char big[4096];
+  size_t taglen = sizeof (tag);
+  gcry_mac_hd_t hd;
+  gcry_error_t err;
+  unsigned int i;
+
+  if (gcry_mac_test_algo (GCRY_MAC_GOST28147_IMIT))
+    return;
+
+  if (verbose)
+    fprintf (stderr, "  checking GOST28147 IMIT verify length handling\n");
+
+  err = gcry_mac_open (&hd, GCRY_MAC_GOST28147_IMIT, 0, NULL);
+  if (err)
+    {
+      fail ("gost imit verify: gcry_mac_open failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  if (!(err = gcry_mac_setkey (hd, key, sizeof (key))))
+    err = gcry_mac_write (hd, data, sizeof (data));
+  if (!err)
+    err = gcry_mac_read (hd, tag, &taglen);
+  if (err || taglen != sizeof (tag))
+    {
+      fail ("gost imit verify: setup failed: %s\n", gpg_strerror (err));
+      goto out;
+    }
+
+  err = gcry_mac_verify (hd, tag, sizeof (tag));
+  if (err)
+    fail ("gost imit verify: 8-byte tag rejected: %s\n", gpg_strerror (err));
+  err = gcry_mac_verify (hd, tag, 4);
+  if (err)
+    fail ("gost imit verify: 4-byte tag rejected: %s\n", gpg_strerror (err));
+
+  memset (big, 0, sizeof (big));
+  memcpy (big, tag, sizeof (tag));
+  for (i = 0; i < DIM (bad_lens); i++)
+    {
+      err = gcry_mac_verify (hd, big, bad_lens[i]);
+      if (gcry_err_code (err) != GPG_ERR_INV_LENGTH)
+        fail ("gost imit verify: oversized len %d not rejected: %s\n",
+              (int)bad_lens[i], gpg_strerror (err));
+    }
+
+out:
+  gcry_mac_close (hd);
+}
+#endif /* USE_GOST28147 */
+
 static void
 check_mac (void)
 {
@@ -17110,6 +17172,10 @@ check_mac (void)
 		     algos[i].expect, 1);
     }
 
+#if USE_GOST28147
+  check_mac_gost_imit_verify_len ();
+#endif
+
   if (verbose)
     fprintf (stderr, "Completed MAC checks.\n");
 }
-- 
2.53.0




More information about the Gcrypt-devel mailing list