dovecot-2.2: Added support for base32 encode/decode.

dovecot at dovecot.org dovecot at dovecot.org
Sat Nov 15 01:28:28 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/1663b76430e1
changeset: 18098:1663b76430e1
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Nov 15 02:39:04 2014 +0200
description:
Added support for base32 encode/decode.

diffstat:

 src/lib/Makefile.am   |    3 +
 src/lib/base32.c      |  326 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/base32.h      |   47 +++++++
 src/lib/test-base32.c |  190 +++++++++++++++++++++++++++++
 src/lib/test-lib.c    |    1 +
 src/lib/test-lib.h    |    1 +
 6 files changed, 568 insertions(+), 0 deletions(-)

diffs (truncated from 624 to 300 lines):

diff -r 2866a692ec47 -r 1663b76430e1 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Sat Nov 15 02:37:45 2014 +0200
+++ b/src/lib/Makefile.am	Sat Nov 15 02:39:04 2014 +0200
@@ -16,6 +16,7 @@
 	aqueue.c \
 	askpass.c \
 	backtrace-string.c \
+	base32.c \
 	base64.c \
 	bits.c \
 	bsearch-insert-pos.c \
@@ -149,6 +150,7 @@
 	array-decl.h \
 	askpass.h \
 	backtrace-string.h \
+	base32.h \
 	base64.h \
 	bits.h \
 	bsearch-insert-pos.h \
@@ -278,6 +280,7 @@
 	test-lib.c \
 	test-array.c \
 	test-aqueue.c \
+	test-base32.c \
 	test-base64.c \
 	test-bits.c \
 	test-bsearch-insert-pos.c \
