1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
27 #include "hexdecoct.h"
29 #include "string-util.h"
36 int unoctchar(char c) {
38 if (c >= '0' && c <= '7')
45 return '0' + (x % 10);
48 int undecchar(char c) {
50 if (c >= '0' && c <= '9')
57 static const char table[16] = "0123456789abcdef";
62 int unhexchar(char c) {
64 if (c >= '0' && c <= '9')
67 if (c >= 'a' && c <= 'f')
70 if (c >= 'A' && c <= 'F')
76 char *hexmem(const void *p, size_t l) {
80 z = r = new(char, l * 2 + 1);
84 for (x = p; x < (const uint8_t*) p + l; x++) {
85 *(z++) = hexchar(*x >> 4);
86 *(z++) = hexchar(*x & 15);
93 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
94 _cleanup_free_ uint8_t *r = NULL;
102 if (l == (size_t) -1)
108 z = r = malloc((l + 1) / 2 + 1);
112 for (x = p; x < p + l; x += 2) {
123 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
135 /* https://tools.ietf.org/html/rfc4648#section-6
136 * Notice that base32hex differs from base32 in the alphabet it uses.
137 * The distinction is that the base32hex representation preserves the
138 * order of the underlying data when compared as bytestrings, this is
139 * useful when representing NSEC3 hashes, as one can then verify the
140 * order of hashes directly from their representation. */
141 char base32hexchar(int x) {
142 static const char table[32] = "0123456789"
143 "ABCDEFGHIJKLMNOPQRSTUV";
145 return table[x & 31];
148 int unbase32hexchar(char c) {
151 if (c >= '0' && c <= '9')
154 offset = '9' - '0' + 1;
156 if (c >= 'A' && c <= 'V')
157 return c - 'A' + offset;
162 char *base32hexmem(const void *p, size_t l, bool padding) {
170 /* five input bytes makes eight output bytes, padding is added so we must round up */
171 len = 8 * (l + 4) / 5;
173 /* same, but round down as there is no padding */
192 z = r = malloc(len + 1);
196 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
197 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
198 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
199 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
200 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
201 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
202 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
203 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
204 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
205 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
206 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
211 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
212 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
213 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
214 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
215 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
216 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
217 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
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 | x[2] >> 4); /* 000YZZZZ */
228 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
238 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
239 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
240 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
241 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
252 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
253 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
270 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
271 _cleanup_free_ uint8_t *r = NULL;
272 int a, b, c, d, e, f, g, h;
282 if (l == (size_t) -1)
285 /* padding ensures any base32hex input has input divisible by 8 */
286 if (padding && l % 8 != 0)
290 /* strip the padding */
291 while (l > 0 && p[l - 1] == '=' && pad < 7) {
297 /* a group of eight input bytes needs five output bytes, in case of
298 padding we need to add some extra bytes */
320 z = r = malloc(len + 1);
324 for (x = p; x < p + (l / 8) * 8; x += 8) {
325 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
326 e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
327 a = unbase32hexchar(x[0]);
331 b = unbase32hexchar(x[1]);
335 c = unbase32hexchar(x[2]);
339 d = unbase32hexchar(x[3]);
343 e = unbase32hexchar(x[4]);
347 f = unbase32hexchar(x[5]);
351 g = unbase32hexchar(x[6]);
355 h = unbase32hexchar(x[7]);
359 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
360 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
361 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
362 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
363 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
368 a = unbase32hexchar(x[0]);
372 b = unbase32hexchar(x[1]);
376 c = unbase32hexchar(x[2]);
380 d = unbase32hexchar(x[3]);
384 e = unbase32hexchar(x[4]);
388 f = unbase32hexchar(x[5]);
392 g = unbase32hexchar(x[6]);
400 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
401 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
402 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
403 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
407 a = unbase32hexchar(x[0]);
411 b = unbase32hexchar(x[1]);
415 c = unbase32hexchar(x[2]);
419 d = unbase32hexchar(x[3]);
423 e = unbase32hexchar(x[4]);
431 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
432 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
433 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
437 a = unbase32hexchar(x[0]);
441 b = unbase32hexchar(x[1]);
445 c = unbase32hexchar(x[2]);
449 d = unbase32hexchar(x[3]);
457 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
458 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
462 a = unbase32hexchar(x[0]);
466 b = unbase32hexchar(x[1]);
474 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
492 /* https://tools.ietf.org/html/rfc4648#section-4 */
493 char base64char(int x) {
494 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
495 "abcdefghijklmnopqrstuvwxyz"
497 return table[x & 63];
500 int unbase64char(char c) {
503 if (c >= 'A' && c <= 'Z')
506 offset = 'Z' - 'A' + 1;
508 if (c >= 'a' && c <= 'z')
509 return c - 'a' + offset;
511 offset += 'z' - 'a' + 1;
513 if (c >= '0' && c <= '9')
514 return c - '0' + offset;
516 offset += '9' - '0' + 1;
529 ssize_t base64mem(const void *p, size_t l, char **out) {
536 /* three input bytes makes four output bytes, padding is added so we must round up */
537 z = r = malloc(4 * (l + 2) / 3 + 1);
541 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
542 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
543 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
544 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
545 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
546 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
551 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
552 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
553 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
558 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
559 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
571 static int base64_append_width(
572 char **prefix, int plen,
573 const char *sep, int indent,
574 const void *p, size_t l,
577 _cleanup_free_ char *x = NULL;
579 ssize_t slen, len, avail;
582 len = base64mem(p, l, &x);
586 lines = (len + width - 1) / width;
588 slen = strlen_ptr(sep);
589 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
593 memcpy_safe(t + plen, sep, slen);
595 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
596 int act = MIN(width, avail);
598 if (line > 0 || sep) {
599 memset(s, ' ', indent);
603 memcpy(s, x + width * line, act);
605 *(s++) = line < lines - 1 ? '\n' : '\0';
615 char **prefix, int plen,
616 const void *p, size_t l,
617 int indent, int width) {
619 if (plen > width / 2 || plen + indent > width)
620 /* leave indent on the left, keep last column free */
621 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
623 /* leave plen on the left, keep last column free */
624 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
627 static int unbase64_next(const char **p, size_t *l) {
633 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
634 * greedily skip all preceeding and all following whitespace. */
640 if (!strchr(WHITESPACE, **p))
643 /* Skip leading whitespace */
648 ret = INT_MAX; /* return padding as INT_MAX */
650 ret = unbase64char(**p);
660 if (!strchr(WHITESPACE, **p))
663 /* Skip following whitespace */
669 int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) {
670 _cleanup_free_ uint8_t *buf = NULL;
679 if (l == (size_t) -1)
682 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
683 bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
684 len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
686 buf = malloc(len + 1);
690 for (x = p, z = buf;;) {
691 int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
693 a = unbase64_next(&x, &l);
694 if (a == -EPIPE) /* End of string */
698 if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */
701 b = unbase64_next(&x, &l);
704 if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */
707 c = unbase64_next(&x, &l);
711 d = unbase64_next(&x, &l);
715 if (c == INT_MAX) { /* Padding at the third character */
717 if (d != INT_MAX) /* If the third character is padding, the fourth must be too */
724 if (l > 0) /* Trailing rubbish? */
725 return -ENAMETOOLONG;
727 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
736 if (l > 0) /* Trailing rubbish? */
737 return -ENAMETOOLONG;
739 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
740 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
744 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
745 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
746 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
752 *ret_size = (size_t) (z - buf);
760 void hexdump(FILE *f, const void *p, size_t s) {
761 const uint8_t *b = p;
772 fprintf(f, "%04x ", n);
774 for (i = 0; i < 16; i++) {
779 fprintf(f, "%02x ", b[i]);
787 for (i = 0; i < 16; i++) {
792 fputc(isprint(b[i]) ? (char) b[i] : '.', f);