1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
11 #include "memory-util.h"
12 #include "string-util.h"
18 int unoctchar(char c
) {
20 if (c
>= '0' && c
<= '7')
27 return '0' + (x
% 10);
30 int undecchar(char c
) {
32 if (c
>= '0' && c
<= '9')
39 static const char table
[16] = "0123456789abcdef";
44 int unhexchar(char c
) {
46 if (c
>= '0' && c
<= '9')
49 if (c
>= 'a' && c
<= 'f')
52 if (c
>= 'A' && c
<= 'F')
58 char *hexmem(const void *p
, size_t l
) {
64 z
= r
= new(char, l
* 2 + 1);
68 for (x
= p
; x
&& x
< (const uint8_t*) p
+ l
; x
++) {
69 *(z
++) = hexchar(*x
>> 4);
70 *(z
++) = hexchar(*x
& 15);
77 static int unhex_next(const char **p
, size_t *l
) {
83 /* Find the next non-whitespace character, and decode it. We
84 * greedily skip all preceding and all following whitespace. */
90 if (!strchr(WHITESPACE
, **p
))
93 /* Skip leading whitespace */
104 if (*l
== 0 || !strchr(WHITESPACE
, **p
))
107 /* Skip following whitespace */
120 _cleanup_free_
uint8_t *buf
= NULL
;
130 /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
131 buf_size
= (l
+ 1) / 2 + 1;
132 buf
= malloc(buf_size
);
136 CLEANUP_ERASE_PTR(secure
? &buf
: NULL
, buf_size
);
138 for (x
= p
, z
= buf
;;) {
141 a
= unhex_next(&x
, &l
);
142 if (a
== -EPIPE
) /* End of string */
147 b
= unhex_next(&x
, &l
);
151 *(z
++) = (uint8_t) a
<< 4 | (uint8_t) b
;
157 *ret_len
= (size_t) (z
- buf
);
159 *ret
= TAKE_PTR(buf
);
164 /* https://tools.ietf.org/html/rfc4648#section-6
165 * Notice that base32hex differs from base32 in the alphabet it uses.
166 * The distinction is that the base32hex representation preserves the
167 * order of the underlying data when compared as bytestrings, this is
168 * useful when representing NSEC3 hashes, as one can then verify the
169 * order of hashes directly from their representation. */
170 char base32hexchar(int x
) {
171 static const char table
[32] = "0123456789"
172 "ABCDEFGHIJKLMNOPQRSTUV";
174 return table
[x
& 31];
177 int unbase32hexchar(char c
) {
180 if (c
>= '0' && c
<= '9')
183 offset
= '9' - '0' + 1;
185 if (c
>= 'A' && c
<= 'V')
186 return c
- 'A' + offset
;
191 char *base32hexmem(const void *p
, size_t l
, bool padding
) {
199 /* five input bytes makes eight output bytes, padding is added so we must round up */
200 len
= 8 * (l
+ 4) / 5;
202 /* same, but round down as there is no padding */
221 z
= r
= malloc(len
+ 1);
225 for (x
= p
; x
< (const uint8_t*) p
+ (l
/ 5) * 5; x
+= 5) {
226 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
227 * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
228 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
229 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
230 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
231 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
232 *(z
++) = base32hexchar((x
[2] & 15) << 1 | x
[3] >> 7); /* 000ZZZZQ */
233 *(z
++) = base32hexchar((x
[3] & 127) >> 2); /* 000QQQQQ */
234 *(z
++) = base32hexchar((x
[3] & 3) << 3 | x
[4] >> 5); /* 000QQWWW */
235 *(z
++) = base32hexchar((x
[4] & 31)); /* 000WWWWW */
240 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
241 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
242 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
243 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
244 *(z
++) = base32hexchar((x
[2] & 15) << 1 | x
[3] >> 7); /* 000ZZZZQ */
245 *(z
++) = base32hexchar((x
[3] & 127) >> 2); /* 000QQQQQ */
246 *(z
++) = base32hexchar((x
[3] & 3) << 3); /* 000QQ000 */
253 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
254 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
255 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
256 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
257 *(z
++) = base32hexchar((x
[2] & 15) << 1); /* 000ZZZZ0 */
267 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
268 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
269 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
270 *(z
++) = base32hexchar((x
[1] & 1) << 4); /* 000Y0000 */
281 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
282 *(z
++) = base32hexchar((x
[0] & 7) << 2); /* 000XXX00 */
299 int unbase32hexmem(const char *p
, size_t l
, bool padding
, void **mem
, size_t *_len
) {
300 _cleanup_free_
uint8_t *r
= NULL
;
301 int a
, b
, c
, d
, e
, f
, g
, h
;
314 /* padding ensures any base32hex input has input divisible by 8 */
315 if (padding
&& l
% 8 != 0)
319 /* strip the padding */
320 while (l
> 0 && p
[l
- 1] == '=' && pad
< 7) {
326 /* a group of eight input bytes needs five output bytes, in case of
327 * padding we need to add some extra bytes */
349 z
= r
= malloc(len
+ 1);
353 for (x
= p
; x
< p
+ (l
/ 8) * 8; x
+= 8) {
354 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
355 * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
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]);
384 h
= unbase32hexchar(x
[7]);
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 */
392 *(z
++) = (uint8_t) g
<< 5 | (uint8_t) h
; /* VVVRRRRR */
397 a
= unbase32hexchar(x
[0]);
401 b
= unbase32hexchar(x
[1]);
405 c
= unbase32hexchar(x
[2]);
409 d
= unbase32hexchar(x
[3]);
413 e
= unbase32hexchar(x
[4]);
417 f
= unbase32hexchar(x
[5]);
421 g
= unbase32hexchar(x
[6]);
429 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
430 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
431 *(z
++) = (uint8_t) d
<< 4 | (uint8_t) e
>> 1; /* WWWWSSSS */
432 *(z
++) = (uint8_t) e
<< 7 | (uint8_t) f
<< 2 | (uint8_t) g
>> 3; /* SQQQQQVV */
436 a
= unbase32hexchar(x
[0]);
440 b
= unbase32hexchar(x
[1]);
444 c
= unbase32hexchar(x
[2]);
448 d
= unbase32hexchar(x
[3]);
452 e
= unbase32hexchar(x
[4]);
460 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
461 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
462 *(z
++) = (uint8_t) d
<< 4 | (uint8_t) e
>> 1; /* WWWWSSSS */
466 a
= unbase32hexchar(x
[0]);
470 b
= unbase32hexchar(x
[1]);
474 c
= unbase32hexchar(x
[2]);
478 d
= unbase32hexchar(x
[3]);
486 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
487 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
491 a
= unbase32hexchar(x
[0]);
495 b
= unbase32hexchar(x
[1]);
503 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
520 /* https://tools.ietf.org/html/rfc4648#section-4 */
521 char base64char(int x
) {
522 static const char table
[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
523 "abcdefghijklmnopqrstuvwxyz"
525 return table
[x
& 63];
528 /* This is almost base64char(), but not entirely, as it uses the "url and filename safe" alphabet,
529 * since we don't want "/" appear in interface names (since interfaces appear in sysfs as filenames).
530 * See section #5 of RFC 4648. */
531 char urlsafe_base64char(int x
) {
532 static const char table
[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
533 "abcdefghijklmnopqrstuvwxyz"
535 return table
[x
& 63];
538 int unbase64char(char c
) {
541 if (c
>= 'A' && c
<= 'Z')
544 offset
= 'Z' - 'A' + 1;
546 if (c
>= 'a' && c
<= 'z')
547 return c
- 'a' + offset
;
549 offset
+= 'z' - 'a' + 1;
551 if (c
>= '0' && c
<= '9')
552 return c
- '0' + offset
;
554 offset
+= '9' - '0' + 1;
567 static void maybe_line_break(char **x
, char *start
, size_t line_break
) {
575 if (line_break
== SIZE_MAX
)
580 if (n
% (line_break
+ 1) == line_break
)
584 ssize_t
base64mem_full(
595 assert(line_break
> 0);
598 /* three input bytes makes four output bytes, padding is added so we must round up */
599 m
= 4 * (l
+ 2) / 3 + 1;
600 if (line_break
!= SIZE_MAX
)
607 for (x
= p
; x
&& x
< (const uint8_t*) p
+ (l
/ 3) * 3; x
+= 3) {
608 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
609 maybe_line_break(&z
, b
, line_break
);
610 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
611 maybe_line_break(&z
, b
, line_break
);
612 *(z
++) = base64char((x
[0] & 3) << 4 | x
[1] >> 4); /* 00XXYYYY */
613 maybe_line_break(&z
, b
, line_break
);
614 *(z
++) = base64char((x
[1] & 15) << 2 | x
[2] >> 6); /* 00YYYYZZ */
615 maybe_line_break(&z
, b
, line_break
);
616 *(z
++) = base64char(x
[2] & 63); /* 00ZZZZZZ */
621 maybe_line_break(&z
, b
, line_break
);
622 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
623 maybe_line_break(&z
, b
, line_break
);
624 *(z
++) = base64char((x
[0] & 3) << 4 | x
[1] >> 4); /* 00XXYYYY */
625 maybe_line_break(&z
, b
, line_break
);
626 *(z
++) = base64char((x
[1] & 15) << 2); /* 00YYYY00 */
627 maybe_line_break(&z
, b
, line_break
);
632 maybe_line_break(&z
, b
, line_break
);
633 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
634 maybe_line_break(&z
, b
, line_break
);
635 *(z
++) = base64char((x
[0] & 3) << 4); /* 00XX0000 */
636 maybe_line_break(&z
, b
, line_break
);
638 maybe_line_break(&z
, b
, line_break
);
646 assert(z
>= b
); /* Let static analyzers know that the answer is non-negative. */
650 static ssize_t
base64_append_width(
659 _cleanup_free_
char *x
= NULL
;
665 assert(*prefix
|| plen
== 0);
668 len
= base64mem(p
, l
, &x
);
674 lines
= DIV_ROUND_UP(len
, width
);
676 if (plen
>= SSIZE_MAX
- 1 - 1 ||
677 lines
> (SSIZE_MAX
- plen
- 1 - 1) / (indent
+ width
+ 1))
680 t
= realloc(*prefix
, plen
+ 1 + 1 + (indent
+ width
+ 1) * lines
);
685 for (size_t line
= 0; line
< lines
; line
++) {
686 size_t act
= MIN(width
, (size_t) len
);
694 s
= mempset(s
, ' ', indent
);
697 s
= mempcpy(s
, x
+ width
* line
, act
);
707 ssize_t
base64_append(
715 if (plen
> width
/ 2 || plen
+ indent
> width
)
716 /* leave indent on the left, keep last column free */
717 return base64_append_width(prefix
, plen
, '\n', indent
, p
, l
, width
- indent
);
719 /* leave plen on the left, keep last column free */
720 return base64_append_width(prefix
, plen
, ' ', plen
+ 1, p
, l
, width
- plen
- 1);
723 static int unbase64_next(const char **p
, size_t *l
) {
729 /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
730 * greedily skip all preceding and all following whitespace. */
736 if (!strchr(WHITESPACE
, **p
))
739 /* Skip leading whitespace */
744 ret
= INT_MAX
; /* return padding as INT_MAX */
746 ret
= unbase64char(**p
);
756 if (!strchr(WHITESPACE
, **p
))
759 /* Skip following whitespace */
765 int unbase64mem_full(
772 _cleanup_free_
uint8_t *buf
= NULL
;
782 /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
783 * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
784 len
= (l
/ 4) * 3 + (l
% 4 != 0 ? (l
% 4) - 1 : 0);
786 buf
= malloc(len
+ 1);
790 CLEANUP_ERASE_PTR(secure
? &buf
: NULL
, len
);
792 for (x
= p
, z
= buf
;;) {
793 int a
, b
, c
, d
; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
795 a
= unbase64_next(&x
, &l
);
796 if (a
== -EPIPE
) /* End of string */
800 if (a
== INT_MAX
) /* Padding is not allowed at the beginning of a 4ch block */
803 b
= unbase64_next(&x
, &l
);
806 if (b
== INT_MAX
) /* Padding is not allowed at the second character of a 4ch block either */
809 c
= unbase64_next(&x
, &l
);
813 d
= unbase64_next(&x
, &l
);
817 if (c
== INT_MAX
) { /* Padding at the third character */
819 if (d
!= INT_MAX
) /* If the third character is padding, the fourth must be too */
826 if (l
> 0) /* Trailing rubbish? */
827 return -ENAMETOOLONG
;
829 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) (b
>> 4); /* XXXXXXYY */
838 if (l
> 0) /* Trailing rubbish? */
839 return -ENAMETOOLONG
;
841 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
842 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
846 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
847 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
848 *(z
++) = (uint8_t) c
<< 6 | (uint8_t) d
; /* ZZWWWWWW */
853 assert((size_t) (z
- buf
) <= len
);
856 *ret_size
= (size_t) (z
- buf
);
858 *ret
= TAKE_PTR(buf
);
863 void hexdump(FILE *f
, const void *p
, size_t s
) {
864 const uint8_t *b
= p
;
875 fprintf(f
, "%04x ", n
);
877 for (i
= 0; i
< 16; i
++) {
882 fprintf(f
, "%02x ", b
[i
]);
890 for (i
= 0; i
< 16; i
++) {
895 fputc(isprint(b
[i
]) ? (char) b
[i
] : '.', f
);