varnish-cache/lib/libvarnish/venc.c
1
/*-
2
 * Copyright (c) 2020 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <stdint.h>
35
#include <string.h>
36
#include <sys/types.h>
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "vrt.h"
41
#include "venc.h"
42
43
#include "vsb.h"
44
45
/*
46
 * Yes: Cumbersome.  But if "..." syntax is used, C adds a NUL
47
 */
48
49
static const char base64_enc[64] = {
50
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
51
    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
52
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
53
    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
54
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
55
    'o', 'p', 'r', 'q', 's', 't', 'u', 'v',
56
    'w', 'x', 'y', 'z', '0', '1', '2', '3',
57
    '4', '5', '6', '7', '8', '9', '+', '/'
58
};
59
60
/*
61
 * Encode base64 (RFC4648 section 4) into VSB.
62
 */
63
64
void
65 640
VENC_Encode_Base64(struct vsb *dst, const void *src, size_t len)
66
{
67 640
        const uint8_t *p = src;
68
        uint32_t u;
69
        char w[4];
70
71 640
        AN(dst);
72 640
        AN(src);
73 4280
        for (; len >= 3; len -= 3, p += 3) {
74 3640
                u = (p[0] << 16) | (p[1] << 8) | p[2];
75 3640
                w[3] = base64_enc[u & 0x3f];
76 3640
                u >>= 6;
77 3640
                w[2] = base64_enc[u & 0x3f];
78 3640
                u >>= 6;
79 3640
                w[1] = base64_enc[u & 0x3f];
80 3640
                u >>= 6;
81 3640
                w[0] = base64_enc[u & 0x3f];
82 3640
                if (VSB_bcat(dst, w, sizeof w))
83 0
                        break;
84 3640
        }
85 640
        if (len) {
86 640
                memset(w, '=', sizeof w);
87 640
                u = (p[0] << 16);
88 640
                if (len == 2)
89 520
                    u |= (p[1] << 8);
90 640
                w[0] = base64_enc[(u >> 18) & 0x3f];
91 640
                w[1] = base64_enc[(u >> 12) & 0x3f];
92 640
                if (len == 2)
93 520
                        w[2] = base64_enc[(u >> 6) & 0x3f];
94 640
                VSB_bcat(dst, w, sizeof w);
95 640
        }
96 640
}
97
98
#define BV 64
99
100
static const uint8_t base64_dec[256] = {
101
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
102
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
103
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, 62, BV, BV, BV, 63,
104
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BV, BV, BV,  0, BV, BV,
105
    BV,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
106
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BV, BV, BV, BV, BV,
107
    BV, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
108
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BV, BV, BV, BV, BV,
109
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
110
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
111
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
112
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
113
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
114
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
115
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV,
116
    BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV, BV
117
};
118
119
struct venc_state {
120
        unsigned                n;
121
        unsigned                f;
122
        uint8_t                 w;
123
        struct vsb              *vsb;
124
        const uint8_t           *tbl;
125
};
126
127
static const char *
128 480
venc_decode_base64(struct venc_state *ves, const char *b, const char *e)
129
{
130
        unsigned i;
131
132 480
        AN(ves);
133 480
        AN(ves->vsb);
134 480
        AN(ves->tbl);
135
136 480
        AN(b);
137 480
        if (e == NULL)
138 0
                e = strchr(b, '\0');
139 480
        assert(e >= b);
140
141 5880
        for (; b < e; b++) {
142 5800
                i = ves->tbl[*(const uint8_t*)b];
143 5800
                if (i == BV)
144 240
                        return (b);
145 5560
                if (*b == '=' && ves->n < 2)
146 120
                        return (b);
147 5440
                else if (*b == '=')
148 160
                        ves->f++;
149 5280
                else if (ves->f)
150 0
                        return (b - 1);
151 5440
                if (ves->f && ves->w)
152 40
                        return (b - 1);
153 5400
                switch(++ves->n) {
154
                case 1:
155 1480
                        ves->w = i << 2;
156 1480
                        break;
157
                case 2:
158 1400
                        ves->w |= i >> 4;
159 1400
                        VSB_putc(ves->vsb, ves->w);
160 1400
                        ves->w = i << 4;
161 1400
                        break;
162
                case 3:
163 1280
                        ves->w |= i >> 2;
164 1280
                        if (!ves->f)
165 1240
                                VSB_putc(ves->vsb, ves->w);
166 1280
                        ves->w = i << 6;
167 1280
                        break;
168
                case 4:
169 1240
                        ves->w |= i;
170 1240
                        if (!ves->f)
171 1160
                                VSB_putc(ves->vsb, ves->w);
172 1240
                        ves->w = 0;
173 1240
                        ves->n = 0;
174 1240
                        break;
175
                default:
176 0
                        WRONG("Wrong turn in venc_decode_base64()");
177 0
                }
178 5400
        }
179 80
        return (NULL);
180 480
}
181
182
/*
183
 * Decode base64 (RFC4648 section 4) into VSB.
184
 *
185
 * Returns NULL on success.
186
 * Returns pointer to offending input character on failure.
187
 */
188
189
const char *
190 480
VENC_Decode_Base64(struct vsb *dst, const char *b, const char *e)
191
{
192
        struct venc_state ves;
193
        const char *rv;
194
195 480
        memset(&ves, 0, sizeof ves);
196 480
        ves.vsb = dst;
197 480
        ves.tbl = base64_dec;
198
199 480
        rv = venc_decode_base64(&ves, b, e);
200 480
        if (rv)
201 400
                return (rv);
202 80
        if (ves.n)
203 0
                return (e);
204 80
        return (NULL);
205 480
}