11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*	$OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $	*/
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1996 by Internet Software Consortium.
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SOFTWARE.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Portions Copyright (c) 1995 by International Business Machines, Inc.
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * International Business Machines, Inc. (hereinafter called IBM) grants
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * permission under its copyrights to use, copy, modify, and distribute this
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Software with or without fee, provided that the above copyright notice and
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * all paragraphs of this notice appear in all copies, and that the name of IBM
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * not be used in connection with the marketing of any product incorporating
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the Software or modifications thereof, without specific, written prior
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * permission.
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * To the extent it has a right to do so, IBM grants an immunity from suit
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * under its patents, if any, for the use, sale or manufacture of products to
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the extent that such products are used for performing Domain Name System
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * granted for any product per se or for any other function of any product.
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in.h>
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <arpa/inet.h>
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <ctype.h>
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "base64.h"
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const char Base64[] =
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const char Pad64 = '=';
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   The following encoding technique is taken from RFC 1521 by Borenstein
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   and Freed.  It is reproduced here in a slightly edited form for
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   convenience.
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   A 65-character subset of US-ASCII is used, enabling 6 bits to be
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   represented per printable character. (The extra 65th character, "=",
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   is used to signify a special processing function.)
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   The encoding process represents 24-bit groups of input bits as output
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   strings of 4 encoded characters. Proceeding from left to right, a
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   24-bit input group is formed by concatenating 3 8-bit input groups.
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   These 24 bits are then treated as 4 concatenated 6-bit groups, each
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   of which is translated into a single digit in the base64 alphabet.
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   Each 6-bit group is used as an index into an array of 64 printable
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   characters. The character referenced by the index is placed in the
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   output string.
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood                         Table 1: The Base64 Alphabet
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood      Value Encoding  Value Encoding  Value Encoding  Value Encoding
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          0 A            17 R            34 i            51 z
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          1 B            18 S            35 j            52 0
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          2 C            19 T            36 k            53 1
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          3 D            20 U            37 l            54 2
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          4 E            21 V            38 m            55 3
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          5 F            22 W            39 n            56 4
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          6 G            23 X            40 o            57 5
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          7 H            24 Y            41 p            58 6
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          8 I            25 Z            42 q            59 7
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood          9 J            26 a            43 r            60 8
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         10 K            27 b            44 s            61 9
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         11 L            28 c            45 t            62 +
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         12 M            29 d            46 u            63 /
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         13 N            30 e            47 v
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         14 O            31 f            48 w         (pad) =
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         15 P            32 g            49 x
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         16 Q            33 h            50 y
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   Special processing is performed if fewer than 24 bits are available
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   at the end of the data being encoded.  A full encoding quantum is
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   always completed at the end of a quantity.  When fewer than 24 input
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   bits are available in an input group, zero bits are added (on the
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   right) to form an integral number of 6-bit groups.  Padding at the
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   end of the data is performed using the '=' character.
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   Since all base64 input is an integral number of octets, only the
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood         -------------------------------------------------
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   following cases can arise:
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood       (1) the final quantum of encoding input is an integral
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood           multiple of 24 bits; here, the final unit of encoded
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	   output will be an integral multiple of 4 characters
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	   with no "=" padding,
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood       (2) the final quantum of encoding input is exactly 8 bits;
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood           here, the final unit of encoded output will be two
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	   characters followed by two "=" padding characters, or
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood       (3) the final quantum of encoding input is exactly 16 bits;
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood           here, the final unit of encoded output will be three
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	   characters followed by one "=" padding character.
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   */
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodb64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t datalength = 0;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char input[3];
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char output[4];
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (2 < srclength) {
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		input[0] = *src++;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		input[1] = *src++;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		input[2] = *src++;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		srclength -= 3;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[0] = input[0] >> 2;
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[3] = input[2] & 0x3f;
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (datalength + 4 > targsize)
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[0]];
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[1]];
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[2]];
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[3]];
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Now we worry about padding. */
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (0 != srclength) {
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Get what's left. */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		input[0] = input[1] = input[2] = '\0';
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < srclength; i++)
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			input[i] = *src++;
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[0] = input[0] >> 2;
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (datalength + 4 > targsize)
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[0]];
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Base64[output[1]];
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (srclength == 1)
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			target[datalength++] = Pad64;
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			target[datalength++] = Base64[output[2]];
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		target[datalength++] = Pad64;
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datalength >= targsize)
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	target[datalength] = '\0';	/* Returned value doesn't count \0. */
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (datalength);
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* skips all whitespace anywhere.
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   converts characters, four at a time, starting at (or after)
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   src from base - 64 numbers into three 8 bit bytes in the target area.
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   it returns the number of data bytes stored at the target, or -1 on error.
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodb64_pton(char const *src, u_char *target, size_t targsize)
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int tarindex, state;
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ch;
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *pos;
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	state = 0;
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tarindex = 0;
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((ch = *src++) != '\0') {
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (isspace(ch))	/* Skip whitespace anywhere. */
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ch == Pad64)
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pos = strchr(Base64, ch);
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (pos == 0) 		/* A non-base64 character. */
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (state) {
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 0:
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (target) {
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (tarindex >= targsize)
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return (-1);
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex] = (pos - Base64) << 2;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = 1;
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 1:
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (target) {
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (tarindex + 1 >= targsize)
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return (-1);
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex]   |=  (pos - Base64) >> 4;
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex+1]  = ((pos - Base64) & 0x0f)
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood							<< 4 ;
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tarindex++;
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = 2;
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 2:
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (target) {
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (tarindex + 1 >= targsize)
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return (-1);
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex]   |=  (pos - Base64) >> 2;
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex+1]  = ((pos - Base64) & 0x03)
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood							<< 6;
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tarindex++;
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = 3;
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 3:
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (target) {
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (tarindex >= targsize)
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return (-1);
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				target[tarindex] |= (pos - Base64);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tarindex++;
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = 0;
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We are done decoding Base-64 chars.  Let's see if we ended
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * on a byte boundary, and/or with erroneous trailing characters.
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ch == Pad64) {		/* We got a pad char. */
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ch = *src++;		/* Skip it, get next. */
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (state) {
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 0:		/* Invalid = in first position */
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 1:		/* Invalid = in second position */
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 2:		/* Valid, means one byte of info */
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Skip any number of spaces. */
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			for (; ch != '\0'; ch = *src++)
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (!isspace(ch))
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Make sure there is another trailing = sign. */
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ch != Pad64)
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return (-1);
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ch = *src++;		/* Skip the = */
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Fall through to "single trailing =" case. */
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* FALLTHROUGH */
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 3:		/* Valid, means two bytes of info */
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * We know this char is an =.  Is there anything but
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * whitespace after it?
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			for (; ch != '\0'; ch = *src++)
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (!isspace(ch))
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return (-1);
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Now make sure for cases 2 and 3 that the "extra"
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * bits that slopped past the last full byte were
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * zeros.  If we don't check them, they become a
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * subliminal channel.
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (target && target[tarindex] != 0)
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return (-1);
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * We ended by seeing the end of the string.  Make sure we
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * have no partial bytes lying around.
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (state != 0)
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (-1);
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (tarindex);
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
316