base64.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/*
10 * Copied from Nettle 3.4 under GPLv2, with adjustments
11 */
12
13#include "squid.h"
14#include "base64.h"
15
16#if !HAVE_NETTLE_BASE64_H || !HAVE_NETTLE34_BASE64
17
18/* base64-encode.c
19
20 Copyright (C) 2002 Niels Möller
21
22 This file is part of GNU Nettle.
23
24 GNU Nettle is free software: you can redistribute it and/or
25 modify it under the terms of either:
26
27 * the GNU Lesser General Public License as published by the Free
28 Software Foundation; either version 3 of the License, or (at your
29 option) any later version.
30
31 or
32
33 * the GNU General Public License as published by the Free
34 Software Foundation; either version 2 of the License, or (at your
35 option) any later version.
36
37 or both in parallel, as here.
38
39 GNU Nettle is distributed in the hope that it will be useful,
40 but WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 General Public License for more details.
43
44 You should have received copies of the GNU General Public License and
45 the GNU Lesser General Public License along with this program. If
46 not, see http://www.gnu.org/licenses/.
47*/
48
49#define TABLE_INVALID -1
50#define TABLE_SPACE -2
51#define TABLE_END -3
52
53void
55{
56 static const signed char base64_decode_table[0x100] =
57 {
58 /* White space is HT, VT, FF, CR, LF and SPC */
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
62 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1,
63 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
64 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
65 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
66 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 };
76
77 ctx->word = ctx->bits = ctx->padding = 0;
78 ctx->table = base64_decode_table;
79}
80
81int
83 uint8_t *dst,
84 char src)
85{
86 int data = ctx->table[(uint8_t) src];
87
88 switch(data)
89 {
90 default:
91 assert(data >= 0 && data < 0x40);
92
93 if (ctx->padding)
94 return -1;
95
96 ctx->word = ctx->word << 6 | data;
97 ctx->bits += 6;
98
99 if (ctx->bits >= 8)
100 {
101 ctx->bits -= 8;
102 dst[0] = ctx->word >> ctx->bits;
103 return 1;
104 }
105 else return 0;
106
107 case TABLE_INVALID:
108 return -1;
109
110 case TABLE_SPACE:
111 return 0;
112
113 case TABLE_END:
114 /* There can be at most two padding characters. */
115 if (!ctx->bits || ctx->padding > 2)
116 return -1;
117
118 if (ctx->word & ( (1<<ctx->bits) - 1))
119 /* We shouldn't have any leftover bits */
120 return -1;
121
122 ctx->padding++;
123 ctx->bits -= 2;
124 return 0;
125 }
126}
127
128int
130 size_t *dst_length,
131 uint8_t *dst,
132 size_t src_length,
133 const char *src)
134{
135 size_t done;
136 size_t i;
137
138 for (i = 0, done = 0; i<src_length; i++)
139 switch(base64_decode_single(ctx, dst + done, src[i]))
140 {
141 case -1:
142 return 0;
143 case 1:
144 done++;
145 /* Fall through */
146 case 0:
147 break;
148 default:
149 abort();
150 }
151
152 assert(done <= BASE64_DECODE_LENGTH(src_length));
153
154 *dst_length = done;
155 return 1;
156}
157
158int
160{
161 return ctx->bits == 0;
162}
163
164/* base64-encode.c */
165
166#define ENCODE(alphabet,x) ((alphabet)[0x3F & (x)])
167
168static void
169encode_raw(const char *alphabet,
170 char *dst, size_t length, const uint8_t *src)
171{
172 const uint8_t *in = src + length;
173 char *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
174
175 unsigned left_over = length % 3;
176
177 if (left_over)
178 {
179 in -= left_over;
180 *--out = '=';
181 switch(left_over)
182 {
183 case 1:
184 *--out = '=';
185 *--out = ENCODE(alphabet, (in[0] << 4));
186 break;
187
188 case 2:
189 *--out = ENCODE(alphabet, (in[1] << 2));
190 *--out = ENCODE(alphabet, ((in[0] << 4) | (in[1] >> 4)));
191 break;
192
193 default:
194 abort();
195 }
196 *--out = ENCODE(alphabet, (in[0] >> 2));
197 }
198
199 while (in > src)
200 {
201 in -= 3;
202 *--out = ENCODE(alphabet, (in[2]));
203 *--out = ENCODE(alphabet, ((in[1] << 2) | (in[2] >> 6)));
204 *--out = ENCODE(alphabet, ((in[0] << 4) | (in[1] >> 4)));
205 *--out = ENCODE(alphabet, (in[0] >> 2));
206 }
207 assert(in == src);
208 assert(out == dst);
209}
210
211static const char base64_encode_table[64] =
212 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
213 "abcdefghijklmnopqrstuvwxyz"
214 "0123456789+/";
215
216void
217base64_encode_raw(char *dst, size_t length, const uint8_t *src)
218{
219 encode_raw(base64_encode_table, dst, length, src);
220}
221
222void
223base64_encode_group(char *dst, uint32_t group)
224{
225 *dst++ = ENCODE(base64_encode_table, (group >> 18));
226 *dst++ = ENCODE(base64_encode_table, (group >> 12));
227 *dst++ = ENCODE(base64_encode_table, (group >> 6));
228 *dst++ = ENCODE(base64_encode_table, group);
229}
230
231void
233{
234 ctx->word = ctx->bits = 0;
236}
237
238/* Encodes a single byte. */
239size_t
241 char *dst,
242 uint8_t src)
243{
244 unsigned done = 0;
245 unsigned word = ctx->word << 8 | src;
246 unsigned bits = ctx->bits + 8;
247
248 while (bits >= 6)
249 {
250 bits -= 6;
251 dst[done++] = ENCODE(ctx->alphabet, (word >> bits));
252 }
253
254 ctx->bits = bits;
255 ctx->word = word;
256
257 assert(done <= 2);
258
259 return done;
260}
261
262/* Returns the number of output characters. DST should point to an
263 * area of size at least BASE64_ENCODE_LENGTH(length). */
264size_t
266 char *dst,
267 size_t length,
268 const uint8_t *src)
269{
270 size_t done = 0;
271 size_t left = length;
272 unsigned left_over;
273 size_t bulk;
274
275 while (ctx->bits && left)
276 {
277 left--;
278 done += base64_encode_single(ctx, dst + done, *src++);
279 }
280
281 left_over = left % 3;
282 bulk = left - left_over;
283
284 if (bulk)
285 {
286 assert(!(bulk % 3));
287
288 encode_raw(ctx->alphabet, dst + done, bulk, src);
289 done += BASE64_ENCODE_RAW_LENGTH(bulk);
290 src += bulk;
291 left = left_over;
292 }
293
294 while (left)
295 {
296 left--;
297 done += base64_encode_single(ctx, dst + done, *src++);
298 }
299
300 assert(done <= BASE64_ENCODE_LENGTH(length));
301
302 return done;
303}
304
305/* DST should point to an area of size at least
306 * BASE64_ENCODE_FINAL_SIZE */
307size_t
309 char *dst)
310{
311 unsigned done = 0;
312 unsigned bits = ctx->bits;
313
314 if (bits)
315 {
316 dst[done++] = ENCODE(ctx->alphabet, (ctx->word << (6 - ctx->bits)));
317 for (; bits < 6; bits += 2)
318 dst[done++] = '=';
319
320 ctx->bits = 0;
321 }
322
324 return done;
325}
326
327#endif /* !HAVE_NETTLE_BASE64_H || !HAVE_NETTLE34_BASE64 */
328
#define assert(EX)
Definition: assert.h:17
void base64_encode_raw(char *dst, size_t length, const uint8_t *src)
Definition: base64.c:217
void base64_encode_group(char *dst, uint32_t group)
Definition: base64.c:223
int base64_decode_single(struct base64_decode_ctx *ctx, uint8_t *dst, char src)
Definition: base64.c:82
void base64_encode_init(struct base64_encode_ctx *ctx)
Definition: base64.c:232
size_t base64_encode_single(struct base64_encode_ctx *ctx, char *dst, uint8_t src)
Definition: base64.c:240
#define TABLE_END
Definition: base64.c:51
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:265
#define ENCODE(alphabet, x)
Definition: base64.c:166
#define TABLE_SPACE
Definition: base64.c:50
static const char base64_encode_table[64]
Definition: base64.c:211
void base64_decode_init(struct base64_decode_ctx *ctx)
Definition: base64.c:54
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
Definition: base64.c:308
#define TABLE_INVALID
Definition: base64.c:49
int base64_decode_update(struct base64_decode_ctx *ctx, size_t *dst_length, uint8_t *dst, size_t src_length, const char *src)
Definition: base64.c:129
int base64_decode_final(struct base64_decode_ctx *ctx)
Definition: base64.c:159
static void encode_raw(const char *alphabet, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:169
#define BASE64_ENCODE_FINAL_LENGTH
Definition: base64.h:62
#define BASE64_ENCODE_RAW_LENGTH(length)
Definition: base64.h:66
#define BASE64_DECODE_LENGTH(length)
Definition: base64.h:120
#define BASE64_ENCODE_LENGTH(length)
Definition: base64.h:59
unsigned char bits
Definition: base64.h:126
unsigned short word
Definition: base64.h:125
const signed char * table
Definition: base64.h:124
unsigned char padding
Definition: base64.h:129
const char * alphabet
Definition: base64.h:70
unsigned short word
Definition: base64.h:71
unsigned char bits
Definition: base64.h:72

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors