]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hexdecoct.c
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 char *base64mem(const void *p
, size_t l
) {
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 */
555 int unbase64mem(const char *p
, size_t l
, void **mem
, size_t *_len
) {
556 _cleanup_free_
uint8_t *r
= NULL
;
564 /* padding ensures any base63 input has input divisible by 4 */
568 /* strip the padding */
569 if (l
> 0 && p
[l
- 1] == '=')
571 if (l
> 0 && p
[l
- 1] == '=')
574 /* a group of four input bytes needs three output bytes, in case of
575 padding we need to add two or three extra bytes */
576 len
= (l
/ 4) * 3 + (l
% 4 ? (l
% 4) - 1 : 0);
578 z
= r
= malloc(len
+ 1);
582 for (x
= p
; x
< p
+ (l
/ 4) * 4; x
+= 4) {
583 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
584 a
= unbase64char(x
[0]);
588 b
= unbase64char(x
[1]);
592 c
= unbase64char(x
[2]);
596 d
= unbase64char(x
[3]);
600 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
601 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
602 *(z
++) = (uint8_t) c
<< 6 | (uint8_t) d
; /* ZZWWWWWW */
607 a
= unbase64char(x
[0]);
611 b
= unbase64char(x
[1]);
615 c
= unbase64char(x
[2]);
623 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
624 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
628 a
= unbase64char(x
[0]);
632 b
= unbase64char(x
[1]);
640 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) (b
>> 4); /* XXXXXXYY */
659 void hexdump(FILE *f
, const void *p
, size_t s
) {
660 const uint8_t *b
= p
;
668 fprintf(f
, "%04x ", n
);
670 for (i
= 0; i
< 16; i
++) {
675 fprintf(f
, "%02x ", b
[i
]);
683 for (i
= 0; i
< 16; i
++) {
688 fputc(isprint(b
[i
]) ? (char) b
[i
] : '.', f
);