Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/base64: RFC4648-compliant base64 encoding

Add RFC4648-compliant base64 encoding and decoding routines, based on
the base64url encoding in fs/crypto/fname.c.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Cc: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Hannes Reinecke and committed by
Jens Axboe
a116e1cd 9e2f284e

+120 -1
+16
include/linux/base64.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * base64 encoding, lifted from fs/crypto/fname.c. 4 + */ 5 + 6 + #ifndef _LINUX_BASE64_H 7 + #define _LINUX_BASE64_H 8 + 9 + #include <linux/types.h> 10 + 11 + #define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) 12 + 13 + int base64_encode(const u8 *src, int len, char *dst); 14 + int base64_decode(const char *src, int len, u8 *dst); 15 + 16 + #endif /* _LINUX_BASE64_H */
+1 -1
lib/Makefile
··· 46 46 bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ 47 47 list_sort.o uuid.o iov_iter.o clz_ctz.o \ 48 48 bsearch.o find_bit.o llist.o memweight.o kfifo.o \ 49 - percpu-refcount.o rhashtable.o \ 49 + percpu-refcount.o rhashtable.o base64.o \ 50 50 once.o refcount.o usercopy.o errseq.o bucket_locks.o \ 51 51 generic-radix-tree.o 52 52 obj-$(CONFIG_STRING_SELFTEST) += test_string.o
+103
lib/base64.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * base64.c - RFC4648-compliant base64 encoding 4 + * 5 + * Copyright (c) 2020 Hannes Reinecke, SUSE 6 + * 7 + * Based on the base64url routines from fs/crypto/fname.c 8 + * (which are using the URL-safe base64 encoding), 9 + * modified to use the standard coding table from RFC4648 section 4. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/types.h> 14 + #include <linux/export.h> 15 + #include <linux/string.h> 16 + #include <linux/base64.h> 17 + 18 + static const char base64_table[65] = 19 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 20 + 21 + /** 22 + * base64_encode() - base64-encode some binary data 23 + * @src: the binary data to encode 24 + * @srclen: the length of @src in bytes 25 + * @dst: (output) the base64-encoded string. Not NUL-terminated. 26 + * 27 + * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specified 28 + * by RFC 4648, including the '='-padding. 29 + * 30 + * Return: the length of the resulting base64-encoded string in bytes. 31 + */ 32 + int base64_encode(const u8 *src, int srclen, char *dst) 33 + { 34 + u32 ac = 0; 35 + int bits = 0; 36 + int i; 37 + char *cp = dst; 38 + 39 + for (i = 0; i < srclen; i++) { 40 + ac = (ac << 8) | src[i]; 41 + bits += 8; 42 + do { 43 + bits -= 6; 44 + *cp++ = base64_table[(ac >> bits) & 0x3f]; 45 + } while (bits >= 6); 46 + } 47 + if (bits) { 48 + *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; 49 + bits -= 6; 50 + } 51 + while (bits < 0) { 52 + *cp++ = '='; 53 + bits += 2; 54 + } 55 + return cp - dst; 56 + } 57 + EXPORT_SYMBOL_GPL(base64_encode); 58 + 59 + /** 60 + * base64_decode() - base64-decode a string 61 + * @src: the string to decode. Doesn't need to be NUL-terminated. 62 + * @srclen: the length of @src in bytes 63 + * @dst: (output) the decoded binary data 64 + * 65 + * Decodes a string using base64 encoding, i.e. the "Base 64 Encoding" 66 + * specified by RFC 4648, including the '='-padding. 67 + * 68 + * This implementation hasn't been optimized for performance. 69 + * 70 + * Return: the length of the resulting decoded binary data in bytes, 71 + * or -1 if the string isn't a valid base64 string. 72 + */ 73 + int base64_decode(const char *src, int srclen, u8 *dst) 74 + { 75 + u32 ac = 0; 76 + int bits = 0; 77 + int i; 78 + u8 *bp = dst; 79 + 80 + for (i = 0; i < srclen; i++) { 81 + const char *p = strchr(base64_table, src[i]); 82 + 83 + if (src[i] == '=') { 84 + ac = (ac << 6); 85 + bits += 6; 86 + if (bits >= 8) 87 + bits -= 8; 88 + continue; 89 + } 90 + if (p == NULL || src[i] == 0) 91 + return -1; 92 + ac = (ac << 6) | (p - base64_table); 93 + bits += 6; 94 + if (bits >= 8) { 95 + bits -= 8; 96 + *bp++ = (u8)(ac >> bits); 97 + } 98 + } 99 + if (ac & ((1 << bits) - 1)) 100 + return -1; 101 + return bp - dst; 102 + } 103 + EXPORT_SYMBOL_GPL(base64_decode);