1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46: #include <config.h>
47:
48:
49: #include "base64.h"
50:
51:
52: #include <stdlib.h>
53:
54:
55: #include <limits.h>
56:
57: #include <string.h>
58:
59:
60: static inline unsigned char
61: to_uchar (char ch)
62: {
63: return ch;
64: }
65:
66:
67:
68:
69:
70: void
71: base64_encode (const char *restrict in, size_t inlen,
72: char *restrict out, size_t outlen)
73: {
74: static const char b64str[64] =
75: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
76:
77: while (inlen && outlen)
78: {
79: *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
80: if (!--outlen)
81: break;
82: *out++ = b64str[((to_uchar (in[0]) << 4)
83: + (--inlen ? to_uchar (in[1]) >> 4 : 0))
84: & 0x3f];
85: if (!--outlen)
86: break;
87: *out++ =
88: (inlen
89: ? b64str[((to_uchar (in[1]) << 2)
90: + (--inlen ? to_uchar (in[2]) >> 6 : 0))
91: & 0x3f]
92: : '=');
93: if (!--outlen)
94: break;
95: *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
96: if (!--outlen)
97: break;
98: if (inlen)
99: inlen--;
100: if (inlen)
101: in += 3;
102: }
103:
104: if (outlen)
105: *out = '\0';
106: }
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117: size_t
118: base64_encode_alloc (const char *in, size_t inlen, char **out)
119: {
120: size_t outlen = 1 + BASE64_LENGTH (inlen);
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134: if (inlen > outlen)
135: {
136: *out = NULL;
137: return 0;
138: }
139:
140: *out = malloc (outlen);
141: if (!*out)
142: return outlen;
143:
144: base64_encode (in, inlen, *out, outlen);
145:
146: return outlen - 1;
147: }
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158: #define B64(_) \
159: ((_) == 'A' ? 0 \
160: : (_) == 'B' ? 1 \
161: : (_) == 'C' ? 2 \
162: : (_) == 'D' ? 3 \
163: : (_) == 'E' ? 4 \
164: : (_) == 'F' ? 5 \
165: : (_) == 'G' ? 6 \
166: : (_) == 'H' ? 7 \
167: : (_) == 'I' ? 8 \
168: : (_) == 'J' ? 9 \
169: : (_) == 'K' ? 10 \
170: : (_) == 'L' ? 11 \
171: : (_) == 'M' ? 12 \
172: : (_) == 'N' ? 13 \
173: : (_) == 'O' ? 14 \
174: : (_) == 'P' ? 15 \
175: : (_) == 'Q' ? 16 \
176: : (_) == 'R' ? 17 \
177: : (_) == 'S' ? 18 \
178: : (_) == 'T' ? 19 \
179: : (_) == 'U' ? 20 \
180: : (_) == 'V' ? 21 \
181: : (_) == 'W' ? 22 \
182: : (_) == 'X' ? 23 \
183: : (_) == 'Y' ? 24 \
184: : (_) == 'Z' ? 25 \
185: : (_) == 'a' ? 26 \
186: : (_) == 'b' ? 27 \
187: : (_) == 'c' ? 28 \
188: : (_) == 'd' ? 29 \
189: : (_) == 'e' ? 30 \
190: : (_) == 'f' ? 31 \
191: : (_) == 'g' ? 32 \
192: : (_) == 'h' ? 33 \
193: : (_) == 'i' ? 34 \
194: : (_) == 'j' ? 35 \
195: : (_) == 'k' ? 36 \
196: : (_) == 'l' ? 37 \
197: : (_) == 'm' ? 38 \
198: : (_) == 'n' ? 39 \
199: : (_) == 'o' ? 40 \
200: : (_) == 'p' ? 41 \
201: : (_) == 'q' ? 42 \
202: : (_) == 'r' ? 43 \
203: : (_) == 's' ? 44 \
204: : (_) == 't' ? 45 \
205: : (_) == 'u' ? 46 \
206: : (_) == 'v' ? 47 \
207: : (_) == 'w' ? 48 \
208: : (_) == 'x' ? 49 \
209: : (_) == 'y' ? 50 \
210: : (_) == 'z' ? 51 \
211: : (_) == '0' ? 52 \
212: : (_) == '1' ? 53 \
213: : (_) == '2' ? 54 \
214: : (_) == '3' ? 55 \
215: : (_) == '4' ? 56 \
216: : (_) == '5' ? 57 \
217: : (_) == '6' ? 58 \
218: : (_) == '7' ? 59 \
219: : (_) == '8' ? 60 \
220: : (_) == '9' ? 61 \
221: : (_) == '+' ? 62 \
222: : (_) == '/' ? 63 \
223: : -1)
224:
225: static const signed char b64[0x100] = {
226: B64 (0), B64 (1), B64 (2), B64 (3),
227: B64 (4), B64 (5), B64 (6), B64 (7),
228: B64 (8), B64 (9), B64 (10), B64 (11),
229: B64 (12), B64 (13), B64 (14), B64 (15),
230: B64 (16), B64 (17), B64 (18), B64 (19),
231: B64 (20), B64 (21), B64 (22), B64 (23),
232: B64 (24), B64 (25), B64 (26), B64 (27),
233: B64 (28), B64 (29), B64 (30), B64 (31),
234: B64 (32), B64 (33), B64 (34), B64 (35),
235: B64 (36), B64 (37), B64 (38), B64 (39),
236: B64 (40), B64 (41), B64 (42), B64 (43),
237: B64 (44), B64 (45), B64 (46), B64 (47),
238: B64 (48), B64 (49), B64 (50), B64 (51),
239: B64 (52), B64 (53), B64 (54), B64 (55),
240: B64 (56), B64 (57), B64 (58), B64 (59),
241: B64 (60), B64 (61), B64 (62), B64 (63),
242: B64 (64), B64 (65), B64 (66), B64 (67),
243: B64 (68), B64 (69), B64 (70), B64 (71),
244: B64 (72), B64 (73), B64 (74), B64 (75),
245: B64 (76), B64 (77), B64 (78), B64 (79),
246: B64 (80), B64 (81), B64 (82), B64 (83),
247: B64 (84), B64 (85), B64 (86), B64 (87),
248: B64 (88), B64 (89), B64 (90), B64 (91),
249: B64 (92), B64 (93), B64 (94), B64 (95),
250: B64 (96), B64 (97), B64 (98), B64 (99),
251: B64 (100), B64 (101), B64 (102), B64 (103),
252: B64 (104), B64 (105), B64 (106), B64 (107),
253: B64 (108), B64 (109), B64 (110), B64 (111),
254: B64 (112), B64 (113), B64 (114), B64 (115),
255: B64 (116), B64 (117), B64 (118), B64 (119),
256: B64 (120), B64 (121), B64 (122), B64 (123),
257: B64 (124), B64 (125), B64 (126), B64 (127),
258: B64 (128), B64 (129), B64 (130), B64 (131),
259: B64 (132), B64 (133), B64 (134), B64 (135),
260: B64 (136), B64 (137), B64 (138), B64 (139),
261: B64 (140), B64 (141), B64 (142), B64 (143),
262: B64 (144), B64 (145), B64 (146), B64 (147),
263: B64 (148), B64 (149), B64 (150), B64 (151),
264: B64 (152), B64 (153), B64 (154), B64 (155),
265: B64 (156), B64 (157), B64 (158), B64 (159),
266: B64 (160), B64 (161), B64 (162), B64 (163),
267: B64 (164), B64 (165), B64 (166), B64 (167),
268: B64 (168), B64 (169), B64 (170), B64 (171),
269: B64 (172), B64 (173), B64 (174), B64 (175),
270: B64 (176), B64 (177), B64 (178), B64 (179),
271: B64 (180), B64 (181), B64 (182), B64 (183),
272: B64 (184), B64 (185), B64 (186), B64 (187),
273: B64 (188), B64 (189), B64 (190), B64 (191),
274: B64 (192), B64 (193), B64 (194), B64 (195),
275: B64 (196), B64 (197), B64 (198), B64 (199),
276: B64 (200), B64 (201), B64 (202), B64 (203),
277: B64 (204), B64 (205), B64 (206), B64 (207),
278: B64 (208), B64 (209), B64 (210), B64 (211),
279: B64 (212), B64 (213), B64 (214), B64 (215),
280: B64 (216), B64 (217), B64 (218), B64 (219),
281: B64 (220), B64 (221), B64 (222), B64 (223),
282: B64 (224), B64 (225), B64 (226), B64 (227),
283: B64 (228), B64 (229), B64 (230), B64 (231),
284: B64 (232), B64 (233), B64 (234), B64 (235),
285: B64 (236), B64 (237), B64 (238), B64 (239),
286: B64 (240), B64 (241), B64 (242), B64 (243),
287: B64 (244), B64 (245), B64 (246), B64 (247),
288: B64 (248), B64 (249), B64 (250), B64 (251),
289: B64 (252), B64 (253), B64 (254), B64 (255)
290: };
291:
292: #if UCHAR_MAX == 255
293: # define uchar_in_range(c) true
294: #else
295: # define uchar_in_range(c) ((c) <= 255)
296: #endif
297:
298:
299:
300:
301: bool
302: isbase64 (char ch)
303: {
304: return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
305: }
306:
307:
308: void
309: base64_decode_ctx_init (struct base64_decode_context *ctx)
310: {
311: ctx->i = 0;
312: }
313:
314:
315:
316:
317:
318:
319:
320:
321: static inline char *
322: get_4 (struct base64_decode_context *ctx,
323: char const *restrict *in, char const *restrict in_end,
324: size_t *n_non_newline)
325: {
326: if (ctx->i == 4)
327: ctx->i = 0;
328:
329: if (ctx->i == 0)
330: {
331: char const *t = *in;
332: if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
333: {
334:
335: *in += 4;
336: *n_non_newline = 4;
337: return (char *) t;
338: }
339: }
340:
341: {
342:
343: char const *p = *in;
344: while (p < in_end)
345: {
346: char c = *p++;
347: if (c != '\n')
348: {
349: ctx->buf[ctx->i++] = c;
350: if (ctx->i == 4)
351: break;
352: }
353: }
354:
355: *in = p;
356: *n_non_newline = ctx->i;
357: return ctx->buf;
358: }
359: }
360:
361: #define return_false \
362: do \
363: { \
364: *outp = out; \
365: return false; \
366: } \
367: while (false)
368:
369:
370:
371:
372:
373:
374:
375: static inline bool
376: decode_4 (char const *restrict in, size_t inlen,
377: char *restrict *outp, size_t *outleft)
378: {
379: char *out = *outp;
380: if (inlen < 2)
381: return false;
382:
383: if (!isbase64 (in[0]) || !isbase64 (in[1]))
384: return false;
385:
386: if (*outleft)
387: {
388: *out++ = ((b64[to_uchar (in[0])] << 2)
389: | (b64[to_uchar (in[1])] >> 4));
390: --*outleft;
391: }
392:
393: if (inlen == 2)
394: return_false;
395:
396: if (in[2] == '=')
397: {
398: if (inlen != 4)
399: return_false;
400:
401: if (in[3] != '=')
402: return_false;
403: }
404: else
405: {
406: if (!isbase64 (in[2]))
407: return_false;
408:
409: if (*outleft)
410: {
411: *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
412: | (b64[to_uchar (in[2])] >> 2));
413: --*outleft;
414: }
415:
416: if (inlen == 3)
417: return_false;
418:
419: if (in[3] == '=')
420: {
421: if (inlen != 4)
422: return_false;
423: }
424: else
425: {
426: if (!isbase64 (in[3]))
427: return_false;
428:
429: if (*outleft)
430: {
431: *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
432: | b64[to_uchar (in[3])]);
433: --*outleft;
434: }
435: }
436: }
437:
438: *outp = out;
439: return true;
440: }
441:
442:
443:
444:
445:
446:
447:
448:
449:
450:
451:
452:
453:
454:
455:
456:
457: bool
458: base64_decode (struct base64_decode_context *ctx,
459: const char *restrict in, size_t inlen,
460: char *restrict out, size_t *outlen)
461: {
462: size_t outleft = *outlen;
463: bool flush_ctx = inlen == 0;
464:
465: while (true)
466: {
467: size_t outleft_save = outleft;
468: if (ctx->i == 0 && !flush_ctx)
469: {
470: while (true)
471: {
472:
473:
474: outleft_save = outleft;
475: if (!decode_4 (in, inlen, &out, &outleft))
476: break;
477:
478: in += 4;
479: inlen -= 4;
480: }
481: }
482:
483: if (inlen == 0 && !flush_ctx)
484: break;
485:
486:
487:
488: if (inlen && *in == '\n')
489: {
490: ++in;
491: --inlen;
492: continue;
493: }
494:
495:
496: out -= outleft_save - outleft;
497: outleft = outleft_save;
498:
499: {
500: char const *in_end = in + inlen;
501: char const *non_nl = get_4 (ctx, &in, in_end, &inlen);
502:
503:
504:
505:
506: if (inlen == 0 || (inlen < 4 && !flush_ctx))
507: {
508: inlen = 0;
509: break;
510: }
511: if (!decode_4 (non_nl, inlen, &out, &outleft))
512: break;
513:
514: inlen = in_end - in;
515: }
516: }
517:
518: *outlen -= outleft;
519:
520: return inlen == 0;
521: }
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534: bool
535: base64_decode_alloc (struct base64_decode_context *ctx,
536: const char *in, size_t inlen, char **out,
537: size_t *outlen)
538: {
539:
540:
541: