forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.4 KiB
103 lines
2.4 KiB
// 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);
|
|
|