1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
11 #include "string-util.h"
18 int unoctchar(char c) {
20 if (c >= '0' && c <= '7')
27 return '0' + (x % 10);
30 int undecchar(char c) {
32 if (c >= '0' && c <= '9')
39 static const char table[16] = "0123456789abcdef";
44 int unhexchar(char c) {
46 if (c >= '0' && c <= '9')
49 if (c >= 'a' && c <= 'f')
52 if (c >= 'A' && c <= 'F')
58 char *hexmem(const void *p, size_t l) {
62 z = r = new(char, l * 2 + 1);
66 for (x = p; x < (const uint8_t*) p + l; x++) {
67 *(z++) = hexchar(*x >> 4);
68 *(z++) = hexchar(*x & 15);
75 static int unhex_next(const char **p, size_t *l) {
81 /* Find the next non-whitespace character, and decode it. We
82 * greedily skip all preceeding and all following whitespace. */
88 if (!strchr(WHITESPACE, **p))
91 /* Skip leading whitespace */
102 if (*l == 0 || !strchr(WHITESPACE, **p))
105 /* Skip following whitespace */
111 int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
112 _cleanup_free_ uint8_t *buf = NULL;
120 if (l == (size_t) -1)
123 /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
124 buf = malloc((l + 1) / 2 + 1);
128 for (x = p, z = buf;;) {
131 a = unhex_next(&x, &l);
132 if (a == -EPIPE) /* End of string */
137 b = unhex_next(&x, &l);
141 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
146 *ret_len = (size_t) (z - buf);
147 *ret = TAKE_PTR(buf);
152 /* https://tools.ietf.org/html/rfc4648#section-6
153 * Notice that base32hex differs from base32 in the alphabet it uses.
154 * The distinction is that the base32hex representation preserves the
155 * order of the underlying data when compared as bytestrings, this is
156 * useful when representing NSEC3 hashes, as one can then verify the
157 * order of hashes directly from their representation. */
158 char base32hexchar(int x) {
159 static const char table[32] = "0123456789"
160 "ABCDEFGHIJKLMNOPQRSTUV";
162 return table[x & 31];
165 int unbase32hexchar(char c) {
168 if (c >= '0' && c <= '9')
171 offset = '9' - '0' + 1;
173 if (c >= 'A' && c <= 'V')
174 return c - 'A' + offset;
179 char *base32hexmem(const void *p, size_t l, bool padding) {
187 /* five input bytes makes eight output bytes, padding is added so we must round up */
188 len = 8 * (l + 4) / 5;
190 /* same, but round down as there is no padding */
209 z = r = malloc(len + 1);
213 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
214 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
215 * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
216 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
217 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
218 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
219 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
220 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
221 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
222 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
223 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
228 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
229 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
230 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
231 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
232 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
233 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
234 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
241 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
242 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
243 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
244 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
245 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
255 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
256 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
257 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
258 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
269 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
270 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
287 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
288 _cleanup_free_ uint8_t *r = NULL;
289 int a, b, c, d, e, f, g, h;
299 if (l == (size_t) -1)
302 /* padding ensures any base32hex input has input divisible by 8 */
303 if (padding && l % 8 != 0)
307 /* strip the padding */
308 while (l > 0 && p[l - 1] == '=' && pad < 7) {
314 /* a group of eight input bytes needs five output bytes, in case of
315 * padding we need to add some extra bytes */
337 z = r = malloc(len + 1);
341 for (x = p; x < p + (l / 8) * 8; x += 8) {
342 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
343 * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
344 a = unbase32hexchar(x[0]);
348 b = unbase32hexchar(x[1]);
352 c = unbase32hexchar(x[2]);
356 d = unbase32hexchar(x[3]);
360 e = unbase32hexchar(x[4]);
364 f = unbase32hexchar(x[5]);
368 g = unbase32hexchar(x[6]);
372 h = unbase32hexchar(x[7]);
376 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
377 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
378 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
379 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
380 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
385 a = unbase32hexchar(x[0]);
389 b = unbase32hexchar(x[1]);
393 c = unbase32hexchar(x[2]);
397 d = unbase32hexchar(x[3]);
401 e = unbase32hexchar(x[4]);
405 f = unbase32hexchar(x[5]);
409 g = unbase32hexchar(x[6]);
417 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
418 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
419 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
420 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
424 a = unbase32hexchar(x[0]);
428 b = unbase32hexchar(x[1]);
432 c = unbase32hexchar(x[2]);
436 d = unbase32hexchar(x[3]);
440 e = unbase32hexchar(x[4]);
448 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
449 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
450 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
454 a = unbase32hexchar(x[0]);
458 b = unbase32hexchar(x[1]);
462 c = unbase32hexchar(x[2]);
466 d = unbase32hexchar(x[3]);
474 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
475 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
479 a = unbase32hexchar(x[0]);
483 b = unbase32hexchar(x[1]);
491 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
508 /* https://tools.ietf.org/html/rfc4648#section-4 */
509 char base64char(int x) {
510 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
511 "abcdefghijklmnopqrstuvwxyz"
513 return table[x & 63];
516 int unbase64char(char c) {
519 if (c >= 'A' && c <= 'Z')
522 offset = 'Z' - 'A' + 1;
524 if (c >= 'a' && c <= 'z')
525 return c - 'a' + offset;
527 offset += 'z' - 'a' + 1;
529 if (c >= '0' && c <= '9')
530 return c - '0' + offset;
532 offset += '9' - '0' + 1;
545 ssize_t base64mem(const void *p, size_t l, char **out) {
552 /* three input bytes makes four output bytes, padding is added so we must round up */
553 z = r = malloc(4 * (l + 2) / 3 + 1);
557 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
558 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
559 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
560 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
561 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
562 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
567 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
568 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
569 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
574 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
575 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
587 static int base64_append_width(
588 char **prefix, int plen,
589 const char *sep, int indent,
590 const void *p, size_t l,
593 _cleanup_free_ char *x = NULL;
595 ssize_t slen, len, avail;
598 len = base64mem(p, l, &x);
602 lines = DIV_ROUND_UP(len, width);
604 slen = strlen_ptr(sep);
605 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
609 memcpy_safe(t + plen, sep, slen);
611 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
612 int act = MIN(width, avail);
614 if (line > 0 || sep) {
615 memset(s, ' ', indent);
619 memcpy(s, x + width * line, act);
621 *(s++) = line < lines - 1 ? '\n' : '\0';
631 char **prefix, int plen,
632 const void *p, size_t l,
633 int indent, int width) {
635 if (plen > width / 2 || plen + indent > width)
636 /* leave indent on the left, keep last column free */
637 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
639 /* leave plen on the left, keep last column free */
640 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
643 static int unbase64_next(const char **p, size_t *l) {
649 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
650 * greedily skip all preceeding and all following whitespace. */
656 if (!strchr(WHITESPACE, **p))
659 /* Skip leading whitespace */
664 ret = INT_MAX; /* return padding as INT_MAX */
666 ret = unbase64char(**p);
676 if (!strchr(WHITESPACE, **p))
679 /* Skip following whitespace */
685 int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
686 _cleanup_free_ uint8_t *buf = NULL;
695 if (l == (size_t) -1)
698 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
699 * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
700 len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
702 buf = malloc(len + 1);
706 for (x = p, z = buf;;) {
707 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
709 a = unbase64_next(&x, &l);
710 if (a == -EPIPE) /* End of string */
714 if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
717 b = unbase64_next(&x, &l);
720 if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
723 c = unbase64_next(&x, &l);
727 d = unbase64_next(&x, &l);
731 if (c == INT_MAX) { /* Padding at the third character */
733 if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
740 if (l > 0) /* Trailing rubbish? */
741 return -ENAMETOOLONG;
743 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
752 if (l > 0) /* Trailing rubbish? */
753 return -ENAMETOOLONG;
755 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
756 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
760 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
761 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
762 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
767 *ret_size = (size_t) (z - buf);
768 *ret = TAKE_PTR(buf);
773 void hexdump(FILE *f, const void *p, size_t s) {
774 const uint8_t *b = p;
785 fprintf(f, "%04x ", n);
787 for (i = 0; i < 16; i++) {
792 fprintf(f, "%02x ", b[i]);
800 for (i = 0; i < 16; i++) {
805 fputc(isprint(b[i]) ? (char) b[i] : '.', f);