summaryrefslogtreecommitdiff
path: root/base64-encode.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2002-10-19 12:40:11 +0200
committerNiels Möller <nisse@lysator.liu.se>2002-10-19 12:40:11 +0200
commitd4b94159dcab0ed788ce29cc89a67329307c5d68 (patch)
treec8ba1820e9b4420a1394e96d52266f426f166ba6 /base64-encode.c
parentf44a94847480df131a1dfc83ed2d2fc9063a4145 (diff)
downloadnettle-d4b94159dcab0ed788ce29cc89a67329307c5d68.tar.gz
* base64-encode.c: New file. New supporting both encode-at-once
and streamed operation. * base64-decode.c: New file. Rev: src/nettle/base64-decode.c:1.1 Rev: src/nettle/base64-encode.c:1.1
Diffstat (limited to 'base64-encode.c')
-rw-r--r--base64-encode.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/base64-encode.c b/base64-encode.c
new file mode 100644
index 00000000..13b62526
--- /dev/null
+++ b/base64-encode.c
@@ -0,0 +1,226 @@
+/* base64-encode.c
+ *
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2002 Niels Möller
+ *
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#include "base64.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+
+static const uint8_t encode_table[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+#define ENCODE(x) (encode_table[0x3F & (x)])
+
+void
+base64_encode_raw(uint8_t *dst, unsigned length, const uint8_t *src)
+{
+ const uint8_t *in = src + length;;
+ uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
+
+ unsigned left_over = length % 3;
+
+ if (left_over)
+ {
+ in -= left_over;
+ *--out = '=';
+ switch(left_over)
+ {
+ case 1:
+ *--out = '=';
+ *--out = ENCODE(in[0] << 4);
+ break;
+
+ case 2:
+ *--out = ENCODE( in[1] << 2);
+ *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
+ break;
+
+ default:
+ abort();
+ }
+ *--out = ENCODE(in[0] >> 2);
+ }
+
+ while (in > src)
+ {
+ in -= 3;
+ *--out = ENCODE( in[2]);
+ *--out = ENCODE((in[1] << 2) | (in[2] >> 6));
+ *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
+ *--out = ENCODE( in[0] >> 2);
+ }
+ assert(in == src);
+ assert(out == dst);
+}
+
+#if 0
+unsigned
+base64_encode(uint8_t *dst,
+ unsigned src_length,
+ const uint8_t *src)
+{
+ unsigned dst_length = BASE64_ENCODE_RAW_LENGTH(src_length);
+ unsigned n = src_length / 3;
+ unsigned left_over = src_length % 3;
+ unsigned done = 0;
+
+ if (left_over)
+ {
+ const uint8_t *in = src + n * 3;
+ uint8_t *out = dst + dst_length;
+
+ switch(left_over)
+ {
+ case 1:
+ *--out = '=';
+ *--out = ENCODE(in[0] << 4);
+ break;
+
+ case 2:
+ *--out = ENCODE( in[1] << 2);
+ *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
+ break;
+
+ default:
+ abort();
+ }
+ *--out = ENCODE(in[0] >> 2);
+
+ done = 4;
+ }
+ base64_encode_raw(n, dst, src);
+ done += n * 4;
+
+ assert(done == dst_length);
+
+ return done;
+}
+#endif
+
+void
+base64_encode_group(uint8_t *dst, uint32_t group)
+{
+ *dst++ = ENCODE(group >> 18);
+ *dst++ = ENCODE(group >> 12);
+ *dst++ = ENCODE(group >> 6);
+ *dst++ = ENCODE(group);
+}
+
+void
+base64_encode_init(struct base64_encode_ctx *ctx)
+{
+ ctx->word = ctx->bits = 0;
+}
+
+/* Encodes a single byte. */
+unsigned
+base64_encode_single(struct base64_encode_ctx *ctx,
+ uint8_t *dst,
+ uint8_t src)
+{
+ unsigned done = 0;
+ unsigned word = ctx->word << 8 | src;
+ unsigned bits = ctx->bits + 8;
+
+ while (bits >= 6)
+ {
+ bits -= 6;
+ dst[done++] = ENCODE(word >> bits);
+ }
+
+ ctx->bits = bits;
+ ctx->word = word;
+
+ assert(done <= 2);
+
+ return done;
+}
+
+/* Returns the number of output characters. DST should point to an
+ * area of size at least BASE64_ENCODE_LENGTH(length). */
+unsigned
+base64_encode_update(struct base64_encode_ctx *ctx,
+ uint8_t *dst,
+ unsigned length,
+ const uint8_t *src)
+{
+ unsigned done = 0;
+ unsigned left = length;
+ unsigned left_over;
+ unsigned bulk;
+
+ while (ctx->bits && left)
+ {
+ left--;
+ done += base64_encode_single(ctx, dst + done, *src++);
+ }
+
+ left_over = left % 3;
+ bulk = left - left_over;
+
+ if (bulk)
+ {
+ assert(!(bulk % 3));
+
+ base64_encode_raw(dst + done, bulk, src);
+ done += BASE64_ENCODE_RAW_LENGTH(bulk);
+ src += bulk;
+ left = left_over;
+ }
+
+ while (left)
+ {
+ left--;
+ done += base64_encode_single(ctx, dst + done, *src++);
+ }
+
+ assert(done <= BASE64_ENCODE_LENGTH(length));
+
+ return done;
+}
+
+/* DST should point to an area of size at least
+ * BASE64_ENCODE_FINAL_SIZE */
+unsigned
+base64_encode_final(struct base64_encode_ctx *ctx,
+ uint8_t *dst)
+{
+ unsigned done = 0;
+ unsigned bits = ctx->bits;
+
+ if (bits)
+ {
+ dst[done++] = ENCODE(ctx->word << (6 - ctx->bits));
+ for (; bits < 6; bits += 2)
+ dst[done++] = '=';
+
+ ctx->bits = 0;
+ }
+
+ assert(done <= BASE64_ENCODE_FINAL_LENGTH);
+ return done;
+}