1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2010 Lennart Poettering
11 #include "alloc-util.h"
12 #include "hexdecoct.h"
14 #include "string-util.h"
21 int unoctchar(char c) {
23 if (c >= '0' && c <= '7')
30 return '0' + (x % 10);
33 int undecchar(char c) {
35 if (c >= '0' && c <= '9')
42 static const char table[16] = "0123456789abcdef";
47 int unhexchar(char c) {
49 if (c >= '0' && c <= '9')
52 if (c >= 'a' && c <= 'f')
55 if (c >= 'A' && c <= 'F')
61 char *hexmem(const void *p, size_t l) {
65 z = r = new(char, l * 2 + 1);
69 for (x = p; x < (const uint8_t*) p + l; x++) {
70 *(z++) = hexchar(*x >> 4);
71 *(z++) = hexchar(*x & 15);
78 static int unhex_next(const char **p, size_t *l) {
84 /* Find the next non-whitespace character, and decode it. We
85 * greedily skip all preceeding and all following whitespace. */
91 if (!strchr(WHITESPACE, **p))
94 /* Skip leading whitespace */
105 if (*l == 0 || !strchr(WHITESPACE, **p))
108 /* Skip following whitespace */
114 int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
115 _cleanup_free_ uint8_t *buf = NULL;
123 if (l == (size_t) -1)
126 /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
127 buf = malloc((l + 1) / 2 + 1);
131 for (x = p, z = buf;;) {
134 a = unhex_next(&x, &l);
135 if (a == -EPIPE) /* End of string */
140 b = unhex_next(&x, &l);
144 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
149 *ret_len = (size_t) (z - buf);
150 *ret = TAKE_PTR(buf);
155 /* https://tools.ietf.org/html/rfc4648#section-6
156 * Notice that base32hex differs from base32 in the alphabet it uses.
157 * The distinction is that the base32hex representation preserves the
158 * order of the underlying data when compared as bytestrings, this is
159 * useful when representing NSEC3 hashes, as one can then verify the
160 * order of hashes directly from their representation. */
161 char base32hexchar(int x) {
162 static const char table[32] = "0123456789"
163 "ABCDEFGHIJKLMNOPQRSTUV";
165 return table[x & 31];
168 int unbase32hexchar(char c) {
171 if (c >= '0' && c <= '9')
174 offset = '9' - '0' + 1;
176 if (c >= 'A' && c <= 'V')
177 return c - 'A' + offset;
182 char *base32hexmem(const void *p, size_t l, bool padding) {
190 /* five input bytes makes eight output bytes, padding is added so we must round up */
191 len = 8 * (l + 4) / 5;
193 /* same, but round down as there is no padding */
212 z = r = malloc(len + 1);
216 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
217 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
218 * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
219 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
220 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
221 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
222 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
223 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
224 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
225 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
226 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
231 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
232 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
233 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
234 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
235 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
236 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
237 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
244 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
245 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
246 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
247 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
248 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
258 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
259 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
260 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
261 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
272 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
273 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
290 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
291 _cleanup_free_ uint8_t *r = NULL;
292 int a, b, c, d, e, f, g, h;
302 if (l == (size_t) -1)
305 /* padding ensures any base32hex input has input divisible by 8 */
306 if (padding && l % 8 != 0)
310 /* strip the padding */
311 while (l > 0 && p[l - 1] == '=' && pad < 7) {
317 /* a group of eight input bytes needs five output bytes, in case of
318 * padding we need to add some extra bytes */
340 z = r = malloc(len + 1);
344 for (x = p; x < p + (l / 8) * 8; x += 8) {
345 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
346 * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
347 a = unbase32hexchar(x[0]);
351 b = unbase32hexchar(x[1]);
355 c = unbase32hexchar(x[2]);
359 d = unbase32hexchar(x[3]);
363 e = unbase32hexchar(x[4]);
367 f = unbase32hexchar(x[5]);
371 g = unbase32hexchar(x[6]);
375 h = unbase32hexchar(x[7]);
379 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
380 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
381 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
382 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
383 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
388 a = unbase32hexchar(x[0]);
392 b = unbase32hexchar(x[1]);
396 c = unbase32hexchar(x[2]);
400 d = unbase32hexchar(x[3]);
404 e = unbase32hexchar(x[4]);
408 f = unbase32hexchar(x[5]);
412 g = unbase32hexchar(x[6]);
420 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
421 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
422 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
423 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
427 a = unbase32hexchar(x[0]);
431 b = unbase32hexchar(x[1]);
435 c = unbase32hexchar(x[2]);
439 d = unbase32hexchar(x[3]);
443 e = unbase32hexchar(x[4]);
451 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
452 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
453 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
457 a = unbase32hexchar(x[0]);
461 b = unbase32hexchar(x[1]);
465 c = unbase32hexchar(x[2]);
469 d = unbase32hexchar(x[3]);
477 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
478 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
482 a = unbase32hexchar(x[0]);
486 b = unbase32hexchar(x[1]);
494 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
511 /* https://tools.ietf.org/html/rfc4648#section-4 */
512 char base64char(int x) {
513 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
514 "abcdefghijklmnopqrstuvwxyz"
516 return table[x & 63];
519 int unbase64char(char c) {
522 if (c >= 'A' && c <= 'Z')
525 offset = 'Z' - 'A' + 1;
527 if (c >= 'a' && c <= 'z')
528 return c - 'a' + offset;
530 offset += 'z' - 'a' + 1;
532 if (c >= '0' && c <= '9')
533 return c - '0' + offset;
535 offset += '9' - '0' + 1;
548 ssize_t base64mem(const void *p, size_t l, char **out) {
555 /* three input bytes makes four output bytes, padding is added so we must round up */
556 z = r = malloc(4 * (l + 2) / 3 + 1);
560 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
561 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
562 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
563 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
564 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
565 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
570 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
571 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
572 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
577 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
578 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
590 static int base64_append_width(
591 char **prefix, int plen,
592 const char *sep, int indent,
593 const void *p, size_t l,
596 _cleanup_free_ char *x = NULL;
598 ssize_t slen, len, avail;
601 len = base64mem(p, l, &x);
605 lines = DIV_ROUND_UP(len, width);
607 slen = strlen_ptr(sep);
608 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
612 memcpy_safe(t + plen, sep, slen);
614 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
615 int act = MIN(width, avail);
617 if (line > 0 || sep) {
618 memset(s, ' ', indent);
622 memcpy(s, x + width * line, act);
624 *(s++) = line < lines - 1 ? '\n' : '\0';
634 char **prefix, int plen,
635 const void *p, size_t l,
636 int indent, int width) {
638 if (plen > width / 2 || plen + indent > width)
639 /* leave indent on the left, keep last column free */
640 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
642 /* leave plen on the left, keep last column free */
643 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
646 static int unbase64_next(const char **p, size_t *l) {
652 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
653 * greedily skip all preceeding and all following whitespace. */
659 if (!strchr(WHITESPACE, **p))
662 /* Skip leading whitespace */
667 ret = INT_MAX; /* return padding as INT_MAX */
669 ret = unbase64char(**p);
679 if (!strchr(WHITESPACE, **p))
682 /* Skip following whitespace */
688 int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
689 _cleanup_free_ uint8_t *buf = NULL;
698 if (l == (size_t) -1)
701 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
702 * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
703 len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
705 buf = malloc(len + 1);
709 for (x = p, z = buf;;) {
710 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
712 a = unbase64_next(&x, &l);
713 if (a == -EPIPE) /* End of string */
717 if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
720 b = unbase64_next(&x, &l);
723 if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
726 c = unbase64_next(&x, &l);
730 d = unbase64_next(&x, &l);
734 if (c == INT_MAX) { /* Padding at the third character */
736 if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
743 if (l > 0) /* Trailing rubbish? */
744 return -ENAMETOOLONG;
746 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
755 if (l > 0) /* Trailing rubbish? */
756 return -ENAMETOOLONG;
758 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
759 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
763 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
764 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
765 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
770 *ret_size = (size_t) (z - buf);
771 *ret = TAKE_PTR(buf);
776 void hexdump(FILE *f, const void *p, size_t s) {
777 const uint8_t *b = p;
788 fprintf(f, "%04x ", n);
790 for (i = 0; i < 16; i++) {
795 fprintf(f, "%02x ", b[i]);
803 for (i = 0; i < 16; i++) {
808 fputc(isprint(b[i]) ? (char) b[i] : '.', f);