1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
13 #include "alloc-util.h"
14 #include "hexdecoct.h"
16 #include "string-util.h"
23 int unoctchar(char c) {
25 if (c >= '0' && c <= '7')
32 return '0' + (x % 10);
35 int undecchar(char c) {
37 if (c >= '0' && c <= '9')
44 static const char table[16] = "0123456789abcdef";
49 int unhexchar(char c) {
51 if (c >= '0' && c <= '9')
54 if (c >= 'a' && c <= 'f')
57 if (c >= 'A' && c <= 'F')
63 char *hexmem(const void *p, size_t l) {
67 z = r = new(char, l * 2 + 1);
71 for (x = p; x < (const uint8_t*) p + l; x++) {
72 *(z++) = hexchar(*x >> 4);
73 *(z++) = hexchar(*x & 15);
80 static int unhex_next(const char **p, size_t *l) {
86 /* Find the next non-whitespace character, and decode it. We
87 * greedily skip all preceeding and all following whitespace. */
93 if (!strchr(WHITESPACE, **p))
96 /* Skip leading whitespace */
107 if (*l == 0 || !strchr(WHITESPACE, **p))
110 /* Skip following whitespace */
116 int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
117 _cleanup_free_ uint8_t *buf = NULL;
125 if (l == (size_t) -1)
128 /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
129 buf = malloc((l + 1) / 2 + 1);
133 for (x = p, z = buf;;) {
136 a = unhex_next(&x, &l);
137 if (a == -EPIPE) /* End of string */
142 b = unhex_next(&x, &l);
146 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
151 *ret_len = (size_t) (z - buf);
152 *ret = TAKE_PTR(buf);
157 /* https://tools.ietf.org/html/rfc4648#section-6
158 * Notice that base32hex differs from base32 in the alphabet it uses.
159 * The distinction is that the base32hex representation preserves the
160 * order of the underlying data when compared as bytestrings, this is
161 * useful when representing NSEC3 hashes, as one can then verify the
162 * order of hashes directly from their representation. */
163 char base32hexchar(int x) {
164 static const char table[32] = "0123456789"
165 "ABCDEFGHIJKLMNOPQRSTUV";
167 return table[x & 31];
170 int unbase32hexchar(char c) {
173 if (c >= '0' && c <= '9')
176 offset = '9' - '0' + 1;
178 if (c >= 'A' && c <= 'V')
179 return c - 'A' + offset;
184 char *base32hexmem(const void *p, size_t l, bool padding) {
192 /* five input bytes makes eight output bytes, padding is added so we must round up */
193 len = 8 * (l + 4) / 5;
195 /* same, but round down as there is no padding */
214 z = r = malloc(len + 1);
218 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
219 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
220 * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
221 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
222 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
223 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
224 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
225 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
226 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
227 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
228 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
233 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
234 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
235 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
236 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
237 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
238 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
239 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
246 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
247 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
248 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
249 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
250 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
260 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
261 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
262 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
263 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
274 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
275 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
292 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
293 _cleanup_free_ uint8_t *r = NULL;
294 int a, b, c, d, e, f, g, h;
304 if (l == (size_t) -1)
307 /* padding ensures any base32hex input has input divisible by 8 */
308 if (padding && l % 8 != 0)
312 /* strip the padding */
313 while (l > 0 && p[l - 1] == '=' && pad < 7) {
319 /* a group of eight input bytes needs five output bytes, in case of
320 * padding we need to add some extra bytes */
342 z = r = malloc(len + 1);
346 for (x = p; x < p + (l / 8) * 8; x += 8) {
347 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
348 * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
349 a = unbase32hexchar(x[0]);
353 b = unbase32hexchar(x[1]);
357 c = unbase32hexchar(x[2]);
361 d = unbase32hexchar(x[3]);
365 e = unbase32hexchar(x[4]);
369 f = unbase32hexchar(x[5]);
373 g = unbase32hexchar(x[6]);
377 h = unbase32hexchar(x[7]);
381 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
382 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
383 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
384 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
385 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
390 a = unbase32hexchar(x[0]);
394 b = unbase32hexchar(x[1]);
398 c = unbase32hexchar(x[2]);
402 d = unbase32hexchar(x[3]);
406 e = unbase32hexchar(x[4]);
410 f = unbase32hexchar(x[5]);
414 g = unbase32hexchar(x[6]);
422 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
423 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
424 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
425 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
429 a = unbase32hexchar(x[0]);
433 b = unbase32hexchar(x[1]);
437 c = unbase32hexchar(x[2]);
441 d = unbase32hexchar(x[3]);
445 e = unbase32hexchar(x[4]);
453 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
454 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
455 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
459 a = unbase32hexchar(x[0]);
463 b = unbase32hexchar(x[1]);
467 c = unbase32hexchar(x[2]);
471 d = unbase32hexchar(x[3]);
479 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
480 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
484 a = unbase32hexchar(x[0]);
488 b = unbase32hexchar(x[1]);
496 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
513 /* https://tools.ietf.org/html/rfc4648#section-4 */
514 char base64char(int x) {
515 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
516 "abcdefghijklmnopqrstuvwxyz"
518 return table[x & 63];
521 int unbase64char(char c) {
524 if (c >= 'A' && c <= 'Z')
527 offset = 'Z' - 'A' + 1;
529 if (c >= 'a' && c <= 'z')
530 return c - 'a' + offset;
532 offset += 'z' - 'a' + 1;
534 if (c >= '0' && c <= '9')
535 return c - '0' + offset;
537 offset += '9' - '0' + 1;
550 ssize_t base64mem(const void *p, size_t l, char **out) {
557 /* three input bytes makes four output bytes, padding is added so we must round up */
558 z = r = malloc(4 * (l + 2) / 3 + 1);
562 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
563 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
564 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
565 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
566 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
567 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
572 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
573 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
574 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
579 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
580 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
592 static int base64_append_width(
593 char **prefix, int plen,
594 const char *sep, int indent,
595 const void *p, size_t l,
598 _cleanup_free_ char *x = NULL;
600 ssize_t slen, len, avail;
603 len = base64mem(p, l, &x);
607 lines = DIV_ROUND_UP(len, width);
609 slen = strlen_ptr(sep);
610 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
614 memcpy_safe(t + plen, sep, slen);
616 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
617 int act = MIN(width, avail);
619 if (line > 0 || sep) {
620 memset(s, ' ', indent);
624 memcpy(s, x + width * line, act);
626 *(s++) = line < lines - 1 ? '\n' : '\0';
636 char **prefix, int plen,
637 const void *p, size_t l,
638 int indent, int width) {
640 if (plen > width / 2 || plen + indent > width)
641 /* leave indent on the left, keep last column free */
642 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
644 /* leave plen on the left, keep last column free */
645 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
648 static int unbase64_next(const char **p, size_t *l) {
654 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
655 * greedily skip all preceeding and all following whitespace. */
661 if (!strchr(WHITESPACE, **p))
664 /* Skip leading whitespace */
669 ret = INT_MAX; /* return padding as INT_MAX */
671 ret = unbase64char(**p);
681 if (!strchr(WHITESPACE, **p))
684 /* Skip following whitespace */
690 int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
691 _cleanup_free_ uint8_t *buf = NULL;
700 if (l == (size_t) -1)
703 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
704 * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
705 len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
707 buf = malloc(len + 1);
711 for (x = p, z = buf;;) {
712 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
714 a = unbase64_next(&x, &l);
715 if (a == -EPIPE) /* End of string */
719 if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
722 b = unbase64_next(&x, &l);
725 if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
728 c = unbase64_next(&x, &l);
732 d = unbase64_next(&x, &l);
736 if (c == INT_MAX) { /* Padding at the third character */
738 if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
745 if (l > 0) /* Trailing rubbish? */
746 return -ENAMETOOLONG;
748 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
757 if (l > 0) /* Trailing rubbish? */
758 return -ENAMETOOLONG;
760 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
761 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
765 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
766 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
767 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
772 *ret_size = (size_t) (z - buf);
773 *ret = TAKE_PTR(buf);
778 void hexdump(FILE *f, const void *p, size_t s) {
779 const uint8_t *b = p;
790 fprintf(f, "%04x ", n);
792 for (i = 0; i < 16; i++) {
797 fprintf(f, "%02x ", b[i]);
805 for (i = 0; i < 16; i++) {
810 fputc(isprint(b[i]) ? (char) b[i] : '.', f);