1/*	$NetBSD$	*/
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*
21 * Portions Copyright (c) 1995 by International Business Machines, Inc.
22 *
23 * International Business Machines, Inc. (hereinafter called IBM) grants
24 * permission under its copyrights to use, copy, modify, and distribute this
25 * Software with or without fee, provided that the above copyright notice and
26 * all paragraphs of this notice appear in all copies, and that the name of IBM
27 * not be used in connection with the marketing of any product incorporating
28 * the Software or modifications thereof, without specific, written prior
29 * permission.
30 *
31 * To the extent it has a right to do so, IBM grants an immunity from suit
32 * under its patents, if any, for the use, sale or manufacture of products to
33 * the extent that such products are used for performing Domain Name System
34 * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
35 * granted for any product per se or for any other function of any product.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
40 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
42 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#if !defined(LINT) && !defined(CODECENTER)
46static const char rcsid[] = "Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp";
47#endif /* not lint */
48
49#include "port_before.h"
50
51#include <sys/types.h>
52#include <sys/param.h>
53#include <sys/socket.h>
54
55#include <netinet/in.h>
56#include <arpa/inet.h>
57#include <arpa/nameser.h>
58
59#include <ctype.h>
60#include <resolv.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64
65#include "port_after.h"
66
67#define Assert(Cond) if (!(Cond)) abort()
68
69static const char Base64[] =
70	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
71static const char Pad64 = '=';
72
73/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
74   The following encoding technique is taken from RFC1521 by Borenstein
75   and Freed.  It is reproduced here in a slightly edited form for
76   convenience.
77
78   A 65-character subset of US-ASCII is used, enabling 6 bits to be
79   represented per printable character. (The extra 65th character, "=",
80   is used to signify a special processing function.)
81
82   The encoding process represents 24-bit groups of input bits as output
83   strings of 4 encoded characters. Proceeding from left to right, a
84   24-bit input group is formed by concatenating 3 8-bit input groups.
85   These 24 bits are then treated as 4 concatenated 6-bit groups, each
86   of which is translated into a single digit in the base64 alphabet.
87
88   Each 6-bit group is used as an index into an array of 64 printable
89   characters. The character referenced by the index is placed in the
90   output string.
91
92                         Table 1: The Base64 Alphabet
93
94      Value Encoding  Value Encoding  Value Encoding  Value Encoding
95          0 A            17 R            34 i            51 z
96          1 B            18 S            35 j            52 0
97          2 C            19 T            36 k            53 1
98          3 D            20 U            37 l            54 2
99          4 E            21 V            38 m            55 3
100          5 F            22 W            39 n            56 4
101          6 G            23 X            40 o            57 5
102          7 H            24 Y            41 p            58 6
103          8 I            25 Z            42 q            59 7
104          9 J            26 a            43 r            60 8
105         10 K            27 b            44 s            61 9
106         11 L            28 c            45 t            62 +
107         12 M            29 d            46 u            63 /
108         13 N            30 e            47 v
109         14 O            31 f            48 w         (pad) =
110         15 P            32 g            49 x
111         16 Q            33 h            50 y
112
113   Special processing is performed if fewer than 24 bits are available
114   at the end of the data being encoded.  A full encoding quantum is
115   always completed at the end of a quantity.  When fewer than 24 input
116   bits are available in an input group, zero bits are added (on the
117   right) to form an integral number of 6-bit groups.  Padding at the
118   end of the data is performed using the '=' character.
119
120   Since all base64 input is an integral number of octets, only the
121         -------------------------------------------------
122   following cases can arise:
123
124       (1) the final quantum of encoding input is an integral
125           multiple of 24 bits; here, the final unit of encoded
126	   output will be an integral multiple of 4 characters
127	   with no "=" padding,
128       (2) the final quantum of encoding input is exactly 8 bits;
129           here, the final unit of encoded output will be two
130	   characters followed by two "=" padding characters, or
131       (3) the final quantum of encoding input is exactly 16 bits;
132           here, the final unit of encoded output will be three
133	   characters followed by one "=" padding character.
134   */
135
136int
137b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
138	size_t datalength = 0;
139	u_char input[3];
140	u_char output[4];
141	size_t i;
142
143	while (2U < srclength) {
144		input[0] = *src++;
145		input[1] = *src++;
146		input[2] = *src++;
147		srclength -= 3;
148
149		output[0] = input[0] >> 2;
150		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
151		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
152		output[3] = input[2] & 0x3f;
153		Assert(output[0] < 64);
154		Assert(output[1] < 64);
155		Assert(output[2] < 64);
156		Assert(output[3] < 64);
157
158		if (datalength + 4 > targsize)
159			return (-1);
160		target[datalength++] = Base64[output[0]];
161		target[datalength++] = Base64[output[1]];
162		target[datalength++] = Base64[output[2]];
163		target[datalength++] = Base64[output[3]];
164	}
165
166	/* Now we worry about padding. */
167	if (0U != srclength) {
168		/* Get what's left. */
169		input[0] = input[1] = input[2] = '\0';
170		for (i = 0; i < srclength; i++)
171			input[i] = *src++;
172
173		output[0] = input[0] >> 2;
174		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
175		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
176		Assert(output[0] < 64);
177		Assert(output[1] < 64);
178		Assert(output[2] < 64);
179
180		if (datalength + 4 > targsize)
181			return (-1);
182		target[datalength++] = Base64[output[0]];
183		target[datalength++] = Base64[output[1]];
184		if (srclength == 1U)
185			target[datalength++] = Pad64;
186		else
187			target[datalength++] = Base64[output[2]];
188		target[datalength++] = Pad64;
189	}
190	if (datalength >= targsize)
191		return (-1);
192	target[datalength] = '\0';	/*%< Returned value doesn't count \\0. */
193	return (datalength);
194}
195
196/* skips all whitespace anywhere.
197   converts characters, four at a time, starting at (or after)
198   src from base - 64 numbers into three 8 bit bytes in the target area.
199   it returns the number of data bytes stored at the target, or -1 on error.
200 */
201
202int
203b64_pton(src, target, targsize)
204	char const *src;
205	u_char *target;
206	size_t targsize;
207{
208	int tarindex, state, ch;
209	char *pos;
210
211	state = 0;
212	tarindex = 0;
213
214	while ((ch = *src++) != '\0') {
215		if (isspace(ch))	/*%< Skip whitespace anywhere. */
216			continue;
217
218		if (ch == Pad64)
219			break;
220
221		pos = strchr(Base64, ch);
222		if (pos == 0) 		/*%< A non-base64 character. */
223			return (-1);
224
225		switch (state) {
226		case 0:
227			if (target) {
228				if ((size_t)tarindex >= targsize)
229					return (-1);
230				target[tarindex] = (pos - Base64) << 2;
231			}
232			state = 1;
233			break;
234		case 1:
235			if (target) {
236				if ((size_t)tarindex + 1 >= targsize)
237					return (-1);
238				target[tarindex]   |=  (pos - Base64) >> 4;
239				target[tarindex+1]  = ((pos - Base64) & 0x0f)
240							<< 4 ;
241			}
242			tarindex++;
243			state = 2;
244			break;
245		case 2:
246			if (target) {
247				if ((size_t)tarindex + 1 >= targsize)
248					return (-1);
249				target[tarindex]   |=  (pos - Base64) >> 2;
250				target[tarindex+1]  = ((pos - Base64) & 0x03)
251							<< 6;
252			}
253			tarindex++;
254			state = 3;
255			break;
256		case 3:
257			if (target) {
258				if ((size_t)tarindex >= targsize)
259					return (-1);
260				target[tarindex] |= (pos - Base64);
261			}
262			tarindex++;
263			state = 0;
264			break;
265		default:
266			abort();
267		}
268	}
269
270	/*
271	 * We are done decoding Base-64 chars.  Let's see if we ended
272	 * on a byte boundary, and/or with erroneous trailing characters.
273	 */
274
275	if (ch == Pad64) {		/*%< We got a pad char. */
276		ch = *src++;		/*%< Skip it, get next. */
277		switch (state) {
278		case 0:		/*%< Invalid = in first position */
279		case 1:		/*%< Invalid = in second position */
280			return (-1);
281
282		case 2:		/*%< Valid, means one byte of info */
283			/* Skip any number of spaces. */
284			for ((void)NULL; ch != '\0'; ch = *src++)
285				if (!isspace(ch))
286					break;
287			/* Make sure there is another trailing = sign. */
288			if (ch != Pad64)
289				return (-1);
290			ch = *src++;		/*%< Skip the = */
291			/* Fall through to "single trailing =" case. */
292			/* FALLTHROUGH */
293
294		case 3:		/*%< Valid, means two bytes of info */
295			/*
296			 * We know this char is an =.  Is there anything but
297			 * whitespace after it?
298			 */
299			for ((void)NULL; ch != '\0'; ch = *src++)
300				if (!isspace(ch))
301					return (-1);
302
303			/*
304			 * Now make sure for cases 2 and 3 that the "extra"
305			 * bits that slopped past the last full byte were
306			 * zeros.  If we don't check them, they become a
307			 * subliminal channel.
308			 */
309			if (target && target[tarindex] != 0)
310				return (-1);
311		}
312	} else {
313		/*
314		 * We ended by seeing the end of the string.  Make sure we
315		 * have no partial bytes lying around.
316		 */
317		if (state != 0)
318			return (-1);
319	}
320
321	return (tarindex);
322}
323
324/*! \file */
325