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 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
81 _cleanup_free_ uint8_t *r = NULL;
95 z = r = malloc((l + 1) / 2 + 1);
99 for (x = p; x < p + l; x += 2) {
110 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
121 /* https://tools.ietf.org/html/rfc4648#section-6
122 * Notice that base32hex differs from base32 in the alphabet it uses.
123 * The distinction is that the base32hex representation preserves the
124 * order of the underlying data when compared as bytestrings, this is
125 * useful when representing NSEC3 hashes, as one can then verify the
126 * order of hashes directly from their representation. */
127 char base32hexchar(int x) {
128 static const char table[32] = "0123456789"
129 "ABCDEFGHIJKLMNOPQRSTUV";
131 return table[x & 31];
134 int unbase32hexchar(char c) {
137 if (c >= '0' && c <= '9')
140 offset = '9' - '0' + 1;
142 if (c >= 'A' && c <= 'V')
143 return c - 'A' + offset;
148 char *base32hexmem(const void *p, size_t l, bool padding) {
156 /* five input bytes makes eight output bytes, padding is added so we must round up */
157 len = 8 * (l + 4) / 5;
159 /* same, but round down as there is no padding */
178 z = r = malloc(len + 1);
182 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
183 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
184 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
185 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
186 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
187 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
188 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
189 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
190 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
191 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
192 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
197 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
198 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
199 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
200 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
201 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
202 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
203 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
210 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
211 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
212 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
213 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
214 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
224 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
225 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
226 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
227 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
238 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
239 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
256 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
257 _cleanup_free_ uint8_t *r = NULL;
258 int a, b, c, d, e, f, g, h;
268 if (l == (size_t) -1)
271 /* padding ensures any base32hex input has input divisible by 8 */
272 if (padding && l % 8 != 0)
276 /* strip the padding */
277 while (l > 0 && p[l - 1] == '=' && pad < 7) {
283 /* a group of eight input bytes needs five output bytes, in case of
284 padding we need to add some extra bytes */
306 z = r = malloc(len + 1);
310 for (x = p; x < p + (l / 8) * 8; x += 8) {
311 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
312 e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
313 a = unbase32hexchar(x[0]);
317 b = unbase32hexchar(x[1]);
321 c = unbase32hexchar(x[2]);
325 d = unbase32hexchar(x[3]);
329 e = unbase32hexchar(x[4]);
333 f = unbase32hexchar(x[5]);
337 g = unbase32hexchar(x[6]);
341 h = unbase32hexchar(x[7]);
345 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
346 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
347 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
348 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
349 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
354 a = unbase32hexchar(x[0]);
358 b = unbase32hexchar(x[1]);
362 c = unbase32hexchar(x[2]);
366 d = unbase32hexchar(x[3]);
370 e = unbase32hexchar(x[4]);
374 f = unbase32hexchar(x[5]);
378 g = unbase32hexchar(x[6]);
386 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
387 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
388 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
389 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
393 a = unbase32hexchar(x[0]);
397 b = unbase32hexchar(x[1]);
401 c = unbase32hexchar(x[2]);
405 d = unbase32hexchar(x[3]);
409 e = unbase32hexchar(x[4]);
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 */
423 a = unbase32hexchar(x[0]);
427 b = unbase32hexchar(x[1]);
431 c = unbase32hexchar(x[2]);
435 d = unbase32hexchar(x[3]);
443 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
444 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
448 a = unbase32hexchar(x[0]);
452 b = unbase32hexchar(x[1]);
460 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
477 /* https://tools.ietf.org/html/rfc4648#section-4 */
478 char base64char(int x) {
479 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
480 "abcdefghijklmnopqrstuvwxyz"
482 return table[x & 63];
485 int unbase64char(char c) {
488 if (c >= 'A' && c <= 'Z')
491 offset = 'Z' - 'A' + 1;
493 if (c >= 'a' && c <= 'z')
494 return c - 'a' + offset;
496 offset += 'z' - 'a' + 1;
498 if (c >= '0' && c <= '9')
499 return c - '0' + offset;
501 offset += '9' - '0' + 1;
514 ssize_t base64mem(const void *p, size_t l, char **out) {
521 /* three input bytes makes four output bytes, padding is added so we must round up */
522 z = r = malloc(4 * (l + 2) / 3 + 1);
526 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
527 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
528 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
529 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
530 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
531 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
536 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
537 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
538 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
543 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
544 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
556 static int base64_append_width(
557 char **prefix, int plen,
558 const char *sep, int indent,
559 const void *p, size_t l,
562 _cleanup_free_ char *x = NULL;
564 ssize_t slen, len, avail;
567 len = base64mem(p, l, &x);
571 lines = DIV_ROUND_UP(len, width);
573 slen = strlen_ptr(sep);
574 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
578 memcpy_safe(t + plen, sep, slen);
580 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
581 int act = MIN(width, avail);
583 if (line > 0 || sep) {
584 memset(s, ' ', indent);
588 memcpy(s, x + width * line, act);
590 *(s++) = line < lines - 1 ? '\n' : '\0';
600 char **prefix, int plen,
601 const void *p, size_t l,
602 int indent, int width) {
604 if (plen > width / 2 || plen + indent > width)
605 /* leave indent on the left, keep last column free */
606 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
608 /* leave plen on the left, keep last column free */
609 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
612 static int unbase64_next(const char **p, size_t *l) {
618 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
619 * greedily skip all preceeding and all following whitespace. */
625 if (!strchr(WHITESPACE, **p))
628 /* Skip leading whitespace */
633 ret = INT_MAX; /* return padding as INT_MAX */
635 ret = unbase64char(**p);
645 if (!strchr(WHITESPACE, **p))
648 /* Skip following whitespace */
654 int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
655 _cleanup_free_ uint8_t *buf = NULL;
664 if (l == (size_t) -1)
667 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
668 bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
669 len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
671 buf = malloc(len + 1);
675 for (x = p, z = buf;;) {
676 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
678 a = unbase64_next(&x, &l);
679 if (a == -EPIPE) /* End of string */
683 if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
686 b = unbase64_next(&x, &l);
689 if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
692 c = unbase64_next(&x, &l);
696 d = unbase64_next(&x, &l);
700 if (c == INT_MAX) { /* Padding at the third character */
702 if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
709 if (l > 0) /* Trailing rubbish? */
710 return -ENAMETOOLONG;
712 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
721 if (l > 0) /* Trailing rubbish? */
722 return -ENAMETOOLONG;
724 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
725 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
729 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
730 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
731 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
737 *ret_size = (size_t) (z - buf);
739 *ret = TAKE_PTR(buf);
744 void hexdump(FILE *f, const void *p, size_t s) {
745 const uint8_t *b = p;
756 fprintf(f, "%04x ", n);
758 for (i = 0; i < 16; i++) {
763 fprintf(f, "%02x ", b[i]);
771 for (i = 0; i < 16; i++) {
776 fputc(isprint(b[i]) ? (char) b[i] : '.', f);