/*- * Copyright (c) 2017 Taylor R. Campbell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Base64 encoding of octet strings, safe for email and various other * text-based protocols. Specified in * * S. Josefsson, `The Base16, Base32, and Base64 Data Encodings', * IETF RFC 4648, October 2006. */ #define _POSIX_C_SOURCE 200809L #include "base64enc.h" #include #include #include /* * base64enc_size(s) * * Return the size in bytes of the base64 encoding of a string of * s octets. */ size_t base64enc_size(size_t s) { return 4*((s + 2)/3); } /* * base64enc(target, tlen, source, slen) * * Encode slen bytes of data at source as NUL-terminated base64 in * the buffer target which has tlen bytes. tlen must be at least * base64enc_size(slen) + 1. */ void base64enc(char *target, size_t tlen, const void *source, size_t slen) { static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char *t = target; const uint8_t *s = source; /* Require enough room in target buffer. */ assert(tlen >= base64enc_size(slen) + 1); /* Map 3-octet chunks to 4-character chunks. */ while (3 <= slen) { assert(4 <= tlen); t[0] = b64[ (s[0] & 0xfc) >> 2]; t[1] = b64[(s[0] & 0x03) << 4 | (s[1] & 0xf0) >> 4]; t[2] = b64[(s[1] & 0x0f) << 2 | (s[2] & 0xc0) >> 6]; t[3] = b64[(s[2] & 0x3f) << 0 ]; s += 3, slen -= 3; t += 4, tlen -= 4; } /* Map trailing chunk with padding if need be. */ if (0 < slen) { uint8_t s0, s1; assert(4 <= tlen); assert(slen == 1 || slen == 2); s0 = s[0]; s1 = (slen <= 1? 0 : s[1]); t[0] = b64[s0 >> 2]; t[1] = b64[(s0 & 0x03) << 4 | s1 >> 4]; t[2] = (slen <= 1? '=' : b64[(s1 & 0x0f) << 2]); t[3] = '='; s += slen, slen -= slen; t += 4, tlen -= 4; } /* NUL-terminate. */ *t++ = '\0', tlen--; /* We had better have encoded the size we promised. */ assert((size_t)(t - target) == base64enc_size((size_t)(s - (const uint8_t *)source)) + 1); }