1 /*
2 **  Copyright (c) 2005, 2008 Sendmail, Inc. and its suppliers.
3 **    All rights reserved.
4 **
5 **  Copyright (c) 2009, 2012, The Trusted Domain Project.  All rights reserved.
6 */
7 
8 /* system includes */
9 #include <sys/types.h>
10 #include <assert.h>
11 
12 /* libopendkim includes */
13 #include "base64.h"
14 
15 /* base64 alphabet */
16 static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17 
18 /* base64 decode stuff */
19 static int decoder[256] =
20 {
21 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 	0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
24 	0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
25 	14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
26 	0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
27 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0,
28 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
34 };
35 
36 #ifndef NULL
37 # define NULL	0
38 #endif /* ! NULL */
39 
40 /*
41 **  DKIM_BASE64_DECODE -- decode a base64 blob
42 **
43 **  Parameters:
44 **  	str -- string to decide
45 **  	buf -- where to write it
46 **  	buflen -- bytes available at "buf"
47 **
48 **  Return value:
49 **  	>= 0 -- success; length of what was decoded is returned
50 **  	-1 -- corrupt
51 **  	-2 -- not enough space at "buf"
52 */
53 
54 int
dkim_base64_decode(u_char * str,u_char * buf,size_t buflen)55 dkim_base64_decode(u_char *str, u_char *buf, size_t buflen)
56 {
57 	int n = 0;
58 	int bits = 0;
59 	int char_count = 0;
60 	u_char *c;
61 
62 	assert(str != NULL);
63 	assert(buf != NULL);
64 
65 	for (c = str; *c != '=' && *c != '\0'; c++)
66 	{
67 		/* end padding */
68 		if (*c == '=' || *c == '\0')
69 			break;
70 
71 		/* skip stuff not part of the base64 alphabet (RFC2045) */
72 		if (!((*c >= 'A' && *c <= 'Z') ||
73 		      (*c >= 'a' && *c <= 'z') ||
74 		      (*c >= '0' && *c <= '9') ||
75 		      (*c == '+') ||
76 		      (*c == '/')))
77 			continue;
78 
79 		/* everything else gets decoded */
80 		bits += decoder[(int) *c];
81 		char_count++;
82 		if (n + 3 > buflen)
83 			return -2;
84 		if (char_count == 4)
85 		{
86 			buf[n++] = (bits >> 16);
87 			buf[n++] = ((bits >> 8) & 0xff);
88 			buf[n++] = (bits & 0xff);
89 			bits = 0;
90 			char_count = 0;
91 		}
92 		else
93 		{
94 			bits <<= 6;
95 		}
96 	}
97 
98 	/* XXX -- don't bother checking for proper termination (for now) */
99 
100 	/* process trailing data, if any */
101 	switch (char_count)
102 	{
103 	  case 0:
104 		break;
105 
106 	  case 1:
107 		/* base64 decoding incomplete; at least two bits missing */
108 		return -1;
109 
110 	  case 2:
111 		if (n + 1 > buflen)
112 			return -2;
113 		buf[n++] = (bits >> 10);
114 		break;
115 
116 	  case 3:
117 		if (n + 2 > buflen)
118 			return -2;
119 		buf[n++] = (bits >> 16);
120 		buf[n++] = ((bits >> 8) & 0xff);
121 		break;
122 	}
123 
124 	return n;
125 }
126 
127 /*
128 **  DKIM_BASE64_ENCODE -- encode base64 data
129 **
130 **  Parameters:
131 **  	data -- data to encode
132 **  	datalen -- bytes at "data" to encode
133 **  	buf -- where to write the encoding
134 **  	buflen -- bytes available at "buf"
135 **
136 **  Return value:
137 **  	>= 0 -- success; number of bytes written to "buf" returned
138 **   	-1 -- failure (not enough space at "buf")
139 */
140 
141 int
dkim_base64_encode(u_char * data,size_t datalen,u_char * buf,size_t buflen)142 dkim_base64_encode(u_char *data, size_t datalen, u_char *buf, size_t buflen)
143 {
144 	int bits;
145 	int c;
146 	int char_count;
147 	size_t n;
148 
149 	assert(data != NULL);
150 	assert(buf != NULL);
151 
152 	bits = 0;
153 	char_count = 0;
154 	n = 0;
155 
156 	for (c = 0; c < datalen; c++)
157 	{
158 		bits += data[c];
159 		char_count++;
160 		if (char_count == 3)
161 		{
162 			if (n + 4 > buflen)
163 				return -1;
164 
165 			buf[n++] = alphabet[bits >> 18];
166 			buf[n++] = alphabet[(bits >> 12) & 0x3f];
167 			buf[n++] = alphabet[(bits >> 6) & 0x3f];
168 			buf[n++] = alphabet[bits & 0x3f];
169 			bits = 0;
170 			char_count = 0;
171 		}
172 		else
173 		{
174 			bits <<= 8;
175 		}
176 	}
177 
178 	if (char_count != 0)
179 	{
180 		if (n + 4 > buflen)
181 			return -1;
182 
183 		bits <<= 16 - (8 * char_count);
184 		buf[n++] = alphabet[bits >> 18];
185 		buf[n++] = alphabet[(bits >> 12) & 0x3f];
186 		if (char_count == 1)
187 		{
188 			buf[n++] = '=';
189 			buf[n++] = '=';
190 		}
191 		else
192 		{
193 			buf[n++] = alphabet[(bits >> 6) & 0x3f];
194 			buf[n++] = '=';
195 		}
196 	}
197 
198 	return n;
199 }
200