vinyl-cache/vmod/vmod_blob_base64.c
0
/*-
1
 * Copyright 2015-2016,2026 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 735
base64nopad_encode_l(size_t l)
205
{
206 735
        return (base64_l(l) + 4);
207
}
208
209
size_t
210 2121
base64_encode_l(size_t l)
211
{
212 2121
        return ((((base64_l(l)) + 3) & ~3) + 1);
213
}
214
215
size_t
216 1365
base64_decode_l(size_t l)
217
{
218 1365
        return ((l * 3) >> 2);
219
}
220
221
static inline int
222 53487
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 53487
        if (n <= 1) {
229 0
                errno = EINVAL;
230 0
                return (-1);
231
        }
232 53487
        d = *dest;
233 212016
        for (i = 0; i < n - 1; i++) {
234 158550
                if (d == buf + buflen) {
235 21
                        errno = ENOMEM;
236 21
                        return (-1);
237
                }
238 158529
                *d++ = (u >> 16) & 0xff;
239 158529
                u <<= 8;
240 158529
        }
241 53466
        *dest += d - *dest;
242 53466
        return (1);
243 53487
}
244
245
ssize_t
246 3444
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 3444
        const struct b64_alphabet *alpha = &b64_alphabet[enc];
251 3444
        char *p = buf;
252 3444
        const uint8_t *in = (const uint8_t *)inbuf;
253 3444
        const uint8_t * const end = in + inlength;
254
255 3444
        (void)kase;
256 3444
        AN(buf);
257 3444
        AN(alpha);
258 3444
        if (in == NULL || inlength == 0)
259 2100
                return (0);
260
261 5292
        if ((enc == BASE64URLNOPAD &&
262 588
            buflen < base64nopad_encode_l(inlength)) ||
263 4074
            (enc != BASE64URLNOPAD && buflen < base64_encode_l(inlength))) {
264 3486
                errno = ENOMEM;
265 3486
                return (-1);
266
        }
267
268 72639
        while (end - in >= 3) {
269 70329
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
270 70329
                *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
271 70329
                *p++ = alpha->b64[((in[1] << 2) | (in[2] >> 6)) & 0x3f];
272 70329
                *p++ = alpha->b64[in[2] & 0x3f];
273 70329
                in += 3;
274
        }
275 2310
        if (end - in > 0) {
276 1974
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
277 1974
                if (end - in == 1) {
278 1512
                        *p++ = alpha->b64[(in[0] << 4) & 0x3f];
279 1512
                        if (alpha->padding) {
280 1113
                                *p++ = alpha->padding;
281 1113
                                *p++ = alpha->padding;
282 1113
                        }
283 1512
                }
284
                else {
285 462
                        *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
286 462
                        *p++ = alpha->b64[(in[1] << 2) & 0x3f];
287 462
                        if (alpha->padding) {
288 273
                                *p++ = alpha->padding;
289 273
                        }
290
                }
291 1974
        }
292 2310
        assert(p >= buf);
293 2310
        assert(p <= buf + buflen);
294 2310
        return (p - buf);
295 2436
}
296
297
ssize_t
298 2814
base64_decode(const enum encoding dec, blob_dest_t buf,
299
    blob_len_t buflen, ssize_t inlen, VCL_STRANDS strings, size_t *consumedp)
300
{
301 2814
        const struct b64_alphabet *alpha = &b64_alphabet[dec];
302
        const char *s;
303 2814
        char *dest = buf;
304 2814
        unsigned u = 0, term = 0;
305 2814
        size_t len = SIZE_MAX;
306 2814
        size_t consumed = 0;
307 2814
        int n = 0, i;
308
        char b;
309
        ssize_t r;
310
311
        /*lint --e{801} goto used as defer pattern */
312
313 2814
        AN(buf);
314 2814
        AN(alpha);
315 2814
        CHECK_OBJ_NOTNULL(strings, STRANDS_MAGIC);
316
317 2814
        if (inlen >= 0)
318 987
                len = inlen;
319
320 6384
        for (i = 0; len > 0 && i < strings->n; i++) {
321 4116
                s = strings->p[i];
322
323 4116
                if (s == NULL)
324 168
                        continue;
325 218106
                while (*s && len) {
326 214704
                        b = alpha->i64[(uint8_t)*s];
327 214704
                        s++;
328 214704
                        len--;
329 214704
                        u <<= 6;
330 214704
                        if (b == ILL) {
331 441
                                errno = EINVAL;
332 441
                                r = -1;
333 441
                                goto out;
334
                        }
335 214263
                        n++;
336 214263
                        if (b == PAD && term < 2) {
337 1428
                                term++;
338 1428
                                continue;
339
                        }
340 212835
                        if (term) {
341 84
                                errno = EINVAL;
342 84
                                r = -1;
343 84
                                goto out;
344
                        }
345 212751
                        u |= (uint8_t)b;
346 212751
                        if (n == 4) {
347 52416
                                if (decode(&dest, buf, buflen, u, n) < 0) {
348 21
                                        r = -1;
349 21
                                        goto out;
350
                                }
351 52395
                                consumed += n;
352 52395
                                n = 0;
353 52395
                        }
354
                }
355 3402
        }
356 2268
        if (n) {
357 1071
                if (n - term != 0)
358 1071
                        u <<= (6 * (4 - n));
359 1071
                if (decode(&dest, buf, buflen, u, n-term) < 0) {
360 0
                        r = -1;
361 0
                        goto out;
362
                }
363 1071
                consumed += n;
364 1071
        }
365
366 2268
        r = dest - buf;
367
368
    out:
369 2814
        if (consumedp)
370 1008
                *consumedp = consumed;
371 2814
        return (r);
372
}