CMS 3D CMS Logo

base64.cc
Go to the documentation of this file.
1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* base64.c -- Encode binary data using printable characters.
4  Copyright (C) 1999-2001, 2004-2006, 2009-2011 Free Software Foundation, Inc.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 3, or (at your option)
9  any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software Foundation,
18  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 
20 /* Written by Simon Josefsson. Partially adapted from GNU MailUtils
21  * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
22  * from Paul Eggert, Bruno Haible, and Stepan Kasal.
23  *
24  * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
25  *
26  * Be careful with error checking. Here is how you would typically
27  * use these functions:
28  *
29  * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
30  * if (!ok)
31  * FAIL: input was not valid base64
32  * if (out == NULL)
33  * FAIL: memory allocation error
34  * OK: data in OUT/OUTLEN
35  *
36  * size_t outlen = base64_encode_alloc (in, inlen, &out);
37  * if (out == NULL && outlen == 0 && inlen != 0)
38  * FAIL: input too long
39  * if (out == NULL)
40  * FAIL: memory allocation error
41  * OK: data in OUT/OUTLEN.
42  *
43  */
44 
45 //#include <config.h>
46 
47 /* Get prototype. */
48 #include "base64.h"
49 
50 /* Get malloc. */
51 #include <cstdlib>
52 
53 /* Get UCHAR_MAX. */
54 #include <climits>
55 
56 #include <cstring>
57 
58 /* C89 compliant way to cast 'char' to 'unsigned char'. */
59 static inline unsigned char to_uchar(char ch) { return ch; }
60 
61 /* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
62  If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
63  possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
64  terminate the output buffer. */
65 void base64_encode(const char *in, size_t inlen, char *out, size_t outlen) {
66  static const char *b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
67 
68  while (inlen && outlen) {
69  *out++ = b64str[(to_uchar(in[0]) >> 2) & 0x3f];
70  if (!--outlen)
71  break;
72  *out++ = b64str[((to_uchar(in[0]) << 4) + (--inlen ? to_uchar(in[1]) >> 4 : 0)) & 0x3f];
73  if (!--outlen)
74  break;
75  *out++ = (inlen ? b64str[((to_uchar(in[1]) << 2) + (--inlen ? to_uchar(in[2]) >> 6 : 0)) & 0x3f] : '=');
76  if (!--outlen)
77  break;
78  *out++ = inlen ? b64str[to_uchar(in[2]) & 0x3f] : '=';
79  if (!--outlen)
80  break;
81  if (inlen)
82  inlen--;
83  if (inlen)
84  in += 3;
85  }
86 
87  if (outlen)
88  *out = '\0';
89 }
90 
91 /* Allocate a buffer and store zero terminated base64 encoded data
92  from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
93  the length of the encoded data, excluding the terminating zero. On
94  return, the OUT variable will hold a pointer to newly allocated
95  memory that must be deallocated by the caller. If output string
96  length would overflow, 0 is returned and OUT is set to NULL. If
97  memory allocation failed, OUT is set to NULL, and the return value
98  indicates length of the requested memory block, i.e.,
99  BASE64_LENGTH(inlen) + 1. */
100 size_t base64_encode_alloc(const char *in, size_t inlen, char **out) {
101  size_t outlen = 1 + BASE64_LENGTH(inlen);
102 
103  /* Check for overflow in outlen computation.
104  *
105  * If there is no overflow, outlen >= inlen.
106  *
107  * If the operation (inlen + 2) overflows then it yields at most +1, so
108  * outlen is 0.
109  *
110  * If the multiplication overflows, we lose at least half of the
111  * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
112  * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
113  * (inlen > 4).
114  */
115  if (inlen > outlen) {
116  *out = nullptr;
117  return 0;
118  }
119 
120  *out = static_cast<char *>(malloc(outlen));
121  if (!*out)
122  return outlen;
123 
124  base64_encode(in, inlen, *out, outlen);
125 
126  return outlen - 1;
127 }
128 
129 /* With this approach this file works independent of the charset used
130  (think EBCDIC). However, it does assume that the characters in the
131  Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
132  1003.1-2001 require that char and unsigned char are 8-bit
133  quantities, though, taking care of that problem. But this may be a
134  potential problem on non-POSIX C99 platforms.
135 
136  IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
137  as the formal parameter rather than "x". */
138 
139 // clang-format off
140 #define B64(_) \
141  ((_) == 'A' ? 0 \
142  : (_) == 'B' ? 1 \
143  : (_) == 'C' ? 2 \
144  : (_) == 'D' ? 3 \
145  : (_) == 'E' ? 4 \
146  : (_) == 'F' ? 5 \
147  : (_) == 'G' ? 6 \
148  : (_) == 'H' ? 7 \
149  : (_) == 'I' ? 8 \
150  : (_) == 'J' ? 9 \
151  : (_) == 'K' ? 10 \
152  : (_) == 'L' ? 11 \
153  : (_) == 'M' ? 12 \
154  : (_) == 'N' ? 13 \
155  : (_) == 'O' ? 14 \
156  : (_) == 'P' ? 15 \
157  : (_) == 'Q' ? 16 \
158  : (_) == 'R' ? 17 \
159  : (_) == 'S' ? 18 \
160  : (_) == 'T' ? 19 \
161  : (_) == 'U' ? 20 \
162  : (_) == 'V' ? 21 \
163  : (_) == 'W' ? 22 \
164  : (_) == 'X' ? 23 \
165  : (_) == 'Y' ? 24 \
166  : (_) == 'Z' ? 25 \
167  : (_) == 'a' ? 26 \
168  : (_) == 'b' ? 27 \
169  : (_) == 'c' ? 28 \
170  : (_) == 'd' ? 29 \
171  : (_) == 'e' ? 30 \
172  : (_) == 'f' ? 31 \
173  : (_) == 'g' ? 32 \
174  : (_) == 'h' ? 33 \
175  : (_) == 'i' ? 34 \
176  : (_) == 'j' ? 35 \
177  : (_) == 'k' ? 36 \
178  : (_) == 'l' ? 37 \
179  : (_) == 'm' ? 38 \
180  : (_) == 'n' ? 39 \
181  : (_) == 'o' ? 40 \
182  : (_) == 'p' ? 41 \
183  : (_) == 'q' ? 42 \
184  : (_) == 'r' ? 43 \
185  : (_) == 's' ? 44 \
186  : (_) == 't' ? 45 \
187  : (_) == 'u' ? 46 \
188  : (_) == 'v' ? 47 \
189  : (_) == 'w' ? 48 \
190  : (_) == 'x' ? 49 \
191  : (_) == 'y' ? 50 \
192  : (_) == 'z' ? 51 \
193  : (_) == '0' ? 52 \
194  : (_) == '1' ? 53 \
195  : (_) == '2' ? 54 \
196  : (_) == '3' ? 55 \
197  : (_) == '4' ? 56 \
198  : (_) == '5' ? 57 \
199  : (_) == '6' ? 58 \
200  : (_) == '7' ? 59 \
201  : (_) == '8' ? 60 \
202  : (_) == '9' ? 61 \
203  : (_) == '+' ? 62 \
204  : (_) == '/' ? 63 \
205  : -1)
206 // clang-format on
207 
208 static const signed char b64[0x100] = {
209  B64(0), B64(1), B64(2), B64(3), B64(4), B64(5), B64(6), B64(7), B64(8), B64(9), B64(10),
210  B64(11), B64(12), B64(13), B64(14), B64(15), B64(16), B64(17), B64(18), B64(19), B64(20), B64(21),
211  B64(22), B64(23), B64(24), B64(25), B64(26), B64(27), B64(28), B64(29), B64(30), B64(31), B64(32),
212  B64(33), B64(34), B64(35), B64(36), B64(37), B64(38), B64(39), B64(40), B64(41), B64(42), B64(43),
213  B64(44), B64(45), B64(46), B64(47), B64(48), B64(49), B64(50), B64(51), B64(52), B64(53), B64(54),
214  B64(55), B64(56), B64(57), B64(58), B64(59), B64(60), B64(61), B64(62), B64(63), B64(64), B64(65),
215  B64(66), B64(67), B64(68), B64(69), B64(70), B64(71), B64(72), B64(73), B64(74), B64(75), B64(76),
216  B64(77), B64(78), B64(79), B64(80), B64(81), B64(82), B64(83), B64(84), B64(85), B64(86), B64(87),
217  B64(88), B64(89), B64(90), B64(91), B64(92), B64(93), B64(94), B64(95), B64(96), B64(97), B64(98),
218  B64(99), B64(100), B64(101), B64(102), B64(103), B64(104), B64(105), B64(106), B64(107), B64(108), B64(109),
219  B64(110), B64(111), B64(112), B64(113), B64(114), B64(115), B64(116), B64(117), B64(118), B64(119), B64(120),
220  B64(121), B64(122), B64(123), B64(124), B64(125), B64(126), B64(127), B64(128), B64(129), B64(130), B64(131),
221  B64(132), B64(133), B64(134), B64(135), B64(136), B64(137), B64(138), B64(139), B64(140), B64(141), B64(142),
222  B64(143), B64(144), B64(145), B64(146), B64(147), B64(148), B64(149), B64(150), B64(151), B64(152), B64(153),
223  B64(154), B64(155), B64(156), B64(157), B64(158), B64(159), B64(160), B64(161), B64(162), B64(163), B64(164),
224  B64(165), B64(166), B64(167), B64(168), B64(169), B64(170), B64(171), B64(172), B64(173), B64(174), B64(175),
225  B64(176), B64(177), B64(178), B64(179), B64(180), B64(181), B64(182), B64(183), B64(184), B64(185), B64(186),
226  B64(187), B64(188), B64(189), B64(190), B64(191), B64(192), B64(193), B64(194), B64(195), B64(196), B64(197),
227  B64(198), B64(199), B64(200), B64(201), B64(202), B64(203), B64(204), B64(205), B64(206), B64(207), B64(208),
228  B64(209), B64(210), B64(211), B64(212), B64(213), B64(214), B64(215), B64(216), B64(217), B64(218), B64(219),
229  B64(220), B64(221), B64(222), B64(223), B64(224), B64(225), B64(226), B64(227), B64(228), B64(229), B64(230),
230  B64(231), B64(232), B64(233), B64(234), B64(235), B64(236), B64(237), B64(238), B64(239), B64(240), B64(241),
231  B64(242), B64(243), B64(244), B64(245), B64(246), B64(247), B64(248), B64(249), B64(250), B64(251), B64(252),
232  B64(253), B64(254), B64(255)};
233 
234 #if UCHAR_MAX == 255
235 #define uchar_in_range(c) true
236 #else
237 #define uchar_in_range(c) ((c) <= 255)
238 #endif
239 
240 /* Return true if CH is a character from the Base64 alphabet, and
241  false otherwise. Note that '=' is padding and not considered to be
242  part of the alphabet. */
243 bool isbase64(char ch) { return uchar_in_range(to_uchar(ch)) && 0 <= b64[to_uchar(ch)]; }
244 
245 /* Initialize decode-context buffer, CTX. */
246 void base64_decode_ctx_init(struct base64_decode_context *ctx) { ctx->i = 0; }
247 
248 /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
249  none of those four is a newline, then return *IN. Otherwise, copy up to
250  4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
251  index CTX->i and setting CTX->i to reflect the number of bytes copied,
252  and return CTX->buf. In either case, advance *IN to point to the byte
253  after the last one processed, and set *N_NON_NEWLINE to the number of
254  verified non-newline bytes accessible through the returned pointer. */
255 static inline char *get_4(struct base64_decode_context *ctx,
256  char const **in,
257  char const *in_end,
258  size_t *n_non_newline) {
259  if (ctx->i == 4)
260  ctx->i = 0;
261 
262  if (ctx->i == 0) {
263  char const *t = *in;
264  if (4 <= in_end - *in && memchr(t, '\n', 4) == nullptr) {
265  /* This is the common case: no newline. */
266  *in += 4;
267  *n_non_newline = 4;
268  return (char *)t;
269  }
270  }
271 
272  {
273  /* Copy non-newline bytes into BUF. */
274  char const *p = *in;
275  while (p < in_end) {
276  char c = *p++;
277  if (c != '\n') {
278  ctx->buf[ctx->i++] = c;
279  if (ctx->i == 4)
280  break;
281  }
282  }
283 
284  *in = p;
285  *n_non_newline = ctx->i;
286  return ctx->buf;
287  }
288 }
289 
290 #define return_false \
291  do { \
292  *outp = out; \
293  return false; \
294  } while (false)
295 
296 /* Decode up to four bytes of base64-encoded data, IN, of length INLEN
297  into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
298  decoding is successful, false otherwise. If *OUTLEN is too small,
299  as many bytes as possible are written to *OUT. On return, advance
300  *OUT to point to the byte after the last one written, and decrement
301  *OUTLEN to reflect the number of bytes remaining in *OUT. */
302 static inline bool decode_4(char const *in, size_t inlen, char **outp, size_t *outleft) {
303  char *out = *outp;
304  if (inlen < 2)
305  return false;
306 
307  if (!isbase64(in[0]) || !isbase64(in[1]))
308  return false;
309 
310  if (*outleft) {
311  *out++ = ((b64[to_uchar(in[0])] << 2) | (b64[to_uchar(in[1])] >> 4));
312  --*outleft;
313  }
314 
315  if (inlen == 2)
316  return_false;
317 
318  if (in[2] == '=') {
319  if (inlen != 4)
320  return_false;
321 
322  if (in[3] != '=')
323  return_false;
324  } else {
325  if (!isbase64(in[2]))
326  return_false;
327 
328  if (*outleft) {
329  *out++ = (((b64[to_uchar(in[1])] << 4) & 0xf0) | (b64[to_uchar(in[2])] >> 2));
330  --*outleft;
331  }
332 
333  if (inlen == 3)
334  return_false;
335 
336  if (in[3] == '=') {
337  if (inlen != 4)
338  return_false;
339  } else {
340  if (!isbase64(in[3]))
341  return_false;
342 
343  if (*outleft) {
344  *out++ = (((b64[to_uchar(in[2])] << 6) & 0xc0) | b64[to_uchar(in[3])]);
345  --*outleft;
346  }
347  }
348  }
349 
350  *outp = out;
351  return true;
352 }
353 
354 /* Decode base64-encoded input array IN of length INLEN to output array
355  OUT that can hold *OUTLEN bytes. The input data may be interspersed
356  with newlines. Return true if decoding was successful, i.e. if the
357  input was valid base64 data, false otherwise. If *OUTLEN is too
358  small, as many bytes as possible will be written to OUT. On return,
359  *OUTLEN holds the length of decoded bytes in OUT. Note that as soon
360  as any non-alphabet, non-newline character is encountered, decoding
361  is stopped and false is returned. If INLEN is zero, then process
362  only whatever data is stored in CTX.
363 
364  Initially, CTX must have been initialized via base64_decode_ctx_init.
365  Subsequent calls to this function must reuse whatever state is recorded
366  in that buffer. It is necessary for when a quadruple of base64 input
367  bytes spans two input buffers.
368 
369  If CTX is NULL then newlines are treated as garbage and the input
370  buffer is processed as a unit. */
371 
372 bool base64_decode_ctx(struct base64_decode_context *ctx, const char *in, size_t inlen, char *out, size_t *outlen) {
373  size_t outleft = *outlen;
374  bool ignore_newlines = ctx != nullptr;
375  bool flush_ctx = false;
376  unsigned int ctx_i = 0;
377 
378  if (ignore_newlines) {
379  ctx_i = ctx->i;
380  flush_ctx = inlen == 0;
381  }
382 
383  while (true) {
384  size_t outleft_save = outleft;
385  if (ctx_i == 0 && !flush_ctx) {
386  while (true) {
387  /* Save a copy of outleft, in case we need to re-parse this
388  block of four bytes. */
389  outleft_save = outleft;
390  if (!decode_4(in, inlen, &out, &outleft))
391  break;
392 
393  in += 4;
394  inlen -= 4;
395  }
396  }
397 
398  if (inlen == 0 && !flush_ctx)
399  break;
400 
401  /* Handle the common case of 72-byte wrapped lines.
402  This also handles any other multiple-of-4-byte wrapping. */
403  if (inlen && *in == '\n' && ignore_newlines) {
404  ++in;
405  --inlen;
406  continue;
407  }
408 
409  /* Restore OUT and OUTLEFT. */
410  out -= outleft_save - outleft;
411  outleft = outleft_save;
412 
413  {
414  char const *in_end = in + inlen;
415  char const *non_nl;
416 
417  if (ignore_newlines)
418  non_nl = get_4(ctx, &in, in_end, &inlen);
419  else
420  non_nl = in; /* Might have nl in this case. */
421 
422  /* If the input is empty or consists solely of newlines (0 non-newlines),
423  then we're done. Likewise if there are fewer than 4 bytes when not
424  flushing context and not treating newlines as garbage. */
425  if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) {
426  inlen = 0;
427  break;
428  }
429  if (!decode_4(non_nl, inlen, &out, &outleft))
430  break;
431 
432  inlen = in_end - in;
433  }
434  }
435 
436  *outlen -= outleft;
437 
438  return inlen == 0;
439 }
440 
441 /* Allocate an output buffer in *OUT, and decode the base64 encoded
442  data stored in IN of size INLEN to the *OUT buffer. On return, the
443  size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
444  if the caller is not interested in the decoded length. *OUT may be
445  NULL to indicate an out of memory error, in which case *OUTLEN
446  contains the size of the memory block needed. The function returns
447  true on successful decoding and memory allocation errors. (Use the
448  *OUT and *OUTLEN parameters to differentiate between successful
449  decoding and memory error.) The function returns false if the
450  input was invalid, in which case *OUT is NULL and *OUTLEN is
451  undefined. */
453  struct base64_decode_context *ctx, const char *in, size_t inlen, char **out, size_t *outlen) {
454  /* This may allocate a few bytes too many, depending on input,
455  but it's not worth the extra CPU time to compute the exact size.
456  The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
457  input ends with "=" and minus another 1 if the input ends with "==".
458  Dividing before multiplying avoids the possibility of overflow. */
459  size_t needlen = 3 * (inlen / 4) + 3;
460 
461  *out = static_cast<char *>(malloc(needlen));
462  if (!*out)
463  return true;
464 
465  if (!base64_decode_ctx(ctx, in, inlen, *out, &needlen)) {
466  free(*out);
467  *out = nullptr;
468  return false;
469  }
470 
471  if (outlen)
472  *outlen = needlen;
473 
474  return true;
475 }
static const signed char b64[0x100]
Definition: base64.cc:208
bool isbase64(char ch)
Definition: base64.cc:243
void base64_encode(const char *in, size_t inlen, char *out, size_t outlen)
Definition: base64.cc:65
#define B64(_)
Definition: base64.cc:140
static const char * b64str
Definition: DecodingKey.cc:18
static unsigned char to_uchar(char ch)
Definition: base64.cc:59
#define BASE64_LENGTH(inlen)
Definition: base64.h:31
void base64_decode_ctx_init(struct base64_decode_context *ctx)
Definition: base64.cc:246
unsigned int i
Definition: base64.h:34
size_t base64_encode_alloc(const char *in, size_t inlen, char **out)
Definition: base64.cc:100
#define return_false
Definition: base64.cc:290
static bool decode_4(char const *in, size_t inlen, char **outp, size_t *outleft)
Definition: base64.cc:302
bool base64_decode_ctx(struct base64_decode_context *ctx, const char *in, size_t inlen, char *out, size_t *outlen)
Definition: base64.cc:372
#define uchar_in_range(c)
Definition: base64.cc:237
bool base64_decode_alloc_ctx(struct base64_decode_context *ctx, const char *in, size_t inlen, char **out, size_t *outlen)
Definition: base64.cc:452
static char * get_4(struct base64_decode_context *ctx, char const **in, char const *in_end, size_t *n_non_newline)
Definition: base64.cc:255