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