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/>.
27 #include "alloc-util.h"
28 #include "hexdecoct.h"
35 int unoctchar(char c) {
37 if (c >= '0' && c <= '7')
44 return '0' + (x % 10);
47 int undecchar(char c) {
49 if (c >= '0' && c <= '9')
56 static const char table[16] = "0123456789abcdef";
61 int unhexchar(char c) {
63 if (c >= '0' && c <= '9')
66 if (c >= 'a' && c <= 'f')
69 if (c >= 'A' && c <= 'F')
75 char *hexmem(const void *p, size_t l) {
79 z = r = malloc(l * 2 + 1);
83 for (x = p; x < (const uint8_t*) p + l; x++) {
84 *(z++) = hexchar(*x >> 4);
85 *(z++) = hexchar(*x & 15);
92 int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
93 _cleanup_free_ uint8_t *r = NULL;
101 z = r = malloc((l + 1) / 2 + 1);
105 for (x = p; x < p + l; x += 2) {
111 else if (x+1 < p + l) {
118 *(z++) = (uint8_t) a << 4 | (uint8_t) b;
130 /* https://tools.ietf.org/html/rfc4648#section-6
131 * Notice that base32hex differs from base32 in the alphabet it uses.
132 * The distinction is that the base32hex representation preserves the
133 * order of the underlying data when compared as bytestrings, this is
134 * useful when representing NSEC3 hashes, as one can then verify the
135 * order of hashes directly from their representation. */
136 char base32hexchar(int x) {
137 static const char table[32] = "0123456789"
138 "ABCDEFGHIJKLMNOPQRSTUV";
140 return table[x & 31];
143 int unbase32hexchar(char c) {
146 if (c >= '0' && c <= '9')
149 offset = '9' - '0' + 1;
151 if (c >= 'A' && c <= 'V')
152 return c - 'A' + offset;
157 char *base32hexmem(const void *p, size_t l, bool padding) {
163 /* five input bytes makes eight output bytes, padding is added so we must round up */
164 len = 8 * (l + 4) / 5;
166 /* same, but round down as there is no padding */
185 z = r = malloc(len + 1);
189 for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
190 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
191 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
192 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
193 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
194 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
195 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
196 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
197 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
198 *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
199 *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
204 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
205 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
206 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
207 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
208 *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
209 *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
210 *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
217 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
218 *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
219 *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
220 *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
221 *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
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); /* 000Y0000 */
245 *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
246 *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
263 int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
264 _cleanup_free_ uint8_t *r = NULL;
265 int a, b, c, d, e, f, g, h;
273 /* padding ensures any base32hex input has input divisible by 8 */
274 if (padding && l % 8 != 0)
278 /* strip the padding */
279 while (l > 0 && p[l - 1] == '=' && pad < 7) {
285 /* a group of eight input bytes needs five output bytes, in case of
286 padding we need to add some extra bytes */
308 z = r = malloc(len + 1);
312 for (x = p; x < p + (l / 8) * 8; x += 8) {
313 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
314 e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
315 a = unbase32hexchar(x[0]);
319 b = unbase32hexchar(x[1]);
323 c = unbase32hexchar(x[2]);
327 d = unbase32hexchar(x[3]);
331 e = unbase32hexchar(x[4]);
335 f = unbase32hexchar(x[5]);
339 g = unbase32hexchar(x[6]);
343 h = unbase32hexchar(x[7]);
347 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
348 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
349 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
350 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
351 *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
356 a = unbase32hexchar(x[0]);
360 b = unbase32hexchar(x[1]);
364 c = unbase32hexchar(x[2]);
368 d = unbase32hexchar(x[3]);
372 e = unbase32hexchar(x[4]);
376 f = unbase32hexchar(x[5]);
380 g = unbase32hexchar(x[6]);
388 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
389 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
390 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
391 *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
395 a = unbase32hexchar(x[0]);
399 b = unbase32hexchar(x[1]);
403 c = unbase32hexchar(x[2]);
407 d = unbase32hexchar(x[3]);
411 e = unbase32hexchar(x[4]);
419 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
420 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
421 *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
425 a = unbase32hexchar(x[0]);
429 b = unbase32hexchar(x[1]);
433 c = unbase32hexchar(x[2]);
437 d = unbase32hexchar(x[3]);
445 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
446 *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
450 a = unbase32hexchar(x[0]);
454 b = unbase32hexchar(x[1]);
462 *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
480 /* https://tools.ietf.org/html/rfc4648#section-4 */
481 char base64char(int x) {
482 static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
483 "abcdefghijklmnopqrstuvwxyz"
485 return table[x & 63];
488 int unbase64char(char c) {
491 if (c >= 'A' && c <= 'Z')
494 offset = 'Z' - 'A' + 1;
496 if (c >= 'a' && c <= 'z')
497 return c - 'a' + offset;
499 offset += 'z' - 'a' + 1;
501 if (c >= '0' && c <= '9')
502 return c - '0' + offset;
504 offset += '9' - '0' + 1;
517 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(char **prefix, int plen,
557 const char *sep, int indent,
558 const void *p, size_t l,
561 _cleanup_free_ char *x = NULL;
563 ssize_t slen, len, avail;
566 len = base64mem(p, l, &x);
570 lines = (len + width - 1) / width;
572 slen = sep ? strlen(sep) : 0;
573 t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
577 memcpy(t + plen, sep, slen);
579 for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
580 int act = MIN(width, avail);
582 if (line > 0 || sep) {
583 memset(s, ' ', indent);
587 memcpy(s, x + width * line, act);
589 *(s++) = line < lines - 1 ? '\n' : '\0';
598 int base64_append(char **prefix, int plen,
599 const void *p, size_t l,
600 int indent, int width) {
601 if (plen > width / 2 || plen + indent > width)
602 /* leave indent on the left, keep last column free */
603 return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
605 /* leave plen on the left, keep last column free */
606 return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
610 int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
611 _cleanup_free_ uint8_t *r = NULL;
619 /* padding ensures any base63 input has input divisible by 4 */
623 /* strip the padding */
624 if (l > 0 && p[l - 1] == '=')
626 if (l > 0 && p[l - 1] == '=')
629 /* a group of four input bytes needs three output bytes, in case of
630 padding we need to add two or three extra bytes */
631 len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
633 z = r = malloc(len + 1);
637 for (x = p; x < p + (l / 4) * 4; x += 4) {
638 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
639 a = unbase64char(x[0]);
643 b = unbase64char(x[1]);
647 c = unbase64char(x[2]);
651 d = unbase64char(x[3]);
655 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
656 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
657 *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
662 a = unbase64char(x[0]);
666 b = unbase64char(x[1]);
670 c = unbase64char(x[2]);
678 *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
679 *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
683 a = unbase64char(x[0]);
687 b = unbase64char(x[1]);
695 *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
714 void hexdump(FILE *f, const void *p, size_t s) {
715 const uint8_t *b = p;
723 fprintf(f, "%04x ", n);
725 for (i = 0; i < 16; i++) {
730 fprintf(f, "%02x ", b[i]);
738 for (i = 0; i < 16; i++) {
743 fputc(isprint(b[i]) ? (char) b[i] : '.', f);