diff --git a/Makefile.in b/Makefile.in index 2a940f9..48cce47 100644 --- a/Makefile.in +++ b/Makefile.in @@ -81,6 +81,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ arctwo.c arctwo-meta.c blowfish.c \ base16-encode.c base16-decode.c base16-meta.c \ base64-encode.c base64-decode.c base64-meta.c \ + base64url-encode.c base64url-decode.c \ buffer.c buffer-init.c \ camellia-crypt-internal.c camellia-table.c \ camellia-absorb.c camellia-invert-key.c \ diff --git a/base64-decode.c b/base64-decode.c index f622baa..69a1133 100644 --- a/base64-decode.c +++ b/base64-decode.c @@ -43,7 +43,7 @@ #define TABLE_END -3 static const signed char -decode_table[0x100] = +default_decode_table[0x100] = { /* White space is HT, VT, FF, CR, LF and SPC */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, @@ -68,6 +68,7 @@ void base64_decode_init(struct base64_decode_ctx *ctx) { ctx->word = ctx->bits = ctx->padding = 0; + ctx->alphabet = default_decode_table; } int @@ -76,8 +77,7 @@ base64_decode_single(struct base64_decode_ctx *ctx, uint8_t src) { int data; - - data = decode_table[src]; + data = ctx->alphabet[src]; switch(data) { diff --git a/base64-encode.c b/base64-encode.c index 313c512..2bc2908 100644 --- a/base64-encode.c +++ b/base64-encode.c @@ -38,16 +38,24 @@ #include "base64.h" -static const uint8_t encode_table[64] = +static const uint8_t default_encode_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -#define ENCODE(x) (encode_table[0x3F & (x)]) +#define ENCODE(x) (ctx->alphabet[0x3F & (x)]) void base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *src) { + struct base64_encode_ctx ctx; + base64_encode_init(&ctx); + _base64_encode_raw(&cxt, dst, length, src); +} + +static void +_base64_encode_raw(struct base64_encode_ctx *ctx, uint8_t *dst, size_t length, const uint8_t *src) +{ const uint8_t *in = src + length; uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length); @@ -87,53 +95,12 @@ base64_encode_raw(uint8_t *dst, size_t length, const uint8_t *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) { + struct base64_encode ctx; + base64_encode_init(&ctx); + *dst++ = ENCODE(group >> 18); *dst++ = ENCODE(group >> 12); *dst++ = ENCODE(group >> 6); @@ -144,6 +111,7 @@ void base64_encode_init(struct base64_encode_ctx *ctx) { ctx->word = ctx->bits = 0; + ctx->alphabet = default_encode_table; } /* Encodes a single byte. */ @@ -196,7 +164,7 @@ base64_encode_update(struct base64_encode_ctx *ctx, { assert(!(bulk % 3)); - base64_encode_raw(dst + done, bulk, src); + _base64_encode_raw(ctx, dst + done, bulk, src); done += BASE64_ENCODE_RAW_LENGTH(bulk); src += bulk; left = left_over; diff --git a/base64.h b/base64.h index a6fb823..21381d2 100644 --- a/base64.h +++ b/base64.h @@ -42,12 +42,14 @@ extern "C" { /* Name mangling */ #define base64_encode_init nettle_base64_encode_init +#define base64url_encode_init nettle_base64url_encode_init #define base64_encode_single nettle_base64_encode_single #define base64_encode_update nettle_base64_encode_update #define base64_encode_final nettle_base64_encode_final #define base64_encode_raw nettle_base64_encode_raw #define base64_encode_group nettle_base64_encode_group #define base64_decode_init nettle_base64_decode_init +#define base64url_decode_init nettle_base64url_decode_init #define base64_decode_single nettle_base64_decode_single #define base64_decode_update nettle_base64_decode_update #define base64_decode_final nettle_base64_decode_final @@ -73,11 +75,17 @@ struct base64_encode_ctx { unsigned word; /* Leftover bits */ unsigned bits; /* Number of bits, always 0, 2, or 4. */ + const uint8_t *alphabet; /* which alphabet to use for encoding */ }; +/* initialize encoding context for base-64 */ void base64_encode_init(struct base64_encode_ctx *ctx); +/* initialize encoding context for base-64 with URL safe extended alphabet */ +void +base64url_encode_init(struct base64_encode_ctx *ctx); + /* Encodes a single byte. Returns amount of output (always 1 or 2). */ size_t base64_encode_single(struct base64_encode_ctx *ctx, @@ -123,11 +131,17 @@ struct base64_decode_ctx /* Number of padding characters encountered */ unsigned padding; + const signed char *alphabet; /* which alphabet to use for encoding */ }; +/* initialize encoding context for base-64 */ void base64_decode_init(struct base64_decode_ctx *ctx); +/* initialize encoding context for base-64 with URL safe extended alphabet */ +void +base64url_decode_init(struct base64_decode_ctx *ctx); + /* Decodes a single byte. Returns amount of output (0 or 1), or -1 on * errors. */ int diff --git a/base64url-decode.c b/base64url-decode.c index e69de29..5b1a802 100644 --- a/base64url-decode.c +++ b/base64url-decode.c @@ -0,0 +1,65 @@ +/* base64url-decode.c + + Copyright (C) 2015 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "base64.h" + +static const signed char +urlextended_decode_table[0x100] = +{ + /* White space is HT, VT, FF, CR, LF and SPC */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -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, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -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, -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, -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, -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, -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, -1, -1, -1, +}; + +void +base64url_decode_init(struct base64_decode_ctx *ctx) +{ + ctx->word = ctx->bits = ctx->padding = 0; + ctx->alphabet = urlextended_decode_table; +} diff --git a/base64url-encode.c b/base64url-encode.c index e69de29..1f1eab7 100644 --- a/base64url-encode.c +++ b/base64url-encode.c @@ -0,0 +1,48 @@ +/* base64url-encode.c + + Copyright (C) 2015 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle 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 + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "base64.h" + +static const uint8_t urlextended_encode_table[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789-_"; + +void +base64url_encode_init(struct base64_encode_ctx *ctx) +{ + ctx->word = ctx->bits = 0; + ctx->alphabet = urlextended_encode_table; +}