Initial import
[project/usign.git] / base64.c
1 /* $OpenBSD: base64.c,v 1.7 2013/12/31 02:32:56 tedu 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 #include <sys/types.h>
46 #include <ctype.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include "base64.h"
51
52 static const char Base64[] =
53 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
54 static const char Pad64 = '=';
55
56 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
57 The following encoding technique is taken from RFC 1521 by Borenstein
58 and Freed. It is reproduced here in a slightly edited form for
59 convenience.
60
61 A 65-character subset of US-ASCII is used, enabling 6 bits to be
62 represented per printable character. (The extra 65th character, "=",
63 is used to signify a special processing function.)
64
65 The encoding process represents 24-bit groups of input bits as output
66 strings of 4 encoded characters. Proceeding from left to right, a
67 24-bit input group is formed by concatenating 3 8-bit input groups.
68 These 24 bits are then treated as 4 concatenated 6-bit groups, each
69 of which is translated into a single digit in the base64 alphabet.
70
71 Each 6-bit group is used as an index into an array of 64 printable
72 characters. The character referenced by the index is placed in the
73 output string.
74
75 Table 1: The Base64 Alphabet
76
77 Value Encoding Value Encoding Value Encoding Value Encoding
78 0 A 17 R 34 i 51 z
79 1 B 18 S 35 j 52 0
80 2 C 19 T 36 k 53 1
81 3 D 20 U 37 l 54 2
82 4 E 21 V 38 m 55 3
83 5 F 22 W 39 n 56 4
84 6 G 23 X 40 o 57 5
85 7 H 24 Y 41 p 58 6
86 8 I 25 Z 42 q 59 7
87 9 J 26 a 43 r 60 8
88 10 K 27 b 44 s 61 9
89 11 L 28 c 45 t 62 +
90 12 M 29 d 46 u 63 /
91 13 N 30 e 47 v
92 14 O 31 f 48 w (pad) =
93 15 P 32 g 49 x
94 16 Q 33 h 50 y
95
96 Special processing is performed if fewer than 24 bits are available
97 at the end of the data being encoded. A full encoding quantum is
98 always completed at the end of a quantity. When fewer than 24 input
99 bits are available in an input group, zero bits are added (on the
100 right) to form an integral number of 6-bit groups. Padding at the
101 end of the data is performed using the '=' character.
102
103 Since all base64 input is an integral number of octets, only the
104 -------------------------------------------------
105 following cases can arise:
106
107 (1) the final quantum of encoding input is an integral
108 multiple of 24 bits; here, the final unit of encoded
109 output will be an integral multiple of 4 characters
110 with no "=" padding,
111 (2) the final quantum of encoding input is exactly 8 bits;
112 here, the final unit of encoded output will be two
113 characters followed by two "=" padding characters, or
114 (3) the final quantum of encoding input is exactly 16 bits;
115 here, the final unit of encoded output will be three
116 characters followed by one "=" padding character.
117 */
118
119 int b64_ntop(const void *_src, size_t srclength,
120 void *dest, size_t targsize)
121 {
122 const unsigned char *src = _src;
123 char *target = dest;
124 size_t datalength = 0;
125 u_char input[3];
126 u_char output[4];
127 int i;
128
129 while (2 < srclength) {
130 input[0] = *src++;
131 input[1] = *src++;
132 input[2] = *src++;
133 srclength -= 3;
134
135 output[0] = input[0] >> 2;
136 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
137 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
138 output[3] = input[2] & 0x3f;
139
140 if (datalength + 4 > targsize)
141 return (-1);
142 target[datalength++] = Base64[output[0]];
143 target[datalength++] = Base64[output[1]];
144 target[datalength++] = Base64[output[2]];
145 target[datalength++] = Base64[output[3]];
146 }
147
148 /* Now we worry about padding. */
149 if (0 != srclength) {
150 /* Get what's left. */
151 input[0] = input[1] = input[2] = '\0';
152 for (i = 0; i < srclength; i++)
153 input[i] = *src++;
154
155 output[0] = input[0] >> 2;
156 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
157 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
158
159 if (datalength + 4 > targsize)
160 return (-1);
161 target[datalength++] = Base64[output[0]];
162 target[datalength++] = Base64[output[1]];
163 if (srclength == 1)
164 target[datalength++] = Pad64;
165 else
166 target[datalength++] = Base64[output[2]];
167 target[datalength++] = Pad64;
168 }
169 if (datalength >= targsize)
170 return (-1);
171 target[datalength] = '\0'; /* Returned value doesn't count \0. */
172 return (datalength);
173 }
174
175 /* skips all whitespace anywhere.
176 converts characters, four at a time, starting at (or after)
177 src from base - 64 numbers into three 8 bit bytes in the target area.
178 it returns the number of data bytes stored at the target, or -1 on error.
179 */
180
181 int b64_pton(const void *_src, void *dest, size_t targsize)
182 {
183 const char *src = _src;
184 unsigned char *target = dest;
185 int tarindex, state, ch;
186 u_char nextbyte;
187 char *pos;
188
189 state = 0;
190 tarindex = 0;
191
192 while ((ch = (unsigned char)*src++) != '\0') {
193 if (isspace(ch)) /* Skip whitespace anywhere. */
194 continue;
195
196 if (ch == Pad64)
197 break;
198
199 pos = strchr(Base64, ch);
200 if (pos == 0) /* A non-base64 character. */
201 return (-1);
202
203 switch (state) {
204 case 0:
205 if (target) {
206 if (tarindex >= targsize)
207 return (-1);
208 target[tarindex] = (pos - Base64) << 2;
209 }
210 state = 1;
211 break;
212 case 1:
213 if (target) {
214 if (tarindex >= targsize)
215 return (-1);
216 target[tarindex] |= (pos - Base64) >> 4;
217 nextbyte = ((pos - Base64) & 0x0f) << 4;
218 if (tarindex + 1 < targsize)
219 target[tarindex+1] = nextbyte;
220 else if (nextbyte)
221 return (-1);
222 }
223 tarindex++;
224 state = 2;
225 break;
226 case 2:
227 if (target) {
228 if (tarindex >= targsize)
229 return (-1);
230 target[tarindex] |= (pos - Base64) >> 2;
231 nextbyte = ((pos - Base64) & 0x03) << 6;
232 if (tarindex + 1 < targsize)
233 target[tarindex+1] = nextbyte;
234 else if (nextbyte)
235 return (-1);
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 - Base64);
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 = (unsigned char)*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 = (unsigned char)*src++)
267 if (!isspace(ch))
268 break;
269 /* Make sure there is another trailing = sign. */
270 if (ch != Pad64)
271 return (-1);
272 ch = (unsigned char)*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 = (unsigned char)*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 && tarindex < targsize &&
292 target[tarindex] != 0)
293 return (-1);
294 }
295 } else {
296 /*
297 * We ended by seeing the end of the string. Make sure we
298 * have no partial bytes lying around.
299 */
300 if (state != 0)
301 return (-1);
302 }
303
304 return (tarindex);
305 }