2 * Copyright (C) 2008-2013 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include <sys/types.h>
33 chunk_t chunk_empty
= { NULL
, 0 };
36 * Described in header.
38 chunk_t
chunk_create_clone(u_char
*ptr
, chunk_t chunk
)
40 chunk_t clone
= chunk_empty
;
42 if (chunk
.ptr
&& chunk
.len
> 0)
45 clone
.len
= chunk
.len
;
46 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
53 * Described in header.
55 size_t chunk_length(const char* mode
, ...)
60 va_start(chunks
, mode
);
69 chunk_t ch
= va_arg(chunks
, chunk_t
);
83 * Described in header.
85 chunk_t
chunk_create_cat(u_char
*ptr
, const char* mode
, ...)
88 chunk_t construct
= chunk_create(ptr
, 0);
90 va_start(chunks
, mode
);
93 bool free_chunk
= FALSE
, clear_chunk
= FALSE
;
105 ch
= va_arg(chunks
, chunk_t
);
106 memcpy(ptr
, ch
.ptr
, ch
.len
);
108 construct
.len
+= ch
.len
;
129 * Described in header.
131 void chunk_split(chunk_t chunk
, const char *mode
, ...)
137 va_start(chunks
, mode
);
144 len
= va_arg(chunks
, u_int
);
145 ch
= va_arg(chunks
, chunk_t
*);
146 /* a null chunk means skip len bytes */
149 chunk
= chunk_skip(chunk
, len
);
156 ch
->len
= min(chunk
.len
, len
);
165 chunk
= chunk_skip(chunk
, ch
->len
);
170 ch
->len
= min(chunk
.len
, len
);
173 ch
->ptr
= malloc(ch
->len
);
174 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
180 chunk
= chunk_skip(chunk
, ch
->len
);
185 ch
->len
= min(ch
->len
, chunk
.len
);
186 ch
->len
= min(ch
->len
, len
);
189 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
195 chunk
= chunk_skip(chunk
, ch
->len
);
207 * Described in header.
209 bool chunk_write(chunk_t chunk
, char *path
, char *label
, mode_t mask
, bool force
)
215 if (!force
&& access(path
, F_OK
) == 0)
217 DBG1(DBG_LIB
, " %s file '%s' already exists", label
, path
);
220 oldmask
= umask(mask
);
221 fd
= fopen(path
, "w");
224 if (fwrite(chunk
.ptr
, sizeof(u_char
), chunk
.len
, fd
) == chunk
.len
)
226 DBG1(DBG_LIB
, " written %s file '%s' (%d bytes)",
227 label
, path
, chunk
.len
);
232 DBG1(DBG_LIB
, " writing %s file '%s' failed: %s",
233 label
, path
, strerror(errno
));
239 DBG1(DBG_LIB
, " could not open %s file '%s': %s", label
, path
,
247 /** hex conversion digits */
248 static char hexdig_upper
[] = "0123456789ABCDEF";
249 static char hexdig_lower
[] = "0123456789abcdef";
252 * Described in header.
254 chunk_t
chunk_to_hex(chunk_t chunk
, char *buf
, bool uppercase
)
257 char *hexdig
= hexdig_lower
;
261 hexdig
= hexdig_upper
;
267 buf
= malloc(len
+ 1);
271 for (i
= 0; i
< chunk
.len
; i
++)
273 buf
[i
*2] = hexdig
[(chunk
.ptr
[i
] >> 4) & 0xF];
274 buf
[i
*2+1] = hexdig
[(chunk
.ptr
[i
] ) & 0xF];
276 return chunk_create(buf
, len
);
280 * convert a signle hex character to its binary value
282 static char hex2bin(char hex
)
289 return hex
- 'A' + 10;
291 return hex
- 'a' + 10;
298 * Described in header.
300 chunk_t
chunk_from_hex(chunk_t hex
, char *buf
)
306 /* subtract the number of optional ':' separation characters */
309 for (i
= 0; i
< hex
.len
; i
++)
317 /* compute the number of binary bytes */
325 /* allocate buffer memory unless provided by caller */
331 /* buffer is filled from the right */
335 for (i
= len
- 1; i
>= 0; i
--)
337 /* skip separation characters */
338 if (*(--hex
.ptr
) == ':')
342 buf
[i
] = hex2bin(*hex
.ptr
);
345 buf
[i
] |= hex2bin(*(--hex
.ptr
)) << 4;
348 return chunk_create(buf
, len
);
351 /** base 64 conversion digits */
352 static char b64digits
[] =
353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
356 * Described in header.
358 chunk_t
chunk_to_base64(chunk_t chunk
, char *buf
)
363 len
= chunk
.len
+ ((3 - chunk
.len
% 3) % 3);
366 buf
= malloc(len
* 4 / 3 + 1);
369 for (i
= 0; i
< len
; i
+=3)
371 *pos
++ = b64digits
[chunk
.ptr
[i
] >> 2];
372 if (i
+1 >= chunk
.len
)
374 *pos
++ = b64digits
[(chunk
.ptr
[i
] & 0x03) << 4];
379 *pos
++ = b64digits
[((chunk
.ptr
[i
] & 0x03) << 4) | (chunk
.ptr
[i
+1] >> 4)];
380 if (i
+2 >= chunk
.len
)
382 *pos
++ = b64digits
[(chunk
.ptr
[i
+1] & 0x0F) << 2];
386 *pos
++ = b64digits
[((chunk
.ptr
[i
+1] & 0x0F) << 2) | (chunk
.ptr
[i
+2] >> 6)];
387 *pos
++ = b64digits
[chunk
.ptr
[i
+2] & 0x3F];
390 return chunk_create(buf
, len
* 4 / 3);
394 * convert a base 64 digit to its binary form (inversion of b64digits array)
396 static int b642bin(char b64
)
403 return ('Z' - 'A' + 1) + b64
- 'a';
405 return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64
- '0';
420 * Described in header.
422 chunk_t
chunk_from_base64(chunk_t base64
, char *buf
)
424 u_char
*pos
, byte
[4];
425 int i
, j
, len
, outlen
;
427 len
= base64
.len
/ 4 * 3;
434 for (i
= 0; i
< len
; i
+=3)
437 for (j
= 0; j
< 4; j
++)
443 byte
[j
] = b642bin(*pos
++);
445 buf
[i
] = (byte
[0] << 2) | (byte
[1] >> 4);
446 buf
[i
+1] = (byte
[1] << 4) | (byte
[2] >> 2);
447 buf
[i
+2] = (byte
[2] << 6) | (byte
[3]);
449 return chunk_create(buf
, outlen
);
452 /** base 32 conversion digits */
453 static char b32digits
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
456 * Described in header.
458 chunk_t
chunk_to_base32(chunk_t chunk
, char *buf
)
463 len
= chunk
.len
+ ((5 - chunk
.len
% 5) % 5);
466 buf
= malloc(len
* 8 / 5 + 1);
469 for (i
= 0; i
< len
; i
+=5)
471 *pos
++ = b32digits
[chunk
.ptr
[i
] >> 3];
472 if (i
+1 >= chunk
.len
)
474 *pos
++ = b32digits
[(chunk
.ptr
[i
] & 0x07) << 2];
479 *pos
++ = b32digits
[((chunk
.ptr
[i
] & 0x07) << 2) |
480 (chunk
.ptr
[i
+1] >> 6)];
481 *pos
++ = b32digits
[(chunk
.ptr
[i
+1] & 0x3E) >> 1];
482 if (i
+2 >= chunk
.len
)
484 *pos
++ = b32digits
[(chunk
.ptr
[i
+1] & 0x01) << 4];
489 *pos
++ = b32digits
[((chunk
.ptr
[i
+1] & 0x01) << 4) |
490 (chunk
.ptr
[i
+2] >> 4)];
491 if (i
+3 >= chunk
.len
)
493 *pos
++ = b32digits
[(chunk
.ptr
[i
+2] & 0x0F) << 1];
498 *pos
++ = b32digits
[((chunk
.ptr
[i
+2] & 0x0F) << 1) |
499 (chunk
.ptr
[i
+3] >> 7)];
500 *pos
++ = b32digits
[(chunk
.ptr
[i
+3] & 0x7F) >> 2];
501 if (i
+4 >= chunk
.len
)
503 *pos
++ = b32digits
[(chunk
.ptr
[i
+3] & 0x03) << 3];
507 *pos
++ = b32digits
[((chunk
.ptr
[i
+3] & 0x03) << 3) |
508 (chunk
.ptr
[i
+4] >> 5)];
509 *pos
++ = b32digits
[chunk
.ptr
[i
+4] & 0x1F];
512 return chunk_create(buf
, len
* 8 / 5);
516 * Described in header.
518 int chunk_compare(chunk_t a
, chunk_t b
)
520 int compare_len
= a
.len
- b
.len
;
521 int len
= (compare_len
< 0)? a
.len
: b
.len
;
523 if (compare_len
!= 0 || len
== 0)
527 return memcmp(a
.ptr
, b
.ptr
, len
);
532 * Described in header.
534 bool chunk_increment(chunk_t chunk
)
538 for (i
= chunk
.len
- 1; i
>= 0; i
--)
540 if (++chunk
.ptr
[i
] != 0)
549 * Remove non-printable characters from a chunk.
551 bool chunk_printable(chunk_t chunk
, chunk_t
*sane
, char replace
)
553 bool printable
= TRUE
;
558 *sane
= chunk_clone(chunk
);
560 for (i
= 0; i
< chunk
.len
; i
++)
562 if (!isprint(chunk
.ptr
[i
]))
566 sane
->ptr
[i
] = replace
;
575 * Helper functions for chunk_mac()
577 static inline u_int64_t
sipget(u_char
*in
)
582 for (i
= 0; i
< 64; i
+= 8, ++in
)
584 v
|= ((u_int64_t
)*in
) << i
;
589 static inline u_int64_t
siprotate(u_int64_t v
, int shift
)
591 return (v
<< shift
) | (v
>> (64 - shift
));
594 static inline void sipround(u_int64_t
*v0
, u_int64_t
*v1
, u_int64_t
*v2
,
598 *v1
= siprotate(*v1
, 13);
600 *v0
= siprotate(*v0
, 32);
603 *v3
= siprotate(*v3
, 16);
607 *v1
= siprotate(*v1
, 17);
609 *v2
= siprotate(*v2
, 32);
612 *v3
= siprotate(*v3
, 21);
616 static inline void sipcompress(u_int64_t
*v0
, u_int64_t
*v1
, u_int64_t
*v2
,
617 u_int64_t
*v3
, u_int64_t m
)
620 sipround(v0
, v1
, v2
, v3
);
621 sipround(v0
, v1
, v2
, v3
);
625 static inline u_int64_t
siplast(size_t len
, u_char
*pos
)
630 b
= ((u_int64_t
)len
) << 56;
634 b
|= ((u_int64_t
)pos
[6]) << 48;
636 b
|= ((u_int64_t
)pos
[5]) << 40;
638 b
|= ((u_int64_t
)pos
[4]) << 32;
640 b
|= ((u_int64_t
)pos
[3]) << 24;
642 b
|= ((u_int64_t
)pos
[2]) << 16;
644 b
|= ((u_int64_t
)pos
[1]) << 8;
646 b
|= ((u_int64_t
)pos
[0]);
655 * Caculate SipHash-2-4 with an optional first block given as argument.
657 static u_int64_t
chunk_mac_inc(chunk_t chunk
, u_char
*key
, u_int64_t m
)
659 u_int64_t v0
, v1
, v2
, v3
, k0
, k1
;
660 size_t len
= chunk
.len
;
661 u_char
*pos
= chunk
.ptr
, *end
;
663 end
= chunk
.ptr
+ len
- (len
% 8);
666 k1
= sipget(key
+ 8);
668 v0
= k0
^ 0x736f6d6570736575ULL
;
669 v1
= k1
^ 0x646f72616e646f6dULL
;
670 v2
= k0
^ 0x6c7967656e657261ULL
;
671 v3
= k1
^ 0x7465646279746573ULL
;
675 sipcompress(&v0
, &v1
, &v2
, &v3
, m
);
678 /* compression with c = 2 */
679 for (; pos
!= end
; pos
+= 8)
682 sipcompress(&v0
, &v1
, &v2
, &v3
, m
);
684 sipcompress(&v0
, &v1
, &v2
, &v3
, siplast(len
, pos
));
686 /* finalization with d = 4 */
688 sipround(&v0
, &v1
, &v2
, &v3
);
689 sipround(&v0
, &v1
, &v2
, &v3
);
690 sipround(&v0
, &v1
, &v2
, &v3
);
691 sipround(&v0
, &v1
, &v2
, &v3
);
692 return v0
^ v1
^ v2
^ v3
;
696 * Described in header.
698 u_int64_t
chunk_mac(chunk_t chunk
, u_char
*key
)
700 return chunk_mac_inc(chunk
, key
, 0);
704 * Secret key allocated randomly during first use.
706 static u_char key
[16];
709 * Only allocate the key once
711 static pthread_once_t key_allocated
= PTHREAD_ONCE_INIT
;
714 * Allocate a key on first use, we do this manually to avoid dependencies on
717 static void allocate_key()
723 fd
= open("/dev/urandom", O_RDONLY
);
726 while (done
< sizeof(key
))
728 len
= read(fd
, key
+ done
, sizeof(key
) - done
);
737 /* on error we use random() to generate the key (better than nothing) */
738 if (done
< sizeof(key
))
740 srandom(time(NULL
) + getpid());
741 for (; done
< sizeof(key
); done
++)
743 key
[done
] = (u_char
)random();
749 * Described in header.
751 u_int32_t
chunk_hash_inc(chunk_t chunk
, u_int32_t hash
)
753 pthread_once(&key_allocated
, allocate_key
);
754 /* we could use a mac of the previous hash, but this is faster */
755 return chunk_mac_inc(chunk
, key
, ((u_int64_t
)hash
) << 32 | hash
);
759 * Described in header.
761 u_int32_t
chunk_hash(chunk_t chunk
)
763 pthread_once(&key_allocated
, allocate_key
);
764 return chunk_mac(chunk
, key
);
768 * Described in header.
770 int chunk_printf_hook(printf_hook_data_t
*data
, printf_hook_spec_t
*spec
,
771 const void *const *args
)
773 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
775 chunk_t copy
= *chunk
;
780 u_int chunk_len
= chunk
->len
;
781 const void *new_args
[] = {&chunk
->ptr
, &chunk_len
};
782 return mem_printf_hook(data
, spec
, new_args
);
793 written
+= print_in_hook(data
, ":");
795 written
+= print_in_hook(data
, "%02x", *copy
.ptr
++);