krb5 commit: Add internal base64 encoding and decoding support
Greg Hudson
ghudson at MIT.EDU
Tue Sep 11 01:18:58 EDT 2012
https://github.com/krb5/krb5/commit/3b55b8aba850fa54a4d0c5017a91641538c16835
commit 3b55b8aba850fa54a4d0c5017a91641538c16835
Author: Greg Hudson <ghudson at mit.edu>
Date: Mon Aug 27 04:18:57 2012 -0400
Add internal base64 encoding and decoding support
Add base64 support based on Heimdal's libroken base64 code.
.gitignore | 1 +
src/include/k5-base64.h | 52 +++++++++++++++
src/util/support/Makefile.in | 14 +++-
src/util/support/base64.c | 145 ++++++++++++++++++++++++++++++++++++++++++
src/util/support/t_base64.c | 110 ++++++++++++++++++++++++++++++++
5 files changed, 319 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 9c14c22..77d4d26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -340,6 +340,7 @@ testlog
/src/util/ss/std_rqs.c
/src/util/support/libkrb5support.exports
+/src/util/support/t_base64
/src/util/support/t_k5buf
/src/util/support/t_path
/src/util/support/t_path_win
diff --git a/src/include/k5-base64.h b/src/include/k5-base64.h
new file mode 100644
index 0000000..a7cc48f
--- /dev/null
+++ b/src/include/k5-base64.h
@@ -0,0 +1,52 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* include/k5-base64.h - base64 declarations */
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef K5_BASE64_H
+#define K5_BASE64_H
+
+#include <stddef.h>
+
+/* base64-encode data and return it in an allocated buffer. Return NULL if out
+ * of memory. */
+char *k5_base64_encode(const void *data, size_t len);
+
+/*
+ * Decode str as base64 and return the result in an allocated buffer, setting
+ * *len_out to the length. Return NULL and *len_out == 0 if out of memory,
+ * NULL and *len_out == SIZE_MAX on invalid input.
+ */
+void *k5_base64_decode(const char *str, size_t *len_out);
+
+#endif /* K5_BASE64_H */
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index 6ac9175..ca04ad7 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -74,6 +74,7 @@ STLIBOBJS= \
utf8_conv.o \
zap.o \
path.o \
+ base64.o \
$(GETTIMEOFDAY_ST_OBJ) \
$(IPC_ST_OBJ) \
$(STRLCPY_ST_OBJ) \
@@ -93,6 +94,7 @@ LIBOBJS= \
$(OUTPRE)utf8_conv.$(OBJEXT) \
$(OUTPRE)zap.$(OBJEXT) \
$(OUTPRE)path.$(OBJEXT) \
+ $(OUTPRE)base64.$(OBJECT) \
$(GETTIMEOFDAY_OBJ) \
$(IPC_OBJ) \
$(STRLCPY_OBJ) \
@@ -123,7 +125,8 @@ SRCS=\
$(srcdir)/t_k5buf.c \
$(srcdir)/t_unal.c \
$(srcdir)/zap.c \
- $(srcdir)/path.c
+ $(srcdir)/path.c \
+ $(srcdir)/base64.c
SHLIB_EXPDEPS =
# Add -lm if dumping thread stats, for sqrt.
@@ -186,20 +189,25 @@ t_path_win.o: $(srcdir)/t_path.c
path_win.o: $(srcdir)/path.c
$(CC) $(ALL_CFLAGS) -DWINDOWS_PATHS -c $(srcdir)/path.c -o $@
+t_base64: t_base64.o base64.o
+ $(CC_LINK) -o $@ t_base64.o base64.o
+
t_unal: t_unal.o
$(CC_LINK) -o t_unal t_unal.o
-TEST_PROGS= t_k5buf t_path t_path_win t_unal
+TEST_PROGS= t_k5buf t_path t_path_win t_base64 t_unal
check-unix:: $(TEST_PROGS)
./t_k5buf
./t_path
./t_path_win
+ ./t_base64
./t_unal
clean::
$(RM) t_k5buf.o t_k5buf t_unal.o t_unal path_win.o path_win
- $(RM) t_path_win.o t_path_win t_path.o t_path libkrb5support.exports
+ $(RM) t_path_win.o t_path_win t_path.o t_path t_base64.o t_base64
+ $(RM) libkrb5support.exports
@lib_frag@
@libobj_frag@
diff --git a/src/util/support/base64.c b/src/util/support/base64.c
new file mode 100644
index 0000000..e964a38
--- /dev/null
+++ b/src/util/support/base64.c
@@ -0,0 +1,145 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* util/support/base64.c - base64 encoder and decoder */
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <k5-platform.h>
+#include <k5-base64.h>
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+char *
+k5_base64_encode(const void *data, size_t len)
+{
+ char *s, *p;
+ size_t i;
+ unsigned int c;
+ const unsigned char *q;
+
+ if (len > SIZE_MAX / 4)
+ return NULL;
+
+ p = s = malloc(len * 4 / 3 + 4);
+ if (p == NULL)
+ return NULL;
+ q = (const unsigned char *)data;
+
+ for (i = 0; i < len;) {
+ c = q[i++];
+ c *= 256;
+ if (i < len)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < len)
+ c += q[i];
+ i++;
+ p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+ p[1] = base64_chars[(c & 0x0003f000) >> 12];
+ p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+ p[3] = base64_chars[(c & 0x0000003f) >> 0];
+ if (i > len)
+ p[3] = '=';
+ if (i > len + 1)
+ p[2] = '=';
+ p += 4;
+ }
+ *p = '\0';
+ return s;
+}
+
+#define DECODE_ERROR 0xffffffff
+
+/* Decode token, which must be four bytes long. */
+static unsigned int
+decode_token(const char *token)
+{
+ int i, marker = 0;
+ unsigned int val = 0;
+ const char *p;
+
+ for (i = 0; i < 4; i++) {
+ val *= 64;
+ if (token[i] == '=') {
+ marker++;
+ } else if (marker > 0) {
+ return DECODE_ERROR;
+ } else {
+ p = strchr(base64_chars, token[i]);
+ if (p == NULL)
+ return DECODE_ERROR;
+ val += p - base64_chars;
+ }
+ }
+ if (marker > 2)
+ return DECODE_ERROR;
+ return (marker << 24) | val;
+}
+
+void *
+k5_base64_decode(const char *str, size_t *len_out)
+{
+ unsigned char *data, *q;
+ unsigned int val, marker;
+ size_t len;
+
+ *len_out = SIZE_MAX;
+
+ /* Allocate the output buffer. */
+ len = strlen(str);
+ if (len % 4)
+ return NULL;
+ q = data = malloc(len / 4 * 3);
+ if (data == NULL) {
+ *len_out = 0;
+ return NULL;
+ }
+
+ /* Decode the string. */
+ for (; *str != '\0'; str += 4) {
+ val = decode_token(str);
+ if (val == DECODE_ERROR) {
+ free(data);
+ return NULL;
+ }
+ marker = (val >> 24) & 0xff;
+ *q++ = (val >> 16) & 0xff;
+ if (marker < 2)
+ *q++ = (val >> 8) & 0xff;
+ if (marker < 1)
+ *q++ = val & 0xff;
+ }
+ *len_out = q - data;
+ return data;
+}
diff --git a/src/util/support/t_base64.c b/src/util/support/t_base64.c
new file mode 100644
index 0000000..3b1fd45
--- /dev/null
+++ b/src/util/support/t_base64.c
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* util/support/t_base64.c - base64 encoding and decoding tests */
+/*
+ * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <k5-platform.h>
+#include <k5-base64.h>
+
+static struct test {
+ void *data;
+ size_t len;
+ const char *result;
+} tests[] = {
+ { "", 0 , "" },
+ { "1", 1, "MQ==" },
+ { "22", 2, "MjI=" },
+ { "333", 3, "MzMz" },
+ { "4444", 4, "NDQ0NA==" },
+ { "55555", 5, "NTU1NTU=" },
+ { "abc:def", 7, "YWJjOmRlZg==" },
+ { "f", 1, "Zg==" },
+ { "fo", 2, "Zm8=" },
+ { "foo", 3, "Zm9v" },
+ { "foob", 4, "Zm9vYg==" },
+ { "fooba", 5, "Zm9vYmE=" },
+ { "foobar", 6, "Zm9vYmFy" },
+ { NULL, 0, NULL }
+};
+
+static char *negative_tests[] = {
+ "M=M=",
+ "MM=M",
+ "MQ===",
+ "====",
+ "M===",
+ NULL
+};
+
+int
+main(int argc, char **argv)
+{
+ char *str, **ntest;
+ void *data;
+ int numerr = 0, numtest = 1;
+ const struct test *t;
+ size_t len;
+
+ for (t = tests; t->data != NULL; t++) {
+ str = k5_base64_encode(t->data, t->len);
+ if (strcmp(str, t->result) != 0) {
+ fprintf(stderr, "failed test %d: %s != %s\n", numtest,
+ str, t->result);
+ numerr++;
+ }
+ free(str);
+ data = k5_base64_decode(t->result, &len);
+ if (len != t->len) {
+ fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+ (unsigned long)len, (unsigned long)t->len);
+ numerr++;
+ } else if (memcmp(data, t->data, t->len) != 0) {
+ fprintf(stderr, "failed test %d: data\n", numtest);
+ numerr++;
+ }
+ free(data);
+ numtest++;
+ }
+
+ for (ntest = negative_tests; *ntest != NULL; ntest++) {
+ data = k5_base64_decode(*ntest, &len);
+ if (data != NULL || len != SIZE_MAX) {
+ fprintf(stderr, "failed test %d: successful decode: %s\n",
+ numtest, *ntest);
+ numerr++;
+ }
+ numtest++;
+ }
+
+ return numerr ? 1 : 0;
+}
More information about the cvs-krb5
mailing list