xref: /dflybsd-src/contrib/ldns/compat/b64_ntop.c (revision 5340022ad92b5f5299ced3631de5d1bf90a7f749)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * Copyright (c) 1996, 1998 by Internet Software Consortium.
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * Permission to use, copy, modify, and distribute this software for any
5825eb42bSJan Lentfer  * purpose with or without fee is hereby granted, provided that the above
6825eb42bSJan Lentfer  * copyright notice and this permission notice appear in all copies.
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9825eb42bSJan Lentfer  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10825eb42bSJan Lentfer  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11825eb42bSJan Lentfer  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12825eb42bSJan Lentfer  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13825eb42bSJan Lentfer  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14825eb42bSJan Lentfer  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15825eb42bSJan Lentfer  * SOFTWARE.
16825eb42bSJan Lentfer  */
17825eb42bSJan Lentfer 
18825eb42bSJan Lentfer /*
19825eb42bSJan Lentfer  * Portions Copyright (c) 1995 by International Business Machines, Inc.
20825eb42bSJan Lentfer  *
21825eb42bSJan Lentfer  * International Business Machines, Inc. (hereinafter called IBM) grants
22825eb42bSJan Lentfer  * permission under its copyrights to use, copy, modify, and distribute this
23825eb42bSJan Lentfer  * Software with or without fee, provided that the above copyright notice and
24825eb42bSJan Lentfer  * all paragraphs of this notice appear in all copies, and that the name of IBM
25825eb42bSJan Lentfer  * not be used in connection with the marketing of any product incorporating
26825eb42bSJan Lentfer  * the Software or modifications thereof, without specific, written prior
27825eb42bSJan Lentfer  * permission.
28825eb42bSJan Lentfer  *
29825eb42bSJan Lentfer  * To the extent it has a right to do so, IBM grants an immunity from suit
30825eb42bSJan Lentfer  * under its patents, if any, for the use, sale or manufacture of products to
31825eb42bSJan Lentfer  * the extent that such products are used for performing Domain Name System
32825eb42bSJan Lentfer  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
33825eb42bSJan Lentfer  * granted for any product per se or for any other function of any product.
34825eb42bSJan Lentfer  *
35825eb42bSJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36825eb42bSJan Lentfer  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37825eb42bSJan Lentfer  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38825eb42bSJan Lentfer  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39825eb42bSJan Lentfer  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40825eb42bSJan Lentfer  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41825eb42bSJan Lentfer  */
42825eb42bSJan Lentfer #include <ldns/config.h>
43825eb42bSJan Lentfer #include <ctype.h>
44825eb42bSJan Lentfer #include <stdlib.h>
45825eb42bSJan Lentfer #include <string.h>
46825eb42bSJan Lentfer 
47825eb42bSJan Lentfer static const char Base64[] =
48825eb42bSJan Lentfer 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
49825eb42bSJan Lentfer static const char Pad64 = '=';
50825eb42bSJan Lentfer 
51825eb42bSJan Lentfer /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
52825eb42bSJan Lentfer    The following encoding technique is taken from RFC 1521 by Borenstein
53825eb42bSJan Lentfer    and Freed.  It is reproduced here in a slightly edited form for
54825eb42bSJan Lentfer    convenience.
55825eb42bSJan Lentfer 
56825eb42bSJan Lentfer    A 65-character subset of US-ASCII is used, enabling 6 bits to be
57825eb42bSJan Lentfer    represented per printable character. (The extra 65th character, "=",
58825eb42bSJan Lentfer    is used to signify a special processing function.)
59825eb42bSJan Lentfer 
60825eb42bSJan Lentfer    The encoding process represents 24-bit groups of input bits as output
61825eb42bSJan Lentfer    strings of 4 encoded characters. Proceeding from left to right, a
62825eb42bSJan Lentfer    24-bit input group is formed by concatenating 3 8-bit input groups.
63825eb42bSJan Lentfer    These 24 bits are then treated as 4 concatenated 6-bit groups, each
64825eb42bSJan Lentfer    of which is translated into a single digit in the base64 alphabet.
65825eb42bSJan Lentfer 
66825eb42bSJan Lentfer    Each 6-bit group is used as an index into an array of 64 printable
67825eb42bSJan Lentfer    characters. The character referenced by the index is placed in the
68825eb42bSJan Lentfer    output string.
69825eb42bSJan Lentfer 
70825eb42bSJan Lentfer                          Table 1: The Base64 Alphabet
71825eb42bSJan Lentfer 
72825eb42bSJan Lentfer       Value Encoding  Value Encoding  Value Encoding  Value Encoding
73825eb42bSJan Lentfer           0 A            17 R            34 i            51 z
74825eb42bSJan Lentfer           1 B            18 S            35 j            52 0
75825eb42bSJan Lentfer           2 C            19 T            36 k            53 1
76825eb42bSJan Lentfer           3 D            20 U            37 l            54 2
77825eb42bSJan Lentfer           4 E            21 V            38 m            55 3
78825eb42bSJan Lentfer           5 F            22 W            39 n            56 4
79825eb42bSJan Lentfer           6 G            23 X            40 o            57 5
80825eb42bSJan Lentfer           7 H            24 Y            41 p            58 6
81825eb42bSJan Lentfer           8 I            25 Z            42 q            59 7
82825eb42bSJan Lentfer           9 J            26 a            43 r            60 8
83825eb42bSJan Lentfer          10 K            27 b            44 s            61 9
84825eb42bSJan Lentfer          11 L            28 c            45 t            62 +
85825eb42bSJan Lentfer          12 M            29 d            46 u            63 /
86825eb42bSJan Lentfer          13 N            30 e            47 v
87825eb42bSJan Lentfer          14 O            31 f            48 w         (pad) =
88825eb42bSJan Lentfer          15 P            32 g            49 x
89825eb42bSJan Lentfer          16 Q            33 h            50 y
90825eb42bSJan Lentfer 
91825eb42bSJan Lentfer    Special processing is performed if fewer than 24 bits are available
92825eb42bSJan Lentfer    at the end of the data being encoded.  A full encoding quantum is
93825eb42bSJan Lentfer    always completed at the end of a quantity.  When fewer than 24 input
94825eb42bSJan Lentfer    bits are available in an input group, zero bits are added (on the
95825eb42bSJan Lentfer    right) to form an integral number of 6-bit groups.  Padding at the
96825eb42bSJan Lentfer    end of the data is performed using the '=' character.
97825eb42bSJan Lentfer 
98825eb42bSJan Lentfer    Since all base64 input is an integral number of octets, only the
99825eb42bSJan Lentfer          -------------------------------------------------
100825eb42bSJan Lentfer    following cases can arise:
101825eb42bSJan Lentfer 
102825eb42bSJan Lentfer        (1) the final quantum of encoding input is an integral
103825eb42bSJan Lentfer            multiple of 24 bits; here, the final unit of encoded
104825eb42bSJan Lentfer 	   output will be an integral multiple of 4 characters
105825eb42bSJan Lentfer 	   with no "=" padding,
106825eb42bSJan Lentfer        (2) the final quantum of encoding input is exactly 8 bits;
107825eb42bSJan Lentfer            here, the final unit of encoded output will be two
108825eb42bSJan Lentfer 	   characters followed by two "=" padding characters, or
109825eb42bSJan Lentfer        (3) the final quantum of encoding input is exactly 16 bits;
110825eb42bSJan Lentfer            here, the final unit of encoded output will be three
111825eb42bSJan Lentfer 	   characters followed by one "=" padding character.
112825eb42bSJan Lentfer    */
113825eb42bSJan Lentfer 
114825eb42bSJan Lentfer int
ldns_b64_ntop(uint8_t const * src,size_t srclength,char * target,size_t targsize)115825eb42bSJan Lentfer ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
116825eb42bSJan Lentfer 	size_t datalength = 0;
117825eb42bSJan Lentfer 	uint8_t input[3];
118825eb42bSJan Lentfer 	uint8_t output[4];
119825eb42bSJan Lentfer 	size_t i;
120825eb42bSJan Lentfer 
121825eb42bSJan Lentfer 	if (srclength == 0) {
122825eb42bSJan Lentfer 		if (targsize > 0) {
123825eb42bSJan Lentfer 			target[0] = '\0';
124825eb42bSJan Lentfer 			return 0;
125825eb42bSJan Lentfer 		} else {
126825eb42bSJan Lentfer 			return -1;
127825eb42bSJan Lentfer 		}
128825eb42bSJan Lentfer 	}
129825eb42bSJan Lentfer 
130825eb42bSJan Lentfer 	while (2 < srclength) {
131825eb42bSJan Lentfer 		input[0] = *src++;
132825eb42bSJan Lentfer 		input[1] = *src++;
133825eb42bSJan Lentfer 		input[2] = *src++;
134825eb42bSJan Lentfer 		srclength -= 3;
135825eb42bSJan Lentfer 
136825eb42bSJan Lentfer 		output[0] = input[0] >> 2;
137825eb42bSJan Lentfer 		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
138825eb42bSJan Lentfer 		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
139825eb42bSJan Lentfer 		output[3] = input[2] & 0x3f;
140*5340022aSzrj 		assert(output[0] < 64);
141*5340022aSzrj 		assert(output[1] < 64);
142*5340022aSzrj 		assert(output[2] < 64);
143*5340022aSzrj 		assert(output[3] < 64);
144825eb42bSJan Lentfer 
145825eb42bSJan Lentfer 		if (datalength + 4 > targsize) {
146825eb42bSJan Lentfer 			return (-1);
147825eb42bSJan Lentfer 		}
148825eb42bSJan Lentfer 		target[datalength++] = Base64[output[0]];
149825eb42bSJan Lentfer 		target[datalength++] = Base64[output[1]];
150825eb42bSJan Lentfer 		target[datalength++] = Base64[output[2]];
151825eb42bSJan Lentfer 		target[datalength++] = Base64[output[3]];
152825eb42bSJan Lentfer 	}
153825eb42bSJan Lentfer 
154825eb42bSJan Lentfer 	/* Now we worry about padding. */
155825eb42bSJan Lentfer 	if (0 != srclength) {
156825eb42bSJan Lentfer 		/* Get what's left. */
157825eb42bSJan Lentfer 		input[0] = input[1] = input[2] = (uint8_t) '\0';
158825eb42bSJan Lentfer 		for (i = 0; i < srclength; i++)
159825eb42bSJan Lentfer 			input[i] = *src++;
160825eb42bSJan Lentfer 
161825eb42bSJan Lentfer 		output[0] = input[0] >> 2;
162825eb42bSJan Lentfer 		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
163825eb42bSJan Lentfer 		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
164*5340022aSzrj 		assert(output[0] < 64);
165*5340022aSzrj 		assert(output[1] < 64);
166*5340022aSzrj 		assert(output[2] < 64);
167825eb42bSJan Lentfer 
168825eb42bSJan Lentfer 		if (datalength + 4 > targsize) {
169825eb42bSJan Lentfer 			return (-2);
170825eb42bSJan Lentfer 		}
171825eb42bSJan Lentfer 		target[datalength++] = Base64[output[0]];
172825eb42bSJan Lentfer 		target[datalength++] = Base64[output[1]];
173825eb42bSJan Lentfer 		if (srclength == 1) {
174825eb42bSJan Lentfer 			target[datalength++] = Pad64;
175825eb42bSJan Lentfer 		} else {
176825eb42bSJan Lentfer 			target[datalength++] = Base64[output[2]];
177825eb42bSJan Lentfer 		}
178825eb42bSJan Lentfer 		target[datalength++] = Pad64;
179825eb42bSJan Lentfer 	}
180825eb42bSJan Lentfer 	if (datalength >= targsize) {
181825eb42bSJan Lentfer 		return (-3);
182825eb42bSJan Lentfer 	}
183825eb42bSJan Lentfer 	target[datalength] = '\0';	/* Returned value doesn't count \0. */
184825eb42bSJan Lentfer 	return (int) (datalength);
185825eb42bSJan Lentfer }
186