xref: /minix3/external/bsd/tmux/dist/compat/b64_ntop.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*
2*0a6a1f1dSLionel Sambuc  * Copyright (c) 1996, 1998 by Internet Software Consortium.
3*0a6a1f1dSLionel Sambuc  *
4*0a6a1f1dSLionel Sambuc  * Permission to use, copy, modify, and distribute this software for any
5*0a6a1f1dSLionel Sambuc  * purpose with or without fee is hereby granted, provided that the above
6*0a6a1f1dSLionel Sambuc  * copyright notice and this permission notice appear in all copies.
7*0a6a1f1dSLionel Sambuc  *
8*0a6a1f1dSLionel Sambuc  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9*0a6a1f1dSLionel Sambuc  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10*0a6a1f1dSLionel Sambuc  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11*0a6a1f1dSLionel Sambuc  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12*0a6a1f1dSLionel Sambuc  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13*0a6a1f1dSLionel Sambuc  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14*0a6a1f1dSLionel Sambuc  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15*0a6a1f1dSLionel Sambuc  * SOFTWARE.
16*0a6a1f1dSLionel Sambuc  */
17*0a6a1f1dSLionel Sambuc 
18*0a6a1f1dSLionel Sambuc /*
19*0a6a1f1dSLionel Sambuc  * Portions Copyright (c) 1995 by International Business Machines, Inc.
20*0a6a1f1dSLionel Sambuc  *
21*0a6a1f1dSLionel Sambuc  * International Business Machines, Inc. (hereinafter called IBM) grants
22*0a6a1f1dSLionel Sambuc  * permission under its copyrights to use, copy, modify, and distribute this
23*0a6a1f1dSLionel Sambuc  * Software with or without fee, provided that the above copyright notice and
24*0a6a1f1dSLionel Sambuc  * all paragraphs of this notice appear in all copies, and that the name of IBM
25*0a6a1f1dSLionel Sambuc  * not be used in connection with the marketing of any product incorporating
26*0a6a1f1dSLionel Sambuc  * the Software or modifications thereof, without specific, written prior
27*0a6a1f1dSLionel Sambuc  * permission.
28*0a6a1f1dSLionel Sambuc  *
29*0a6a1f1dSLionel Sambuc  * To the extent it has a right to do so, IBM grants an immunity from suit
30*0a6a1f1dSLionel Sambuc  * under its patents, if any, for the use, sale or manufacture of products to
31*0a6a1f1dSLionel Sambuc  * the extent that such products are used for performing Domain Name System
32*0a6a1f1dSLionel Sambuc  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
33*0a6a1f1dSLionel Sambuc  * granted for any product per se or for any other function of any product.
34*0a6a1f1dSLionel Sambuc  *
35*0a6a1f1dSLionel Sambuc  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36*0a6a1f1dSLionel Sambuc  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37*0a6a1f1dSLionel Sambuc  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38*0a6a1f1dSLionel Sambuc  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39*0a6a1f1dSLionel Sambuc  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40*0a6a1f1dSLionel Sambuc  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41*0a6a1f1dSLionel Sambuc  */
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc #include <sys/types.h>
44*0a6a1f1dSLionel Sambuc #include <sys/param.h>
45*0a6a1f1dSLionel Sambuc #include <sys/socket.h>
46*0a6a1f1dSLionel Sambuc 
47*0a6a1f1dSLionel Sambuc #include <netinet/in.h>
48*0a6a1f1dSLionel Sambuc #include <arpa/inet.h>
49*0a6a1f1dSLionel Sambuc 
50*0a6a1f1dSLionel Sambuc #include <ctype.h>
51*0a6a1f1dSLionel Sambuc #include <stdio.h>
52*0a6a1f1dSLionel Sambuc #include <stdlib.h>
53*0a6a1f1dSLionel Sambuc #include <string.h>
54*0a6a1f1dSLionel Sambuc 
55*0a6a1f1dSLionel Sambuc #define Assert(Cond) if (!(Cond)) abort()
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc static const char Base64[] =
58*0a6a1f1dSLionel Sambuc 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
59*0a6a1f1dSLionel Sambuc static const char Pad64 = '=';
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
62*0a6a1f1dSLionel Sambuc    The following encoding technique is taken from RFC 1521 by Borenstein
63*0a6a1f1dSLionel Sambuc    and Freed.  It is reproduced here in a slightly edited form for
64*0a6a1f1dSLionel Sambuc    convenience.
65*0a6a1f1dSLionel Sambuc 
66*0a6a1f1dSLionel Sambuc    A 65-character subset of US-ASCII is used, enabling 6 bits to be
67*0a6a1f1dSLionel Sambuc    represented per printable character. (The extra 65th character, "=",
68*0a6a1f1dSLionel Sambuc    is used to signify a special processing function.)
69*0a6a1f1dSLionel Sambuc 
70*0a6a1f1dSLionel Sambuc    The encoding process represents 24-bit groups of input bits as output
71*0a6a1f1dSLionel Sambuc    strings of 4 encoded characters. Proceeding from left to right, a
72*0a6a1f1dSLionel Sambuc    24-bit input group is formed by concatenating 3 8-bit input groups.
73*0a6a1f1dSLionel Sambuc    These 24 bits are then treated as 4 concatenated 6-bit groups, each
74*0a6a1f1dSLionel Sambuc    of which is translated into a single digit in the base64 alphabet.
75*0a6a1f1dSLionel Sambuc 
76*0a6a1f1dSLionel Sambuc    Each 6-bit group is used as an index into an array of 64 printable
77*0a6a1f1dSLionel Sambuc    characters. The character referenced by the index is placed in the
78*0a6a1f1dSLionel Sambuc    output string.
79*0a6a1f1dSLionel Sambuc 
80*0a6a1f1dSLionel Sambuc                          Table 1: The Base64 Alphabet
81*0a6a1f1dSLionel Sambuc 
82*0a6a1f1dSLionel Sambuc       Value Encoding  Value Encoding  Value Encoding  Value Encoding
83*0a6a1f1dSLionel Sambuc           0 A            17 R            34 i            51 z
84*0a6a1f1dSLionel Sambuc           1 B            18 S            35 j            52 0
85*0a6a1f1dSLionel Sambuc           2 C            19 T            36 k            53 1
86*0a6a1f1dSLionel Sambuc           3 D            20 U            37 l            54 2
87*0a6a1f1dSLionel Sambuc           4 E            21 V            38 m            55 3
88*0a6a1f1dSLionel Sambuc           5 F            22 W            39 n            56 4
89*0a6a1f1dSLionel Sambuc           6 G            23 X            40 o            57 5
90*0a6a1f1dSLionel Sambuc           7 H            24 Y            41 p            58 6
91*0a6a1f1dSLionel Sambuc           8 I            25 Z            42 q            59 7
92*0a6a1f1dSLionel Sambuc           9 J            26 a            43 r            60 8
93*0a6a1f1dSLionel Sambuc          10 K            27 b            44 s            61 9
94*0a6a1f1dSLionel Sambuc          11 L            28 c            45 t            62 +
95*0a6a1f1dSLionel Sambuc          12 M            29 d            46 u            63 /
96*0a6a1f1dSLionel Sambuc          13 N            30 e            47 v
97*0a6a1f1dSLionel Sambuc          14 O            31 f            48 w         (pad) =
98*0a6a1f1dSLionel Sambuc          15 P            32 g            49 x
99*0a6a1f1dSLionel Sambuc          16 Q            33 h            50 y
100*0a6a1f1dSLionel Sambuc 
101*0a6a1f1dSLionel Sambuc    Special processing is performed if fewer than 24 bits are available
102*0a6a1f1dSLionel Sambuc    at the end of the data being encoded.  A full encoding quantum is
103*0a6a1f1dSLionel Sambuc    always completed at the end of a quantity.  When fewer than 24 input
104*0a6a1f1dSLionel Sambuc    bits are available in an input group, zero bits are added (on the
105*0a6a1f1dSLionel Sambuc    right) to form an integral number of 6-bit groups.  Padding at the
106*0a6a1f1dSLionel Sambuc    end of the data is performed using the '=' character.
107*0a6a1f1dSLionel Sambuc 
108*0a6a1f1dSLionel Sambuc    Since all base64 input is an integral number of octets, only the
109*0a6a1f1dSLionel Sambuc          -------------------------------------------------
110*0a6a1f1dSLionel Sambuc    following cases can arise:
111*0a6a1f1dSLionel Sambuc 
112*0a6a1f1dSLionel Sambuc        (1) the final quantum of encoding input is an integral
113*0a6a1f1dSLionel Sambuc            multiple of 24 bits; here, the final unit of encoded
114*0a6a1f1dSLionel Sambuc 	   output will be an integral multiple of 4 characters
115*0a6a1f1dSLionel Sambuc 	   with no "=" padding,
116*0a6a1f1dSLionel Sambuc        (2) the final quantum of encoding input is exactly 8 bits;
117*0a6a1f1dSLionel Sambuc            here, the final unit of encoded output will be two
118*0a6a1f1dSLionel Sambuc 	   characters followed by two "=" padding characters, or
119*0a6a1f1dSLionel Sambuc        (3) the final quantum of encoding input is exactly 16 bits;
120*0a6a1f1dSLionel Sambuc            here, the final unit of encoded output will be three
121*0a6a1f1dSLionel Sambuc 	   characters followed by one "=" padding character.
122*0a6a1f1dSLionel Sambuc    */
123*0a6a1f1dSLionel Sambuc 
124*0a6a1f1dSLionel Sambuc int
b64_ntop(uint8_t const * src,size_t srclength,char * target,size_t targsize)125*0a6a1f1dSLionel Sambuc b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
126*0a6a1f1dSLionel Sambuc 	size_t datalength = 0;
127*0a6a1f1dSLionel Sambuc 	uint8_t input[3];
128*0a6a1f1dSLionel Sambuc 	uint8_t output[4];
129*0a6a1f1dSLionel Sambuc 	size_t i;
130*0a6a1f1dSLionel Sambuc 
131*0a6a1f1dSLionel Sambuc 	while (2 < srclength) {
132*0a6a1f1dSLionel Sambuc 		input[0] = *src++;
133*0a6a1f1dSLionel Sambuc 		input[1] = *src++;
134*0a6a1f1dSLionel Sambuc 		input[2] = *src++;
135*0a6a1f1dSLionel Sambuc 		srclength -= 3;
136*0a6a1f1dSLionel Sambuc 
137*0a6a1f1dSLionel Sambuc 		output[0] = input[0] >> 2;
138*0a6a1f1dSLionel Sambuc 		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
139*0a6a1f1dSLionel Sambuc 		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
140*0a6a1f1dSLionel Sambuc 		output[3] = input[2] & 0x3f;
141*0a6a1f1dSLionel Sambuc 		Assert(output[0] < 64);
142*0a6a1f1dSLionel Sambuc 		Assert(output[1] < 64);
143*0a6a1f1dSLionel Sambuc 		Assert(output[2] < 64);
144*0a6a1f1dSLionel Sambuc 		Assert(output[3] < 64);
145*0a6a1f1dSLionel Sambuc 
146*0a6a1f1dSLionel Sambuc 		if (datalength + 4 > targsize)
147*0a6a1f1dSLionel Sambuc 			return (-1);
148*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[0]];
149*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[1]];
150*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[2]];
151*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[3]];
152*0a6a1f1dSLionel Sambuc 	}
153*0a6a1f1dSLionel Sambuc 
154*0a6a1f1dSLionel Sambuc 	/* Now we worry about padding. */
155*0a6a1f1dSLionel Sambuc 	if (0 != srclength) {
156*0a6a1f1dSLionel Sambuc 		/* Get what's left. */
157*0a6a1f1dSLionel Sambuc 		input[0] = input[1] = input[2] = '\0';
158*0a6a1f1dSLionel Sambuc 		for (i = 0; i < srclength; i++)
159*0a6a1f1dSLionel Sambuc 			input[i] = *src++;
160*0a6a1f1dSLionel Sambuc 
161*0a6a1f1dSLionel Sambuc 		output[0] = input[0] >> 2;
162*0a6a1f1dSLionel Sambuc 		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
163*0a6a1f1dSLionel Sambuc 		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
164*0a6a1f1dSLionel Sambuc 		Assert(output[0] < 64);
165*0a6a1f1dSLionel Sambuc 		Assert(output[1] < 64);
166*0a6a1f1dSLionel Sambuc 		Assert(output[2] < 64);
167*0a6a1f1dSLionel Sambuc 
168*0a6a1f1dSLionel Sambuc 		if (datalength + 4 > targsize)
169*0a6a1f1dSLionel Sambuc 			return (-1);
170*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[0]];
171*0a6a1f1dSLionel Sambuc 		target[datalength++] = Base64[output[1]];
172*0a6a1f1dSLionel Sambuc 		if (srclength == 1)
173*0a6a1f1dSLionel Sambuc 			target[datalength++] = Pad64;
174*0a6a1f1dSLionel Sambuc 		else
175*0a6a1f1dSLionel Sambuc 			target[datalength++] = Base64[output[2]];
176*0a6a1f1dSLionel Sambuc 		target[datalength++] = Pad64;
177*0a6a1f1dSLionel Sambuc 	}
178*0a6a1f1dSLionel Sambuc 	if (datalength >= targsize)
179*0a6a1f1dSLionel Sambuc 		return (-1);
180*0a6a1f1dSLionel Sambuc 	target[datalength] = '\0';	/* Returned value doesn't count \0. */
181*0a6a1f1dSLionel Sambuc 	return (datalength);
182*0a6a1f1dSLionel Sambuc }
183