vinyl-cache/vmod/vmod_blob_base64.c
0
/*-
1
 * Copyright 2015-2016 UPLEX - Nils Goroll Systemoptimierung
2
 * All rights reserved.
3
 *
4
 * Authors: Nils Goroll <nils.goroll@uplex.de>
5
 *          Geoffrey Simmons <geoffrey.simmons@uplex.de>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 * 1. Redistributions of source code must retain the above copyright notice,
12
 *    this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright notice,
14
 *    this list of conditions and the following disclaimer in the documentation
15
 *    and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
 * DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 *
28
 */
29
30
#include "config.h"
31
32
#include "vdef.h"
33
#include "vrt.h"
34
#include "vas.h"
35
#include "miniobj.h"
36
37
#include "vmod_blob.h"
38
39
static const struct b64_alphabet {
40
        const char b64[65];
41
        const int8_t i64[256];
42
        const int padding;
43
} b64_alphabet[] = {
44
        [BASE64] = {
45
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
46
                "ghijklmnopqrstuvwxyz0123456789+/",
47
                {
48
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
49
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
50
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
51
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
52
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
53
                        ILL, ILL, ILL,  62, ILL, ILL, ILL,  63, /* +, /    */
54
                         52,  53,  54,  55,  56,  57,  58,  59, /* 0 - 7   */
55
                         60,  61, ILL, ILL, ILL, PAD, ILL, ILL, /* 8, 9, = */
56
                        ILL,   0,   1,   2,   3,   4,   5,   6, /* A - G   */
57
                          7,   8,   9,  10,  11,  12,  13,  14, /* H - O   */
58
                         15,  16,  17,  18,  19,  20,  21,  22, /* P - W   */
59
                         23,  24,  25, ILL, ILL, ILL, ILL, ILL, /* X, Y, Z */
60
                        ILL,  26,  27,  28,  29,  30,  31,  32, /* a - g   */
61
                         33,  34,  35,  36,  37,  38,  39,  40, /* h - o   */
62
                         41,  42,  43,  44,  45,  46,  47,  48, /* p - w   */
63
                         49,  50,  51, ILL, ILL, ILL, ILL, ILL, /* x, y, z */
64
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
65
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
66
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
67
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
68
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
69
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
70
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
71
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
72
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
73
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
74
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
75
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
76
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
77
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
78
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
79
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
80
                },
81
                '='
82
        },
83
        [BASE64URL] = {
84
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
85
                "ghijklmnopqrstuvwxyz0123456789-_",
86
                {
87
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
88
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
89
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
90
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
91
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
92
                        ILL, ILL, ILL, ILL, ILL,  62, ILL, ILL, /* -       */
93
                         52,  53,  54,  55,  56,  57,  58,  59, /* 0 - 7   */
94
                         60,  61, ILL, ILL, ILL, PAD, ILL, ILL, /* 8, 9, = */
95
                        ILL,   0,   1,   2,   3,   4,   5,   6, /* A - G   */
96
                          7,   8,   9,  10,  11,  12,  13,  14, /* H - O   */
97
                         15,  16,  17,  18,  19,  20,  21,  22, /* P - W   */
98
                         23,  24,  25, ILL, ILL, ILL, ILL,  63, /* X-Z, _  */
99
                        ILL,  26,  27,  28,  29,  30,  31,  32, /* a - g   */
100
                         33,  34,  35,  36,  37,  38,  39,  40, /* h - o   */
101
                         41,  42,  43,  44,  45,  46,  47,  48, /* p - w   */
102
                         49,  50,  51, ILL, ILL, ILL, ILL, ILL, /* x, y, z */
103
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
104
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
105
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
106
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
107
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
108
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
109
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
110
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
111
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
112
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
113
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
114
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
115
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
116
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
117
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
118
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
119
                },
120
                '='
121
        },
122
        [BASE64URLNOPAD] = {
123
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
124
                "ghijklmnopqrstuvwxyz0123456789-_",
125
                {
126
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
127
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
128
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
129
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
130
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
131
                        ILL, ILL, ILL, ILL, ILL,  62, ILL, ILL, /* -       */
132
                         52,  53,  54,  55,  56,  57,  58,  59, /* 0 - 7   */
133
                         60,  61, ILL, ILL, ILL, ILL, ILL, ILL, /* 8, 9    */
134
                        ILL,   0,   1,   2,   3,   4,   5,   6, /* A - G   */
135
                          7,   8,   9,  10,  11,  12,  13,  14, /* H - O   */
136
                         15,  16,  17,  18,  19,  20,  21,  22, /* P - W   */
137
                         23,  24,  25, ILL, ILL, ILL, ILL,  63, /* X-Z, _  */
138
                        ILL,  26,  27,  28,  29,  30,  31,  32, /* a - g   */
139
                         33,  34,  35,  36,  37,  38,  39,  40, /* h - o   */
140
                         41,  42,  43,  44,  45,  46,  47,  48, /* p - w   */
141
                         49,  50,  51, ILL, ILL, ILL, ILL, ILL, /* x, y, z */
142
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
143
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
144
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
145
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
146
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
147
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
148
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
149
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
150
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
151
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
152
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
153
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
154
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
155
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
156
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
157
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
158
                },
159
                0
160
        },
161
        [BASE64CF] = {
162
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
163
                "ghijklmnopqrstuvwxyz0123456789-~",
164
                {
165
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
166
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
167
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
168
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
169
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
170
                        ILL, ILL, ILL, ILL, ILL,  62, ILL, ILL, /* -          */
171
                         52,  53,  54,  55,  56,  57,  58,  59, /* 0 - 7      */
172
                         60,  61, ILL, ILL, ILL, ILL, ILL, ILL, /* 8, 9       */
173
                        ILL,   0,   1,   2,   3,   4,   5,   6, /* A - G      */
174
                          7,   8,   9,  10,  11,  12,  13,  14, /* H - O      */
175
                         15,  16,  17,  18,  19,  20,  21,  22, /* P - W      */
176
                         23,  24,  25, ILL, ILL, ILL, ILL, PAD, /* X, Y, Z, _ */
177
                        ILL,  26,  27,  28,  29,  30,  31,  32, /* a - g      */
178
                         33,  34,  35,  36,  37,  38,  39,  40, /* h - o      */
179
                         41,  42,  43,  44,  45,  46,  47,  48, /* p - w      */
180
                         49,  50,  51, ILL, ILL, ILL,  63, ILL, /* x, y, z,  ~*/
181
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
182
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
183
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
184
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
185
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
186
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
187
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
188
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
189
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
190
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
191
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
192
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
193
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
194
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
195
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
196
                        ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
197
                },
198
                '_'
199
        }
200
};
201
#define base64_l(l)             (((l) << 2) / 3)
202
203
size_t
204 105
base64nopad_encode_l(size_t l)
205
{
206 105
        return (base64_l(l) + 4);
207
}
208
209
size_t
210 297
base64_encode_l(size_t l)
211
{
212 297
        return ((((base64_l(l)) + 3) & ~3) + 1);
213
}
214
215
size_t
216 192
base64_decode_l(size_t l)
217
{
218 192
        return ((l * 3) >> 2);
219
}
220
221
static inline int
222 7611
decode(char *restrict *restrict dest, blob_src_t buf,
223
    blob_len_t buflen, unsigned u, const int n)
