7b8fe2920cf6e55fb02a23cb7b57624e3139d587
[paraslash.git] / base64.c
1 /*
2 * The code in this file was taken from openssh-5.2p1, Copyright (c) 1996 by
3 * Internet Software Consortium. Portions Copyright (c) 1995 by International
4 * Business Machines, Inc.
5 */
6
7 /** \file base64.c Uudecode and base64decode implementation. */
8
9 #include <regex.h>
10
11 #include "para.h"
12 #include "error.h"
13 #include "base64.h"
14 #include "string.h"
15
16 static const char Base64[] =
17 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18 static const unsigned char base64_tab[256] = {
19 255, 255, 255, 255, 255, 255, 255, 255, /* 00-07 */
20 255, 255, 255, 255, 255, 255, 255, 255, /* 08-0f */
21 255, 255, 255, 255, 255, 255, 255, 255, /* 10-17 */
22 255, 255, 255, 255, 255, 255, 255, 255, /* 18-1f */
23 255, 255, 255, 255, 255, 255, 255, 255, /* 20-2f */
24 255, 255, 255, 62, 255, 255, 255, 63, /* 28-2f */
25 52 , 53, 54, 55, 56, 57, 58, 59, /* 30-37 */
26 60 , 61, 255, 255, 255, 255, 255, 255, /* 38-3f */
27 255, 0, 1, 2, 3, 4, 5, 6, /* 40-47 */
28 7 , 8, 9, 10, 11, 12, 13, 14, /* 48-4f */
29 15 , 16, 17, 18, 19, 20, 21, 22, /* 50-57 */
30 23 , 24, 25, 255, 255, 255, 255, 255, /* 58-5f */
31 255, 26, 27, 28, 29, 30, 31, 32, /* 60-6f */
32 33 , 34, 35, 36, 37, 38, 39, 40, /* 68-6f */
33 41 , 42, 43, 44, 45, 46, 47, 48, /* 70-77 */
34 49 , 50, 51, 255, 255, 255, 255, 255, /* 78-7f */
35 255, 255, 255, 255, 255, 255, 255, 255, /* 80-87 */
36 255, 255, 255, 255, 255, 255, 255, 255, /* 88-8f */
37 255, 255, 255, 255, 255, 255, 255, 255, /* 90-97 */
38 255, 255, 255, 255, 255, 255, 255, 255, /* 98-9f */
39 255, 255, 255, 255, 255, 255, 255, 255, /* a0-a7 */
40 255, 255, 255, 255, 255, 255, 255, 255, /* a8-af */
41 255, 255, 255, 255, 255, 255, 255, 255, /* b0-b7 */
42 255, 255, 255, 255, 255, 255, 255, 255, /* b8-bf */
43 255, 255, 255, 255, 255, 255, 255, 255, /* c0-c7 */
44 255, 255, 255, 255, 255, 255, 255, 255, /* c8-cf */
45 255, 255, 255, 255, 255, 255, 255, 255, /* d0-d7 */
46 255, 255, 255, 255, 255, 255, 255, 255, /* d8-df */
47 255, 255, 255, 255, 255, 255, 255, 255, /* e0-e7 */
48 255, 255, 255, 255, 255, 255, 255, 255, /* e8-ef */
49 255, 255, 255, 255, 255, 255, 255, 255, /* f0-f7 */
50 255, 255, 255, 255, 255, 255, 255, 255, /* f8-ff */
51 };
52
53 /** Maximal possible size of the decoded data. */
54 #define BASE64_MAX_DECODED_SIZE(_encoded_size) ((_encoded_size) / 4 * 3)
55
56 #define PAD64 '='
57 /**
58 * base64-decode a buffer.
59 *
60 * \param src The buffer to decode.
61 * \param encoded_size The special value -1 means: look for terminating zero byte.
62 * \param result Points to dynamically allocated target buffer on success.
63 * \param decoded_size Number of bytes written to \a result.
64 *
65 * Skips all whitespace anywhere. Converts characters, four at a time, starting
66 * at (or after) src from base - 64 numbers into three 8 bit bytes in the
67 * target area.
68 *
69 * It is OK to pass a \p NULL pointer as \a decoded_size. The result is
70 * terminated with a zero byte.
71 *
72 * \return Standard. The contents of result \a and \a decoded_size are
73 * undefined on failure.
74 */
75 int base64_decode(char const *src, size_t encoded_size, char **result,
76 size_t *decoded_size)
77 {
78 size_t i, j, state; /* source/target indices */
79 const char *end = src + encoded_size, *p;
80 unsigned char *target, uch;
81
82 if (encoded_size == (size_t)-1)
83 encoded_size = strlen(src);
84 target = para_malloc(BASE64_MAX_DECODED_SIZE(encoded_size) + 1);
85
86 for (
87 i = 0, j = 0, state = 0;
88 i < encoded_size && (uch = src[i]) != '\0';
89 i++
90 ) {
91 if (para_isspace(uch)) /* Skip whitespace anywhere. */
92 continue;
93 if (uch == PAD64)
94 break;
95 if (base64_tab[uch] == 255) /* A non-base64 character. */
96 goto fail;
97 uch = base64_tab[uch];
98 switch (state) {
99 case 0:
100 target[j] = uch << 2;
101 break;
102 case 1:
103 target[j] |= uch >> 4;
104 j++;
105 target[j] = (uch & 0x0f) << 4;
106 break;
107 case 2:
108 target[j] |= uch >> 2;
109 j++;
110 target[j] = (uch & 0x03) << 6;
111 break;
112 case 3:
113 target[j] |= uch;
114 j++;
115 break;
116 }
117 state = (state + 1) % 4;
118 }
119 p = (i < encoded_size)? src + i : NULL;
120 /*
121 * We are done decoding Base-64 chars. Let's see if we ended
122 * on a byte boundary, and/or with erroneous trailing characters.
123 */
124 if (p && *p == PAD64) { /* We got a pad char. Skip it, get next. */
125 p++;
126 switch (state) {
127 case 0: /* Invalid = in first position */
128 case 1: /* Invalid = in second position */
129 goto fail;
130
131 case 2: /* Valid, means one byte of info */
132 /* Skip any number of spaces. */
133 for (; p < end && *p != '\0'; p++)
134 if (!para_isspace(*p))
135 break;
136 /* Make sure there is another trailing = sign. */
137 if (*p != PAD64)
138 goto fail;
139 /* Fall through to "single trailing =" case. */
140 p++;
141
142 case 3: /* Valid, means two bytes of info */
143 /*
144 * We know this char is an =. Is there anything but
145 * whitespace after it?
146 */
147 for (; p < end && *p != '\0'; p++)
148 if (!para_isspace(*p))
149 goto fail;
150 /*
151 * Now make sure for cases 2 and 3 that the "extra"
152 * bits that slopped past the last full byte were
153 * zeros. If we don't check them, they become a
154 * subliminal channel.
155 */
156 if (target[j] != 0)
157 goto fail;
158 }
159 } else {
160 /*
161 * We ended by seeing the end of the string. Make sure we
162 * have no partial bytes lying around.
163 */
164 if (state != 0)
165 goto fail;
166 }
167 /* success */
168 target[j] = '\0'; /* just to be sure */
169 if (decoded_size)
170 *decoded_size = j;
171 *result = (char *)target;
172 return 1;
173 fail:
174 free(target);
175 return -E_BASE64;
176 }
177
178 /**
179 * Decode a buffer using the uuencode Base64 algorithm.
180 *
181 * \param src The buffer to decode.
182 * \param encoded_size Number of input bytes in the source buffer.
183 * \param result Contains the decoded data on success.
184 * \param decoded_size Number of output bytes on success.
185 *
186 * This is just a simple wrapper for \ref base64_decode() which strips
187 * whitespace.
188 *
189 * \return The return value of the underlying call to \ref base64_decode().
190 *
191 * \sa uuencode(1), uudecode(1).
192 */
193 int uudecode(char const *src, size_t encoded_size, char **result,
194 size_t *decoded_size)
195 {
196 const char *end = src + encoded_size, *p;
197
198 /* skip whitespace and data */
199 for (p = src; p < end && (*p == ' ' || *p == '\t'); p++)
200 ;
201 for (; p < end && *p != '\0' && *p != ' ' && *p != '\t'; p++)
202 ;
203 /* and remove trailing whitespace because base64_decode needs this */
204 return base64_decode(src, p - src, result, decoded_size);
205 }