]>
git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/utils/chunk.c
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
27 /* required for chunk_hash */
29 #if (defined(__GNUC__) && defined(__i386__))
30 #define get16bits(d) (*((const u_int16_t*)(d)))
32 #if !defined (get16bits)
33 #define get16bits(d) ((((u_int32_t)(((const u_int8_t*)(d))[1])) << 8)\
34 + (u_int32_t)(((const u_int8_t*)(d))[0]) )
40 chunk_t chunk_empty
= { NULL
, 0 };
43 * Described in header.
45 chunk_t
chunk_create_clone(u_char
*ptr
, chunk_t chunk
)
47 chunk_t clone
= chunk_empty
;
49 if (chunk
.ptr
&& chunk
.len
> 0)
52 clone
.len
= chunk
.len
;
53 memcpy(clone
.ptr
, chunk
.ptr
, chunk
.len
);
60 * Described in header.
62 size_t chunk_length(const char* mode
, ...)
67 va_start(chunks
, mode
);
76 chunk_t ch
= va_arg(chunks
, chunk_t
);
90 * Described in header.
92 chunk_t
chunk_create_cat(u_char
*ptr
, const char* mode
, ...)
95 chunk_t construct
= chunk_create(ptr
, 0);
97 va_start(chunks
, mode
);
100 bool free_chunk
= FALSE
, clear_chunk
= FALSE
;
112 ch
= va_arg(chunks
, chunk_t
);
113 memcpy(ptr
, ch
.ptr
, ch
.len
);
115 construct
.len
+= ch
.len
;
136 * Described in header.
138 void chunk_split(chunk_t chunk
, const char *mode
, ...)
144 va_start(chunks
, mode
);
151 len
= va_arg(chunks
, u_int
);
152 ch
= va_arg(chunks
, chunk_t
*);
153 /* a null chunk means skip len bytes */
156 chunk
= chunk_skip(chunk
, len
);
163 ch
->len
= min(chunk
.len
, len
);
172 chunk
= chunk_skip(chunk
, ch
->len
);
177 ch
->len
= min(chunk
.len
, len
);
180 ch
->ptr
= malloc(ch
->len
);
181 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
187 chunk
= chunk_skip(chunk
, ch
->len
);
192 ch
->len
= min(ch
->len
, chunk
.len
);
193 ch
->len
= min(ch
->len
, len
);
196 memcpy(ch
->ptr
, chunk
.ptr
, ch
->len
);
202 chunk
= chunk_skip(chunk
, ch
->len
);
214 * Described in header.
216 bool chunk_write(chunk_t chunk
, char *path
, char *label
, mode_t mask
, bool force
)
222 if (!force
&& access(path
, F_OK
) == 0)
224 DBG1(DBG_LIB
, " %s file '%s' already exists", label
, path
);
227 oldmask
= umask(mask
);
228 fd
= fopen(path
, "w");
231 if (fwrite(chunk
.ptr
, sizeof(u_char
), chunk
.len
, fd
) == chunk
.len
)
233 DBG1(DBG_LIB
, " written %s file '%s' (%d bytes)",
234 label
, path
, chunk
.len
);
239 DBG1(DBG_LIB
, " writing %s file '%s' failed: %s",
240 label
, path
, strerror(errno
));
246 DBG1(DBG_LIB
, " could not open %s file '%s': %s", label
, path
,
254 /** hex conversion digits */
255 static char hexdig_upper
[] = "0123456789ABCDEF";
256 static char hexdig_lower
[] = "0123456789abcdef";
259 * Described in header.
261 chunk_t
chunk_to_hex(chunk_t chunk
, char *buf
, bool uppercase
)
264 char *hexdig
= hexdig_lower
;
268 hexdig
= hexdig_upper
;
274 buf
= malloc(len
+ 1);
278 for (i
= 0; i
< chunk
.len
; i
++)
280 buf
[i
*2] = hexdig
[(chunk
.ptr
[i
] >> 4) & 0xF];
281 buf
[i
*2+1] = hexdig
[(chunk
.ptr
[i
] ) & 0xF];
283 return chunk_create(buf
, len
);
287 * convert a signle hex character to its binary value
289 static char hex2bin(char hex
)
296 return hex
- 'A' + 10;
298 return hex
- 'a' + 10;
305 * Described in header.
307 chunk_t
chunk_from_hex(chunk_t hex
, char *buf
)
313 /* subtract the number of optional ':' separation characters */
316 for (i
= 0; i
< hex
.len
; i
++)
324 /* compute the number of binary bytes */
332 /* allocate buffer memory unless provided by caller */
338 /* buffer is filled from the right */
342 for (i
= len
- 1; i
>= 0; i
--)
344 /* skip separation characters */
345 if (*(--hex
.ptr
) == ':')
349 buf
[i
] = hex2bin(*hex
.ptr
);
352 buf
[i
] |= hex2bin(*(--hex
.ptr
)) << 4;
355 return chunk_create(buf
, len
);
358 /** base 64 conversion digits */
359 static char b64digits
[] =
360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
363 * Described in header.
365 chunk_t
chunk_to_base64(chunk_t chunk
, char *buf
)
370 len
= chunk
.len
+ ((3 - chunk
.len
% 3) % 3);
373 buf
= malloc(len
* 4 / 3 + 1);
376 for (i
= 0; i
< len
; i
+=3)
378 *pos
++ = b64digits
[chunk
.ptr
[i
] >> 2];
379 if (i
+1 >= chunk
.len
)
381 *pos
++ = b64digits
[(chunk
.ptr
[i
] & 0x03) << 4];
386 *pos
++ = b64digits
[((chunk
.ptr
[i
] & 0x03) << 4) | (chunk
.ptr
[i
+1] >> 4)];
387 if (i
+2 >= chunk
.len
)
389 *pos
++ = b64digits
[(chunk
.ptr
[i
+1] & 0x0F) << 2];
393 *pos
++ = b64digits
[((chunk
.ptr
[i
+1] & 0x0F) << 2) | (chunk
.ptr
[i
+2] >> 6)];
394 *pos
++ = b64digits
[chunk
.ptr
[i
+2] & 0x3F];
397 return chunk_create(buf
, len
* 4 / 3);
401 * convert a base 64 digit to its binary form (inversion of b64digits array)
403 static int b642bin(char b64
)
410 return ('Z' - 'A' + 1) + b64
- 'a';
412 return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64
- '0';
427 * Described in header.
429 chunk_t
chunk_from_base64(chunk_t base64
, char *buf
)
431 u_char
*pos
, byte
[4];
432 int i
, j
, len
, outlen
;
434 len
= base64
.len
/ 4 * 3;
441 for (i
= 0; i
< len
; i
+=3)
444 for (j
= 0; j
< 4; j
++)
450 byte
[j
] = b642bin(*pos
++);
452 buf
[i
] = (byte
[0] << 2) | (byte
[1] >> 4);
453 buf
[i
+1] = (byte
[1] << 4) | (byte
[2] >> 2);
454 buf
[i
+2] = (byte
[2] << 6) | (byte
[3]);
456 return chunk_create(buf
, outlen
);
459 /** base 32 conversion digits */
460 static char b32digits
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
463 * Described in header.
465 chunk_t
chunk_to_base32(chunk_t chunk
, char *buf
)
470 len
= chunk
.len
+ ((5 - chunk
.len
% 5) % 5);
473 buf
= malloc(len
* 8 / 5 + 1);
476 for (i
= 0; i
< len
; i
+=5)
478 *pos
++ = b32digits
[chunk
.ptr
[i
] >> 3];
479 if (i
+1 >= chunk
.len
)
481 *pos
++ = b32digits
[(chunk
.ptr
[i
] & 0x07) << 2];
486 *pos
++ = b32digits
[((chunk
.ptr
[i
] & 0x07) << 2) |
487 (chunk
.ptr
[i
+1] >> 6)];
488 *pos
++ = b32digits
[(chunk
.ptr
[i
+1] & 0x3E) >> 1];
489 if (i
+2 >= chunk
.len
)
491 *pos
++ = b32digits
[(chunk
.ptr
[i
+1] & 0x01) << 4];
496 *pos
++ = b32digits
[((chunk
.ptr
[i
+1] & 0x01) << 4) |
497 (chunk
.ptr
[i
+2] >> 4)];
498 if (i
+3 >= chunk
.len
)
500 *pos
++ = b32digits
[(chunk
.ptr
[i
+2] & 0x0F) << 1];
505 *pos
++ = b32digits
[((chunk
.ptr
[i
+2] & 0x0F) << 1) |
506 (chunk
.ptr
[i
+3] >> 7)];
507 *pos
++ = b32digits
[(chunk
.ptr
[i
+3] & 0x7F) >> 2];
508 if (i
+4 >= chunk
.len
)
510 *pos
++ = b32digits
[(chunk
.ptr
[i
+3] & 0x03) << 3];
514 *pos
++ = b32digits
[((chunk
.ptr
[i
+3] & 0x03) << 3) |
515 (chunk
.ptr
[i
+4] >> 5)];
516 *pos
++ = b32digits
[chunk
.ptr
[i
+4] & 0x1F];
519 return chunk_create(buf
, len
* 8 / 5);
523 * Described in header.
525 int chunk_compare(chunk_t a
, chunk_t b
)
527 int compare_len
= a
.len
- b
.len
;
528 int len
= (compare_len
< 0)? a
.len
: b
.len
;
530 if (compare_len
!= 0 || len
== 0)
534 return memcmp(a
.ptr
, b
.ptr
, len
);
539 * Described in header.
541 bool chunk_increment(chunk_t chunk
)
545 for (i
= chunk
.len
- 1; i
>= 0; i
--)
547 if (++chunk
.ptr
[i
] != 0)
556 * Remove non-printable characters from a chunk.
558 bool chunk_printable(chunk_t chunk
, chunk_t
*sane
, char replace
)
560 bool printable
= TRUE
;
565 *sane
= chunk_clone(chunk
);
567 for (i
= 0; i
< chunk
.len
; i
++)
569 if (!isprint(chunk
.ptr
[i
]))
573 sane
->ptr
[i
] = replace
;
582 * Helper functions for chunk_mac()
584 static inline u_int64_t
sipget(u_char
*in
)
589 for (i
= 0; i
< 64; i
+= 8, ++in
)
591 v
|= ((u_int64_t
)*in
) << i
;
596 static inline u_int64_t
siprotate(u_int64_t v
, int shift
)
598 return (v
<< shift
) | (v
>> (64 - shift
));
601 static inline void sipround(u_int64_t
*v0
, u_int64_t
*v1
, u_int64_t
*v2
,
605 *v1
= siprotate(*v1
, 13);
607 *v0
= siprotate(*v0
, 32);
610 *v3
= siprotate(*v3
, 16);
614 *v1
= siprotate(*v1
, 17);
616 *v2
= siprotate(*v2
, 32);
619 *v3
= siprotate(*v3
, 21);
623 static inline void sipcompress(u_int64_t
*v0
, u_int64_t
*v1
, u_int64_t
*v2
,
624 u_int64_t
*v3
, u_int64_t m
)
627 sipround(v0
, v1
, v2
, v3
);
628 sipround(v0
, v1
, v2
, v3
);
632 static inline u_int64_t
siplast(size_t len
, u_char
*pos
)
637 b
= ((u_int64_t
)len
) << 56;
641 b
|= ((u_int64_t
)pos
[6]) << 48;
643 b
|= ((u_int64_t
)pos
[5]) << 40;
645 b
|= ((u_int64_t
)pos
[4]) << 32;
647 b
|= ((u_int64_t
)pos
[3]) << 24;
649 b
|= ((u_int64_t
)pos
[2]) << 16;
651 b
|= ((u_int64_t
)pos
[1]) << 8;
653 b
|= ((u_int64_t
)pos
[0]);
662 * Described in header.
664 u_int64_t
chunk_mac(chunk_t chunk
, u_char
*key
)
666 u_int64_t v0
, v1
, v2
, v3
, k0
, k1
, m
;
667 size_t len
= chunk
.len
;
668 u_char
*pos
= chunk
.ptr
, *end
;
670 end
= chunk
.ptr
+ len
- (len
% 8);
673 k1
= sipget(key
+ 8);
675 v0
= k0
^ 0x736f6d6570736575ULL
;
676 v1
= k1
^ 0x646f72616e646f6dULL
;
677 v2
= k0
^ 0x6c7967656e657261ULL
;
678 v3
= k1
^ 0x7465646279746573ULL
;
680 /* compression with c = 2 */
681 for (; pos
!= end
; pos
+= 8)
684 sipcompress(&v0
, &v1
, &v2
, &v3
, m
);
686 sipcompress(&v0
, &v1
, &v2
, &v3
, siplast(len
, pos
));
688 /* finalization with d = 4 */
690 sipround(&v0
, &v1
, &v2
, &v3
);
691 sipround(&v0
, &v1
, &v2
, &v3
);
692 sipround(&v0
, &v1
, &v2
, &v3
);
693 sipround(&v0
, &v1
, &v2
, &v3
);
694 return v0
^ v1
^ v2
^ v3
;
698 * Described in header.
700 * The implementation is based on Paul Hsieh's SuperFastHash:
701 * http://www.azillionmonkeys.com/qed/hash.html
703 u_int32_t
chunk_hash_inc(chunk_t chunk
, u_int32_t hash
)
705 u_char
*data
= chunk
.ptr
;
706 size_t len
= chunk
.len
;
710 if (!len
|| data
== NULL
)
719 for (; len
> 0; --len
)
721 hash
+= get16bits(data
);
722 tmp
= (get16bits(data
+ 2) << 11) ^ hash
;
723 hash
= (hash
<< 16) ^ tmp
;
724 data
+= 2 * sizeof(u_int16_t
);
728 /* Handle end cases */
733 hash
+= get16bits(data
);
735 hash
^= data
[sizeof(u_int16_t
)] << 18;
741 hash
+= get16bits(data
);
755 /* Force "avalanching" of final 127 bits */
767 * Described in header.
769 u_int32_t
chunk_hash(chunk_t chunk
)
771 return chunk_hash_inc(chunk
, chunk
.len
);
775 * Described in header.
777 int chunk_printf_hook(printf_hook_data_t
*data
, printf_hook_spec_t
*spec
,
778 const void *const *args
)
780 chunk_t
*chunk
= *((chunk_t
**)(args
[0]));
782 chunk_t copy
= *chunk
;
787 u_int chunk_len
= chunk
->len
;
788 const void *new_args
[] = {&chunk
->ptr
, &chunk_len
};
789 return mem_printf_hook(data
, spec
, new_args
);
800 written
+= print_in_hook(data
, ":");
802 written
+= print_in_hook(data
, "%02x", *copy
.ptr
++);