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