Add base64 decode support

This is based on the hostap.git implementation (licensed under the BSD
license).

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
diff --git a/utils.c b/utils.c
index 201dad5..4b27d77 100644
--- a/utils.c
+++ b/utils.c
@@ -986,6 +986,74 @@
 }
 
 
+unsigned char * base64_decode(const char *src, size_t len, size_t *out_len)
+{
+	unsigned char dtable[256], *out, *pos, block[4], tmp;
+	size_t i, count, olen;
+	int pad = 0;
+	size_t extra_pad;
+
+	memset(dtable, 0x80, 256);
+	for (i = 0; i < sizeof(base64_table) - 1; i++)
+		dtable[(unsigned char) base64_table[i]] = (unsigned char) i;
+	dtable['='] = 0;
+
+	count = 0;
+	for (i = 0; i < len; i++) {
+		if (dtable[(unsigned char) src[i]] != 0x80)
+			count++;
+	}
+
+	if (count == 0)
+		return NULL;
+	extra_pad = (4 - count % 4) % 4;
+
+	olen = (count + extra_pad) / 4 * 3;
+	pos = out = malloc(olen);
+	if (!out)
+		return NULL;
+
+	count = 0;
+	for (i = 0; i < len + extra_pad; i++) {
+		unsigned char val;
+
+		if (i >= len)
+			val = '=';
+		else
+			val = src[i];
+		tmp = dtable[val];
+		if (tmp == 0x80)
+			continue;
+
+		if (val == '=')
+			pad++;
+		block[count] = tmp;
+		count++;
+		if (count == 4) {
+			*pos++ = (block[0] << 2) | (block[1] >> 4);
+			*pos++ = (block[1] << 4) | (block[2] >> 2);
+			*pos++ = (block[2] << 6) | block[3];
+			count = 0;
+			if (pad) {
+				if (pad == 1)
+					pos--;
+				else if (pad == 2)
+					pos -= 2;
+				else {
+					/* Invalid padding */
+					free(out);
+					return NULL;
+				}
+				break;
+			}
+		}
+	}
+
+	*out_len = pos - out;
+	return out;
+}
+
+
 int random_get_bytes(char *buf, size_t len)
 {
 	FILE *f;