126fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes/*	$OpenBSD: base64.c,v 1.8 2015/01/16 16:48:51 deraadt 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/types.h>
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
49569fb9887d00104509df79fa77d92e3cf9afe7dbCalin Juravle#include <arpa/nameser.h>
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char Base64[] =
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char Pad64 = '=';
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   The following encoding technique is taken from RFC 1521 by Borenstein
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   and Freed.  It is reproduced here in a slightly edited form for
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   convenience.
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   A 65-character subset of US-ASCII is used, enabling 6 bits to be
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   represented per printable character. (The extra 65th character, "=",
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   is used to signify a special processing function.)
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   The encoding process represents 24-bit groups of input bits as output
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   strings of 4 encoded characters. Proceeding from left to right, a
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   24-bit input group is formed by concatenating 3 8-bit input groups.
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   These 24 bits are then treated as 4 concatenated 6-bit groups, each
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   of which is translated into a single digit in the base64 alphabet.
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Each 6-bit group is used as an index into an array of 64 printable
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   characters. The character referenced by the index is placed in the
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   output string.
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                         Table 1: The Base64 Alphabet
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      Value Encoding  Value Encoding  Value Encoding  Value Encoding
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          0 A            17 R            34 i            51 z
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          1 B            18 S            35 j            52 0
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          2 C            19 T            36 k            53 1
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          3 D            20 U            37 l            54 2
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          4 E            21 V            38 m            55 3
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          5 F            22 W            39 n            56 4
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          6 G            23 X            40 o            57 5
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          7 H            24 Y            41 p            58 6
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          8 I            25 Z            42 q            59 7
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project          9 J            26 a            43 r            60 8
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         10 K            27 b            44 s            61 9
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         11 L            28 c            45 t            62 +
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         12 M            29 d            46 u            63 /
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         13 N            30 e            47 v
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         14 O            31 f            48 w         (pad) =
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         15 P            32 g            49 x
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project         16 Q            33 h            50 y
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Special processing is performed if fewer than 24 bits are available
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   at the end of the data being encoded.  A full encoding quantum is
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   always completed at the end of a quantity.  When fewer than 24 input
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   bits are available in an input group, zero bits are added (on the
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   right) to form an integral number of 6-bit groups.  Padding at the
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   end of the data is performed using the '=' character.
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   Since all base64 input is an integral number of octets, only the
11026fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes         -------------------------------------------------
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   following cases can arise:
11226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (1) the final quantum of encoding input is an integral
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           multiple of 24 bits; here, the final unit of encoded
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   output will be an integral multiple of 4 characters
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   with no "=" padding,
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (2) the final quantum of encoding input is exactly 8 bits;
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           here, the final unit of encoded output will be two
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   characters followed by two "=" padding characters, or
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       (3) the final quantum of encoding input is exactly 16 bits;
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           here, the final unit of encoded output will be three
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   characters followed by one "=" padding character.
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   */
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectb64_ntop(src, srclength, target, targsize)
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char const *src;
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t srclength;
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *target;
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t targsize;
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t datalength = 0;
13326fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	u_char input[3];
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char output[4];
13526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	int i;
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (2 < srclength) {
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[0] = *src++;
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[1] = *src++;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[2] = *src++;
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srclength -= 3;
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14326fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[0] = input[0] >> 2;
14426fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
14526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		output[3] = input[2] & 0x3f;
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (datalength + 4 > targsize)
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[0]];
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[1]];
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[2]];
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[3]];
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
15526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Now we worry about padding. */
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (0 != srclength) {
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Get what's left. */
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		input[0] = input[1] = input[2] = '\0';
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (i = 0; i < srclength; i++)
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			input[i] = *src++;
16226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes
16326fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[0] = input[0] >> 2;
16426fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
16526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (datalength + 4 > targsize)
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[0]];
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Base64[output[1]];
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (srclength == 1)
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			target[datalength++] = Pad64;
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			target[datalength++] = Base64[output[2]];
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		target[datalength++] = Pad64;
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (datalength >= targsize)
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	target[datalength] = '\0';	/* Returned value doesn't count \0. */
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (datalength);
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* skips all whitespace anywhere.
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   converts characters, four at a time, starting at (or after)
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   src from base - 64 numbers into three 8 bit bytes in the target area.
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project   it returns the number of data bytes stored at the target, or -1 on error.
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectb64_pton(src, target, targsize)
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char const *src;
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *target;
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t targsize;
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
19526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	int tarindex, state, ch;
19626fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	u_char nextbyte;
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *pos;
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	state = 0;
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	tarindex = 0;
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	while ((ch = (unsigned char)*src++) != '\0') {
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (isspace(ch))	/* Skip whitespace anywhere. */
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (ch == Pad64)
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		pos = strchr(Base64, ch);
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (pos == 0) 		/* A non-base64 character. */
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (state) {
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex >= targsize)
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] = (pos - Base64) << 2;
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 1;
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 1:
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
22426fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				if (tarindex >= targsize)
22526fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes					return (-1);
22626fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				target[tarindex]   |=  (pos - Base64) >> 4;
22726fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				nextbyte = ((pos - Base64) & 0x0f) << 4;
22826fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				if (tarindex + 1 < targsize)
22926fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes					target[tarindex+1] = nextbyte;
23026fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				else if (nextbyte)
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 2;
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 2:
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
23826fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				if (tarindex >= targsize)
23926fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes					return (-1);
24026fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				target[tarindex]   |=  (pos - Base64) >> 2;
24126fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				nextbyte = ((pos - Base64) & 0x03) << 6;
24226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				if (tarindex + 1 < targsize)
24326fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes					target[tarindex+1] = nextbyte;
24426fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes				else if (nextbyte)
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 3;
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 3:
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (target) {
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tarindex >= targsize)
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				target[tarindex] |= (pos - Base64);
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tarindex++;
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			state = 0;
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * We are done decoding Base-64 chars.  Let's see if we ended
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * on a byte boundary, and/or with erroneous trailing characters.
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
26726fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes	if (ch == Pad64) {			/* We got a pad char. */
26826fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes		ch = (unsigned char)*src++;	/* Skip it, get next. */
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (state) {
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:		/* Invalid = in first position */
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 1:		/* Invalid = in second position */
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 2:		/* Valid, means one byte of info */
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Skip any number of spaces. */
27626fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes			for (; ch != '\0'; ch = (unsigned char)*src++)
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isspace(ch))
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Make sure there is another trailing = sign. */
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch != Pad64)
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
28226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes			ch = (unsigned char)*src++;		/* Skip the = */
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Fall through to "single trailing =" case. */
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* FALLTHROUGH */
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 3:		/* Valid, means two bytes of info */
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * We know this char is an =.  Is there anything but
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * whitespace after it?
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
29126fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes			for (; ch != '\0'; ch = (unsigned char)*src++)
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isspace(ch))
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * Now make sure for cases 2 and 3 that the "extra"
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * bits that slopped past the last full byte were
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * zeros.  If we don't check them, they become a
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * subliminal channel.
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
30126fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes			if (target && tarindex < targsize &&
30226fda778f7dcc8654c737efcb4a6dbbbf59b99d5Elliott Hughes			    target[tarindex] != 0)
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * We ended by seeing the end of the string.  Make sure we
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * have no partial bytes lying around.
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (state != 0)
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (tarindex);
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
316