]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Fix ubsan issue in hash update functions.
authorNiels Möller <nisse@lysator.liu.se>
Fri, 8 Mar 2024 16:52:51 +0000 (17:52 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Fri, 8 Mar 2024 16:52:51 +0000 (17:52 +0100)
ChangeLog
macros.h
sha256.c
sha3.c
testsuite/testutils.c

index 69df1d18678da6ad7e05489447d6187a33d968d0..4fa4a72f003f561c8ad8751c44a64449305396d4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2024-03-08  Niels Möller  <nisse@lysator.liu.se>
+
+       Fix ubsan issues for empty hash updates.
+       * macros.h (MD_UPDATE): Check upfront if length is zero. Avoids
+       calling memcpy(dst, NULL, 0), which is undefined behavior.
+       * sha256.c (sha256_update): Likewise.
+       * sha3.c (_nettle_sha3_update): Likewise.
+       * testsuite/testutils.c (test_hash): Test with message split into
+       two pieces in different ways, and also add an call to update(ctx,
+       0, NULL) in the middle.
+
 2024-02-16  Niels Möller  <nisse@lysator.liu.se>
 
        RSA-OAEP support contributed by Nicolas Mora and Daiki Ueno:
index 990d32ee3b36e6050b6d8df6bf039448a21bfe22..320f61ce519d0a62c19b3670ad62b1d4c1b1098c 100644 (file)
--- a/macros.h
+++ b/macros.h
@@ -180,6 +180,7 @@ do {                                                \
    length and data. */
 #define MD_UPDATE(ctx, length, data, f, incr)                          \
   do {                                                                 \
+    if (!length) goto __md_done;                                       \
     if ((ctx)->index)                                                  \
       {                                                                        \
        /* Try to fill partial block */                                 \
index 0c9c21a0e3a8b9bb9403ebf686dcb0a0e85b848b..44551224c20a2de415373abf7ffe5c1f96fc71fe 100644 (file)
--- a/sha256.c
+++ b/sha256.c
@@ -105,6 +105,9 @@ sha256_update(struct sha256_ctx *ctx,
              size_t length, const uint8_t *data)
 {
   size_t blocks;
+  if (!length)
+    return;
+
   if (ctx->index > 0)
     {
       /* Try to fill partial block */
diff --git a/sha3.c b/sha3.c
index cd22041b969c897a8b8b6477b3333de9a4f9af9e..0eecfb22229dc0448faf679c266823f4387ae185 100644 (file)
--- a/sha3.c
+++ b/sha3.c
@@ -67,6 +67,9 @@ _nettle_sha3_update (struct sha3_state *state,
                     unsigned pos,
                     size_t length, const uint8_t *data)
 {
+  if (!length)
+    return pos;
+
   if (pos > 0)
     {
       unsigned left = block_size - pos;
index 6fc8a8b824367ad5353ac6a52678de45f3781eb7..ac9d8f634c1b058d28e4a89593282092ba62f612 100644 (file)
@@ -1108,16 +1108,22 @@ test_hash(const struct nettle_hash *hash,
     ASSERT (digest->length == hash->digest_size);
 
   hash->init(ctx);
-  hash->update(ctx, msg->length, msg->data);
-  hash->digest(ctx, digest->length, buffer);
-
-  if (MEMEQ(digest->length, digest->data, buffer) == 0)
+  for (offset = 0; offset <= msg->length && offset < 40; offset++)
     {
-      fprintf(stdout, "\nGot:\n");
-      print_hex(digest->length, buffer);
-      fprintf(stdout, "\nExpected:\n");
-      print_hex(digest->length, digest->data);
-      abort();
+      hash->update(ctx, offset, msg->data);
+      hash->update(ctx, 0, NULL);
+      hash->update(ctx, msg->length - offset, msg->data + offset);
+
+      hash->digest(ctx, digest->length, buffer);
+
+      if (MEMEQ(digest->length, digest->data, buffer) == 0)
+       {
+         fprintf(stdout, "Offset %u\nGot:\n", offset);
+         print_hex(digest->length, buffer);
+         fprintf(stdout, "\nExpected:\n");
+         print_hex(digest->length, digest->data);
+         abort();
+       }
     }
 
   memset(buffer, 0, digest->length);