224
{
225
        char *d;
226
        int i;
227
228 7611
        if (n <= 1) {
229 0
                errno = EINVAL;
230 0
                return (-1);
231
        }
232 7611
        d = *dest;
233 30177
        for (i = 0; i < n - 1; i++) {
234 22569
                if (d == buf + buflen) {
235 3
                        errno = ENOMEM;
236 3
                        return (-1);
237
                }
238 22566
                *d++ = (u >> 16) & 0xff;
239 22566
                u <<= 8;
240 22566
        }
241 7608
        *dest += d - *dest;
242 7608
        return (1);
243 7611
}
244
245
ssize_t
246 486
base64_encode(const enum encoding enc, const enum case_e kase,
247
    blob_dest_t buf, blob_len_t buflen,
248
    blob_src_t inbuf, blob_len_t inlength)
249
{
250 486
        const struct b64_alphabet *alpha = &b64_alphabet[enc];
251 486
        char *p = buf;
252 486
        const uint8_t *in = (const uint8_t *)inbuf;
253 486
        const uint8_t * const end = in + inlength;
254
255 486
        (void)kase;
256 486
        AN(buf);
257 486
        AN(alpha);
258 486
        if (in == NULL || inlength == 0)
259 300
                return (0);
260
261 744
        if ((enc == BASE64URLNOPAD &&
262 84
            buflen < base64nopad_encode_l(inlength)) ||
263 576
            (enc != BASE64URLNOPAD && buflen < base64_encode_l(inlength))) {
264 492
                errno = ENOMEM;
265 492
                return (-1);
266
        }
267
268 10377
        while (end - in >= 3) {
269 10047
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
270 10047
                *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
271 10047
                *p++ = alpha->b64[((in[1] << 2) | (in[2] >> 6)) & 0x3f];
272 10047
                *p++ = alpha->b64[in[2] & 0x3f];
273 10047
                in += 3;
274
        }
275 330
        if (end - in > 0) {
276 282
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
277 282
                if (end - in == 1) {
278 216
                        *p++ = alpha->b64[(in[0] << 4) & 0x3f];
279 216
                        if (alpha->padding) {
280 159
                                *p++ = alpha->padding;
281 159
                                *p++ = alpha->padding;
282 159
                        }
283 216
                }
284
                else {
285 66
                        *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
286 66
                        *p++ = alpha->b64[(in[1] << 2) & 0x3f];
287 66
                        if (alpha->padding) {
288 39
                                *p++ = alpha->padding;
289 39
                        }
290
                }
291 282
        }
292 330
        assert(p >= buf);
293 330
        assert(p <= buf + buflen);
294 330
        return (p - buf);
295 342
}
296
297
ssize_t
298 381
base64_decode(const enum encoding dec, blob_dest_t buf,
299
    blob_len_t buflen, ssize_t inlen, VCL_STRANDS strings)
