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 140
base64nopad_encode_l(size_t l)
205
{
206 140
        return (base64_l(l) + 4);
207
}
208
209
size_t
210 404
base64_encode_l(size_t l)
211
{
212 404
        return ((((base64_l(l)) + 3) & ~3) + 1);
213
}
214
215
size_t
216 256
base64_decode_l(size_t l)
217
{
218 256
        return ((l * 3) >> 2);
219
}
220
221
static inline int
222 10148
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 10148
        if (n <= 1) {
229 0
                errno = EINVAL;
230 0
                return (-1);
231
        }
232 10148
        d = *dest;
233 40236
        for (i = 0; i < n - 1; i++) {
234 30092
                if (d == buf + buflen) {
235 4
                        errno = ENOMEM;
236 4
                        return (-1);
237
                }
238 30088
                *d++ = (u >> 16) & 0xff;
239 30088
                u <<= 8;
240 30088
        }
241 10144
        *dest += d - *dest;
242 10144
        return (1);
243 10148
}
244
245
ssize_t
246 656
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 656
        const struct b64_alphabet *alpha = &b64_alphabet[enc];
251 656
        char *p = buf;
252 656
        const uint8_t *in = (const uint8_t *)inbuf;
253 656
        const uint8_t * const end = in + inlength;
254
255 656
        (void)kase;
256 656
        AN(buf);
257 656
        AN(alpha);
258 656
        if (in == NULL || inlength == 0)
259 400
                return (0);
260
261 1008
        if ((enc == BASE64URLNOPAD &&
262 112
            buflen < base64nopad_encode_l(inlength)) ||
263 776
            (enc != BASE64URLNOPAD && buflen < base64_encode_l(inlength))) {
264 664
                errno = ENOMEM;
265 664
                return (-1);
266
        }
267
268 13836
        while (end - in >= 3) {
269 13396
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
270 13396
                *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
271 13396
                *p++ = alpha->b64[((in[1] << 2) | (in[2] >> 6)) & 0x3f];
272 13396
                *p++ = alpha->b64[in[2] & 0x3f];
273 13396
                in += 3;
274
        }
275 440
        if (end - in > 0) {
276 376
                *p++ = alpha->b64[(in[0] >> 2) & 0x3f];
277 376
                if (end - in == 1) {
278 288
                        *p++ = alpha->b64[(in[0] << 4) & 0x3f];
279 288
                        if (alpha->padding) {
280 212
                                *p++ = alpha->padding;
281 212
                                *p++ = alpha->padding;
282 212
                        }
283 288
                }
284
                else {
285 88
                        *p++ = alpha->b64[((in[0] << 4) | (in[1] >> 4)) & 0x3f];
286 88
                        *p++ = alpha->b64[(in[1] << 2) & 0x3f];
287 88
                        if (alpha->padding) {
288 52
                                *p++ = alpha->padding;
289 52
                        }
290
                }
291 376
        }
292 440
        assert(p >= buf);
293 440
        assert(p <= buf + buflen);
294 440
        return (p - buf);
295 464
}
296
297
ssize_t
298 508
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 508
        const struct b64_alphabet *alpha = &b64_alphabet[dec];
302
        const char *s;
303 508
        char *dest = buf;
304 508
        unsigned u = 0, term = 0;
305 508
        size_t len = SIZE_MAX;
306 508
        size_t consumed = 0;
307 508
        int n = 0, i;
308
        char b;
309
        ssize_t r;
310
311
        /*lint --e{801} goto used as defer pattern */
312
313 508
        AN(buf);
314 508
        AN(alpha);
315 508
        CHECK_OBJ_NOTNULL(strings, STRANDS_MAGIC);
316
317 508
        if (inlen >= 0)
318 188
                len = inlen;
319
320 1152
        for (i = 0; len > 0 && i < strings->n; i++) {
321 732
                s = strings->p[i];
322
323 732
                if (s == NULL)
324 24
                        continue;
325 708
                if (*s && term) {
326 0
                        errno = EINVAL;
327 0
                        r = -1;
328 0
                        goto out;
329
                }
330 41276
                while (*s && len) {
331 40656
                        b = alpha->i64[(uint8_t)*s];
332 40656
                        s++;
333 40656
                        len--;
334 40656
                        u <<= 6;
335 40656
                        if (b == ILL) {
336 84
                                errno = EINVAL;
337 84
                                r = -1;
338 84
                                goto out;
339
                        }
340 40572
                        n++;
341 40572
                        if (b == PAD) {
342 240
                                term++;
343 240
                                continue;
344
                        }
345 40332
                        u |= (uint8_t)b;
346 40332
                        if (n == 4) {
347 9952
                                if (decode(&dest, buf, buflen, u, n-term) < 0) {
348 4
                                        r = -1;
349 4
                                        goto out;
350
                                }
351 9948
                                consumed += n;
352 9948
                                n = 0;
353 9948
                        }
354
                }
355 620
        }
356 420
        if (n) {
357 196
                if (n - term != 0)
358 196
                        u <<= (6 * (4 - n));
359 196
                if (decode(&dest, buf, buflen, u, n-term) < 0) {
360 0
                        r = -1;
361 0
                        goto out;
362
                }
363 196
                consumed += n;
364 196
        }
365
366 420
        r = dest - buf;
367
368
    out:
369 508
        if (consumedp)
370 188
                *consumedp = consumed;
371 508
        return (r);
372
}