/* * UCW Library -- Base 64 Encoding & Decoding * * (c) 2002, Robert Spalek * (c) 2018, Pavel Charvat * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #undef LOCAL_DEBUG #include #include const byte base64_enc_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const byte base64_dec_table[256] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, }; uint base64_encode(byte *dest, const byte *src, uint len) { const byte *ptr = src; const byte *end = src + len; byte *out = dest; /* keep going until we have less than 24 bits */ if (end - ptr >= 3) for (const byte *x = end - 2; ptr < x; ) { out[0] = base64_enc_table[ptr[0] >> 2]; out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)]; out[2] = base64_enc_table[((ptr[1] & 0x0f) << 2) + (ptr[2] >> 6)]; out[3] = base64_enc_table[ptr[2] & 0x3f]; out += 4; ptr += 3; } /* now deal with the tail end of things */ if (ptr != end) { out[0] = base64_enc_table[ptr[0] >> 2]; out[3] = BASE64_PADDING; if (end - ptr >= 2) { out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)]; out[2] = base64_enc_table[(ptr[1] & 0x0f) << 2]; } else { out[1] = base64_enc_table[(ptr[0] & 0x03) << 4]; out[2] = BASE64_PADDING; } out += 4; } return out - dest; } uint base64_decode(byte *dest, const byte *src, uint len) { const byte *ptr = src; const byte *end = src + len; byte *out = dest; while (1) { uint val, ch; do { if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING) goto end; } while (ch > BASE64_DEC_PADDING); val = ch; do { if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING) goto end; // Broken base64 encoding, we only have 6 bits } while (ch > BASE64_DEC_PADDING); val = (val << 6) | ch; do { if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING) { out[0] = val >> 4; out += 1; goto end; } } while (ch > BASE64_DEC_PADDING); val = (val << 6) | ch; do { if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING) { out[0] = val >> 10; out[1] = val >> 2; out += 2; goto end; } } while (ch > BASE64_DEC_PADDING); val = (val << 6) | ch; out[0] = val >> 16; out[1] = val >> 8; out[2] = val; out += 3; } end: return out - dest; }