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