LCOV - code coverage report
Current view: top level - lib - base64.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 30 70 42.9 %
Date: 2023-04-18 16:19:03 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /*
       2             :  * Base64 encoding/decoding (RFC1341)
       3             :  * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include <stdlib.h>
      10             : #include <string.h>
      11             : 
      12             : #include "base64.h"
      13             : 
      14             : static const unsigned char base64_table[65] =
      15             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      16             : 
      17             : /*
      18             :  * Calculated using:
      19             :  * memset(dtable, 0x80, 256);
      20             :  * for (i = 0; i < sizeof(base64_table) - 1; i++)
      21             :  *    dtable[base64_table[i]] = (unsigned char) i;
      22             :  * dtable['='] = 0;
      23             :  */
      24             : static const unsigned char base64_decode_table[256] = {
      25             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      26             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      27             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      28             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
      29             :     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80,
      30             :     0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
      31             :     0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
      32             :     0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
      33             :     0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
      34             :     0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
      35             :     0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      36             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      37             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      38             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      39             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      40             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      41             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      42             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      43             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      44             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      45             :     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
      46             :     0x80, 0x80, 0x80, 0x80};
      47             : 
      48             : bool
      49           0 : base64_validate(const unsigned char *src, size_t len)
      50             : {
      51           0 :     for (size_t i = 0; i < len; i++) {
      52           0 :         if (base64_decode_table[src[i]] == 0x80)
      53           0 :             return false;
      54             :     }
      55             : 
      56           0 :     return true;
      57             : }
      58             : 
      59             : /**
      60             :  * base64_encode - Base64 encode
      61             :  * @src: Data to be encoded
      62             :  * @len: Length of the data to be encoded
      63             :  * @out_len: Pointer to output length variable, or %NULL if not used
      64             :  * Returns: Allocated buffer of out_len bytes of encoded data,
      65             :  * or %NULL on failure
      66             :  *
      67             :  * Caller is responsible for freeing the returned buffer. Returned buffer is
      68             :  * nul terminated to make it easier to use as a C string. The nul terminator is
      69             :  * not included in out_len.
      70             :  */
      71             : unsigned char *
      72           0 : base64_encode(const unsigned char *src, size_t len, size_t *out_len)
      73             : {
      74             :     unsigned char *out, *pos;
      75             :     const unsigned char *end, *in;
      76             :     size_t olen;
      77             : 
      78           0 :     olen = base64_encoded_len(len) + 1 /* for NUL termination */;
      79           0 :     if (olen < len)
      80           0 :         return NULL; /* integer overflow */
      81             : 
      82           0 :     out = malloc(olen);
      83           0 :     if (out == NULL)
      84           0 :         return NULL;
      85             : 
      86           0 :     end = src + len;
      87           0 :     in = src;
      88           0 :     pos = out;
      89           0 :     while (end - in >= 3) {
      90           0 :         *pos++ = base64_table[in[0] >> 2];
      91           0 :         *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
      92           0 :         *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
      93           0 :         *pos++ = base64_table[in[2] & 0x3f];
      94           0 :         in += 3;
      95             :     }
      96             : 
      97           0 :     if (end - in) {
      98           0 :         *pos++ = base64_table[in[0] >> 2];
      99           0 :         if (end - in == 1) {
     100           0 :             *pos++ = base64_table[(in[0] & 0x03) << 4];
     101           0 :             *pos++ = '=';
     102             :         } else {
     103           0 :             *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
     104           0 :             *pos++ = base64_table[(in[1] & 0x0f) << 2];
     105             :         }
     106           0 :         *pos++ = '=';
     107             :     }
     108             : 
     109           0 :     *pos = '\0';
     110           0 :     if (out_len)
     111           0 :         *out_len = (size_t)(pos - out);
     112           0 :     return out;
     113             : }
     114             : 
     115             : /**
     116             :  * base64_decode - Base64 decode
     117             :  * @src: Data to be decoded
     118             :  * @len: Length of the data to be decoded
     119             :  * @out_len: Pointer to output length variable
     120             :  * Returns: Allocated buffer of out_len bytes of decoded data,
     121             :  * or %NULL on failure
     122             :  *
     123             :  * Caller is responsible for freeing the returned buffer.
     124             :  */
     125             : unsigned char *
     126           3 : base64_decode(const unsigned char *src, size_t len, size_t *out_len)
     127             : {
     128             :     unsigned char *out, *pos, block[4];
     129             :     size_t i, count, olen;
     130           3 :     int pad = 0;
     131             : 
     132           3 :     count = 0;
     133          55 :     for (i = 0; i < len; i++) {
     134          52 :         if (base64_decode_table[src[i]] != 0x80)
     135          52 :             count++;
     136             :     }
     137             : 
     138           3 :     if (count == 0 || count % 4)
     139           0 :         return NULL;
     140             : 
     141           3 :     olen = (count / 4 * 3) + 1;
     142           3 :     pos = out = malloc(olen);
     143           3 :     if (out == NULL)
     144           0 :         return NULL;
     145             : 
     146           3 :     count = 0;
     147          52 :     for (i = 0; i < len; i++) {
     148          52 :         unsigned char tmp = base64_decode_table[src[i]];
     149          52 :         if (tmp == 0x80)
     150           0 :             continue;
     151             : 
     152          52 :         if (src[i] == '=')
     153           3 :             pad++;
     154          52 :         block[count] = tmp;
     155          52 :         count++;
     156          52 :         if (count == 4) {
     157          13 :             *pos++ = (unsigned char)((block[0] << 2) | (block[1] >> 4));
     158          13 :             *pos++ = (unsigned char)((block[1] << 4) | (block[2] >> 2));
     159          13 :             *pos++ = (unsigned char)((block[2] << 6) | block[3]);
     160          13 :             count = 0;
     161          13 :             if (pad) {
     162           3 :                 if (pad == 1)
     163           3 :                     pos--;
     164           0 :                 else if (pad == 2)
     165           0 :                     pos -= 2;
     166             :                 else {
     167             :                     /* Invalid padding */
     168           0 :                     free(out);
     169           0 :                     return NULL;
     170             :                 }
     171           3 :                 break;
     172             :             }
     173             :         }
     174             :     }
     175           3 :     *pos = '\0';
     176             : 
     177           3 :     *out_len = (size_t)(pos - out);
     178           3 :     return out;
     179             : }

Generated by: LCOV version 1.15-2-gb9d6727