117680Spst/*	$NetBSD$	*/
217680Spst
317680Spst/*
417680Spst * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
517680Spst * Copyright (c) 1996-1999 by Internet Software Consortium.
617680Spst *
717680Spst * Permission to use, copy, modify, and distribute this software for any
817680Spst * purpose with or without fee is hereby granted, provided that the above
917680Spst * copyright notice and this permission notice appear in all copies.
1017680Spst *
1117680Spst * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
1217680Spst * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1317680Spst * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
1417680Spst * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1517680Spst * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1617680Spst * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1717680Spst * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1817680Spst */
1917680Spst
2017680Spst/*
2198527Sfenner * Portions Copyright (c) 1995 by International Business Machines, Inc.
2298527Sfenner *
2353146Sbrian * International Business Machines, Inc. (hereinafter called IBM) grants
2417680Spst * permission under its copyrights to use, copy, modify, and distribute this
2517680Spst * Software with or without fee, provided that the above copyright notice and
2675118Sfenner * all paragraphs of this notice appear in all copies, and that the name of IBM
2775118Sfenner * not be used in connection with the marketing of any product incorporating
2875118Sfenner * the Software or modifications thereof, without specific, written prior
2975118Sfenner * permission.
3075118Sfenner *
3175118Sfenner * To the extent it has a right to do so, IBM grants an immunity from suit
3275118Sfenner * under its patents, if any, for the use, sale or manufacture of products to
3375118Sfenner * the extent that such products are used for performing Domain Name System
3475118Sfenner * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
3575118Sfenner * granted for any product per se or for any other function of any product.
3675118Sfenner *
3717680Spst * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
3875118Sfenner * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
3975118Sfenner * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
4075118Sfenner * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
4175118Sfenner * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
4275118Sfenner * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
4375118Sfenner */
4475118Sfenner
4575118Sfenner#if !defined(LINT) && !defined(CODECENTER)
4675118Sfennerstatic const char rcsid[] = "Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp ";
4775118Sfenner#endif /* not lint */
4875118Sfenner
4975118Sfenner#include "port_before.h"
5017680Spst
5117680Spst#include <sys/types.h>
5217680Spst#include <sys/param.h>
5317680Spst#include <sys/socket.h>
5417680Spst
5517680Spst#include <netinet/in.h>
5617680Spst#include <arpa/inet.h>
5717680Spst#include <arpa/nameser.h>
5817680Spst
5917680Spst#include <ctype.h>
6017680Spst#include <resolv.h>
6117680Spst#include <stdio.h>
6217680Spst#include <stdlib.h>
6317680Spst#include <string.h>
6417680Spst
6517680Spst#include "port_after.h"
6617680Spst
6717680Spst#define Assert(Cond) if (!(Cond)) abort()
6817680Spst
6917680Spststatic const char Base64[] =
7017680Spst	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7117680Spststatic const char Pad64 = '=';
7217680Spst
7317680Spst/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
7417680Spst   The following encoding technique is taken from RFC1521 by Borenstein
7517680Spst   and Freed.  It is reproduced here in a slightly edited form for
7617680Spst   convenience.
7717680Spst
7817680Spst   A 65-character subset of US-ASCII is used, enabling 6 bits to be
7917680Spst   represented per printable character. (The extra 65th character, "=",
8017680Spst   is used to signify a special processing function.)
8117680Spst
8217680Spst   The encoding process represents 24-bit groups of input bits as output
8317680Spst   strings of 4 encoded characters. Proceeding from left to right, a
8417680Spst   24-bit input group is formed by concatenating 3 8-bit input groups.
8517680Spst   These 24 bits are then treated as 4 concatenated 6-bit groups, each
8617680Spst   of which is translated into a single digit in the base64 alphabet.
8717680Spst
8817680Spst   Each 6-bit group is used as an index into an array of 64 printable
8917680Spst   characters. The character referenced by the index is placed in the
9017680Spst   output string.
9117680Spst
9217680Spst                         Table 1: The Base64 Alphabet
9317680Spst
9417680Spst      Value Encoding  Value Encoding  Value Encoding  Value Encoding
9517680Spst          0 A            17 R            34 i            51 z
9617680Spst          1 B            18 S            35 j            52 0
9717680Spst          2 C            19 T            36 k            53 1
9856896Sfenner          3 D            20 U            37 l            54 2
9956896Sfenner          4 E            21 V            38 m            55 3
10056896Sfenner          5 F            22 W            39 n            56 4
10117692Spst          6 G            23 X            40 o            57 5
10298527Sfenner          7 H            24 Y            41 p            58 6
10317692Spst          8 I            25 Z            42 q            59 7
10456896Sfenner          9 J            26 a            43 r            60 8
10556896Sfenner         10 K            27 b            44 s            61 9
10653146Sbrian         11 L            28 c            45 t            62 +
10798527Sfenner         12 M            29 d            46 u            63 /
10898527Sfenner         13 N            30 e            47 v
10998527Sfenner         14 O            31 f            48 w         (pad) =
11098527Sfenner         15 P            32 g            49 x
11198527Sfenner         16 Q            33 h            50 y
11298527Sfenner
11398527Sfenner   Special processing is performed if fewer than 24 bits are available
11498527Sfenner   at the end of the data being encoded.  A full encoding quantum is
11598527Sfenner   always completed at the end of a quantity.  When fewer than 24 input
11656896Sfenner   bits are available in an input group, zero bits are added (on the
11756896Sfenner   right) to form an integral number of 6-bit groups.  Padding at the
11853146Sbrian   end of the data is performed using the '=' character.
11956896Sfenner
12056896Sfenner   Since all base64 input is an integral number of octets, only the
12156896Sfenner         -------------------------------------------------
12284019Sjulian   following cases can arise:
12384019Sjulian
12484019Sjulian       (1) the final quantum of encoding input is an integral
12584019Sjulian           multiple of 24 bits; here, the final unit of encoded
12684019Sjulian	   output will be an integral multiple of 4 characters
12784019Sjulian	   with no "=" padding,
12817680Spst       (2) the final quantum of encoding input is exactly 8 bits;
12917680Spst           here, the final unit of encoded output will be two
13017680Spst	   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