1 /* $NetBSD: base64.c,v 1.1.1.2 2012/09/09 16:08:02 christos Exp $ */
2
3 /*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 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 #if !defined(LINT) && !defined(CODECENTER)
46 static const char rcsid[] = "Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp ";
47 #endif /* not lint */
48
49 #include "port_before.h"
50
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/socket.h>
54
55 #include <netinet/in.h>
56 #include <arpa/inet.h>
57 #include <arpa/nameser.h>
58
59 #include <ctype.h>
60 #include <resolv.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64
65 #include "port_after.h"
66
67 #define Assert(Cond) if (!(Cond)) abort()
68
69 static const char Base64[] =
70 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
71 static const char Pad64 = '=';
72
73 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
74 The following encoding technique is taken from RFC1521 by Borenstein
75 and Freed. It is reproduced here in a slightly edited form for
76 convenience.
77
78 A 65-character subset of US-ASCII is used, enabling 6 bits to be
79 represented per printable character. (The extra 65th character, "=",
80 is used to signify a special processing function.)
81
82 The encoding process represents 24-bit groups of input bits as output
83 strings of 4 encoded characters. Proceeding from left to right, a
84 24-bit input group is formed by concatenating 3 8-bit input groups.
85 These 24 bits are then treated as 4 concatenated 6-bit groups, each
86 of which is translated into a single digit in the base64 alphabet.
87
88 Each 6-bit group is used as an index into an array of 64 printable
89 characters. The character referenced by the index is placed in the
90 output string.
91
92 Table 1: The Base64 Alphabet
93
94 Value Encoding Value Encoding Value Encoding Value Encoding
95 0 A 17 R 34 i 51 z
96 1 B 18 S 35 j 52 0
97 2 C 19 T 36 k 53 1
98 3 D 20 U 37 l 54 2
99 4 E 21 V 38 m 55 3
100 5 F 22 W 39 n 56 4
101 6 G 23 X 40 o 57 5
102 7 H 24 Y 41 p 58 6
103 8 I 25 Z 42 q 59 7
104 9 J 26 a 43 r 60 8
105 10 K 27 b 44 s 61 9
106 11 L 28 c 45 t 62 +
107 12 M 29 d 46 u 63 /
108 13 N 30 e 47 v
109 14 O 31 f 48 w (pad) =
110 15 P 32 g 49 x
111 16 Q 33 h 50 y
112
113 Special processing is performed if fewer than 24 bits are available
114 at the end of the data being encoded. A full encoding quantum is
115 always completed at the end of a quantity. When fewer than 24 input
116 bits are available in an input group, zero bits are added (on the
117 right) to form an integral number of 6-bit groups. Padding at the
118 end of the data is performed using the '=' character.
119
120 Since all base64 input is an integral number of octets, only the
121 -------------------------------------------------
122 following cases can arise:
123
124 (1) the final quantum of encoding input is an integral
125 multiple of 24 bits; here, the final unit of encoded
126 output will be an integral multiple of 4 characters
127 with no "=" padding,
128 (2) the final quantum of encoding input is exactly 8 bits;
129 here, the final unit of encoded output will be two
130 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
136 int
b64_ntop(u_char const * src,size_t srclength,char * target,size_t targsize)137 b64_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
202 int
b64_pton(src,target,targsize)203 b64_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