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
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 
53 void
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 
81 int
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 
128 int
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 
158 int
160 {
161  return ctx->bits == 0;
162 }
163 
164 /* base64-encode.c */
165 
166 #define ENCODE(alphabet,x) ((alphabet)[0x3F & (x)])
167 
168 static void
169 encode_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 
211 static const char base64_encode_table[64] =
212  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
213  "abcdefghijklmnopqrstuvwxyz"
214  "0123456789+/";
215 
216 void
217 base64_encode_raw(char *dst, size_t length, const uint8_t *src)
218 {
219  encode_raw(base64_encode_table, dst, length, src);
220 }
221 
222 void
223 base64_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 
231 void
233 {
234  ctx->word = ctx->bits = 0;
236 }
237 
238 /* Encodes a single byte. */
239 size_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). */
264 size_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 */
307 size_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 */
328 
#define TABLE_SPACE
Definition: base64.c:50
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
Definition: base64.c:308
const signed char * table
Definition: base64.h:124
int base64_decode_single(struct base64_decode_ctx *ctx, uint8_t *dst, char src)
Definition: base64.c:82
unsigned short word
Definition: base64.h:125
#define BASE64_ENCODE_FINAL_LENGTH
Definition: base64.h:62
#define ENCODE(alphabet, x)
Definition: base64.c:166
unsigned char bits
Definition: base64.h:126
unsigned char bits
Definition: base64.h:72
size_t base64_encode_single(struct base64_encode_ctx *ctx, char *dst, uint8_t src)
Definition: base64.c:240
static const char base64_encode_table[64]
Definition: base64.c:211
void base64_decode_init(struct base64_decode_ctx *ctx)
Definition: base64.c:54
#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
unsigned short word
Definition: base64.h:71
void base64_encode_raw(char *dst, size_t length, const uint8_t *src)
Definition: base64.c:217
#define assert(EX)
Definition: assert.h:17
#define BASE64_ENCODE_LENGTH(length)
Definition: base64.h:59
static void encode_raw(const char *alphabet, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:169
void base64_encode_group(char *dst, uint32_t group)
Definition: base64.c:223
#define BASE64_ENCODE_RAW_LENGTH(length)
Definition: base64.h:66
void base64_encode_init(struct base64_encode_ctx *ctx)
Definition: base64.c:232
unsigned char padding
Definition: base64.h:129
#define TABLE_END
Definition: base64.c:51
const char * alphabet
Definition: base64.h:70
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:265
#define BASE64_DECODE_LENGTH(length)
Definition: base64.h:120

 

Introduction

Documentation

Support

Miscellaneous