Skip to content

Commit a116e1c

Browse files
hreineckeaxboe
authored andcommitted
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 <[email protected]> Reviewed-by: Himanshu Madhani <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Cc: Eric Biggers <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 9e2f284 commit a116e1c

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

include/linux/base64.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 */

lib/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
4646
bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
4747
list_sort.o uuid.o iov_iter.o clz_ctz.o \
4848
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 \
5050
once.o refcount.o usercopy.o errseq.o bucket_locks.o \
5151
generic-radix-tree.o
5252
obj-$(CONFIG_STRING_SELFTEST) += test_string.o

lib/base64.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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);

0 commit comments

Comments
 (0)