1 /* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "base32.h"
5 #include "buffer.h"
6 
7 static const char b32enc[] =
8 	"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
9 
10 static const char b32hexenc[] =
11 	"0123456789ABCDEFGHIJKLMNOPQRSTUV";
12 
13 static const unsigned char b32dec[256] = {
14 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
15 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
16 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
17 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
18 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
19 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
20 	0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 48-55 */
21 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
22 	0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* 64-71 */
23 	0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* 72-79 */
24 	0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* 80-87 */
25 	0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
26 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
27 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
28 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
29 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
30 
31 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
32 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 };
48 
49 static const unsigned char b32hexdec[256] = {
50 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
51 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
52 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
53 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
54 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
55 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
56 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 48-55 */
57 	0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
58 	0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 64-71 */
59 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 72-79 */
60 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 80-87 */
61 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
62 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
63 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
64 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
65 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
66 
67 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
68 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
80 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
81 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
83 };
84 
85 static void
base32_encode_with_alphabet(const char * alph,bool pad,const void * src,size_t src_size,buffer_t * dest)86 base32_encode_with_alphabet(const char *alph,
87 	bool pad, const void *src, size_t src_size, buffer_t *dest)
88 {
89 	const unsigned char *src_c = src;
90 	unsigned char tmp[8], endb;
91 	size_t src_pos;
92 
93 	/* [5  3][2  5  1][4  4][1  5  2][3  5]
94 	   (5)(3  2)(5)(1  4)(4  1)(5)(2  3)(5)
95 	 */
96 
97 	/* encode main part */
98 	for (src_pos = 0; src_pos + 4 < src_size; src_pos += 5) {
99 		tmp[0] = alph[src_c[src_pos] >> 3];
100 		tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
101 				((src_c[src_pos+1] >> 6) & 0x03)];
102 		tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
103 		tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
104 				(src_c[src_pos+2] >> 4)];
105 		tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
106 				(src_c[src_pos+3] >> 7)];
107 		tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
108 		tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3) |
109 				(src_c[src_pos+4] >> 5)];
110 		tmp[7] = alph[src_c[src_pos+4] & 0x1f];
111 		buffer_append(dest, tmp, 8);
112 	}
113 
114 	/* encode last < 5 bytes if any */
115 	if (src_pos < src_size) {
116 		tmp[0] = alph[src_c[src_pos] >> 3];
117 		switch (src_size - src_pos) {
118 		case 1:
119 			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2)];
120 			endb = 2;
121 			break;
122 		case 2:
123 			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
124 					((src_c[src_pos+1] >> 6) & 0x03)];
125 			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
126 			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4)];
127 			endb = 4;
128 			break;
129 		case 3:
130 			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
131 					((src_c[src_pos+1] >> 6) & 0x03)];
132 			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
133 			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
134 					(src_c[src_pos+2] >> 4)];
135 			tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1)];
136 			endb = 5;
137 			break;
138 		case 4:
139 			tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
140 					((src_c[src_pos+1] >> 6) & 0x03)];
141 			tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
142 			tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
143 					(src_c[src_pos+2] >> 4)];
144 			tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
145 					(src_c[src_pos+3] >> 7)];
146 			tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
147 			tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3)];
148 			endb = 7;
149 			break;
150 		default:
151 			i_unreached();
152 		}
153 
154 		/* add padding if required */
155 		if (pad) {
156 			memset(&tmp[endb], '=', sizeof(tmp)-endb);
157 			buffer_append(dest, tmp, 8);
158 		} else {
159 			buffer_append(dest, tmp, endb);
160 		}
161 	}
162 }
163 
base32_encode(bool pad,const void * src,size_t src_size,buffer_t * dest)164 void base32_encode(bool pad, const void *src, size_t src_size,
165 	buffer_t *dest)
166 {
167 	base32_encode_with_alphabet(b32enc, pad, src, src_size, dest);
168 }
169 
base32hex_encode(bool pad,const void * src,size_t src_size,buffer_t * dest)170 void base32hex_encode(bool pad, const void *src, size_t src_size,
171 	buffer_t *dest)
172 {
173 	base32_encode_with_alphabet(b32hexenc, pad, src, src_size, dest);
174 }
175 
176 #define IS_EMPTY(c) \
177 	((c) == '\n' || (c) == '\r' || (c) == ' ' || (c) == '\t')
178 
179 static int
base32_decode_with_alphabet(const unsigned char * alph,const void * src,size_t src_size,size_t * src_pos_r,buffer_t * dest)180 base32_decode_with_alphabet(const unsigned char *alph,
181 		  const void *src, size_t src_size, size_t *src_pos_r,
182 		  buffer_t *dest)
183 {
184 	const unsigned char *src_c = src;
185 	size_t block_pos, src_pos;
186 	unsigned char output[5], ipos, opos;
187 	int ret = 1;
188 
189 	/* (5)(3  2)(5)(1  4)(4  1)(5)(2  3)(5)
190 	   [5  3][2  5  1][4  4][1  5  2][3  5]
191 	 */
192 	ipos = opos = 0;
193 	block_pos = 0;
194 	for (src_pos = 0; src_pos < src_size; src_pos++) {
195 		unsigned char input = alph[src_c[src_pos]];
196 
197 		if (input == 0xff) {
198 			if (unlikely(!IS_EMPTY(src_c[src_pos])))
199 				break;
200 			continue;
201 		}
202 
203 		ipos++;
204 		switch (ipos) {
205 		case 1:
206 			output[0] = input << 3;
207 			opos = 0;
208 			break;
209 		case 2:
210 			output[0] |= input >> 2;
211 			output[1] = (input & 0x03) << 6;
212 			opos = 1;
213 			break;
214 		case 3:
215 		 	output[1] |= input << 1;
216 			opos = 1;
217 			break;
218 		case 4:
219 			output[1] |= input >> 4;
220 			output[2] = (input & 0x0f) << 4;
221 			opos = 2;
222 			break;
223 		case 5:
224 			output[2] |= input >> 1;
225 			output[3] = (input & 0x01) << 7;
226 			opos = 3;
227 			break;
228 		case 6:
229 			output[3] |= input << 2;
230 			opos = 3;
231 			break;
232 		case 7:
233 			output[3] |= input >> 3;
234 			output[4] = ((input & 0x07) << 5);
235 			opos = 4;
236 			break;
237 		case 8:
238 			output[4] |= input;
239 			buffer_append(dest, output, 5);
240 			ipos = 0;
241 			opos = 0;
242 			block_pos = src_pos;
243 			break;
244 		default:
245 			i_unreached();
246 		}
247 	}
248 
249 	if (ipos > 0) {
250 		for (; src_pos < src_size; src_pos++) {
251 			if (src_c[src_pos] != '=') {
252 				if (unlikely(!IS_EMPTY(src_c[src_pos]))) {
253 					ret = -1;
254 					break;
255 				}
256 				continue;
257 			}
258 			if (++ipos >= 8) {
259 				buffer_append(dest, output, opos);
260 				ipos = 0;
261 				ret = 0;
262 				src_pos++;
263 				break;
264 			}
265 		}
266 	}
267 
268 	if (src_pos_r != NULL) {
269 		if (ipos == 0) {
270 			for (; src_pos < src_size; src_pos++) {
271 				if (!IS_EMPTY(src_c[src_pos]))
272 					break;
273 			}
274 
275 			*src_pos_r = src_pos;
276 		} else {
277 			*src_pos_r = block_pos;
278 		}
279 	}
280 	return ret;
281 }
282 
base32_decode(const void * src,size_t src_size,size_t * src_pos_r,buffer_t * dest)283 int base32_decode(const void *src, size_t src_size,
284 		  size_t *src_pos_r, buffer_t *dest)
285 {
286 	return base32_decode_with_alphabet
287 		(b32dec, src, src_size, src_pos_r, dest);
288 }
base32hex_decode(const void * src,size_t src_size,size_t * src_pos_r,buffer_t * dest)289 int base32hex_decode(const void *src, size_t src_size,
290 		  size_t *src_pos_r, buffer_t *dest)
291 {
292 	return base32_decode_with_alphabet
293 		(b32hexdec, src, src_size, src_pos_r, dest);
294 }
295 
t_base32_decode_str(const char * str)296 buffer_t *t_base32_decode_str(const char *str)
297 {
298 	buffer_t *buf;
299 	size_t len = strlen(str);
300 
301 	buf = t_buffer_create(MAX_BASE32_DECODED_SIZE(len));
302 	(void)base32_decode(str, len, NULL, buf);
303 	return buf;
304 }
305 
t_base32hex_decode_str(const char * str)306 buffer_t *t_base32hex_decode_str(const char *str)
307 {
308 	buffer_t *buf;
309 	size_t len = strlen(str);
310 
311 	buf = t_buffer_create(MAX_BASE32_DECODED_SIZE(len));
312 	(void)base32hex_decode(str, len, NULL, buf);
313 	return buf;
314 }
315 
base32_is_valid_char(char c)316 bool base32_is_valid_char(char c)
317 {
318 	return b32dec[(uint8_t)c] != 0xff;
319 }
320 
base32hex_is_valid_char(char c)321 bool base32hex_is_valid_char(char c)
322 {
323 	return b32hexdec[(uint8_t)c] != 0xff;
324 }
325