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); 104