gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] 03/06: Implemented base64 decoding with thorough checks


From: gnunet
Subject: [libmicrohttpd] 03/06: Implemented base64 decoding with thorough checks for the input data validity
Date: Thu, 09 Jun 2022 15:56:18 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit b1dd47abbf944e12beac30b1387a75d191b80c9f
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Wed Jun 8 18:10:55 2022 +0300

    Implemented base64 decoding with thorough checks for the input data validity
---
 src/microhttpd/mhd_str.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++
 src/microhttpd/mhd_str.h |  27 ++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c
index 014e71a3..d90008c0 100644
--- a/src/microhttpd/mhd_str.c
+++ b/src/microhttpd/mhd_str.c
@@ -1535,3 +1535,115 @@ MHD_str_quote (const char *unquoted,
 
 
 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
+
+#ifdef BAUTH_SUPPORT
+
+size_t
+MHD_base64_to_bin_n (const char *base64,
+                     size_t base64_len,
+                     void *bin,
+                     size_t bin_size)
+{
+#ifndef MHD_FAVOR_SMALL_CODE
+#define map_type int
+#else  /* MHD_FAVOR_SMALL_CODE */
+#define map_type int8_t
+#endif /* MHD_FAVOR_SMALL_CODE */
+  static const map_type map[] = {
+    /* -1 = invalid char, -2 = padding
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 00..0F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 10..1F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  /* 20..2F 
*/
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,  /* 30..3F 
*/
+    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 40..4F 
*/
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  /* 50..5F 
*/
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 60..6F 
*/
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1   /* 70..7F 
*/
+#ifndef MHD_FAVOR_SMALL_CODE
+    ,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 80..8F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 90..9F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* A0..AF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* B0..BF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* C0..CF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* D0..DF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* E0..EF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* F0..FF 
*/
+#endif /* ! MHD_FAVOR_SMALL_CODE */
+  };
+  const uint8_t *const in = (const uint8_t *) base64;
+  uint8_t *const out = (uint8_t *) bin;
+  size_t i;
+  size_t j;
+  if (0 == base64_len)
+    return 0;  /* Nothing to decode */
+  if (0 != base64_len % 4)
+    return 0;  /* Wrong input length */
+  if (base64_len / 4 * 3 - 2 > bin_size)
+    return 0;
+
+  j = 0;
+  for (i = 0; i < (base64_len - 4); i += 4)
+  {
+#ifdef MHD_FAVOR_SMALL_CODE
+    if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
+      return 0;
+#endif /* MHD_FAVOR_SMALL_CODE */
+    if (1)
+    {
+      const map_type v1 = map[in[i + 0]];
+      const map_type v2 = map[in[i + 1]];
+      const map_type v3 = map[in[i + 2]];
+      const map_type v4 = map[in[i + 3]];
+      if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4))
+        return 0;
+      out[j + 0] = (uint8_t) ((((uint8_t) v1) << 2) | (((uint8_t) v2) >> 4));
+      out[j + 1] = (uint8_t) ((((uint8_t) v2) << 4) | (((uint8_t) v3) >> 2));
+      out[j + 2] = (uint8_t) ((((uint8_t) v3) << 6) | (((uint8_t) v4)));
+    }
+    j += 3;
+  }
+#ifdef MHD_FAVOR_SMALL_CODE
+  if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
+    return 0;
+#endif /* MHD_FAVOR_SMALL_CODE */
+  if (1)
+  { /* The last four chars block */
+    const map_type v1 = map[in[i + 0]];
+    const map_type v2 = map[in[i + 1]];
+    const map_type v3 = map[in[i + 2]];
+    const map_type v4 = map[in[i + 3]];
+    if ((0 > v1) || (0 > v2))
+      return 0; /* Invalid char or padding at first two positions */
+    mhd_assert (j < bin_size);
+    out[j++] = (uint8_t) ((((uint8_t) v1) << 2) | (((uint8_t) v2) >> 4));
+    if (0 > v3)
+    { /* Third char is either padding or invalid */
+      if ((-2 != v3) || (-2 != v4))
+        return 0;  /* Both two last chars must be padding */
+      if (0 != (uint8_t) (((uint8_t) v2) << 4))
+        return 0;  /* Wrong last char */
+      return j;
+    }
+    if (j >= bin_size)
+      return 0; /* Not enough space */
+    out[j++] = (uint8_t) ((((uint8_t) v2) << 4) | (((uint8_t) v3) >> 2));
+    if (0 > v4)
+    { /* Fourth char is either padding or invalid */
+      if (-2 != v4)
+        return 0;  /* The char must be padding */
+      if (0 != (uint8_t) (((uint8_t) v3) << 6))
+        return 0;  /* Wrong last char */
+      return j;
+    }
+    if (j >= bin_size)
+      return 0; /* Not enough space */
+    out[j++] = (uint8_t) ((((uint8_t) v3) << 6) | (((uint8_t) v4)));
+  }
+  return j;
+#undef map_type
+}
+
+
+#endif /* BAUTH_SUPPORT */
diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h
index af58d5d4..17921aa1 100644
--- a/src/microhttpd/mhd_str.h
+++ b/src/microhttpd/mhd_str.h
@@ -583,4 +583,31 @@ MHD_str_quote (const char *unquoted,
 
 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
 
+#ifdef BAUTH_SUPPORT
+
+/**
+ * Convert Base64 encoded string to binary data.
+ * @param base64 the input string with Base64 encoded data, could be NOT zero
+ *               terminated
+ * @param base64_len the number of characters to decode in @a base64 string,
+ *                   valid number must be a multiple of four
+ * @param[out] bin the pointer to the output buffer, the buffer may be altered
+ *                 even if decoding failed
+ * @param bin_size the size of the @a bin buffer in bytes, if the size is
+ *                 at least @a base64_len / 4 * 3 then result will always
+ *                 fit, regardless of the amount of the padding characters
+ * @return 0 if @base64_len is zero, or input string has wrong data (not
+ *         valid Base64 sequence), or @a bin_size is too small;
+ *         non-zero number of bytes written to the @a bin, the number must be
+ *         (base64_len / 4 * 3 - 2), (base64_len / 4 * 3 - 1) or
+ *         (base64_len / 4 * 3), depending on the number of padding characters.
+ */
+size_t
+MHD_base64_to_bin_n (const char *base64,
+                     size_t base64_len,
+                     void *bin,
+                     size_t bin_size);
+
+#endif /* BAUTH_SUPPORT */
+
 #endif /* MHD_STR_H */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]