11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*	$NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1996 by Internet Software Consortium.
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies.
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SOFTWARE.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Portions Copyright (c) 1995 by International Business Machines, Inc.
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * International Business Machines, Inc. (hereinafter called IBM) grants
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * permission under its copyrights to use, copy, modify, and distribute this
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Software with or without fee, provided that the above copyright notice and
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * all paragraphs of this notice appear in all copies, and that the name of IBM
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not be used in connection with the marketing of any product incorporating
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the Software or modifications thereof, without specific, written prior
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * permission.
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * To the extent it has a right to do so, IBM grants an immunity from suit
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * under its patents, if any, for the use, sale or manufacture of products to
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the extent that such products are used for performing Domain Name System
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * granted for any product per se or for any other function of any product.
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined(LIBC_SCCS) && !defined(lint)
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__RCSID("$NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $");
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* LIBC_SCCS and not lint */
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "arpa_nameser.h"
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <assert.h>
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char Base64[] =
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char Pad64 = '=';
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   The following encoding technique is taken from RFC 1521 by Borenstein
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   and Freed.  It is reproduced here in a slightly edited form for
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   convenience.
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   A 65-character subset of US-ASCII is used, enabling 6 bits to be
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   represented per printable character. (The extra 65th character, "=",
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   is used to signify a special processing function.)
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   The encoding process represents 24-bit groups of input bits as output
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   strings of 4 encoded characters. Proceeding from left to right, a
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   24-bit input group is formed by concatenating 3 8-bit input groups.
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   These 24 bits are then treated as 4 concatenated 6-bit groups, each
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   of which is translated into a single digit in the base64 alphabet.
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Each 6-bit group is used as an index into an array of 64 printable
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   characters. The character referenced by the index is placed in the
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   output string.
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                         Table 1: The Base64 Alphabet
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      Value Encoding  Value Encoding  Value Encoding  Value Encoding
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          0 A            17 R            34 i            51 z
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          1 B            18 S            35 j            52 0
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          2 C            19 T            36 k            53 1
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          3 D            20 U            37 l            54 2
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          4 E            21 V            38 m            55 3
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          5 F            22 W            39 n            56 4
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          6 G            23 X            40 o            57 5
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          7 H            24 Y            41 p            58 6
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          8 I            25 Z            42 q            59 7
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          9 J            26 a            43 r            60 8
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         10 K            27 b            44 s            61 9
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         11 L            28 c            45 t            62 +
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         12 M            29 d            46 u            63 /
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         13 N            30 e            47 v
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         14 O            31 f            48 w         (pad) =
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         15 P            32 g            49 x
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         16 Q            33 h            50 y
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Special processing is performed if fewer than 24 bits are available
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   at the end of the data being encoded.  A full encoding quantum is
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   always completed at the end of a quantity.  When fewer than 24 input
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   bits are available in an input group, zero bits are added (on the
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   right) to form an integral number of 6-bit groups.  Padding at the
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   end of the data is performed using the '=' character.
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Since all base64 input is an integral number of octets, only the
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         -------------------------------------------------
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   following cases can arise:
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (1) the final quantum of encoding input is an integral
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           multiple of 24 bits; here, the final unit of encoded
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   output will be an integral multiple of 4 characters
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   with no "=" padding,
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (2) the final quantum of encoding input is exactly 8 bits;
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           here, the final unit of encoded output will be two
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   characters followed by two "=" padding characters, or
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (3) the final quantum of encoding input is exactly 16 bits;
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           here, the final unit of encoded output will be three
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   characters followed by one "=" padding character.
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   */
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectb64_ntop(src, srclength, target, targsize)
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char const *src;
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t srclength;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *target;
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t targsize;
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t datalength = 0;
14450ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner	u_char input[3] = { 0, 0, 0 };  /* make compiler happy */
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char output[4];
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t i;
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	assert(src != NULL);
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	assert(target != NULL);
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (2 < srclength) {
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[0] = *src++;
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[1] = *src++;
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[2] = *src++;
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srclength -= 3;
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[0] = (u_int32_t)input[0] >> 2;
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ((u_int32_t)input[1] >> 4);
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ((u_int32_t)input[2] >> 6);
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[3] = input[2] & 0x3f;
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[0] < 64);
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[1] < 64);
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[2] < 64);
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[3] < 64);
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (datalength + 4 > targsize)
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[0]];
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[1]];
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[2]];
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[3]];
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Now we worry about padding. */
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (0 != srclength) {
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Get what's left. */
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[0] = input[1] = input[2] = '\0';
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (i = 0; i < srclength; i++)
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			input[i] = *src++;
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[0] = (u_int32_t)input[0] >> 2;
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ((u_int32_t)input[1] >> 4);
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ((u_int32_t)input[2] >> 6);
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[0] < 64);
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[1] < 64);
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		assert(output[2] < 64);
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (datalength + 4 > targsize)
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[0]];
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[1]];
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (srclength == 1)
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			target[datalength++] = Pad64;
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			target[datalength++] = Base64[output[2]];
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Pad64;
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (datalength >= targsize)
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	target[datalength] = '\0';	/* Returned value doesn't count \0. */
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (datalength);
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* skips all whitespace anywhere.
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   converts characters, four at a time, starting at (or after)
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   src from base - 64 numbers into three 8 bit bytes in the target area.
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   it returns the number of data bytes stored at the target, or -1 on error.
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectb64_pton(src, target, targsize)
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char const *src;
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *target;
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t targsize;
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t tarindex;
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int state, ch;
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *pos;
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	assert(src != NULL);
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	assert(target != NULL);
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	state = 0;
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	tarindex = 0;
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((ch = (u_char) *src++) != '\0') {
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (isspace(ch))	/* Skip whitespace anywhere. */
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (ch == Pad64)
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		pos = strchr(Base64, ch);
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (pos == 0) 		/* A non-base64 character. */
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (state) {
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex >= targsize)
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] = (pos - Base64) << 2;
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 1;
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 1:
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex + 1 >= targsize)
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] |=
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (u_int32_t)(pos - Base64) >> 4;
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex+1]  = ((pos - Base64) & 0x0f)
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							<< 4 ;
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 2;
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 2:
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex + 1 >= targsize)
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] |=
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					(u_int32_t)(pos - Base64) >> 2;
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex+1] = ((pos - Base64) & 0x03)
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							<< 6;
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 3;
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 3:
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex >= targsize)
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] |= (pos - Base64);
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 0;
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			abort();
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * We are done decoding Base-64 chars.  Let's see if we ended
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * on a byte boundary, and/or with erroneous trailing characters.
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ch == Pad64) {		/* We got a pad char. */
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ch = *src++;		/* Skip it, get next. */
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (state) {
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:		/* Invalid = in first position */
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 1:		/* Invalid = in second position */
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 2:		/* Valid, means one byte of info */
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Skip any number of spaces. */
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (; ch != '\0'; ch = (u_char) *src++)
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isspace(ch))
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Make sure there is another trailing = sign. */
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch != Pad64)
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ch = *src++;		/* Skip the = */
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Fall through to "single trailing =" case. */
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* FALLTHROUGH */
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 3:		/* Valid, means two bytes of info */
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * We know this char is an =.  Is there anything but
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * whitespace after it?
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (; ch != '\0'; ch = (u_char) *src++)
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isspace(ch))
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * Now make sure for cases 2 and 3 that the "extra"
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * bits that slopped past the last full byte were
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * zeros.  If we don't check them, they become a
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * subliminal channel.
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target && target[tarindex] != 0)
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * We ended by seeing the end of the string.  Make sure we
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * have no partial bytes lying around.
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (state != 0)
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (tarindex);
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
341