300
{
301 381
        const struct b64_alphabet *alpha = &b64_alphabet[dec];
302
        const char *s;
303 381
        char *dest = buf;
304 381
        unsigned u = 0, term = 0;
305 381
        size_t len = SIZE_MAX;
306 381
        int n = 0, i;
307
        char b;
308
309 381
        AN(buf);
310 381
        AN(alpha);
311 381
        CHECK_OBJ_NOTNULL(strings, STRANDS_MAGIC);
312
313 381
        if (inlen >= 0)
314 141
                len = inlen;
315
316 864
        for (i = 0; len > 0 && i < strings->n; i++) {
317 549
                s = strings->p[i];
318
319 549
                if (s == NULL)
320 18
                        continue;
321 531
                if (*s && term) {
322 0
                        errno = EINVAL;
323 0
                        return (-1);
324
                }
325 30957
                while (*s && len) {
326 30492
                        b = alpha->i64[(uint8_t)*s];
327 30492
                        s++;
328 30492
                        len--;
329 30492
                        u <<= 6;
330 30492
                        if (b == ILL) {
331 63
                                errno = EINVAL;
332 63
                                return (-1);
333
                        }
334 30429
                        n++;
335 30429
                        if (b == PAD) {
336 180
                                term++;
337 180
                                continue;
338
                        }
339 30249
                        u |= (uint8_t)b;
340 30249
                        if (n == 4) {
341 7464
                                if (decode(&dest, buf, buflen, u, n-term) < 0)
342 3
                                        return (-1);
343 7461
                                n = 0;
344 7461
                        }
345
                }
346 465
        }
347 315
        if (n) {
348 147
                if (n - term != 0)
349 147
                        u <<= (6 * (4 - n));
350 147
                if (decode(&dest, buf, buflen, u, n-term) < 0)
351 0
                        return (-1);
352 147
        }
353
354 315
        return (dest - buf);
355 381
}