1 /*
2 
3 	This code is public domain software.
4 
5 */
6 
7 #include "base64.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 //  base64 encoding
13 //
14 //  buf:     binary input data
15 //  size:    size of input (bytes)
16 //  return:  base64-encoded string (null-terminated)
17 //           memory for output will be allocated here, free it later
18 //
base64_encode(const void * buf,size_t size)19 char* base64_encode(const void* buf, size_t size)
20 {
21 	static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22 
23 	char* str = (char*) malloc((size+3)*4/3 + 1);
24 
25 	char* p = str;
26 	const unsigned char* q = (const unsigned char*) buf;
27 	size_t i = 0;
28 
29 	if (str == NULL) {
30 		return NULL;
31 	}
32 
33 	while (i < size) {
34 		int c = q[i++];
35 		c *= 256;
36 		if (i < size)
37             c += q[i];
38 		i++;
39 
40 		c *= 256;
41 		if (i < size)
42             c += q[i];
43 		i++;
44 
45 		*p++ = base64[(c & 0x00fc0000) >> 18];
46 		*p++ = base64[(c & 0x0003f000) >> 12];
47 
48 		if (i > size + 1)
49 			*p++ = '=';
50 		else
51 			*p++ = base64[(c & 0x00000fc0) >> 6];
52 
53 		if (i > size)
54 			*p++ = '=';
55 		else
56 			*p++ = base64[c & 0x0000003f];
57 	}
58 
59 	*p = 0;
60 
61 	return str;
62 }
63 
64 
65 //  single base64 character conversion
66 //
POS(char c)67 static int POS(char c)
68 {
69 	if (c>='A' && c<='Z') return c - 'A';
70 	if (c>='a' && c<='z') return c - 'a' + 26;
71 	if (c>='0' && c<='9') return c - '0' + 52;
72 	if (c == '+') return 62;
73 	if (c == '/') return 63;
74 	if (c == '=') return -1;
75     return -2;
76 }
77 
78 //  base64 decoding
79 //
80 //  s:       base64 string, must be null-terminated
81 //  data:    output buffer for decoded data
82 //  data_len size of decoded data
83 //  return:  allocated data buffer
84 //
base64_decode(const char * s,size_t * data_len)85 void* base64_decode(const char* s, size_t *data_len)
86 {
87     const char *p;
88     unsigned char *q, *data;
89     int n[4] = { 0, 0, 0, 0 };
90 
91 	size_t len = strlen(s);
92 	if (len % 4)
93 		return NULL;
94 	data = (unsigned char*) malloc(len/4*3);
95 	q = (unsigned char*) data;
96 
97 	for (p = s; *p; ) {
98 	    n[0] = POS(*p++);
99 	    n[1] = POS(*p++);
100 	    n[2] = POS(*p++);
101 	    n[3] = POS(*p++);
102 
103             if (n[0] == -2 || n[1] == -2 || n[2] == -2 || n[3] == -2)
104                 return NULL;
105 
106 	    if (n[0] == -1 || n[1] == -1)
107 		return NULL;
108 
109 	    if (n[2] == -1 && n[3] != -1)
110 		return NULL;
111 
112             q[0] = (n[0] << 2) + (n[1] >> 4);
113 	    if (n[2] != -1)
114                 q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
115 	    if (n[3] != -1)
116                 q[2] = ((n[2] & 3) << 6) + n[3];
117 	    q += 3;
118 	}
119 
120 	*data_len = q-data - (n[2]==-1) - (n[3]==-1);
121 
122 	return data;
123 }
124