Line data Source code
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 0 : int base64_encode(const u8 *src, int srclen, char *dst) 33 : { 34 0 : u32 ac = 0; 35 0 : int bits = 0; 36 : int i; 37 0 : char *cp = dst; 38 : 39 0 : for (i = 0; i < srclen; i++) { 40 0 : ac = (ac << 8) | src[i]; 41 0 : bits += 8; 42 : do { 43 0 : bits -= 6; 44 0 : *cp++ = base64_table[(ac >> bits) & 0x3f]; 45 0 : } while (bits >= 6); 46 : } 47 0 : if (bits) { 48 0 : *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; 49 0 : bits -= 6; 50 : } 51 0 : while (bits < 0) { 52 0 : *cp++ = '='; 53 0 : bits += 2; 54 : } 55 0 : 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 0 : int base64_decode(const char *src, int srclen, u8 *dst) 74 : { 75 0 : u32 ac = 0; 76 0 : int bits = 0; 77 : int i; 78 0 : u8 *bp = dst; 79 : 80 0 : for (i = 0; i < srclen; i++) { 81 0 : const char *p = strchr(base64_table, src[i]); 82 : 83 0 : if (src[i] == '=') { 84 0 : ac = (ac << 6); 85 0 : bits += 6; 86 0 : if (bits >= 8) 87 0 : bits -= 8; 88 0 : continue; 89 : } 90 0 : if (p == NULL || src[i] == 0) 91 : return -1; 92 0 : ac = (ac << 6) | (p - base64_table); 93 0 : bits += 6; 94 0 : if (bits >= 8) { 95 0 : bits -= 8; 96 0 : *bp++ = (u8)(ac >> bits); 97 : } 98 : } 99 0 : if (ac & ((1 << bits) - 1)) 100 : return -1; 101 0 : return bp - dst; 102 : } 103 : EXPORT_SYMBOL_GPL(base64_decode);