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;
84 buf[n++] = Enc6Bits(i1);
85 mike 1.1 }
86
87 /* Process byte 2 */
88
89 if (size)
90 {
91 unsigned char b2 = *data++;
92 size--;
93 m++;
94
95 i2 |= (b2 & 0xF0) >> 4;
96 i3 |= (b2 & 0x0F) << 2;
97 buf[n++] = Enc6Bits(i2);
98 }
99 else
100 {
101 buf[n++] = Enc6Bits(i2);
102 done = 1;
103 }
104
105 /* Process byte 3 */
106 mike 1.1
107 if (size)
108 {
109 unsigned char b3 = *data++;
110 size--;
111 m++;
112
113 i3 |= (b3 & 0xCF) >> 6;
114 i4 |= b3 & 0x3F;
115
116 buf[n++] = Enc6Bits(i3);
117 buf[n++] = Enc6Bits(i4);
118 }
119 else if (!done)
120 {
121 buf[n++] = Enc6Bits(i3);
122 }
123
124 /* Add padding */
125
126 switch (m)
127 mike 1.1 {
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
144 return 0;
145 }
146
147 #if !defined(CONFIG_FAVORSIZE)
148 mike 1.1
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 /* 0 -9 */
165 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
166
167 /* :;<=>? */
168 0xFF,0xFF,0xFF,64,0xFF,0xFF,
169 mike 1.1
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
186 #endif /* CONFIG_FAVORSIZE */
187
188 static unsigned char DecChar(unsigned char c)
189 {
190 mike 1.1 #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
207 if (c == '=')
208 return 64;
209
210 return 0xFF;
211 mike 1.1
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 {
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 mike 1.1
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 c1 = DecChar((*data++) & 0x7f);
249
250 if (c1 == 0xFF || data == end)
251 return -1;
252
253 mike 1.1 /* 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 c4 = DecChar((*data++) & 0x7f);
270
271 if (c4 == 0xFF)
272 return -1;
273
274 mike 1.1 /* 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
291 if (c4 != 64)
292 buf[n++] = ((c3 & 0x3) << 6) | c4;
293 }
294
295 mike 1.1 /* Send any remaining bytes */
296
297 if (n)
298 {
299 if ((*callback)(buf, n, callbackData) != 0)
300 return -1;
301 }
302
303 return 0;
304 }
|