diff -r 2866a692ec47 -r 1663b76430e1 src/lib/base32.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/base32.c	Sat Nov 15 02:39:04 2014 +0200
@@ -0,0 +1,326 @@
+/* Copyright (c) 2007-2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "base32.h"
+#include "buffer.h"
+
+static const char b32enc[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+static const char b32hexenc[] =
+	"0123456789ABCDEFGHIJKLMNOPQRSTUV";
+
+static const unsigned char b32dec[256] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
+	0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 48-55 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
+	0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* 64-71 */
+	0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* 72-79 */
+	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* 80-87 */
+	0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
+
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static const unsigned char b32hexdec[256] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 48-55 */
+	0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
+	0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 64-71 */
+	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 72-79 */
+	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 80-87 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
+
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static void
+base32_encode_with_alphabet(const char *alph,
+	bool pad, const void *src, size_t src_size, buffer_t *dest)
+{
+	const unsigned char *src_c = src;
+	unsigned char tmp[8], endb;
+	size_t src_pos;
+
+	/* [5  3][2  5  1][4  4][1  5  2][3  5]
+	   (5)(3  2)(5)(1  4)(4  1)(5)(2  3)(5)
+	 */
+
+	/* encode main part */
+	for (src_pos = 0; src_pos + 4 < src_size; src_pos += 5) {
+		tmp[0] = alph[src_c[src_pos] >> 3];
+		tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
+				((src_c[src_pos+1] >> 6) & 0x03)];
+		tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
+		tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
+				(src_c[src_pos+2] >> 4)];
+		tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
+				(src_c[src_pos+3] >> 7)];
+		tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
+		tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3) |
+				(src_c[src_pos+4] >> 5)];
+		tmp[7] = alph[src_c[src_pos+4] & 0x1f];
+		buffer_append(dest, tmp, 8);
+	}
+
+	/* encode last < 5 bytes if any */
+	if (src_pos < src_size) {	
+		tmp[0] = alph[src_c[src_pos] >> 3];
+		switch (src_size - src_pos) {
+		case 1:
+			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2)];
+			endb = 2;
+			break;
+		case 2:
+			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
+					((src_c[src_pos+1] >> 6) & 0x03)];
+			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
+			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4)];
+			endb = 4;
+			break;
+		case 3:
+			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
+					((src_c[src_pos+1] >> 6) & 0x03)];
+			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
+			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
+					(src_c[src_pos+2] >> 4)];
+			tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1)];
+			endb = 5;
+			break;
+		case 4:
+			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
+					((src_c[src_pos+1] >> 6) & 0x03)];
+			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
+			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
+					(src_c[src_pos+2] >> 4)];
+			tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
+					(src_c[src_pos+3] >> 7)];
+			tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
+			tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3)];
+			endb = 7;
+			break;
+		default:
+			i_unreached();
+		}
+
+		/* add padding if required */
+		if (pad) {
+			memset(&tmp[endb], '=', sizeof(tmp)-endb);
+			buffer_append(dest, tmp, 8);
+		} else {
+			buffer_append(dest, tmp, endb);
+		}
+	}
+}
+
+void base32_encode(bool pad, const void *src, size_t src_size,
+	buffer_t *dest)
+{
+	base32_encode_with_alphabet(b32enc, pad, src, src_size, dest);
+}
+
+void base32hex_encode(bool pad, const void *src, size_t src_size,
+	buffer_t *dest)
+{
+	base32_encode_with_alphabet(b32hexenc, pad, src, src_size, dest);
+}
+
+#define IS_EMPTY(c) \
+	((c) == '\n' || (c) == '\r' || (c) == ' ' || (c) == '\t')
+
+static int
+base32_decode_with_alphabet(const unsigned char *alph,
+		  const void *src, size_t src_size, size_t *src_pos_r,
+		  buffer_t *dest)
+{
+	const unsigned char *src_c = src;
+	size_t block_pos, src_pos;
+	unsigned char output[5], ipos, opos;
+	int ret = 1;
+
+	/* (5)(3  2)(5)(1  4)(4  1)(5)(2  3)(5)
+	   [5  3][2  5  1][4  4][1  5  2][3  5]
+	 */
+	ipos = opos = 0;
+	block_pos = 0;
+	for (src_pos = 0; src_pos < src_size; src_pos++) {
+		unsigned char input = alph[src_c[src_pos]];
+
+		if (input == 0xff) {
+			if (unlikely(!IS_EMPTY(src_c[src_pos])))
+				break;
+			continue;
+		}
+
+		ipos++;
+		switch (ipos) {
+		case 1:
+			output[0] = input << 3;
+			opos = 0;
+			break;
+		case 2:
+			output[0] |= input >> 2;
+			output[1] = (input & 0x03) << 6;
+			opos = 1;
+			break;
+		case 3: 
+		 	output[1] |= input << 1;
+			opos = 1;
+			break;
+		case 4:
+			output[1] |= input >> 4;
+			output[2] = (input & 0x0f) << 4;
+			opos = 2;
+			break;
+		case 5:
+			output[2] |= input >> 1;
+			output[3] = (input & 0x01) << 7;
+			opos = 3;
+			break;
+		case 6:
+			output[3] |= input << 2;
+			opos = 3;
+			break;
+		case 7:
+			output[3] |= input >> 3;
+			output[4] = ((input & 0x07) << 5);
+			opos = 4;
+			break;
+		case 8:
+			output[4] |= input;
+			buffer_append(dest, output, 5);
+			ipos = 0;
+			opos = 0;
+			block_pos = src_pos;
+			break;
+		default:
+			i_unreached();
+		}
+	}
+
+	if (ipos > 0) {
+		for (; src_pos < src_size; src_pos++) {
+			if (src_c[src_pos] != '=') {
+				if (unlikely(!IS_EMPTY(src_c[src_pos]))) {
+					ret = -1;
+					break;
+				}
+				continue;
+			}
+			if (++ipos >= 8) {
+				buffer_append(dest, output, opos);
+				ipos = 0;
+				ret = 0;
+				src_pos++;
+				break;
+			}
+		}
+	}
+
+	if (src_pos_r != NULL) {
+		if (ipos == 0) {


More information about the dovecot-cvs mailing list