-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

RFC 4648 (https://tools.ietf.org/html/rfc4648) standardizes two
Base-64 alphabets. Nettle currently only supports the traditional
base-64 alphabet from section 4.

There is growing use amongst new protocol definitions and extensions,
particularly in the HTTP area for the URL-safe extension alphabet
instead of the classical Base-64 alphabet.


The attached patch implements a proposed API/ABI extension adding
support for RFC 4648 section 5 "Base 64 Encoding with URL and Filename
Safe Alphabet"

External code simply calls the init() function relevant to the
alphabet it is needing to encode/decode with. The library internally
uses the context to select which lookup table to use for later base64
function calls.

The base64_encode_raw() and base64_encode_group() functions which do
not use contexts are left untouched for now.


Amos Jeffries
Treehouse Networks Ltd.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQEcBAEBAgAGBQJUiXerAAoJELJo5wb/XPRjPxEIAJGMXNF0H84kJntKpe1idimr
+x7/xg55GJ2sWEBAbVIHvKvjFZoBIeqNmPeeK+yrqMdA+dtALA37AuezqhiNBtuj
YfGd/DyRvys2O2bQ4XNRHxj6zGQU6tlRHHZzSnWp9ywwN4xk/zfNc5JM0EKYqiuu
8crNPzQxP91N33gkdi9LrOkAA8v+/bTYJgTrT46D/2Ut+8ECAcpjS5jwsJiljETu
uqO50QlhqGC3ZsHKs1kYnjrbl1Peiqw/b/srEnY3shfS9MKrTYe3qLOsvU5CQpnD
A7e8w/SW716D0s4t0SGf85WvUnS6UvDTfAdm3EXAPKNU8PaYpK9D8izq8kgxCP4=
=NgGG
-----END PGP SIGNATURE-----
diff --git a/base64-decode.c b/base64-decode.c
index f622baa..fbaf54f 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, 
@@ -64,10 +64,40 @@ decode_table[0x100] =
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
+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
 base64_decode_init(struct base64_decode_ctx *ctx)
 {
   ctx->word = ctx->bits = ctx->padding = 0;
+  ctx->alphabet = BASE64_ALPHABET;
+}
+
+void
+base64url_decode_init(struct base64_decode_ctx *ctx)
+{
+  ctx->word = ctx->bits = ctx->padding = 0;
+  ctx->alphabet = BASE64URL_ALPHABET;
 }
 
 int
@@ -76,8 +106,11 @@ base64_decode_single(struct base64_decode_ctx *ctx,
                     uint8_t src)
 {
   int data;
-  
-  data = decode_table[src];
+
+  if (ctx->alphabet == BASE64URL_ALPHABET)
+    data = urlextended_decode_table[src];
+  else
+    data = default_decode_table[src];
 
   switch(data)
     {
diff --git a/base64-encode.c b/base64-encode.c
index 313c512..fcf8546 100644
--- a/base64-encode.c
+++ b/base64-encode.c
@@ -38,11 +38,16 @@
 
 #include "base64.h"
 
-static const uint8_t encode_table[64] =
+static const uint8_t default_encode_table[64] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   "abcdefghijklmnopqrstuvwxyz"
   "0123456789+/";
 
+static const uint8_t urlextended_encode_table[64] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+  "abcdefghijklmnopqrstuvwxyz"
+  "0123456789-_";
+
 #define ENCODE(x) (encode_table[0x3F & (x)])
 
 void
@@ -52,6 +57,7 @@ base64_encode_raw(uint8_t *dst, size_t length, const uint8_t 
*src)
   uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
 
   unsigned left_over = length % 3;
+  const uint8_t *encode_table = default_encode_table;
 
   if (left_over)
     {
@@ -97,6 +103,7 @@ base64_encode(uint8_t *dst,
   unsigned n = src_length / 3;
   unsigned left_over  = src_length % 3;
   unsigned done = 0;
+  const uint8_t *encode_table = default_encode_table;
   
   if (left_over)
     {
@@ -134,6 +141,7 @@ base64_encode(uint8_t *dst,
 void
 base64_encode_group(uint8_t *dst, uint32_t group)
 {
+  const uint8_t *encode_table = default_encode_table;
   *dst++ = ENCODE(group >> 18);
   *dst++ = ENCODE(group >> 12);
   *dst++ = ENCODE(group >> 6);
@@ -144,6 +152,14 @@ void
 base64_encode_init(struct base64_encode_ctx *ctx)
 {
   ctx->word = ctx->bits = 0;
+  ctx->alphabet = BASE64_ALPHABET;
+}
+
+void
+base64url_encode_init(struct base64_encode_ctx *ctx)
+{
+  ctx->word = ctx->bits = 0;
+  ctx->alphabet = BASE64URL_ALPHABET;
 }
 
 /* Encodes a single byte. */
@@ -155,6 +171,7 @@ base64_encode_single(struct base64_encode_ctx *ctx,
   unsigned done = 0;
   unsigned word = ctx->word << 8 | src;
   unsigned bits = ctx->bits + 8;
+  const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ? 
urlextended_encode_table : default_encode_table);
   
   while (bits >= 6)
     {
@@ -182,6 +199,7 @@ base64_encode_update(struct base64_encode_ctx *ctx,
   size_t left = length;
   unsigned left_over;
   size_t bulk;
+  const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ? 
urlextended_encode_table : default_encode_table);
   
   while (ctx->bits && left)
     {
@@ -221,6 +239,7 @@ base64_encode_final(struct base64_encode_ctx *ctx,
 {
   unsigned done = 0;
   unsigned bits = ctx->bits;
+  const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ? 
urlextended_encode_table : default_encode_table);
   
   if (bits)
     {
diff --git a/base64.h b/base64.h
index a6fb823..4f6d5e3 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
@@ -55,6 +57,10 @@ extern "C" {
 #define BASE64_BINARY_BLOCK_SIZE 3
 #define BASE64_TEXT_BLOCK_SIZE 4
 
+/* which alphabet to use */
+#define BASE64_ALPHABET 0
+#define BASE64URL_ALPHABET 1
+
 /* Base64 encoding */
 
 /* Maximum length of output for base64_encode_update. NOTE: Doesn't
@@ -73,11 +79,17 @@ struct base64_encode_ctx
 {
   unsigned word;   /* Leftover bits */
   unsigned bits;  /* Number of bits, always 0, 2, or 4. */
+  unsigned 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 +135,17 @@ struct base64_decode_ctx
 
   /* Number of padding characters encountered */
   unsigned padding;
+  unsigned 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
_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to