]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hexdecoct.c
f958582e68a96ccf4b2e343d1161ba0c1691ccc8
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 "hexdecoct.h"
32 int unoctchar(char c
) {
34 if (c
>= '0' && c
<= '7')
41 return '0' + (x
% 10);
44 int undecchar(char c
) {
46 if (c
>= '0' && c
<= '9')
53 static const char table
[16] = "0123456789abcdef";
58 int unhexchar(char c
) {
60 if (c
>= '0' && c
<= '9')
63 if (c
>= 'a' && c
<= 'f')
66 if (c
>= 'A' && c
<= 'F')
72 char *hexmem(const void *p
, size_t l
) {
76 z
= r
= malloc(l
* 2 + 1);
80 for (x
= p
; x
< (const uint8_t*) p
+ l
; x
++) {
81 *(z
++) = hexchar(*x
>> 4);
82 *(z
++) = hexchar(*x
& 15);
89 int unhexmem(const char *p
, size_t l
, void **mem
, size_t *len
) {
90 _cleanup_free_
uint8_t *r
= NULL
;
98 z
= r
= malloc((l
+ 1) / 2 + 1);
102 for (x
= p
; x
< p
+ l
; x
+= 2) {
108 else if (x
+1 < p
+ l
) {
115 *(z
++) = (uint8_t) a
<< 4 | (uint8_t) b
;
127 /* https://tools.ietf.org/html/rfc4648#section-6
128 * Notice that base32hex differs from base32 in the alphabet it uses.
129 * The distinction is that the base32hex representation preserves the
130 * order of the underlying data when compared as bytestrings, this is
131 * useful when representing NSEC3 hashes, as one can then verify the
132 * order of hashes directly from their representation. */
133 char base32hexchar(int x
) {
134 static const char table
[32] = "0123456789"
135 "ABCDEFGHIJKLMNOPQRSTUV";
137 return table
[x
& 31];
140 int unbase32hexchar(char c
) {
143 if (c
>= '0' && c
<= '9')
146 offset
= '9' - '0' + 1;
148 if (c
>= 'A' && c
<= 'V')
149 return c
- 'A' + offset
;
154 char *base32hexmem(const void *p
, size_t l
, bool padding
) {
160 /* five input bytes makes eight output bytes, padding is added so we must round up */
161 len
= 8 * (l
+ 4) / 5;
163 /* same, but round down as there is no padding */
182 z
= r
= malloc(len
+ 1);
186 for (x
= p
; x
< (const uint8_t*) p
+ (l
/ 5) * 5; x
+= 5) {
187 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
188 x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
189 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
190 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
191 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
192 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
193 *(z
++) = base32hexchar((x
[2] & 15) << 1 | x
[3] >> 7); /* 000ZZZZQ */
194 *(z
++) = base32hexchar((x
[3] & 127) >> 2); /* 000QQQQQ */
195 *(z
++) = base32hexchar((x
[3] & 3) << 3 | x
[4] >> 5); /* 000QQWWW */
196 *(z
++) = base32hexchar((x
[4] & 31)); /* 000WWWWW */
201 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
202 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
203 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
204 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
205 *(z
++) = base32hexchar((x
[2] & 15) << 1 | x
[3] >> 7); /* 000ZZZZQ */
206 *(z
++) = base32hexchar((x
[3] & 127) >> 2); /* 000QQQQQ */
207 *(z
++) = base32hexchar((x
[3] & 3) << 3); /* 000QQ000 */
214 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
215 *(z
++) = base32hexchar((x
[0] & 7) << 2 | x
[1] >> 6); /* 000XXXYY */
216 *(z
++) = base32hexchar((x
[1] & 63) >> 1); /* 000YYYYY */
217 *(z
++) = base32hexchar((x
[1] & 1) << 4 | x
[2] >> 4); /* 000YZZZZ */
218 *(z
++) = base32hexchar((x
[2] & 15) << 1); /* 000ZZZZ0 */
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); /* 000Y0000 */
242 *(z
++) = base32hexchar(x
[0] >> 3); /* 000XXXXX */
243 *(z
++) = base32hexchar((x
[0] & 7) << 2); /* 000XXX00 */
260 int unbase32hexmem(const char *p
, size_t l
, bool padding
, void **mem
, size_t *_len
) {
261 _cleanup_free_
uint8_t *r
= NULL
;
262 int a
, b
, c
, d
, e
, f
, g
, h
;
270 /* padding ensures any base32hex input has input divisible by 8 */
271 if (padding
&& l
% 8 != 0)
275 /* strip the padding */
276 while (l
> 0 && p
[l
- 1] == '=' && pad
< 7) {
282 /* a group of eight input bytes needs five output bytes, in case of
283 padding we need to add some extra bytes */
305 z
= r
= malloc(len
+ 1);
309 for (x
= p
; x
< p
+ (l
/ 8) * 8; x
+= 8) {
310 /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
311 e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
312 a
= unbase32hexchar(x
[0]);
316 b
= unbase32hexchar(x
[1]);
320 c
= unbase32hexchar(x
[2]);
324 d
= unbase32hexchar(x
[3]);
328 e
= unbase32hexchar(x
[4]);
332 f
= unbase32hexchar(x
[5]);
336 g
= unbase32hexchar(x
[6]);
340 h
= unbase32hexchar(x
[7]);
344 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
345 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
346 *(z
++) = (uint8_t) d
<< 4 | (uint8_t) e
>> 1; /* WWWWSSSS */
347 *(z
++) = (uint8_t) e
<< 7 | (uint8_t) f
<< 2 | (uint8_t) g
>> 3; /* SQQQQQVV */
348 *(z
++) = (uint8_t) g
<< 5 | (uint8_t) h
; /* VVVRRRRR */
353 a
= unbase32hexchar(x
[0]);
357 b
= unbase32hexchar(x
[1]);
361 c
= unbase32hexchar(x
[2]);
365 d
= unbase32hexchar(x
[3]);
369 e
= unbase32hexchar(x
[4]);
373 f
= unbase32hexchar(x
[5]);
377 g
= unbase32hexchar(x
[6]);
385 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
386 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
387 *(z
++) = (uint8_t) d
<< 4 | (uint8_t) e
>> 1; /* WWWWSSSS */
388 *(z
++) = (uint8_t) e
<< 7 | (uint8_t) f
<< 2 | (uint8_t) g
>> 3; /* SQQQQQVV */
392 a
= unbase32hexchar(x
[0]);
396 b
= unbase32hexchar(x
[1]);
400 c
= unbase32hexchar(x
[2]);
404 d
= unbase32hexchar(x
[3]);
408 e
= unbase32hexchar(x
[4]);
416 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
417 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
418 *(z
++) = (uint8_t) d
<< 4 | (uint8_t) e
>> 1; /* WWWWSSSS */
422 a
= unbase32hexchar(x
[0]);
426 b
= unbase32hexchar(x
[1]);
430 c
= unbase32hexchar(x
[2]);
434 d
= unbase32hexchar(x
[3]);
442 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
443 *(z
++) = (uint8_t) b
<< 6 | (uint8_t) c
<< 1 | (uint8_t) d
>> 4; /* YYZZZZZW */
447 a
= unbase32hexchar(x
[0]);
451 b
= unbase32hexchar(x
[1]);
459 *(z
++) = (uint8_t) a
<< 3 | (uint8_t) b
>> 2; /* XXXXXYYY */
477 /* https://tools.ietf.org/html/rfc4648#section-4 */
478 char base64char(int x
) {
479 static const char table
[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
480 "abcdefghijklmnopqrstuvwxyz"
482 return table
[x
& 63];
485 int unbase64char(char c
) {
488 if (c
>= 'A' && c
<= 'Z')
491 offset
= 'Z' - 'A' + 1;
493 if (c
>= 'a' && c
<= 'z')
494 return c
- 'a' + offset
;
496 offset
+= 'z' - 'a' + 1;
498 if (c
>= '0' && c
<= '9')
499 return c
- '0' + offset
;
501 offset
+= '9' - '0' + 1;
514 char *base64mem(const void *p
, size_t l
) {
518 /* three input bytes makes four output bytes, padding is added so we must round up */
519 z
= r
= malloc(4 * (l
+ 2) / 3 + 1);
523 for (x
= p
; x
< (const uint8_t*) p
+ (l
/ 3) * 3; x
+= 3) {
524 /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
525 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
526 *(z
++) = base64char((x
[0] & 3) << 4 | x
[1] >> 4); /* 00XXYYYY */
527 *(z
++) = base64char((x
[1] & 15) << 2 | x
[2] >> 6); /* 00YYYYZZ */
528 *(z
++) = base64char(x
[2] & 63); /* 00ZZZZZZ */
533 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
534 *(z
++) = base64char((x
[0] & 3) << 4 | x
[1] >> 4); /* 00XXYYYY */
535 *(z
++) = base64char((x
[1] & 15) << 2); /* 00YYYY00 */
540 *(z
++) = base64char(x
[0] >> 2); /* 00XXXXXX */
541 *(z
++) = base64char((x
[0] & 3) << 4); /* 00XX0000 */
552 int unbase64mem(const char *p
, size_t l
, void **mem
, size_t *_len
) {
553 _cleanup_free_
uint8_t *r
= NULL
;
561 /* padding ensures any base63 input has input divisible by 4 */
565 /* strip the padding */
566 if (l
> 0 && p
[l
- 1] == '=')
568 if (l
> 0 && p
[l
- 1] == '=')
571 /* a group of four input bytes needs three output bytes, in case of
572 padding we need to add two or three extra bytes */
573 len
= (l
/ 4) * 3 + (l
% 4 ? (l
% 4) - 1 : 0);
575 z
= r
= malloc(len
+ 1);
579 for (x
= p
; x
< p
+ (l
/ 4) * 4; x
+= 4) {
580 /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
581 a
= unbase64char(x
[0]);
585 b
= unbase64char(x
[1]);
589 c
= unbase64char(x
[2]);
593 d
= unbase64char(x
[3]);
597 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
598 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
599 *(z
++) = (uint8_t) c
<< 6 | (uint8_t) d
; /* ZZWWWWWW */
604 a
= unbase64char(x
[0]);
608 b
= unbase64char(x
[1]);
612 c
= unbase64char(x
[2]);
620 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) b
>> 4; /* XXXXXXYY */
621 *(z
++) = (uint8_t) b
<< 4 | (uint8_t) c
>> 2; /* YYYYZZZZ */
625 a
= unbase64char(x
[0]);
629 b
= unbase64char(x
[1]);
637 *(z
++) = (uint8_t) a
<< 2 | (uint8_t) (b
>> 4); /* XXXXXXYY */
656 void hexdump(FILE *f
, const void *p
, size_t s
) {
657 const uint8_t *b
= p
;
665 fprintf(f
, "%04x ", n
);
667 for (i
= 0; i
< 16; i
++) {
672 fprintf(f
, "%02x ", b
[i
]);
680 for (i
= 0; i
< 16; i
++) {
685 fputc(isprint(b
[i
]) ? (char) b
[i
] : '.', f
);