summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2023-10-23 16:31:21 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2023-11-01 10:09:19 +0100
commitfc609f75f9c89f098a772ed47184c3bdf086c19d (patch)
tree7b56a4452aebaa521848af79e7b392a20a5e9f74 /lib
parent066a6b11456547471e5b1f949b3e9ca0865d79f6 (diff)
downloadbarebox-fc609f75f9c89f098a772ed47184c3bdf086c19d.tar.gz
barebox-fc609f75f9c89f098a772ed47184c3bdf086c19d.tar.xz
lib: base64: add support for base64url
base64url has some small differences to our current base64 implementation: - Instead of encoding to `+', `-' is used - Instead of encoding to `/', `_' is used - Padding with = to reach four byte boundary is optional - Invalid characters aren't silently skipped Everything else is the same though, so let's reuse the code and have an optional url bool parameter control whether to decode base64 or base64url. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20231023143122.1760217-2-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/base64.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/lib/base64.c b/lib/base64.c
index ac165ab168..d5ab217528 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -25,6 +25,25 @@ static const char uuenc_tbl_base64[65 + 1] = {
'\0' /* needed for uudecode.c only */
};
+static char base64_trchr(char ch, bool url)
+{
+ if (!url)
+ return ch;
+
+ switch (ch) {
+ case '+':
+ return '-';
+ case '/':
+ return '_';
+ case '-':
+ return '+';
+ case '_':
+ return '/';
+ default:
+ return ch;
+ }
+}
+
/*
* Encode bytes at S of length LENGTH to uuencode or base64 format and place it
* to STORE. STORE will be 0-terminated, and must point to a writable
@@ -68,13 +87,14 @@ EXPORT_SYMBOL(uuencode);
* Decode base64 encoded string. Stops on '\0'.
*
*/
-int decode_base64(char *p_dst, int dst_len, const char *src)
+static int __decode_base64(char *p_dst, int dst_len, const char *src, bool url)
{
const char *src_tail;
char *dst = p_dst;
int length = 0;
+ bool end_reached = false;
- while (dst_len > 0) {
+ while (dst_len > 0 && !end_reached) {
unsigned char six_bit[4];
int count = 0;
@@ -101,13 +121,23 @@ int decode_base64(char *p_dst, int dst_len, const char *src)
* because we did fully decode
* the string (to "ABC").
*/
- if (count == 0)
+ if (count == 0) {
src_tail = src;
+ } else if (url) {
+ end_reached = true;
+ goto out;
+ }
+
goto ret;
}
src++;
- table_ptr = strchr(uuenc_tbl_base64, ch);
- } while (!table_ptr);
+ table_ptr = strchr(uuenc_tbl_base64, base64_trchr(ch, url));
+ } while (!table_ptr && !url);
+
+ if (!table_ptr) {
+ end_reached = true;
+ goto out;
+ }
/* Convert encoded character to decimal */
ch = table_ptr - uuenc_tbl_base64;
@@ -119,6 +149,7 @@ int decode_base64(char *p_dst, int dst_len, const char *src)
six_bit[count] = ch;
count++;
}
+out:
/*
* Transform 6-bit values to 8-bit ones.
@@ -151,4 +182,23 @@ ret:
return length;
}
+
+/*
+ * Decode base64 encoded string. Stops on '\0'.
+ *
+ */
+int decode_base64(char *p_dst, int dst_len, const char *src)
+{
+ return __decode_base64(p_dst, dst_len, src, false);
+}
EXPORT_SYMBOL(decode_base64);
+
+/*
+ * Decode base64url encoded string. Stops on '\0'.
+ *
+ */
+int decode_base64url(char *p_dst, int dst_len, const char *src)
+{
+ return __decode_base64(p_dst, dst_len, src, true);
+}
+EXPORT_SYMBOL(decode_base64url);