Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:50:21

0001 /* -*- buffer-read-only: t -*- vi: set ro: */
0002 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
0003 /* base64.c -- Encode binary data using printable characters.
0004    Copyright (C) 1999-2001, 2004-2006, 2009-2011 Free Software Foundation, Inc.
0005 
0006    This program is free software; you can redistribute it and/or modify
0007    it under the terms of the GNU General Public License as published by
0008    the Free Software Foundation; either version 3, or (at your option)
0009    any later version.
0010 
0011    This program is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014    GNU General Public License for more details.
0015 
0016    You should have received a copy of the GNU General Public License
0017    along with this program; if not, write to the Free Software Foundation,
0018    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
0019 
0020 /* Written by Simon Josefsson.  Partially adapted from GNU MailUtils
0021  * (mailbox/filter_trans.c, as of 2004-11-28).  Improved by review
0022  * from Paul Eggert, Bruno Haible, and Stepan Kasal.
0023  *
0024  * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
0025  *
0026  * Be careful with error checking.  Here is how you would typically
0027  * use these functions:
0028  *
0029  * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
0030  * if (!ok)
0031  *   FAIL: input was not valid base64
0032  * if (out == NULL)
0033  *   FAIL: memory allocation error
0034  * OK: data in OUT/OUTLEN
0035  *
0036  * size_t outlen = base64_encode_alloc (in, inlen, &out);
0037  * if (out == NULL && outlen == 0 && inlen != 0)
0038  *   FAIL: input too long
0039  * if (out == NULL)
0040  *   FAIL: memory allocation error
0041  * OK: data in OUT/OUTLEN.
0042  *
0043  */
0044 
0045 //#include <config.h>
0046 
0047 /* Get prototype. */
0048 #include "base64.h"
0049 
0050 /* Get malloc. */
0051 #include <cstdlib>
0052 
0053 /* Get UCHAR_MAX. */
0054 #include <climits>
0055 
0056 #include <cstring>
0057 
0058 /* C89 compliant way to cast 'char' to 'unsigned char'. */
0059 static inline unsigned char to_uchar(char ch) { return ch; }
0060 
0061 /* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
0062    If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
0063    possible.  If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
0064    terminate the output buffer. */
0065 void base64_encode(const char *in, size_t inlen, char *out, size_t outlen) {
0066   static const char *b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
0067 
0068   while (inlen && outlen) {
0069     *out++ = b64str[(to_uchar(in[0]) >> 2) & 0x3f];
0070     if (!--outlen)
0071       break;
0072     *out++ = b64str[((to_uchar(in[0]) << 4) + (--inlen ? to_uchar(in[1]) >> 4 : 0)) & 0x3f];
0073     if (!--outlen)
0074       break;
0075     *out++ = (inlen ? b64str[((to_uchar(in[1]) << 2) + (--inlen ? to_uchar(in[2]) >> 6 : 0)) & 0x3f] : '=');
0076     if (!--outlen)
0077       break;
0078     *out++ = inlen ? b64str[to_uchar(in[2]) & 0x3f] : '=';
0079     if (!--outlen)
0080       break;
0081     if (inlen)
0082       inlen--;
0083     if (inlen)
0084       in += 3;
0085   }
0086 
0087   if (outlen)
0088     *out = '\0';
0089 }
0090 
0091 /* Allocate a buffer and store zero terminated base64 encoded data
0092    from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
0093    the length of the encoded data, excluding the terminating zero.  On
0094    return, the OUT variable will hold a pointer to newly allocated
0095    memory that must be deallocated by the caller.  If output string
0096    length would overflow, 0 is returned and OUT is set to NULL.  If
0097    memory allocation failed, OUT is set to NULL, and the return value
0098    indicates length of the requested memory block, i.e.,
0099    BASE64_LENGTH(inlen) + 1. */
0100 size_t base64_encode_alloc(const char *in, size_t inlen, char **out) {
0101   size_t outlen = 1 + BASE64_LENGTH(inlen);
0102 
0103   /* Check for overflow in outlen computation.
0104    *
0105    * If there is no overflow, outlen >= inlen.
0106    *
0107    * If the operation (inlen + 2) overflows then it yields at most +1, so
0108    * outlen is 0.
0109    *
0110    * If the multiplication overflows, we lose at least half of the
0111    * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
0112    * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
0113    * (inlen > 4).
0114    */
0115   if (inlen > outlen) {
0116     *out = nullptr;
0117     return 0;
0118   }
0119 
0120   *out = static_cast<char *>(malloc(outlen));
0121   if (!*out)
0122     return outlen;
0123 
0124   base64_encode(in, inlen, *out, outlen);
0125 
0126   return outlen - 1;
0127 }
0128 
0129 /* With this approach this file works independent of the charset used
0130    (think EBCDIC).  However, it does assume that the characters in the
0131    Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255.  POSIX
0132    1003.1-2001 require that char and unsigned char are 8-bit
0133    quantities, though, taking care of that problem.  But this may be a
0134    potential problem on non-POSIX C99 platforms.
0135 
0136    IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
0137    as the formal parameter rather than "x".  */
0138 
0139 // clang-format off
0140 #define B64(_)                                  \
0141   ((_) == 'A' ? 0                               \
0142    : (_) == 'B' ? 1                             \
0143    : (_) == 'C' ? 2                             \
0144    : (_) == 'D' ? 3                             \
0145    : (_) == 'E' ? 4                             \
0146    : (_) == 'F' ? 5                             \
0147    : (_) == 'G' ? 6                             \
0148    : (_) == 'H' ? 7                             \
0149    : (_) == 'I' ? 8                             \
0150    : (_) == 'J' ? 9                             \
0151    : (_) == 'K' ? 10                            \
0152    : (_) == 'L' ? 11                            \
0153    : (_) == 'M' ? 12                            \
0154    : (_) == 'N' ? 13                            \
0155    : (_) == 'O' ? 14                            \
0156    : (_) == 'P' ? 15                            \
0157    : (_) == 'Q' ? 16                            \
0158    : (_) == 'R' ? 17                            \
0159    : (_) == 'S' ? 18                            \
0160    : (_) == 'T' ? 19                            \
0161    : (_) == 'U' ? 20                            \
0162    : (_) == 'V' ? 21                            \
0163    : (_) == 'W' ? 22                            \
0164    : (_) == 'X' ? 23                            \
0165    : (_) == 'Y' ? 24                            \
0166    : (_) == 'Z' ? 25                            \
0167    : (_) == 'a' ? 26                            \
0168    : (_) == 'b' ? 27                            \
0169    : (_) == 'c' ? 28                            \
0170    : (_) == 'd' ? 29                            \
0171    : (_) == 'e' ? 30                            \
0172    : (_) == 'f' ? 31                            \
0173    : (_) == 'g' ? 32                            \
0174    : (_) == 'h' ? 33                            \
0175    : (_) == 'i' ? 34                            \
0176    : (_) == 'j' ? 35                            \
0177    : (_) == 'k' ? 36                            \
0178    : (_) == 'l' ? 37                            \
0179    : (_) == 'm' ? 38                            \
0180    : (_) == 'n' ? 39                            \
0181    : (_) == 'o' ? 40                            \
0182    : (_) == 'p' ? 41                            \
0183    : (_) == 'q' ? 42                            \
0184    : (_) == 'r' ? 43                            \
0185    : (_) == 's' ? 44                            \
0186    : (_) == 't' ? 45                            \
0187    : (_) == 'u' ? 46                            \
0188    : (_) == 'v' ? 47                            \
0189    : (_) == 'w' ? 48                            \
0190    : (_) == 'x' ? 49                            \
0191    : (_) == 'y' ? 50                            \
0192    : (_) == 'z' ? 51                            \
0193    : (_) == '0' ? 52                            \
0194    : (_) == '1' ? 53                            \
0195    : (_) == '2' ? 54                            \
0196    : (_) == '3' ? 55                            \
0197    : (_) == '4' ? 56                            \
0198    : (_) == '5' ? 57                            \
0199    : (_) == '6' ? 58                            \
0200    : (_) == '7' ? 59                            \
0201    : (_) == '8' ? 60                            \
0202    : (_) == '9' ? 61                            \
0203    : (_) == '+' ? 62                            \
0204    : (_) == '/' ? 63                            \
0205    : -1)
0206 // clang-format on
0207 
0208 static const signed char b64[0x100] = {
0209     B64(0),   B64(1),   B64(2),   B64(3),   B64(4),   B64(5),   B64(6),   B64(7),   B64(8),   B64(9),   B64(10),
0210     B64(11),  B64(12),  B64(13),  B64(14),  B64(15),  B64(16),  B64(17),  B64(18),  B64(19),  B64(20),  B64(21),
0211     B64(22),  B64(23),  B64(24),  B64(25),  B64(26),  B64(27),  B64(28),  B64(29),  B64(30),  B64(31),  B64(32),
0212     B64(33),  B64(34),  B64(35),  B64(36),  B64(37),  B64(38),  B64(39),  B64(40),  B64(41),  B64(42),  B64(43),
0213     B64(44),  B64(45),  B64(46),  B64(47),  B64(48),  B64(49),  B64(50),  B64(51),  B64(52),  B64(53),  B64(54),
0214     B64(55),  B64(56),  B64(57),  B64(58),  B64(59),  B64(60),  B64(61),  B64(62),  B64(63),  B64(64),  B64(65),
0215     B64(66),  B64(67),  B64(68),  B64(69),  B64(70),  B64(71),  B64(72),  B64(73),  B64(74),  B64(75),  B64(76),
0216     B64(77),  B64(78),  B64(79),  B64(80),  B64(81),  B64(82),  B64(83),  B64(84),  B64(85),  B64(86),  B64(87),
0217     B64(88),  B64(89),  B64(90),  B64(91),  B64(92),  B64(93),  B64(94),  B64(95),  B64(96),  B64(97),  B64(98),
0218     B64(99),  B64(100), B64(101), B64(102), B64(103), B64(104), B64(105), B64(106), B64(107), B64(108), B64(109),
0219     B64(110), B64(111), B64(112), B64(113), B64(114), B64(115), B64(116), B64(117), B64(118), B64(119), B64(120),
0220     B64(121), B64(122), B64(123), B64(124), B64(125), B64(126), B64(127), B64(128), B64(129), B64(130), B64(131),
0221     B64(132), B64(133), B64(134), B64(135), B64(136), B64(137), B64(138), B64(139), B64(140), B64(141), B64(142),
0222     B64(143), B64(144), B64(145), B64(146), B64(147), B64(148), B64(149), B64(150), B64(151), B64(152), B64(153),
0223     B64(154), B64(155), B64(156), B64(157), B64(158), B64(159), B64(160), B64(161), B64(162), B64(163), B64(164),
0224     B64(165), B64(166), B64(167), B64(168), B64(169), B64(170), B64(171), B64(172), B64(173), B64(174), B64(175),
0225     B64(176), B64(177), B64(178), B64(179), B64(180), B64(181), B64(182), B64(183), B64(184), B64(185), B64(186),
0226     B64(187), B64(188), B64(189), B64(190), B64(191), B64(192), B64(193), B64(194), B64(195), B64(196), B64(197),
0227     B64(198), B64(199), B64(200), B64(201), B64(202), B64(203), B64(204), B64(205), B64(206), B64(207), B64(208),
0228     B64(209), B64(210), B64(211), B64(212), B64(213), B64(214), B64(215), B64(216), B64(217), B64(218), B64(219),
0229     B64(220), B64(221), B64(222), B64(223), B64(224), B64(225), B64(226), B64(227), B64(228), B64(229), B64(230),
0230     B64(231), B64(232), B64(233), B64(234), B64(235), B64(236), B64(237), B64(238), B64(239), B64(240), B64(241),
0231     B64(242), B64(243), B64(244), B64(245), B64(246), B64(247), B64(248), B64(249), B64(250), B64(251), B64(252),
0232     B64(253), B64(254), B64(255)};
0233 
0234 #if UCHAR_MAX == 255
0235 #define uchar_in_range(c) true
0236 #else
0237 #define uchar_in_range(c) ((c) <= 255)
0238 #endif
0239 
0240 /* Return true if CH is a character from the Base64 alphabet, and
0241    false otherwise.  Note that '=' is padding and not considered to be
0242    part of the alphabet.  */
0243 bool isbase64(char ch) { return uchar_in_range(to_uchar(ch)) && 0 <= b64[to_uchar(ch)]; }
0244 
0245 /* Initialize decode-context buffer, CTX.  */
0246 void base64_decode_ctx_init(struct base64_decode_context *ctx) { ctx->i = 0; }
0247 
0248 /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
0249    none of those four is a newline, then return *IN.  Otherwise, copy up to
0250    4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
0251    index CTX->i and setting CTX->i to reflect the number of bytes copied,
0252    and return CTX->buf.  In either case, advance *IN to point to the byte
0253    after the last one processed, and set *N_NON_NEWLINE to the number of
0254    verified non-newline bytes accessible through the returned pointer.  */
0255 static inline char *get_4(struct base64_decode_context *ctx,
0256                           char const **in,
0257                           char const *in_end,
0258                           size_t *n_non_newline) {
0259   if (ctx->i == 4)
0260     ctx->i = 0;
0261 
0262   if (ctx->i == 0) {
0263     char const *t = *in;
0264     if (4 <= in_end - *in && memchr(t, '\n', 4) == nullptr) {
0265       /* This is the common case: no newline.  */
0266       *in += 4;
0267       *n_non_newline = 4;
0268       return (char *)t;
0269     }
0270   }
0271 
0272   {
0273     /* Copy non-newline bytes into BUF.  */
0274     char const *p = *in;
0275     while (p < in_end) {
0276       char c = *p++;
0277       if (c != '\n') {
0278         ctx->buf[ctx->i++] = c;
0279         if (ctx->i == 4)
0280           break;
0281       }
0282     }
0283 
0284     *in = p;
0285     *n_non_newline = ctx->i;
0286     return ctx->buf;
0287   }
0288 }
0289 
0290 #define return_false \
0291   do {               \
0292     *outp = out;     \
0293     return false;    \
0294   } while (false)
0295 
0296 /* Decode up to four bytes of base64-encoded data, IN, of length INLEN
0297    into the output buffer, *OUT, of size *OUTLEN bytes.  Return true if
0298    decoding is successful, false otherwise.  If *OUTLEN is too small,
0299    as many bytes as possible are written to *OUT.  On return, advance
0300    *OUT to point to the byte after the last one written, and decrement
0301    *OUTLEN to reflect the number of bytes remaining in *OUT.  */
0302 static inline bool decode_4(char const *in, size_t inlen, char **outp, size_t *outleft) {
0303   char *out = *outp;
0304   if (inlen < 2)
0305     return false;
0306 
0307   if (!isbase64(in[0]) || !isbase64(in[1]))
0308     return false;
0309 
0310   if (*outleft) {
0311     *out++ = ((b64[to_uchar(in[0])] << 2) | (b64[to_uchar(in[1])] >> 4));
0312     --*outleft;
0313   }
0314 
0315   if (inlen == 2)
0316     return_false;
0317 
0318   if (in[2] == '=') {
0319     if (inlen != 4)
0320       return_false;
0321 
0322     if (in[3] != '=')
0323       return_false;
0324   } else {
0325     if (!isbase64(in[2]))
0326       return_false;
0327 
0328     if (*outleft) {
0329       *out++ = (((b64[to_uchar(in[1])] << 4) & 0xf0) | (b64[to_uchar(in[2])] >> 2));
0330       --*outleft;
0331     }
0332 
0333     if (inlen == 3)
0334       return_false;
0335 
0336     if (in[3] == '=') {
0337       if (inlen != 4)
0338         return_false;
0339     } else {
0340       if (!isbase64(in[3]))
0341         return_false;
0342 
0343       if (*outleft) {
0344         *out++ = (((b64[to_uchar(in[2])] << 6) & 0xc0) | b64[to_uchar(in[3])]);
0345         --*outleft;
0346       }
0347     }
0348   }
0349 
0350   *outp = out;
0351   return true;
0352 }
0353 
0354 /* Decode base64-encoded input array IN of length INLEN to output array
0355    OUT that can hold *OUTLEN bytes.  The input data may be interspersed
0356    with newlines.  Return true if decoding was successful, i.e. if the
0357    input was valid base64 data, false otherwise.  If *OUTLEN is too
0358    small, as many bytes as possible will be written to OUT.  On return,
0359    *OUTLEN holds the length of decoded bytes in OUT.  Note that as soon
0360    as any non-alphabet, non-newline character is encountered, decoding
0361    is stopped and false is returned.  If INLEN is zero, then process
0362    only whatever data is stored in CTX.
0363 
0364    Initially, CTX must have been initialized via base64_decode_ctx_init.
0365    Subsequent calls to this function must reuse whatever state is recorded
0366    in that buffer.  It is necessary for when a quadruple of base64 input
0367    bytes spans two input buffers.
0368 
0369    If CTX is NULL then newlines are treated as garbage and the input
0370    buffer is processed as a unit.  */
0371 
0372 bool base64_decode_ctx(struct base64_decode_context *ctx, const char *in, size_t inlen, char *out, size_t *outlen) {
0373   size_t outleft = *outlen;
0374   bool ignore_newlines = ctx != nullptr;
0375   bool flush_ctx = false;
0376   unsigned int ctx_i = 0;
0377 
0378   if (ignore_newlines) {
0379     ctx_i = ctx->i;
0380     flush_ctx = inlen == 0;
0381   }
0382 
0383   while (true) {
0384     size_t outleft_save = outleft;
0385     if (ctx_i == 0 && !flush_ctx) {
0386       while (true) {
0387         /* Save a copy of outleft, in case we need to re-parse this
0388                  block of four bytes.  */
0389         outleft_save = outleft;
0390         if (!decode_4(in, inlen, &out, &outleft))
0391           break;
0392 
0393         in += 4;
0394         inlen -= 4;
0395       }
0396     }
0397 
0398     if (inlen == 0 && !flush_ctx)
0399       break;
0400 
0401     /* Handle the common case of 72-byte wrapped lines.
0402          This also handles any other multiple-of-4-byte wrapping.  */
0403     if (inlen && *in == '\n' && ignore_newlines) {
0404       ++in;
0405       --inlen;
0406       continue;
0407     }
0408 
0409     /* Restore OUT and OUTLEFT.  */
0410     out -= outleft_save - outleft;
0411     outleft = outleft_save;
0412 
0413     {
0414       char const *in_end = in + inlen;
0415       char const *non_nl;
0416 
0417       if (ignore_newlines)
0418         non_nl = get_4(ctx, &in, in_end, &inlen);
0419       else
0420         non_nl = in; /* Might have nl in this case. */
0421 
0422       /* If the input is empty or consists solely of newlines (0 non-newlines),
0423            then we're done.  Likewise if there are fewer than 4 bytes when not
0424            flushing context and not treating newlines as garbage.  */
0425       if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) {
0426         inlen = 0;
0427         break;
0428       }
0429       if (!decode_4(non_nl, inlen, &out, &outleft))
0430         break;
0431 
0432       inlen = in_end - in;
0433     }
0434   }
0435 
0436   *outlen -= outleft;
0437 
0438   return inlen == 0;
0439 }
0440 
0441 /* Allocate an output buffer in *OUT, and decode the base64 encoded
0442    data stored in IN of size INLEN to the *OUT buffer.  On return, the
0443    size of the decoded data is stored in *OUTLEN.  OUTLEN may be NULL,
0444    if the caller is not interested in the decoded length.  *OUT may be
0445    NULL to indicate an out of memory error, in which case *OUTLEN
0446    contains the size of the memory block needed.  The function returns
0447    true on successful decoding and memory allocation errors.  (Use the
0448    *OUT and *OUTLEN parameters to differentiate between successful
0449    decoding and memory error.)  The function returns false if the
0450    input was invalid, in which case *OUT is NULL and *OUTLEN is
0451    undefined. */
0452 bool base64_decode_alloc_ctx(
0453     struct base64_decode_context *ctx, const char *in, size_t inlen, char **out, size_t *outlen) {
0454   /* This may allocate a few bytes too many, depending on input,
0455      but it's not worth the extra CPU time to compute the exact size.
0456      The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
0457      input ends with "=" and minus another 1 if the input ends with "==".
0458      Dividing before multiplying avoids the possibility of overflow.  */
0459   size_t needlen = 3 * (inlen / 4) + 3;
0460 
0461   *out = static_cast<char *>(malloc(needlen));
0462   if (!*out)
0463     return true;
0464 
0465   if (!base64_decode_ctx(ctx, in, inlen, *out, &needlen)) {
0466     free(*out);
0467     *out = nullptr;
0468     return false;
0469   }
0470 
0471   if (outlen)
0472     *outlen = needlen;
0473 
0474   return true;
0475 }