[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.
- [libmicrohttpd] branch master updated (3eb2fb6d -> eecdde25), gnunet, 2022/06/09
- [libmicrohttpd] 02/06: MHD_bin_to_hex(): fixed wrong return value (unused currently by MHD)., gnunet, 2022/06/09
- [libmicrohttpd] 01/06: mhd_str.h: fixed typo in doxy, gnunet, 2022/06/09
- [libmicrohttpd] 04/06: test_str_base64: added test for base64 decoding, gnunet, 2022/06/09
- [libmicrohttpd] 05/06: Basic Auth: switched to the internal Base64 decoding implementation, gnunet, 2022/06/09
- [libmicrohttpd] 03/06: Implemented base64 decoding with thorough checks for the input data validity,
gnunet <=
- [libmicrohttpd] 06/06: Removed Public Domain base64 decoding files, gnunet, 2022/06/09