1 mike 1.1 #include "common.h"
2 #include "base64.h"
3
4 /* Maximum block size to send to Base64EncCallback (a multiple of 4) */
5
6 #if defined(CONFIG_FAVORSIZE)
7 # define BASE64ENC_BLOCK_SIZE 64
8 #else
9 # define BASE64ENC_BLOCK_SIZE 512
10 #endif
11
12 /* Maximum block size to send to Base64DecCallback (a multiple of 3) */
13 #if defined(CONFIG_FAVORSIZE)
14 # define BASE64DEC_BLOCK_SIZE 64
15 #else
16 # define BASE64DEC_BLOCK_SIZE 512
17 #endif
18
19 static const char encTable[64] =
20 {
21 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
22 mike 1.1 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
23 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
24 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
25 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
26 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
27 'w', 'x', 'y', 'z', '0', '1', '2', '3',
28 '4', '5', '6', '7', '8', '9', '+', '/',
29 };
30
31 MI_INLINE char Enc6Bits(unsigned char x)
32 {
33 return encTable[x];
34 }
35
36 int Base64Enc(
37 const void* data_,
38 size_t size,
39 Base64EncCallback callback,
40 void* callbackData)
41 {
42 const unsigned char* data = (const unsigned char*)data_;
43 mike 1.1 char buf[BASE64ENC_BLOCK_SIZE];
44 size_t n = 0;
45
46 /* Encode each group of 3 bytes into a group of 4 characters */
47
48 while (size)
49 {
50 unsigned int i1 = 0;
51 unsigned int i2 = 0;
52 unsigned int i3 = 0;
53 unsigned int i4 = 0;
54 size_t m = 0;
55 int done = 0;
56
57 /* Check whether there is room in the buffer for 4 more bytes (the
58 * maximum number of bytes that one pass of this loop can inject.
59 */
60
61 if (n + 4 > BASE64ENC_BLOCK_SIZE)
62 {
63 if ((*callback)(buf, n, callbackData) != 0)
64 mike 1.1 return -1;
65
66 n = 0;
67 }
68
69 /*
70 * B1 B2 B3
71 * +--------+--------+--------+
72 * |11111100|00002222|22333333|
73 * +--------+--------+--------+
74 */
75
76 /* Process byte 1 */
77 {
78 unsigned char b1 = *data++;
79 size--;
80 m++;
81
82 i1 |= (b1 & 0xFC) >> 2;
83 i2 |= (b1 & 0x03) << 4;
|
122 mike 1.1 }
123
124 /* Add padding */
125
126 switch (m)
127 {
128 case 1:
129 buf[n++] = '=';
130 /* Fallthorugh intentional */
131 case 2:
132 buf[n++] = '=';
133 }
134 }
135
136 /* Send any remaining bytes */
137
138 if (n)
139 {
140 if ((*callback)(buf, n, callbackData) != 0)
141 return -1;
142 }
143 mike 1.1
144 return 0;
145 }
146
147 #if !defined(CONFIG_FAVORSIZE)
148
149 /* decoding table: 0-63 - valid value, 64-padding, 65-skip, 0xFF-invalid */
150 static const unsigned char decTable[128] =
151 {
152 /* 0 - 31 */
153 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
154 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
155 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
156 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
157
158 /* 32 - 39: !"#$%&' */
159 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
160
161 /* 40 - 42: ()*+,-./ */
162 0xFF, 0xFF, 0xFF, 62, 0xFF, 0xFF, 0xFF, 63,
163
164 mike 1.1 /* 0 -9 */
165 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
166
167 /* :;<=>? */
168 0xFF,0xFF,0xFF,64,0xFF,0xFF,
169
170 /* @ A-Z */
171 0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
172 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
173
174 /* []\\^_` */
175 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
176
177 /* a-z */
178 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
179 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
180
181
182 /* {|} ~ 127 */
183 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
184 };
185 mike 1.1
186 #endif /* CONFIG_FAVORSIZE */
187
188 static unsigned char DecChar(unsigned char c)
189 {
190 #if defined(CONFIG_FAVORSIZE)
191
192 if (c >= 'A' && c <= 'Z')
193 return c - 'A';
194
195 if (c >= 'a' && c <= 'z')
196 return c - 'a' + 26;
197
198 if (c >= '0' && c <= '9')
199 return c - '0' + 52;
200
201 if (c == '+')
202 return 62;
203
204 if (c == '/')
205 return 63;
206 mike 1.1
207 if (c == '=')
208 return 64;
209
210 return 0xFF;
211
212 #else /* defined(CONFIG_FAVORSIZE) */
213
214 if (c >= 128)
215 return 0xFF;
216
217 return decTable[c];
218
219 #endif /* !defined(CONFIG_FAVORSIZE) */
220 }
221
222 int Base64Dec(
223 const void* data_,
224 size_t size,
225 Base64DecCallback callback,
226 void* callbackData)
227 mike 1.1 {
228 unsigned char* data = (unsigned char*)data_;
229 unsigned char* end = data + size;
230 unsigned char buf[BASE64DEC_BLOCK_SIZE];
231 size_t n = 0;
232
233 /* perform decoding - 4 input bytes are converted into 3 output,
234 * using porvided pointers data/tgt
235 * since decoding is done inplace and result is smaller than input,
236 * no checks for buffer size is required
237 */
238
239 while (data != end)
240 {
241 unsigned char c1;
242 unsigned char c2;
243 unsigned char c3;
244 unsigned char c4;
245
246 /* Decode character 1 */
247
248 mike 1.1 c1 = DecChar((*data++) & 0x7f);
249
250 if (c1 == 0xFF || data == end)
251 return -1;
252
253 /* Decode character 2 */
254
255 c2 = DecChar((*data++) & 0x7f);
256
257 if (c2 == 0xFF || data == end)
258 return -1;
259
260 /* Decode character 3 */
261
262 c3 = DecChar((*data++) & 0x7f);
263
264 if (c3 == 0xFF || data == end)
265 return -1;
266
267 /* Decode character 4 */
268
269 mike 1.1 c4 = DecChar((*data++) & 0x7f);
270
271 if (c4 == 0xFF)
272 return -1;
273
274 /* Invoke callback if buffer would overflow below */
275
276 if (n + 3 > BASE64ENC_BLOCK_SIZE)
277 {
278 if ((*callback)(buf, n, callbackData) != 0)
279 return -1;
280
281 n = 0;
282 }
283
284 /* Convert 4 characters to 3 bytes */
285
286 buf[n++] = (c1 << 2) | (c2 >> 4);
287
288 if (c3 != 64)
289 buf[n++] = ((c2 & 0xF) << 4) | (c3 >> 2);
290 mike 1.1
291 if (c4 != 64)
292 buf[n++] = ((c3 & 0x3) << 6) | c4;
293 }
294
295 /* Send any remaining bytes */
296
297 if (n)
298 {
299 if ((*callback)(buf, n, callbackData) != 0)
300 return -1;
301 }
302
|