1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "alloc-util.h"
26 #include "hexdecoct.h"
33 int unoctchar(char c) {
35 if (c >= '0' && c <= '7')
42 return '0' + (x % 10);
45 int undecchar(char c) {
47 if (c >= '0' && c <= '9')
54 static const char table[16] = "0123456789abcdef";
59 int unhexchar(char c) {
61 if (c >= '0' && c <= '9')
64 if (c >= 'a' && c <= 'f')
67 if (c >= 'A' && c <= 'F')
73 char *hexmem(const void *p, size_t l) {
77 z = r = malloc(l * 2 + 1);
81 for (x = p; x < (const uint8_t*) p + l; x++) {
82 *(z++) = hexchar(*x >> 4);
83 *(z++) = hexchar(*x & 15);
90 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
91 _cleanup_free_ uint8_t *r = NULL;
99 z = r = malloc((l + 1) / 2 + 1);
103 for (x = p; x < p + l; x += 2) {
109 else if (x+1 < p + l) {
116 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
128 /* https://tools.ietf.org/html/rfc4648#section-6
129 * Notice that base32hex differs from base32 in the alphabet it uses.
130 * The distinction is that the base32hex representation preserves the
131 * order of the underlying data when compared as bytestrings, this is
132 * useful when representing NSEC3 hashes, as one can then verify the
133 * order of hashes directly from their representation. */
134 char base32hexchar(int x) {
135 static const char table[32] = "0123456789"
136 "ABCDEFGHIJKLMNOPQRSTUV";
138 return table[x & 31];
141 int unbase32hexchar(char c) {
144 if (c >= '0' && c <= '9')
147 offset = '9' - '0' + 1;
149 if (c >= 'A' && c <= 'V')
150 return c - 'A' + offset;
155 char *base32hexmem(const void *p, size_t l, bool padding) {
161 /* five input bytes makes eight output bytes, padding is added so we must round up */
162 len = 8 * (l + 4) / 5;
164 /* same, but round down as there is no padding */
183 z = r = malloc(len + 1);
187 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
188 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
189 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
190 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
191 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
192 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
193 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
194 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
195 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
196 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
197 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
202 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
203 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
204 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
205 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
206 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
207 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
208 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
215 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
216 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
217 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
218 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
219 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
229 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
230 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
231 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
232 *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
243 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
244 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
261 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
262 _cleanup_free_ uint8_t *r = NULL;
263 int a, b, c, d, e, f, g, h;
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 */
478 /* https://tools.ietf.org/html/rfc4648#section-4 */
479 char base64char(int x) {
480 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
481 "abcdefghijklmnopqrstuvwxyz"
483 return table[x & 63];
486 int unbase64char(char c) {
489 if (c >= 'A' && c <= 'Z')
492 offset = 'Z' - 'A' + 1;
494 if (c >= 'a' && c <= 'z')
495 return c - 'a' + offset;
497 offset += 'z' - 'a' + 1;
499 if (c >= '0' && c <= '9')
500 return c - '0' + offset;
502 offset += '9' - '0' + 1;
515 ssize_t base64mem(const void *p, size_t l, char **out) {
519 /* three input bytes makes four output bytes, padding is added so we must round up */
520 z = r = malloc(4 * (l + 2) / 3 + 1);
524 for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
525 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
526 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
527 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
528 *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
529 *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
534 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
535 *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
536 *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
541 *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
542 *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
554 static int base64_append_width(char **prefix, int plen,
555 const char *sep, int indent,
556 const void *p, size_t l,
559 _cleanup_free_ char *x = NULL;
561 ssize_t slen, len, avail;
564 len = base64mem(p, l, &x);
568 lines = (len + width - 1) / width;
570 slen = sep ? strlen(sep) : 0;
571 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
575 memcpy(t + plen, sep, slen);
577 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
578 int act = MIN(width, avail);
580 if (line > 0 || sep) {
581 memset(s, ' ', indent);
585 memcpy(s, x + width * line, act);
587 *(s++) = line < lines - 1 ? '\n' : '\0';
596 int base64_append(char **prefix, int plen,
597 const void *p, size_t l,
598 int indent, int width) {
599 if (plen > width / 2 || plen + indent > width)
600 /* leave indent on the left, keep last column free */
601 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
603 /* leave plen on the left, keep last column free */
604 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
608 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
609 _cleanup_free_ uint8_t *r = NULL;
617 /* padding ensures any base63 input has input divisible by 4 */
621 /* strip the padding */
622 if (l > 0 && p[l - 1] == '=')
624 if (l > 0 && p[l - 1] == '=')
627 /* a group of four input bytes needs three output bytes, in case of
628 padding we need to add two or three extra bytes */
629 len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
631 z = r = malloc(len + 1);
635 for (x = p; x < p + (l / 4) * 4; x += 4) {
636 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
637 a = unbase64char(x[0]);
641 b = unbase64char(x[1]);
645 c = unbase64char(x[2]);
649 d = unbase64char(x[3]);
653 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
654 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
655 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
660 a = unbase64char(x[0]);
664 b = unbase64char(x[1]);
668 c = unbase64char(x[2]);
676 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
677 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
681 a = unbase64char(x[0]);
685 b = unbase64char(x[1]);
693 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
712 void hexdump(FILE *f, const void *p, size_t s) {
713 const uint8_t *b = p;
721 fprintf(f, "%04x ", n);
723 for (i = 0; i < 16; i++) {
728 fprintf(f, "%02x ", b[i]);
736 for (i = 0; i < 16; i++) {
741 fputc(isprint(b[i]) ? (char) b[i] : '.', f);