LCOV - code coverage report
Current view: top level - basic - hexdecoct.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 457 506 90.3 %
Date: 2019-08-23 13:36:53 Functions: 21 21 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 248 325 76.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <ctype.h>
       4                 :            : #include <errno.h>
       5                 :            : #include <stdint.h>
       6                 :            : #include <stdlib.h>
       7                 :            : 
       8                 :            : #include "alloc-util.h"
       9                 :            : #include "hexdecoct.h"
      10                 :            : #include "macro.h"
      11                 :            : #include "memory-util.h"
      12                 :            : #include "string-util.h"
      13                 :            : 
      14                 :     118232 : char octchar(int x) {
      15                 :     118232 :         return '0' + (x & 7);
      16                 :            : }
      17                 :            : 
      18                 :        296 : int unoctchar(char c) {
      19                 :            : 
      20   [ +  -  +  - ]:        296 :         if (c >= '0' && c <= '7')
      21                 :        296 :                 return c - '0';
      22                 :            : 
      23                 :          0 :         return -EINVAL;
      24                 :            : }
      25                 :            : 
      26                 :          8 : char decchar(int x) {
      27                 :          8 :         return '0' + (x % 10);
      28                 :            : }
      29                 :            : 
      30                 :       2400 : int undecchar(char c) {
      31                 :            : 
      32   [ +  -  +  - ]:       2400 :         if (c >= '0' && c <= '9')
      33                 :       2400 :                 return c - '0';
      34                 :            : 
      35                 :          0 :         return -EINVAL;
      36                 :            : }
      37                 :            : 
      38                 :     394160 : char hexchar(int x) {
      39                 :            :         static const char table[16] = "0123456789abcdef";
      40                 :            : 
      41                 :     394160 :         return table[x & 15];
      42                 :            : }
      43                 :            : 
      44                 :     324376 : int unhexchar(char c) {
      45                 :            : 
      46   [ +  +  +  + ]:     324376 :         if (c >= '0' && c <= '9')
      47                 :     207926 :                 return c - '0';
      48                 :            : 
      49   [ +  +  +  + ]:     116450 :         if (c >= 'a' && c <= 'f')
      50                 :     115190 :                 return c - 'a' + 10;
      51                 :            : 
      52   [ +  +  +  + ]:       1260 :         if (c >= 'A' && c <= 'F')
      53                 :       1228 :                 return c - 'A' + 10;
      54                 :            : 
      55                 :         32 :         return -EINVAL;
      56                 :            : }
      57                 :            : 
      58                 :        324 : char *hexmem(const void *p, size_t l) {
      59                 :            :         const uint8_t *x;
      60                 :            :         char *r, *z;
      61                 :            : 
      62                 :        324 :         z = r = new(char, l * 2 + 1);
      63         [ -  + ]:        324 :         if (!r)
      64                 :          0 :                 return NULL;
      65                 :            : 
      66         [ +  + ]:       7612 :         for (x = p; x < (const uint8_t*) p + l; x++) {
      67                 :       7288 :                 *(z++) = hexchar(*x >> 4);
      68                 :       7288 :                 *(z++) = hexchar(*x & 15);
      69                 :            :         }
      70                 :            : 
      71                 :        324 :         *z = 0;
      72                 :        324 :         return r;
      73                 :            : }
      74                 :            : 
      75                 :        388 : static int unhex_next(const char **p, size_t *l) {
      76                 :            :         int r;
      77                 :            : 
      78         [ -  + ]:        388 :         assert(p);
      79         [ -  + ]:        388 :         assert(l);
      80                 :            : 
      81                 :            :         /* Find the next non-whitespace character, and decode it. We
      82                 :            :          * greedily skip all preceding and all following whitespace. */
      83                 :            : 
      84                 :            :         for (;;) {
      85         [ +  + ]:        468 :                 if (*l == 0)
      86                 :         40 :                         return -EPIPE;
      87                 :            : 
      88         [ +  + ]:        428 :                 if (!strchr(WHITESPACE, **p))
      89                 :        348 :                         break;
      90                 :            : 
      91                 :            :                 /* Skip leading whitespace */
      92                 :         80 :                 (*p)++, (*l)--;
      93                 :            :         }
      94                 :            : 
      95                 :        348 :         r = unhexchar(**p);
      96         [ +  + ]:        348 :         if (r < 0)
      97                 :          8 :                 return r;
      98                 :            : 
      99                 :            :         for (;;) {
     100                 :        160 :                 (*p)++, (*l)--;
     101                 :            : 
     102   [ +  +  +  + ]:        500 :                 if (*l == 0 || !strchr(WHITESPACE, **p))
     103                 :            :                         break;
     104                 :            : 
     105                 :            :                 /* Skip following whitespace */
     106                 :            :         }
     107                 :            : 
     108                 :        340 :         return r;
     109                 :            : }
     110                 :            : 
     111                 :         48 : int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) {
     112                 :         48 :         _cleanup_free_ uint8_t *buf = NULL;
     113                 :            :         size_t buf_size;
     114                 :            :         const char *x;
     115                 :            :         uint8_t *z;
     116                 :            :         int r;
     117                 :            : 
     118         [ -  + ]:         48 :         assert(ret);
     119         [ -  + ]:         48 :         assert(ret_len);
     120   [ +  +  -  + ]:         48 :         assert(p || l == 0);
     121                 :            : 
     122         [ +  + ]:         48 :         if (l == (size_t) -1)
     123                 :         20 :                 l = strlen(p);
     124                 :            : 
     125                 :            :         /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
     126                 :         48 :         buf_size = (l + 1) / 2 + 1;
     127                 :         48 :         buf = malloc(buf_size);
     128         [ -  + ]:         48 :         if (!buf)
     129                 :          0 :                 return -ENOMEM;
     130                 :            : 
     131                 :         48 :         for (x = p, z = buf;;) {
     132                 :            :                 int a, b;
     133                 :            : 
     134                 :        212 :                 a = unhex_next(&x, &l);
     135         [ +  + ]:        212 :                 if (a == -EPIPE) /* End of string */
     136                 :         36 :                         break;
     137         [ -  + ]:        176 :                 if (a < 0) {
     138                 :          0 :                         r = a;
     139                 :          0 :                         goto on_failure;
     140                 :            :                 }
     141                 :            : 
     142                 :        176 :                 b = unhex_next(&x, &l);
     143         [ +  + ]:        176 :                 if (b < 0) {
     144                 :         12 :                         r = b;
     145                 :         12 :                         goto on_failure;
     146                 :            :                 }
     147                 :            : 
     148                 :        164 :                 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
     149                 :            :         }
     150                 :            : 
     151                 :         36 :         *z = 0;
     152                 :            : 
     153                 :         36 :         *ret_len = (size_t) (z - buf);
     154                 :         36 :         *ret = TAKE_PTR(buf);
     155                 :            : 
     156                 :         36 :         return 0;
     157                 :            : 
     158                 :         12 : on_failure:
     159         [ -  + ]:         12 :         if (secure)
     160                 :          0 :                 explicit_bzero_safe(buf, buf_size);
     161                 :            : 
     162                 :         12 :         return r;
     163                 :            : }
     164                 :            : 
     165                 :            : /* https://tools.ietf.org/html/rfc4648#section-6
     166                 :            :  * Notice that base32hex differs from base32 in the alphabet it uses.
     167                 :            :  * The distinction is that the base32hex representation preserves the
     168                 :            :  * order of the underlying data when compared as bytestrings, this is
     169                 :            :  * useful when representing NSEC3 hashes, as one can then verify the
     170                 :            :  * order of hashes directly from their representation. */
     171                 :        560 : char base32hexchar(int x) {
     172                 :            :         static const char table[32] = "0123456789"
     173                 :            :                                       "ABCDEFGHIJKLMNOPQRSTUV";
     174                 :            : 
     175                 :        560 :         return table[x & 31];
     176                 :            : }
     177                 :            : 
     178                 :        672 : int unbase32hexchar(char c) {
     179                 :            :         unsigned offset;
     180                 :            : 
     181   [ +  -  +  + ]:        672 :         if (c >= '0' && c <= '9')
     182                 :         40 :                 return c - '0';
     183                 :            : 
     184                 :        632 :         offset = '9' - '0' + 1;
     185                 :            : 
     186   [ +  +  +  + ]:        632 :         if (c >= 'A' && c <= 'V')
     187                 :        588 :                 return c - 'A' + offset;
     188                 :            : 
     189                 :         44 :         return -EINVAL;
     190                 :            : }
     191                 :            : 
     192                 :         64 : char *base32hexmem(const void *p, size_t l, bool padding) {
     193                 :            :         char *r, *z;
     194                 :            :         const uint8_t *x;
     195                 :            :         size_t len;
     196                 :            : 
     197   [ -  +  #  # ]:         64 :         assert(p || l == 0);
     198                 :            : 
     199         [ +  + ]:         64 :         if (padding)
     200                 :            :                 /* five input bytes makes eight output bytes, padding is added so we must round up */
     201                 :         28 :                 len = 8 * (l + 4) / 5;
     202                 :            :         else {
     203                 :            :                 /* same, but round down as there is no padding */
     204                 :         36 :                 len = 8 * l / 5;
     205                 :            : 
     206   [ +  +  +  +  :         36 :                 switch (l % 5) {
                      + ]
     207                 :          4 :                 case 4:
     208                 :          4 :                         len += 7;
     209                 :          4 :                         break;
     210                 :          4 :                 case 3:
     211                 :          4 :                         len += 5;
     212                 :          4 :                         break;
     213                 :          4 :                 case 2:
     214                 :          4 :                         len += 4;
     215                 :          4 :                         break;
     216                 :          8 :                 case 1:
     217                 :          8 :                         len += 2;
     218                 :          8 :                         break;
     219                 :            :                 }
     220                 :         64 :         }
     221                 :            : 
     222                 :         64 :         z = r = malloc(len + 1);
     223         [ -  + ]:         64 :         if (!r)
     224                 :          0 :                 return NULL;
     225                 :            : 
     226         [ +  + ]:        112 :         for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
     227                 :            :                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
     228                 :            :                  * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
     229                 :         48 :                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
     230                 :         48 :                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
     231                 :         48 :                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
     232                 :         48 :                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);  /* 000YZZZZ */
     233                 :         48 :                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
     234                 :         48 :                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
     235                 :         48 :                 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5);  /* 000QQWWW */
     236                 :         48 :                 *(z++) = base32hexchar((x[4] & 31));                  /* 000WWWWW */
     237                 :            :         }
     238                 :            : 
     239   [ +  +  +  +  :         64 :         switch (l % 5) {
                      + ]
     240                 :          8 :         case 4:
     241                 :          8 :                 *(z++) = base32hexchar(x[0] >> 3);                    /* 000XXXXX */
     242                 :          8 :                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6);  /* 000XXXYY */
     243                 :          8 :                 *(z++) = base32hexchar((x[1] & 63) >> 1);             /* 000YYYYY */
     244                 :          8 :                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4);   /* 000YZZZZ */
     245                 :          8 :                 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
     246                 :          8 :                 *(z++) = base32hexchar((x[3] & 127) >> 2);            /* 000QQQQQ */
     247                 :          8 :                 *(z++) = base32hexchar((x[3] & 3) << 3);              /* 000QQ000 */
     248         [ +  + ]:          8 :                 if (padding)
     249                 :          4 :                         *(z++) = '=';
     250                 :            : 
     251                 :          8 :                 break;
     252                 :            : 
     253                 :          8 :         case 3:
     254                 :          8 :                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
     255                 :          8 :                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
     256                 :          8 :                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
     257                 :          8 :                 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
     258                 :          8 :                 *(z++) = base32hexchar((x[2] & 15) << 1);            /* 000ZZZZ0 */
     259         [ +  + ]:          8 :                 if (padding) {
     260                 :          4 :                         *(z++) = '=';
     261                 :          4 :                         *(z++) = '=';
     262                 :          4 :                         *(z++) = '=';
     263                 :            :                 }
     264                 :            : 
     265                 :          8 :                 break;
     266                 :            : 
     267                 :          8 :         case 2:
     268                 :          8 :                 *(z++) = base32hexchar(x[0] >> 3);                   /* 000XXXXX */
     269                 :          8 :                 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
     270                 :          8 :                 *(z++) = base32hexchar((x[1] & 63) >> 1);            /* 000YYYYY */
     271                 :          8 :                 *(z++) = base32hexchar((x[1] & 1) << 4);             /* 000Y0000 */
     272         [ +  + ]:          8 :                 if (padding) {
     273                 :          4 :                         *(z++) = '=';
     274                 :          4 :                         *(z++) = '=';
     275                 :          4 :                         *(z++) = '=';
     276                 :          4 :                         *(z++) = '=';
     277                 :            :                 }
     278                 :            : 
     279                 :          8 :                 break;
     280                 :            : 
     281                 :         16 :         case 1:
     282                 :         16 :                 *(z++) = base32hexchar(x[0] >> 3);       /* 000XXXXX */
     283                 :         16 :                 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
     284         [ +  + ]:         16 :                 if (padding) {
     285                 :          8 :                         *(z++) = '=';
     286                 :          8 :                         *(z++) = '=';
     287                 :          8 :                         *(z++) = '=';
     288                 :          8 :                         *(z++) = '=';
     289                 :          8 :                         *(z++) = '=';
     290                 :          8 :                         *(z++) = '=';
     291                 :            :                 }
     292                 :            : 
     293                 :         16 :                 break;
     294                 :            :         }
     295                 :            : 
     296                 :         64 :         *z = 0;
     297                 :         64 :         return r;
     298                 :            : }
     299                 :            : 
     300                 :        156 : int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
     301                 :        156 :         _cleanup_free_ uint8_t *r = NULL;
     302                 :            :         int a, b, c, d, e, f, g, h;
     303                 :            :         uint8_t *z;
     304                 :            :         const char *x;
     305                 :            :         size_t len;
     306                 :        156 :         unsigned pad = 0;
     307                 :            : 
     308   [ -  +  #  # ]:        156 :         assert(p || l == 0);
     309         [ -  + ]:        156 :         assert(mem);
     310         [ -  + ]:        156 :         assert(_len);
     311                 :            : 
     312         [ +  - ]:        156 :         if (l == (size_t) -1)
     313                 :        156 :                 l = strlen(p);
     314                 :            : 
     315                 :            :         /* padding ensures any base32hex input has input divisible by 8 */
     316   [ +  +  +  + ]:        156 :         if (padding && l % 8 != 0)
     317                 :          4 :                 return -EINVAL;
     318                 :            : 
     319         [ +  + ]:        152 :         if (padding) {
     320                 :            :                 /* strip the padding */
     321   [ +  +  +  +  :        280 :                 while (l > 0 && p[l - 1] == '=' && pad < 7) {
                   +  - ]
     322                 :        192 :                         pad++;
     323                 :        192 :                         l--;
     324                 :            :                 }
     325                 :            :         }
     326                 :            : 
     327                 :            :         /* a group of eight input bytes needs five output bytes, in case of
     328                 :            :          * padding we need to add some extra bytes */
     329                 :        152 :         len = (l / 8) * 5;
     330                 :            : 
     331   [ +  +  +  +  :        152 :         switch (l % 8) {
                   +  + ]
     332                 :         16 :         case 7:
     333                 :         16 :                 len += 4;
     334                 :         16 :                 break;
     335                 :         16 :         case 5:
     336                 :         16 :                 len += 3;
     337                 :         16 :                 break;
     338                 :         16 :         case 4:
     339                 :         16 :                 len += 2;
     340                 :         16 :                 break;
     341                 :         24 :         case 2:
     342                 :         24 :                 len += 1;
     343                 :         24 :                 break;
     344                 :         56 :         case 0:
     345                 :         56 :                 break;
     346                 :         24 :         default:
     347                 :         24 :                 return -EINVAL;
     348                 :            :         }
     349                 :            : 
     350                 :        128 :         z = r = malloc(len + 1);
     351         [ -  + ]:        128 :         if (!r)
     352                 :          0 :                 return -ENOMEM;
     353                 :            : 
     354         [ +  + ]:        148 :         for (x = p; x < p + (l / 8) * 8; x += 8) {
     355                 :            :                 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
     356                 :            :                  * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
     357                 :         60 :                 a = unbase32hexchar(x[0]);
     358         [ +  + ]:         60 :                 if (a < 0)
     359                 :          4 :                         return -EINVAL;
     360                 :            : 
     361                 :         56 :                 b = unbase32hexchar(x[1]);
     362         [ +  + ]:         56 :                 if (b < 0)
     363                 :          4 :                         return -EINVAL;
     364                 :            : 
     365                 :         52 :                 c = unbase32hexchar(x[2]);
     366         [ +  + ]:         52 :                 if (c < 0)
     367                 :          8 :                         return -EINVAL;
     368                 :            : 
     369                 :         44 :                 d = unbase32hexchar(x[3]);
     370         [ +  + ]:         44 :                 if (d < 0)
     371                 :          4 :                         return -EINVAL;
     372                 :            : 
     373                 :         40 :                 e = unbase32hexchar(x[4]);
     374         [ +  + ]:         40 :                 if (e < 0)
     375                 :          4 :                         return -EINVAL;
     376                 :            : 
     377                 :         36 :                 f = unbase32hexchar(x[5]);
     378         [ +  + ]:         36 :                 if (f < 0)
     379                 :          4 :                         return -EINVAL;
     380                 :            : 
     381                 :         32 :                 g = unbase32hexchar(x[6]);
     382         [ +  + ]:         32 :                 if (g < 0)
     383                 :          4 :                         return -EINVAL;
     384                 :            : 
     385                 :         28 :                 h = unbase32hexchar(x[7]);
     386         [ +  + ]:         28 :                 if (h < 0)
     387                 :          8 :                         return -EINVAL;
     388                 :            : 
     389                 :         20 :                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
     390                 :         20 :                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
     391                 :         20 :                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
     392                 :         20 :                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
     393                 :         20 :                 *(z++) = (uint8_t) g << 5 | (uint8_t) h;                         /* VVVRRRRR */
     394                 :            :         }
     395                 :            : 
     396   [ +  +  +  +  :         88 :         switch (l % 8) {
                   +  - ]
     397                 :         16 :         case 7:
     398                 :         16 :                 a = unbase32hexchar(x[0]);
     399         [ -  + ]:         16 :                 if (a < 0)
     400                 :          0 :                         return -EINVAL;
     401                 :            : 
     402                 :         16 :                 b = unbase32hexchar(x[1]);
     403         [ -  + ]:         16 :                 if (b < 0)
     404                 :          0 :                         return -EINVAL;
     405                 :            : 
     406                 :         16 :                 c = unbase32hexchar(x[2]);
     407         [ -  + ]:         16 :                 if (c < 0)
     408                 :          0 :                         return -EINVAL;
     409                 :            : 
     410                 :         16 :                 d = unbase32hexchar(x[3]);
     411         [ -  + ]:         16 :                 if (d < 0)
     412                 :          0 :                         return -EINVAL;
     413                 :            : 
     414                 :         16 :                 e = unbase32hexchar(x[4]);
     415         [ -  + ]:         16 :                 if (e < 0)
     416                 :          0 :                         return -EINVAL;
     417                 :            : 
     418                 :         16 :                 f = unbase32hexchar(x[5]);
     419         [ -  + ]:         16 :                 if (f < 0)
     420                 :          0 :                         return -EINVAL;
     421                 :            : 
     422                 :         16 :                 g = unbase32hexchar(x[6]);
     423         [ -  + ]:         16 :                 if (g < 0)
     424                 :          0 :                         return -EINVAL;
     425                 :            : 
     426                 :            :                 /* g == 000VV000 */
     427         [ +  + ]:         16 :                 if (g & 7)
     428                 :          8 :                         return -EINVAL;
     429                 :            : 
     430                 :          8 :                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
     431                 :          8 :                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
     432                 :          8 :                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
     433                 :          8 :                 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
     434                 :            : 
     435                 :          8 :                 break;
     436                 :         16 :         case 5:
     437                 :         16 :                 a = unbase32hexchar(x[0]);
     438         [ -  + ]:         16 :                 if (a < 0)
     439                 :          0 :                         return -EINVAL;
     440                 :            : 
     441                 :         16 :                 b = unbase32hexchar(x[1]);
     442         [ -  + ]:         16 :                 if (b < 0)
     443                 :          0 :                         return -EINVAL;
     444                 :            : 
     445                 :         16 :                 c = unbase32hexchar(x[2]);
     446         [ -  + ]:         16 :                 if (c < 0)
     447                 :          0 :                         return -EINVAL;
     448                 :            : 
     449                 :         16 :                 d = unbase32hexchar(x[3]);
     450         [ -  + ]:         16 :                 if (d < 0)
     451                 :          0 :                         return -EINVAL;
     452                 :            : 
     453                 :         16 :                 e = unbase32hexchar(x[4]);
     454         [ -  + ]:         16 :                 if (e < 0)
     455                 :          0 :                         return -EINVAL;
     456                 :            : 
     457                 :            :                 /* e == 000SSSS0 */
     458         [ +  + ]:         16 :                 if (e & 1)
     459                 :          8 :                         return -EINVAL;
     460                 :            : 
     461                 :          8 :                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
     462                 :          8 :                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
     463                 :          8 :                 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1;                    /* WWWWSSSS */
     464                 :            : 
     465                 :          8 :                 break;
     466                 :         16 :         case 4:
     467                 :         16 :                 a = unbase32hexchar(x[0]);
     468         [ -  + ]:         16 :                 if (a < 0)
     469                 :          0 :                         return -EINVAL;
     470                 :            : 
     471                 :         16 :                 b = unbase32hexchar(x[1]);
     472         [ -  + ]:         16 :                 if (b < 0)
     473                 :          0 :                         return -EINVAL;
     474                 :            : 
     475                 :         16 :                 c = unbase32hexchar(x[2]);
     476         [ -  + ]:         16 :                 if (c < 0)
     477                 :          0 :                         return -EINVAL;
     478                 :            : 
     479                 :         16 :                 d = unbase32hexchar(x[3]);
     480         [ -  + ]:         16 :                 if (d < 0)
     481                 :          0 :                         return -EINVAL;
     482                 :            : 
     483                 :            :                 /* d == 000W0000 */
     484         [ +  + ]:         16 :                 if (d & 15)
     485                 :          8 :                         return -EINVAL;
     486                 :            : 
     487                 :          8 :                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2;                    /* XXXXXYYY */
     488                 :          8 :                 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
     489                 :            : 
     490                 :          8 :                 break;
     491                 :         24 :         case 2:
     492                 :         24 :                 a = unbase32hexchar(x[0]);
     493         [ -  + ]:         24 :                 if (a < 0)
     494                 :          0 :                         return -EINVAL;
     495                 :            : 
     496                 :         24 :                 b = unbase32hexchar(x[1]);
     497         [ -  + ]:         24 :                 if (b < 0)
     498                 :          0 :                         return -EINVAL;
     499                 :            : 
     500                 :            :                 /* b == 000YYY00 */
     501         [ +  + ]:         24 :                 if (b & 3)
     502                 :          8 :                         return -EINVAL;
     503                 :            : 
     504                 :         16 :                 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
     505                 :            : 
     506                 :         16 :                 break;
     507                 :         16 :         case 0:
     508                 :         16 :                 break;
     509                 :          0 :         default:
     510                 :          0 :                 return -EINVAL;
     511                 :            :         }
     512                 :            : 
     513                 :         56 :         *z = 0;
     514                 :            : 
     515                 :         56 :         *mem = TAKE_PTR(r);
     516                 :         56 :         *_len = len;
     517                 :            : 
     518                 :         56 :         return 0;
     519                 :            : }
     520                 :            : 
     521                 :            : /* https://tools.ietf.org/html/rfc4648#section-4 */
     522                 :     130776 : char base64char(int x) {
     523                 :            :         static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     524                 :            :                                       "abcdefghijklmnopqrstuvwxyz"
     525                 :            :                                       "0123456789+/";
     526                 :     130776 :         return table[x & 63];
     527                 :            : }
     528                 :            : 
     529                 :        324 : int unbase64char(char c) {
     530                 :            :         unsigned offset;
     531                 :            : 
     532   [ +  +  +  + ]:        324 :         if (c >= 'A' && c <= 'Z')
     533                 :        136 :                 return c - 'A';
     534                 :            : 
     535                 :        188 :         offset = 'Z' - 'A' + 1;
     536                 :            : 
     537   [ +  +  +  - ]:        188 :         if (c >= 'a' && c <= 'z')
     538                 :        124 :                 return c - 'a' + offset;
     539                 :            : 
     540                 :         64 :         offset += 'z' - 'a' + 1;
     541                 :            : 
     542   [ +  +  +  + ]:         64 :         if (c >= '0' && c <= '9')
     543                 :         52 :                 return c - '0' + offset;
     544                 :            : 
     545                 :         12 :         offset += '9' - '0' + 1;
     546                 :            : 
     547         [ +  + ]:         12 :         if (c == '+')
     548                 :          4 :                 return offset;
     549                 :            : 
     550                 :          8 :         offset++;
     551                 :            : 
     552         [ +  + ]:          8 :         if (c == '/')
     553                 :          4 :                 return offset;
     554                 :            : 
     555                 :          4 :         return -EINVAL;
     556                 :            : }
     557                 :            : 
     558                 :        280 : ssize_t base64mem(const void *p, size_t l, char **out) {
     559                 :            :         char *r, *z;
     560                 :            :         const uint8_t *x;
     561                 :            : 
     562   [ -  +  #  # ]:        280 :         assert(p || l == 0);
     563         [ -  + ]:        280 :         assert(out);
     564                 :            : 
     565                 :            :         /* three input bytes makes four output bytes, padding is added so we must round up */
     566                 :        280 :         z = r = malloc(4 * (l + 2) / 3 + 1);
     567         [ -  + ]:        280 :         if (!r)
     568                 :          0 :                 return -ENOMEM;
     569                 :            : 
     570         [ +  + ]:      32852 :         for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
     571                 :            :                 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
     572                 :      32572 :                 *(z++) = base64char(x[0] >> 2);                    /* 00XXXXXX */
     573                 :      32572 :                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4);  /* 00XXYYYY */
     574                 :      32572 :                 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
     575                 :      32572 :                 *(z++) = base64char(x[2] & 63);                    /* 00ZZZZZZ */
     576                 :            :         }
     577                 :            : 
     578      [ +  +  + ]:        280 :         switch (l % 3) {
     579                 :        148 :         case 2:
     580                 :        148 :                 *(z++) = base64char(x[0] >> 2);                   /* 00XXXXXX */
     581                 :        148 :                 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
     582                 :        148 :                 *(z++) = base64char((x[1] & 15) << 2);            /* 00YYYY00 */
     583                 :        148 :                 *(z++) = '=';
     584                 :            : 
     585                 :        148 :                 break;
     586                 :         16 :         case 1:
     587                 :         16 :                 *(z++) = base64char(x[0] >> 2);        /* 00XXXXXX */
     588                 :         16 :                 *(z++) = base64char((x[0] & 3) << 4);  /* 00XX0000 */
     589                 :         16 :                 *(z++) = '=';
     590                 :         16 :                 *(z++) = '=';
     591                 :            : 
     592                 :         16 :                 break;
     593                 :            :         }
     594                 :            : 
     595                 :        280 :         *z = 0;
     596                 :        280 :         *out = r;
     597                 :        280 :         return z - r;
     598                 :            : }
     599                 :            : 
     600                 :        252 : static int base64_append_width(
     601                 :            :                 char **prefix, int plen,
     602                 :            :                 const char *sep, int indent,
     603                 :            :                 const void *p, size_t l,
     604                 :            :                 int width) {
     605                 :            : 
     606                 :        252 :         _cleanup_free_ char *x = NULL;
     607                 :            :         char *t, *s;
     608                 :            :         ssize_t len, slen, avail, line, lines;
     609                 :            : 
     610                 :        252 :         len = base64mem(p, l, &x);
     611         [ -  + ]:        252 :         if (len <= 0)
     612                 :          0 :                 return len;
     613                 :            : 
     614                 :        252 :         lines = DIV_ROUND_UP(len, width);
     615                 :            : 
     616                 :        252 :         slen = strlen_ptr(sep);
     617         [ +  - ]:        252 :         if (plen >= SSIZE_MAX - 1 - slen ||
     618         [ -  + ]:        252 :             lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1))
     619                 :          0 :                 return -ENOMEM;
     620                 :            : 
     621                 :        252 :         t = realloc(*prefix, (ssize_t) plen + 1 + slen + (indent + width + 1) * lines);
     622         [ -  + ]:        252 :         if (!t)
     623                 :          0 :                 return -ENOMEM;
     624                 :            : 
     625                 :        252 :         memcpy_safe(t + plen, sep, slen);
     626                 :            : 
     627         [ +  + ]:       2460 :         for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
     628                 :       2208 :                 int act = MIN(width, avail);
     629                 :            : 
     630   [ +  +  +  - ]:       2208 :                 if (line > 0 || sep) {
     631                 :       2208 :                         memset(s, ' ', indent);
     632                 :       2208 :                         s += indent;
     633                 :            :                 }
     634                 :            : 
     635                 :       2208 :                 memcpy(s, x + width * line, act);
     636                 :       2208 :                 s += act;
     637         [ +  + ]:       2208 :                 *(s++) = line < lines - 1 ? '\n' : '\0';
     638                 :       2208 :                 avail -= act;
     639                 :            :         }
     640         [ -  + ]:        252 :         assert(avail == 0);
     641                 :            : 
     642                 :        252 :         *prefix = t;
     643                 :        252 :         return 0;
     644                 :            : }
     645                 :            : 
     646                 :        252 : int base64_append(
     647                 :            :                 char **prefix, int plen,
     648                 :            :                 const void *p, size_t l,
     649                 :            :                 int indent, int width) {
     650                 :            : 
     651   [ +  +  -  + ]:        252 :         if (plen > width / 2 || plen + indent > width)
     652                 :            :                 /* leave indent on the left, keep last column free */
     653                 :        136 :                 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
     654                 :            :         else
     655                 :            :                 /* leave plen on the left, keep last column free */
     656                 :        116 :                 return base64_append_width(prefix, plen, " ", plen, p, l, width - plen - 1);
     657                 :            : }
     658                 :            : 
     659                 :        384 : static int unbase64_next(const char **p, size_t *l) {
     660                 :            :         int ret;
     661                 :            : 
     662         [ -  + ]:        384 :         assert(p);
     663         [ -  + ]:        384 :         assert(l);
     664                 :            : 
     665                 :            :         /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
     666                 :            :          * greedily skip all preceding and all following whitespace. */
     667                 :            : 
     668                 :            :         for (;;) {
     669         [ +  + ]:        460 :                 if (*l == 0)
     670                 :         32 :                         return -EPIPE;
     671                 :            : 
     672         [ +  + ]:        428 :                 if (!strchr(WHITESPACE, **p))
     673                 :        352 :                         break;
     674                 :            : 
     675                 :            :                 /* Skip leading whitespace */
     676                 :         76 :                 (*p)++, (*l)--;
     677                 :            :         }
     678                 :            : 
     679         [ +  + ]:        352 :         if (**p == '=')
     680                 :         64 :                 ret = INT_MAX; /* return padding as INT_MAX */
     681                 :            :         else {
     682                 :        288 :                 ret = unbase64char(**p);
     683         [ -  + ]:        288 :                 if (ret < 0)
     684                 :          0 :                         return ret;
     685                 :            :         }
     686                 :            : 
     687                 :            :         for (;;) {
     688                 :        164 :                 (*p)++, (*l)--;
     689                 :            : 
     690         [ +  + ]:        516 :                 if (*l == 0)
     691                 :         56 :                         break;
     692         [ +  + ]:        460 :                 if (!strchr(WHITESPACE, **p))
     693                 :        296 :                         break;
     694                 :            : 
     695                 :            :                 /* Skip following whitespace */
     696                 :            :         }
     697                 :            : 
     698                 :        352 :         return ret;
     699                 :            : }
     700                 :            : 
     701                 :         80 : int unbase64mem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_size) {
     702                 :         80 :         _cleanup_free_ uint8_t *buf = NULL;
     703                 :            :         const char *x;
     704                 :            :         uint8_t *z;
     705                 :            :         size_t len;
     706                 :            :         int r;
     707                 :            : 
     708   [ -  +  #  # ]:         80 :         assert(p || l == 0);
     709         [ -  + ]:         80 :         assert(ret);
     710         [ -  + ]:         80 :         assert(ret_size);
     711                 :            : 
     712         [ +  - ]:         80 :         if (l == (size_t) -1)
     713                 :         80 :                 l = strlen(p);
     714                 :            : 
     715                 :            :         /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
     716                 :            :          * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
     717         [ +  + ]:         80 :         len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
     718                 :            : 
     719                 :         80 :         buf = malloc(len + 1);
     720         [ -  + ]:         80 :         if (!buf)
     721                 :          0 :                 return -ENOMEM;
     722                 :            : 
     723                 :         80 :         for (x = p, z = buf;;) {
     724                 :            :                 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
     725                 :            : 
     726                 :        124 :                 a = unbase64_next(&x, &l);
     727         [ +  + ]:        124 :                 if (a == -EPIPE) /* End of string */
     728                 :         28 :                         break;
     729         [ -  + ]:         96 :                 if (a < 0) {
     730                 :          0 :                         r = a;
     731                 :          0 :                         goto on_failure;
     732                 :            :                 }
     733         [ +  + ]:         96 :                 if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */
     734                 :          4 :                         r = -EINVAL;
     735                 :          4 :                         goto on_failure;
     736                 :            :                 }
     737                 :            : 
     738                 :         92 :                 b = unbase64_next(&x, &l);
     739         [ +  + ]:         92 :                 if (b < 0) {
     740                 :          4 :                         r = b;
     741                 :          4 :                         goto on_failure;
     742                 :            :                 }
     743         [ +  + ]:         88 :                 if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */
     744                 :          4 :                         r = -EINVAL;
     745                 :          4 :                         goto on_failure;
     746                 :            :                 }
     747                 :            : 
     748                 :         84 :                 c = unbase64_next(&x, &l);
     749         [ -  + ]:         84 :                 if (c < 0) {
     750                 :          0 :                         r = c;
     751                 :          0 :                         goto on_failure;
     752                 :            :                 }
     753                 :            : 
     754                 :         84 :                 d = unbase64_next(&x, &l);
     755         [ -  + ]:         84 :                 if (d < 0) {
     756                 :          0 :                         r = d;
     757                 :          0 :                         goto on_failure;
     758                 :            :                 }
     759                 :            : 
     760         [ +  + ]:         84 :                 if (c == INT_MAX) { /* Padding at the third character */
     761                 :            : 
     762         [ -  + ]:         16 :                         if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
     763                 :          0 :                                 r = -EINVAL;
     764                 :          0 :                                 goto on_failure;
     765                 :            :                         }
     766                 :            : 
     767                 :            :                         /* b == 00YY0000 */
     768         [ -  + ]:         16 :                         if (b & 15) {
     769                 :          0 :                                 r = -EINVAL;
     770                 :          0 :                                 goto on_failure;
     771                 :            :                         }
     772                 :            : 
     773         [ -  + ]:         16 :                         if (l > 0) { /* Trailing rubbish? */
     774                 :          0 :                                 r = -ENAMETOOLONG;
     775                 :          0 :                                 goto on_failure;
     776                 :            :                         }
     777                 :            : 
     778                 :         16 :                         *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
     779                 :         16 :                         break;
     780                 :            :                 }
     781                 :            : 
     782         [ +  + ]:         68 :                 if (d == INT_MAX) {
     783                 :            :                         /* c == 00ZZZZ00 */
     784         [ +  + ]:         24 :                         if (c & 3) {
     785                 :          4 :                                 r = -EINVAL;
     786                 :          4 :                                 goto on_failure;
     787                 :            :                         }
     788                 :            : 
     789         [ +  + ]:         20 :                         if (l > 0) { /* Trailing rubbish? */
     790                 :          4 :                                 r = -ENAMETOOLONG;
     791                 :          4 :                                 goto on_failure;
     792                 :            :                         }
     793                 :            : 
     794                 :         16 :                         *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
     795                 :         16 :                         *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
     796                 :         16 :                         break;
     797                 :            :                 }
     798                 :            : 
     799                 :         44 :                 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
     800                 :         44 :                 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
     801                 :         44 :                 *(z++) = (uint8_t) c << 6 | (uint8_t) d;      /* ZZWWWWWW */
     802                 :            :         }
     803                 :            : 
     804                 :         60 :         *z = 0;
     805                 :            : 
     806                 :         60 :         *ret_size = (size_t) (z - buf);
     807                 :         60 :         *ret = TAKE_PTR(buf);
     808                 :            : 
     809                 :         60 :         return 0;
     810                 :            : 
     811                 :         20 : on_failure:
     812         [ -  + ]:         20 :         if (secure)
     813                 :          0 :                 explicit_bzero_safe(buf, len);
     814                 :            : 
     815                 :         20 :         return r;
     816                 :            : }
     817                 :            : 
     818                 :        336 : void hexdump(FILE *f, const void *p, size_t s) {
     819                 :        336 :         const uint8_t *b = p;
     820                 :        336 :         unsigned n = 0;
     821                 :            : 
     822   [ +  +  -  + ]:        336 :         assert(b || s == 0);
     823                 :            : 
     824         [ -  + ]:        336 :         if (!f)
     825                 :          0 :                 f = stdout;
     826                 :            : 
     827         [ +  + ]:        376 :         while (s > 0) {
     828                 :            :                 size_t i;
     829                 :            : 
     830                 :        368 :                 fprintf(f, "%04x  ", n);
     831                 :            : 
     832         [ +  + ]:       6256 :                 for (i = 0; i < 16; i++) {
     833                 :            : 
     834         [ +  + ]:       5888 :                         if (i >= s)
     835                 :       2740 :                                 fputs("   ", f);
     836                 :            :                         else
     837                 :       3148 :                                 fprintf(f, "%02x ", b[i]);
     838                 :            : 
     839         [ +  + ]:       5888 :                         if (i == 7)
     840                 :        368 :                                 fputc(' ', f);
     841                 :            :                 }
     842                 :            : 
     843                 :        368 :                 fputc(' ', f);
     844                 :            : 
     845         [ +  + ]:       6256 :                 for (i = 0; i < 16; i++) {
     846                 :            : 
     847         [ +  + ]:       5888 :                         if (i >= s)
     848                 :       2740 :                                 fputc(' ', f);
     849                 :            :                         else
     850         [ +  + ]:       3148 :                                 fputc(isprint(b[i]) ? (char) b[i] : '.', f);
     851                 :            :                 }
     852                 :            : 
     853                 :        368 :                 fputc('\n', f);
     854                 :            : 
     855         [ +  + ]:        368 :                 if (s < 16)
     856                 :        328 :                         break;
     857                 :            : 
     858                 :         40 :                 n += 16;
     859                 :         40 :                 b += 16;
     860                 :         40 :                 s -= 16;
     861                 :            :         }
     862                 :        336 : }

Generated by: LCOV version 1.14