From 630de7b78ded22aee0dcea431088b9bd02aa7279 Mon Sep 17 00:00:00 2001 From: Sebastian Reimers Date: Sun, 7 Aug 2022 10:55:57 +0200 Subject: [PATCH] base64: Encoding/Decoding with URL and Filename Safe Alphabet --- include/re_base64.h | 1 + src/base64/b64.c | 85 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/include/re_base64.h b/include/re_base64.h index dce768263..8ab074cfa 100644 --- a/include/re_base64.h +++ b/include/re_base64.h @@ -6,5 +6,6 @@ int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen); +int base64url_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen); int base64_print(struct re_printf *pf, const uint8_t *ptr, size_t len); int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen); diff --git a/src/base64/b64.c b/src/base64/b64.c index a2358754b..7285dc6c8 100644 --- a/src/base64/b64.c +++ b/src/base64/b64.c @@ -13,6 +13,12 @@ static const char b64_table[65] = "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; +/* Base 64 Encoding with URL and Filename Safe Alphabet, RFC 4648 section 5 */ +static const char b64url_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789-_"; + /** * Base-64 encode a buffer @@ -53,10 +59,63 @@ int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen) ++pad; } - *out++ = b64_table[v>>18 & 0x3f]; - *out++ = b64_table[v>>12 & 0x3f]; - *out++ = (pad >= 2) ? '=' : b64_table[v>>6 & 0x3f]; - *out++ = (pad >= 1) ? '=' : b64_table[v>>0 & 0x3f]; + *out++ = b64_table[v >> 18 & 0x3f]; + *out++ = b64_table[v >> 12 & 0x3f]; + *out++ = (pad >= 2) ? '=' : b64_table[v >> 6 & 0x3f]; + *out++ = (pad >= 1) ? '=' : b64_table[v >> 0 & 0x3f]; + } + + *olen = out - o; + + return 0; +} + + +/** + * Base-64 url encode a buffer (without padding) + * + * @param in Input buffer + * @param ilen Length of input buffer + * @param out Output buffer + * @param olen Size of output buffer, actual written on return + * + * @return 0 if success, otherwise errorcode + */ +int base64url_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen) +{ + const uint8_t *in_end = in + ilen; + const char *o = out; + + if (!in || !out || !olen) + return EINVAL; + + if (*olen < 4 * ((ilen+2)/3)) + return EOVERFLOW; + + for (; in < in_end; ) { + uint32_t v; + int pad = 0; + + v = *in++ << 16; + if (in < in_end) { + v |= *in++ << 8; + } + else { + ++pad; + } + if (in < in_end) { + v |= *in++ << 0; + } + else { + ++pad; + } + + *out++ = b64url_table[v >> 18 & 0x3f]; + *out++ = b64url_table[v >> 12 & 0x3f]; + if (pad < 2) + *out++ = b64url_table[v >> 6 & 0x3f]; + if (pad < 1) + *out++ = b64url_table[v >> 0 & 0x3f]; } *olen = out - o; @@ -103,9 +162,9 @@ static inline uint32_t b64val(char c) return c - 'a' + 26; else if ('0' <= c && c <= '9') return c - '0' + 52; - else if ('+' == c) + else if ('+' == c || '-' == c) return 62; - else if ('/' == c) + else if ('/' == c || '_' == c) return 63; else if ('=' == c) return 1<<24; /* special trick */ @@ -135,13 +194,21 @@ int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen) if (*olen < 3 * (ilen/4)) return EOVERFLOW; - for (;in+3 < in_end; ) { + for (;in+1 < in_end; ) { uint32_t v; v = b64val(*in++) << 18; v |= b64val(*in++) << 12; - v |= b64val(*in++) << 6; - v |= b64val(*in++) << 0; + + if (in < in_end) + v |= b64val(*in++) << 6; + else + v |= (1<<24) << 6; /* padding fallback */ + + if (in < in_end) + v |= b64val(*in++) << 0; + else + v |= (1<<24) << 0; /* padding fallback */ *out++ = v>>16; if (!(v & (1<<30)))