1*a116e1cdSHannes Reinecke // SPDX-License-Identifier: GPL-2.0 2*a116e1cdSHannes Reinecke /* 3*a116e1cdSHannes Reinecke * base64.c - RFC4648-compliant base64 encoding 4*a116e1cdSHannes Reinecke * 5*a116e1cdSHannes Reinecke * Copyright (c) 2020 Hannes Reinecke, SUSE 6*a116e1cdSHannes Reinecke * 7*a116e1cdSHannes Reinecke * Based on the base64url routines from fs/crypto/fname.c 8*a116e1cdSHannes Reinecke * (which are using the URL-safe base64 encoding), 9*a116e1cdSHannes Reinecke * modified to use the standard coding table from RFC4648 section 4. 10*a116e1cdSHannes Reinecke */ 11*a116e1cdSHannes Reinecke 12*a116e1cdSHannes Reinecke #include <linux/kernel.h> 13*a116e1cdSHannes Reinecke #include <linux/types.h> 14*a116e1cdSHannes Reinecke #include <linux/export.h> 15*a116e1cdSHannes Reinecke #include <linux/string.h> 16*a116e1cdSHannes Reinecke #include <linux/base64.h> 17*a116e1cdSHannes Reinecke 18*a116e1cdSHannes Reinecke static const char base64_table[65] = 19*a116e1cdSHannes Reinecke "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 20*a116e1cdSHannes Reinecke 21*a116e1cdSHannes Reinecke /** 22*a116e1cdSHannes Reinecke * base64_encode() - base64-encode some binary data 23*a116e1cdSHannes Reinecke * @src: the binary data to encode 24*a116e1cdSHannes Reinecke * @srclen: the length of @src in bytes 25*a116e1cdSHannes Reinecke * @dst: (output) the base64-encoded string. Not NUL-terminated. 26*a116e1cdSHannes Reinecke * 27*a116e1cdSHannes Reinecke * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specified 28*a116e1cdSHannes Reinecke * by RFC 4648, including the '='-padding. 29*a116e1cdSHannes Reinecke * 30*a116e1cdSHannes Reinecke * Return: the length of the resulting base64-encoded string in bytes. 31*a116e1cdSHannes Reinecke */ 32*a116e1cdSHannes Reinecke int base64_encode(const u8 *src, int srclen, char *dst) 33*a116e1cdSHannes Reinecke { 34*a116e1cdSHannes Reinecke u32 ac = 0; 35*a116e1cdSHannes Reinecke int bits = 0; 36*a116e1cdSHannes Reinecke int i; 37*a116e1cdSHannes Reinecke char *cp = dst; 38*a116e1cdSHannes Reinecke 39*a116e1cdSHannes Reinecke for (i = 0; i < srclen; i++) { 40*a116e1cdSHannes Reinecke ac = (ac << 8) | src[i]; 41*a116e1cdSHannes Reinecke bits += 8; 42*a116e1cdSHannes Reinecke do { 43*a116e1cdSHannes Reinecke bits -= 6; 44*a116e1cdSHannes Reinecke *cp++ = base64_table[(ac >> bits) & 0x3f]; 45*a116e1cdSHannes Reinecke } while (bits >= 6); 46*a116e1cdSHannes Reinecke } 47*a116e1cdSHannes Reinecke if (bits) { 48*a116e1cdSHannes Reinecke *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; 49*a116e1cdSHannes Reinecke bits -= 6; 50*a116e1cdSHannes Reinecke } 51*a116e1cdSHannes Reinecke while (bits < 0) { 52*a116e1cdSHannes Reinecke *cp++ = '='; 53*a116e1cdSHannes Reinecke bits += 2; 54*a116e1cdSHannes Reinecke } 55*a116e1cdSHannes Reinecke return cp - dst; 56*a116e1cdSHannes Reinecke } 57*a116e1cdSHannes Reinecke EXPORT_SYMBOL_GPL(base64_encode); 58*a116e1cdSHannes Reinecke 59*a116e1cdSHannes Reinecke /** 60*a116e1cdSHannes Reinecke * base64_decode() - base64-decode a string 61*a116e1cdSHannes Reinecke * @src: the string to decode. Doesn't need to be NUL-terminated. 62*a116e1cdSHannes Reinecke * @srclen: the length of @src in bytes 63*a116e1cdSHannes Reinecke * @dst: (output) the decoded binary data 64*a116e1cdSHannes Reinecke * 65*a116e1cdSHannes Reinecke * Decodes a string using base64 encoding, i.e. the "Base 64 Encoding" 66*a116e1cdSHannes Reinecke * specified by RFC 4648, including the '='-padding. 67*a116e1cdSHannes Reinecke * 68*a116e1cdSHannes Reinecke * This implementation hasn't been optimized for performance. 69*a116e1cdSHannes Reinecke * 70*a116e1cdSHannes Reinecke * Return: the length of the resulting decoded binary data in bytes, 71*a116e1cdSHannes Reinecke * or -1 if the string isn't a valid base64 string. 72*a116e1cdSHannes Reinecke */ 73*a116e1cdSHannes Reinecke int base64_decode(const char *src, int srclen, u8 *dst) 74*a116e1cdSHannes Reinecke { 75*a116e1cdSHannes Reinecke u32 ac = 0; 76*a116e1cdSHannes Reinecke int bits = 0; 77*a116e1cdSHannes Reinecke int i; 78*a116e1cdSHannes Reinecke u8 *bp = dst; 79*a116e1cdSHannes Reinecke 80*a116e1cdSHannes Reinecke for (i = 0; i < srclen; i++) { 81*a116e1cdSHannes Reinecke const char *p = strchr(base64_table, src[i]); 82*a116e1cdSHannes Reinecke 83*a116e1cdSHannes Reinecke if (src[i] == '=') { 84*a116e1cdSHannes Reinecke ac = (ac << 6); 85*a116e1cdSHannes Reinecke bits += 6; 86*a116e1cdSHannes Reinecke if (bits >= 8) 87*a116e1cdSHannes Reinecke bits -= 8; 88*a116e1cdSHannes Reinecke continue; 89*a116e1cdSHannes Reinecke } 90*a116e1cdSHannes Reinecke if (p == NULL || src[i] == 0) 91*a116e1cdSHannes Reinecke return -1; 92*a116e1cdSHannes Reinecke ac = (ac << 6) | (p - base64_table); 93*a116e1cdSHannes Reinecke bits += 6; 94*a116e1cdSHannes Reinecke if (bits >= 8) { 95*a116e1cdSHannes Reinecke bits -= 8; 96*a116e1cdSHannes Reinecke *bp++ = (u8)(ac >> bits); 97*a116e1cdSHannes Reinecke } 98*a116e1cdSHannes Reinecke } 99*a116e1cdSHannes Reinecke if (ac & ((1 << bits) - 1)) 100*a116e1cdSHannes Reinecke return -1; 101*a116e1cdSHannes Reinecke return bp - dst; 102*a116e1cdSHannes Reinecke } 103*a116e1cdSHannes Reinecke EXPORT_SYMBOL_GPL(base64_decode); 104