new file mode 100644
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * base64 encoding, lifted from fs/crypto/fname.c.
+ */
+
+#ifndef _LINUX_BASE64_H
+#define _LINUX_BASE64_H
+
+#include <linux/types.h>
+
+#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
+
+int base64_encode(const u8 *src, int len, char *dst);
+int base64_decode(const char *src, int len, u8 *dst);
+
+#endif /* _LINUX_BASE64_H */
@@ -46,7 +46,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
list_sort.o uuid.o iov_iter.o clz_ctz.o \
bsearch.o find_bit.o llist.o memweight.o kfifo.o \
- percpu-refcount.o rhashtable.o \
+ percpu-refcount.o rhashtable.o base64.o \
once.o refcount.o usercopy.o errseq.o bucket_locks.o \
generic-radix-tree.o
obj-$(CONFIG_STRING_SELFTEST) += test_string.o
new file mode 100644
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * base64.c - RFC4648-compliant base64 encoding
+ *
+ * Copyright (c) 2020 Hannes Reinecke, SUSE
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/base64.h>
+
+static const char lookup_table[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * base64_encode() - base64-encode some bytes
+ * @src: the bytes to encode
+ * @len: number of bytes to encode
+ * @dst: (output) the base64-encoded string. Not NUL-terminated.
+ *
+ * Encodes the input string using characters from the set [A-Za-z0-9+,].
+ * The encoded string is roughly 4/3 times the size of the input string.
+ *
+ * Return: length of the encoded string
+ */
+int base64_encode(const u8 *src, int len, char *dst)
+{
+ int i, bits = 0;
+ u32 ac = 0;
+ char *cp = dst;
+
+ for (i = 0; i < len; i++) {
+ ac = (ac << 8) | src[i];
+ bits += 8;
+ if (bits < 24)
+ continue;
+ do {
+ bits -= 6;
+ *cp++ = lookup_table[(ac >> bits) & 0x3f];
+ } while (bits);
+ ac = 0;
+ }
+ if (bits) {
+ int more = 0;
+
+ if (bits < 16)
+ more = 2;
+ ac = (ac << (2 + more));
+ bits += (2 + more);
+ do {
+ bits -= 6;
+ *cp++ = lookup_table[(ac >> bits) & 0x3f];
+ } while (bits);
+ *cp++ = '=';
+ if (more)
+ *cp++ = '=';
+ }
+
+ return cp - dst;
+}
+EXPORT_SYMBOL_GPL(base64_encode);
+
+/**
+ * base64_decode() - base64-decode some bytes
+ * @src: the base64-encoded string to decode
+ * @len: number of bytes to decode
+ * @dst: (output) the decoded bytes.
+ *
+ * Decodes the base64-encoded bytes @src according to RFC 4648.
+ *
+ * Return: number of decoded bytes
+ */
+int base64_decode(const char *src, int len, u8 *dst)
+{
+ int i, bits = 0, pad = 0;
+ u32 ac = 0;
+ size_t dst_len = 0;
+
+ for (i = 0; i < len; i++) {
+ int c, p = -1;
+
+ if (src[i] == '=') {
+ pad++;
+ if (i + 1 < len && src[i + 1] == '=')
+ pad++;
+ break;
+ }
+ for (c = 0; c < strlen(lookup_table); c++) {
+ if (src[i] == lookup_table[c]) {
+ p = c;
+ break;
+ }
+ }
+ if (p < 0)
+ break;
+ ac = (ac << 6) | p;
+ bits += 6;
+ if (bits < 24)
+ continue;
+ while (bits) {
+ bits -= 8;
+ dst[dst_len++] = (ac >> bits) & 0xff;
+ }
+ ac = 0;
+ }
+ dst_len -= pad;
+ return dst_len;
+}
+EXPORT_SYMBOL_GPL(base64_decode);
Add RFC4648-compliant base64 encoding and decoding routines. Signed-off-by: Hannes Reinecke <hare@suse.de> --- include/linux/base64.h | 16 ++++++ lib/Makefile | 2 +- lib/base64.c | 111 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 include/linux/base64.h create mode 100644 lib/base64.c