diff options
Diffstat (limited to 'lib/base64.c')
| -rw-r--r-- | lib/base64.c | 103 | 
1 files changed, 103 insertions, 0 deletions
diff --git a/lib/base64.c b/lib/base64.c new file mode 100644 index 000000000000..b736a7a431c5 --- /dev/null +++ b/lib/base64.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * base64.c - RFC4648-compliant base64 encoding + * + * Copyright (c) 2020 Hannes Reinecke, SUSE + * + * Based on the base64url routines from fs/crypto/fname.c + * (which are using the URL-safe base64 encoding), + * modified to use the standard coding table from RFC4648 section 4. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/export.h> +#include <linux/string.h> +#include <linux/base64.h> + +static const char base64_table[65] = +	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * base64_encode() - base64-encode some binary data + * @src: the binary data to encode + * @srclen: the length of @src in bytes + * @dst: (output) the base64-encoded string.  Not NUL-terminated. + * + * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specified + * by RFC 4648, including the  '='-padding. + * + * Return: the length of the resulting base64-encoded string in bytes. + */ +int base64_encode(const u8 *src, int srclen, char *dst) +{ +	u32 ac = 0; +	int bits = 0; +	int i; +	char *cp = dst; + +	for (i = 0; i < srclen; i++) { +		ac = (ac << 8) | src[i]; +		bits += 8; +		do { +			bits -= 6; +			*cp++ = base64_table[(ac >> bits) & 0x3f]; +		} while (bits >= 6); +	} +	if (bits) { +		*cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; +		bits -= 6; +	} +	while (bits < 0) { +		*cp++ = '='; +		bits += 2; +	} +	return cp - dst; +} +EXPORT_SYMBOL_GPL(base64_encode); + +/** + * base64_decode() - base64-decode a string + * @src: the string to decode.  Doesn't need to be NUL-terminated. + * @srclen: the length of @src in bytes + * @dst: (output) the decoded binary data + * + * Decodes a string using base64 encoding, i.e. the "Base 64 Encoding" + * specified by RFC 4648, including the  '='-padding. + * + * This implementation hasn't been optimized for performance. + * + * Return: the length of the resulting decoded binary data in bytes, + *	   or -1 if the string isn't a valid base64 string. + */ +int base64_decode(const char *src, int srclen, u8 *dst) +{ +	u32 ac = 0; +	int bits = 0; +	int i; +	u8 *bp = dst; + +	for (i = 0; i < srclen; i++) { +		const char *p = strchr(base64_table, src[i]); + +		if (src[i] == '=') { +			ac = (ac << 6); +			bits += 6; +			if (bits >= 8) +				bits -= 8; +			continue; +		} +		if (p == NULL || src[i] == 0) +			return -1; +		ac = (ac << 6) | (p - base64_table); +		bits += 6; +		if (bits >= 8) { +			bits -= 8; +			*bp++ = (u8)(ac >> bits); +		} +	} +	if (ac & ((1 << bits) - 1)) +		return -1; +	return bp - dst; +} +EXPORT_SYMBOL_GPL(base64_decode);  |