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