[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