add integer overflow guards and avoid (unlimited) stack allocation
authorChristian Grothoff <christian@grothoff.org>
Wed, 15 Apr 2020 18:35:45 +0000 (20:35 +0200)
committerChristian Grothoff <christian@grothoff.org>
Wed, 15 Apr 2020 18:35:45 +0000 (20:35 +0200)
src/util/crypto_hkdf.c

index 9cdb9d9bcbf7a3ae250bac5c871b6e88415b248a..86a814b129f0503a9c6069875bda6eae3833e7fd 100644 (file)
@@ -175,10 +175,28 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
 
   ctx_len = 0;
   while (NULL != va_arg (args, void *))
-    ctx_len += va_arg (args, size_t);
+  {
+    size_t nxt = va_arg (args, size_t);
+    if (nxt + ctx_len < nxt)
+    {
+      /* integer overflow */
+      GNUNET_break (0);
+      va_end (args);
+      goto hkdf_error;
+    }
+    ctx_len += nxt;
+  }
 
   va_end (args);
 
+  if ( (k + ctx_len < ctx_len) ||
+       (k + ctx_len + 1 < ctx_len) )
+  {
+    /* integer overflow */
+    GNUNET_break (0);
+    goto hkdf_error;
+  }
+
   memset (result, 0, out_len);
   if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES)
     goto hkdf_error;
@@ -192,10 +210,11 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
   /* K(1) */
   {
     size_t plain_len = k + ctx_len + 1;
-    char plain[plain_len];
+    char *plain;
     const void *ctx;
     char *dst;
 
+    plain = GNUNET_malloc (plain_len);
     dst = plain + k;
     va_copy (args, argp);
     while ((ctx = va_arg (args, void *)))
@@ -216,7 +235,10 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
 #endif
       hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1);
       if (hc == NULL)
+      {
+        GNUNET_free (plain);
         goto hkdf_error;
+      }
       GNUNET_memcpy (result, hc, k);
       result += k;
     }
@@ -232,7 +254,10 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
 #endif
       hc = doHMAC (prf, prk, xtr_len, plain, plain_len);
       if (hc == NULL)
+      {
+        GNUNET_free (plain);
         goto hkdf_error;
+      }
       GNUNET_memcpy (result, hc, k);
       result += k;
     }
@@ -255,7 +280,10 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
       else
         hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k);
       if (hc == NULL)
+      {
+        GNUNET_free (plain);
         goto hkdf_error;
+      }
       GNUNET_memcpy (result, hc, d);
     }
 #if DEBUG_HKDF
@@ -263,6 +291,7 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
 #endif
 
     ret = GNUNET_YES;
+    GNUNET_free (plain);
     goto hkdf_ok;
   }
 hkdf_error: