summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base16-decode.c127
-rw-r--r--base16-encode.c54
-rw-r--r--base16-meta.c64
-rw-r--r--base16.h91
4 files changed, 336 insertions, 0 deletions
diff --git a/base16-decode.c b/base16-decode.c
new file mode 100644
index 00000000..a5e6185c
--- /dev/null
+++ b/base16-decode.c
@@ -0,0 +1,127 @@
+/* base16-encode.c
+ *
+ * Hex decoding.
+ */
+
+/* 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 "base16.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+void
+base16_decode_init(struct base16_decode_ctx *ctx)
+{
+ ctx->word = ctx->bits = 0;
+}
+
+enum { HEX_INVALID = -1, HEX_SPACE=-2 };
+
+static const signed char
+hex_decode_table[0x80] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+/* Decodes a single byte. Returns amount of output (0 or 1), or -1 on
+ * errors. */
+int
+base16_decode_single(struct base16_decode_ctx *ctx,
+ uint8_t *dst,
+ uint8_t src)
+{
+ int digit;
+
+ if (src >= 0x80)
+ return -1;
+
+ /* FIXME: This code could use more clever choices of constants. */
+ digit = hex_decode_table[src];
+ switch (digit)
+ {
+ case -1:
+ return -1;
+ case -2:
+ return 0;
+ default:
+ assert(digit >= 0);
+ assert(digit < 0x10);
+
+ if (ctx->bits)
+ {
+ *dst = (ctx->word << 4) | digit;
+ ctx->bits = 0;
+ return 1;
+ }
+ else
+ {
+ ctx->word = digit;
+ ctx->bits = 4;
+ return 0;
+ }
+ }
+}
+
+int
+base16_decode_update(struct base16_decode_ctx *ctx,
+ unsigned *dst_length,
+ uint8_t *dst,
+ unsigned src_length,
+ const uint8_t *src)
+{
+ unsigned done;
+ unsigned i;
+
+ assert(*dst_length >= BASE16_DECODE_LENGTH(src_length));
+
+ for (i = 0, done = 0; i<src_length; i++)
+ switch(base16_decode_single(ctx, dst + done, src[i]))
+ {
+ case -1:
+ return 0;
+ case 1:
+ done++;
+ /* Fall through */
+ case 0:
+ break;
+ default:
+ abort();
+ }
+
+ assert(done <= BASE16_DECODE_LENGTH(src_length));
+
+ *dst_length = done;
+ return 1;
+}
+
+int
+base16_decode_final(struct base16_decode_ctx *ctx)
+{
+ return ctx->bits == 0;
+}
diff --git a/base16-encode.c b/base16-encode.c
new file mode 100644
index 00000000..48ce3006
--- /dev/null
+++ b/base16-encode.c
@@ -0,0 +1,54 @@
+/* base16-encode.c
+ *
+ * Hex encoding.
+ */
+
+/* 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 "base16.h"
+
+
+static const uint8_t
+hex_digits[16] = "0123456789abcdef";
+
+#define DIGIT(x) (hex_digits[(x) & 0xf])
+
+/* FIXME: Is this really needed? */
+/* Encodes a single byte. Always stores two digits in dst[0] and dst[1]. */
+void
+base16_encode_single(uint8_t *dst,
+ uint8_t src)
+{
+ dst[0] = DIGIT(src/0x10);
+ dst[1] = DIGIT(src);
+}
+
+/* Always stores BASE16_ENCODE_LENGTH(length) digits in dst. */
+void
+base16_encode_update(uint8_t *dst,
+ unsigned length,
+ const uint8_t *src)
+{
+ unsigned i;
+
+ for (i = 0, dst; i<length; i++, dst += 2)
+ base16_encode_single(dst, src[i]);
+}
diff --git a/base16-meta.c b/base16-meta.c
new file mode 100644
index 00000000..ebfb7e25
--- /dev/null
+++ b/base16-meta.c
@@ -0,0 +1,64 @@
+/* base16-meta.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 "nettle-meta.h"
+
+#include "base16.h"
+
+/* Same as the macros with the same name */
+static unsigned
+base16_encode_length(unsigned length)
+{
+ return BASE16_ENCODE_LENGTH(length);
+}
+
+static unsigned
+base16_decode_length(unsigned length)
+{
+ return BASE16_DECODE_LENGTH(length);
+}
+
+static void
+base16_encode_init(void *ctx)
+{ (void) ctx; }
+
+static unsigned
+base16_encode_update_wrapper(void *ctx, uint8_t *dst,
+ unsigned length, const uint8_t *src)
+{
+ (void) ctx;
+
+ base16_encode_update(dst, length, src);
+ return BASE16_ENCODE_LENGTH(length);
+}
+
+#define base16_encode_update base16_encode_update_wrapper
+
+static unsigned
+base16_encode_final(void *ctx, uint8_t *dst)
+{ (void) ctx; (void) dst; return 0; }
+
+
+#define BASE16_ENCODE_FINAL_LENGTH 0
+
+const struct nettle_armor nettle_base16
+= _NETTLE_ARMOR_0(base16, BASE16);
diff --git a/base16.h b/base16.h
new file mode 100644
index 00000000..b00bc869
--- /dev/null
+++ b/base16.h
@@ -0,0 +1,91 @@
+/* base16.h
+ *
+ * Hex encoding and decoding, following spki conventions (i.e.
+ * allowing whitespace between digits).
+ */
+
+/* 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.
+ */
+
+#ifndef NETTLE_BASE16_H_INCLUDED
+#define NETTLE_BASE16_H_INCLUDED
+
+#include <inttypes.h>
+
+
+/* Base16 encoding */
+
+/* Maximum length of output for base16_encode_update. */
+#define BASE16_ENCODE_LENGTH(length) ((length) * 2)
+
+/* Encodes a single byte. Always stores two digits in dst[0] and dst[1]. */
+void
+base16_encode_single(uint8_t *dst,
+ uint8_t src);
+
+/* Always stores BASE16_ENCODE_LENGTH(length) digits in dst. */
+void
+base16_encode_update(uint8_t *dst,
+ unsigned length,
+ const uint8_t *src);
+
+
+/* Base16 decoding */
+
+/* Maximum length of output for base16_decode_update. */
+/* We have at most 4 buffered bits, and a total of (length + 1) * 4 bits. */
+#define BASE16_DECODE_LENGTH(length) (((length) + 1) / 2)
+
+struct base16_decode_ctx
+{
+ unsigned word; /* Leftover bits */
+ unsigned bits; /* Number buffered bits */
+};
+
+void
+base16_decode_init(struct base16_decode_ctx *ctx);
+
+/* Decodes a single byte. Returns amount of output (0 or 1), or -1 on
+ * errors. */
+int
+base16_decode_single(struct base16_decode_ctx *ctx,
+ uint8_t *dst,
+ uint8_t src);
+
+/* Returns 1 on success, 0 on error. DST should point to an area of
+ * size at least BASE16_DECODE_LENGTH(length), and for sanity
+ * checking, *DST_LENGTH should be initialized to the size of that
+ * area before the call. *DST_LENGTH is updated to the amount of
+ * decoded output. */
+
+/* FIXME: Currently results in an assertion failure if *DST_LENGTH is
+ * too small. Return some error instead? */
+int
+base16_decode_update(struct base16_decode_ctx *ctx,
+ unsigned *dst_length,
+ uint8_t *dst,
+ unsigned src_length,
+ const uint8_t *src);
+
+/* Returns 1 on success. */
+int
+base16_decode_final(struct base16_decode_ctx *ctx);
+
+#endif /* NETTLE_BASE16_H_INCLUDED */