04f3eea7dff6751068f8785af6cdb054b7ee9f18
[strongswan.git] / src / libstrongswan / utils / chunk.c
1 /*
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
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <pthread.h>
25 #include <ctype.h>
26
27 #include "chunk.h"
28 #include "debug.h"
29
30 /**
31 * Empty chunk.
32 */
33 chunk_t chunk_empty = { NULL, 0 };
34
35 /**
36 * Described in header.
37 */
38 chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
39 {
40 chunk_t clone = chunk_empty;
41
42 if (chunk.ptr && chunk.len > 0)
43 {
44 clone.ptr = ptr;
45 clone.len = chunk.len;
46 memcpy(clone.ptr, chunk.ptr, chunk.len);
47 }
48
49 return clone;
50 }
51
52 /**
53 * Described in header.
54 */
55 size_t chunk_length(const char* mode, ...)
56 {
57 va_list chunks;
58 size_t length = 0;
59
60 va_start(chunks, mode);
61 while (TRUE)
62 {
63 switch (*mode++)
64 {
65 case 'm':
66 case 'c':
67 case 's':
68 {
69 chunk_t ch = va_arg(chunks, chunk_t);
70 length += ch.len;
71 continue;
72 }
73 default:
74 break;
75 }
76 break;
77 }
78 va_end(chunks);
79 return length;
80 }
81
82 /**
83 * Described in header.
84 */
85 chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
86 {
87 va_list chunks;
88 chunk_t construct = chunk_create(ptr, 0);
89
90 va_start(chunks, mode);
91 while (TRUE)
92 {
93 bool free_chunk = FALSE, clear_chunk = FALSE;
94 chunk_t ch;
95
96 switch (*mode++)
97 {
98 case 's':
99 clear_chunk = TRUE;
100 /* FALL */
101 case 'm':
102 free_chunk = TRUE;
103 /* FALL */
104 case 'c':
105 ch = va_arg(chunks, chunk_t);
106 memcpy(ptr, ch.ptr, ch.len);
107 ptr += ch.len;
108 construct.len += ch.len;
109 if (clear_chunk)
110 {
111 chunk_clear(&ch);
112 }
113 else if (free_chunk)
114 {
115 free(ch.ptr);
116 }
117 continue;
118 default:
119 break;
120 }
121 break;
122 }
123 va_end(chunks);
124
125 return construct;
126 }
127
128 /**
129 * Described in header.
130 */
131 void chunk_split(chunk_t chunk, const char *mode, ...)
132 {
133 va_list chunks;
134 u_int len;
135 chunk_t *ch;
136
137 va_start(chunks, mode);
138 while (TRUE)
139 {
140 if (*mode == '\0')
141 {
142 break;
143 }
144 len = va_arg(chunks, u_int);
145 ch = va_arg(chunks, chunk_t*);
146 /* a null chunk means skip len bytes */
147 if (ch == NULL)
148 {
149 chunk = chunk_skip(chunk, len);
150 continue;
151 }
152 switch (*mode++)
153 {
154 case 'm':
155 {
156 ch->len = min(chunk.len, len);
157 if (ch->len)
158 {
159 ch->ptr = chunk.ptr;
160 }
161 else
162 {
163 ch->ptr = NULL;
164 }
165 chunk = chunk_skip(chunk, ch->len);
166 continue;
167 }
168 case 'a':
169 {
170 ch->len = min(chunk.len, len);
171 if (ch->len)
172 {
173 ch->ptr = malloc(ch->len);
174 memcpy(ch->ptr, chunk.ptr, ch->len);
175 }
176 else
177 {
178 ch->ptr = NULL;
179 }
180 chunk = chunk_skip(chunk, ch->len);
181 continue;
182 }
183 case 'c':
184 {
185 ch->len = min(ch->len, chunk.len);
186 ch->len = min(ch->len, len);
187 if (ch->len)
188 {
189 memcpy(ch->ptr, chunk.ptr, ch->len);
190 }
191 else
192 {
193 ch->ptr = NULL;
194 }
195 chunk = chunk_skip(chunk, ch->len);
196 continue;
197 }
198 default:
199 break;
200 }
201 break;
202 }
203 va_end(chunks);
204 }
205
206 /**
207 * Described in header.
208 */
209 bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force)
210 {
211 mode_t oldmask;
212 FILE *fd;
213 bool good = FALSE;
214
215 if (!force && access(path, F_OK) == 0)
216 {
217 DBG1(DBG_LIB, " %s file '%s' already exists", label, path);
218 return FALSE;
219 }
220 oldmask = umask(mask);
221 fd = fopen(path, "w");
222 if (fd)
223 {
224 if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
225 {
226 DBG1(DBG_LIB, " written %s file '%s' (%d bytes)",
227 label, path, chunk.len);
228 good = TRUE;
229 }
230 else
231 {
232 DBG1(DBG_LIB, " writing %s file '%s' failed: %s",
233 label, path, strerror(errno));
234 }
235 fclose(fd);
236 }
237 else
238 {
239 DBG1(DBG_LIB, " could not open %s file '%s': %s", label, path,
240 strerror(errno));
241 }
242 umask(oldmask);
243 return good;
244 }
245
246
247 /** hex conversion digits */
248 static char hexdig_upper[] = "0123456789ABCDEF";
249 static char hexdig_lower[] = "0123456789abcdef";
250
251 /**
252 * Described in header.
253 */
254 chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase)
255 {
256 int i, len;
257 char *hexdig = hexdig_lower;
258
259 if (uppercase)
260 {
261 hexdig = hexdig_upper;
262 }
263
264 len = chunk.len * 2;
265 if (!buf)
266 {
267 buf = malloc(len + 1);
268 }
269 buf[len] = '\0';
270
271 for (i = 0; i < chunk.len; i++)
272 {
273 buf[i*2] = hexdig[(chunk.ptr[i] >> 4) & 0xF];
274 buf[i*2+1] = hexdig[(chunk.ptr[i] ) & 0xF];
275 }
276 return chunk_create(buf, len);
277 }
278
279 /**
280 * convert a signle hex character to its binary value
281 */
282 static char hex2bin(char hex)
283 {
284 switch (hex)
285 {
286 case '0' ... '9':
287 return hex - '0';
288 case 'A' ... 'F':
289 return hex - 'A' + 10;
290 case 'a' ... 'f':
291 return hex - 'a' + 10;
292 default:
293 return 0;
294 }
295 }
296
297 /**
298 * Described in header.
299 */
300 chunk_t chunk_from_hex(chunk_t hex, char *buf)
301 {
302 int i, len;
303 u_char *ptr;
304 bool odd = FALSE;
305
306 /* subtract the number of optional ':' separation characters */
307 len = hex.len;
308 ptr = hex.ptr;
309 for (i = 0; i < hex.len; i++)
310 {
311 if (*ptr++ == ':')
312 {
313 len--;
314 }
315 }
316
317 /* compute the number of binary bytes */
318 if (len % 2)
319 {
320 odd = TRUE;
321 len++;
322 }
323 len /= 2;
324
325 /* allocate buffer memory unless provided by caller */
326 if (!buf)
327 {
328 buf = malloc(len);
329 }
330
331 /* buffer is filled from the right */
332 memset(buf, 0, len);
333 hex.ptr += hex.len;
334
335 for (i = len - 1; i >= 0; i--)
336 {
337 /* skip separation characters */
338 if (*(--hex.ptr) == ':')
339 {
340 --hex.ptr;
341 }
342 buf[i] = hex2bin(*hex.ptr);
343 if (i > 0 || !odd)
344 {
345 buf[i] |= hex2bin(*(--hex.ptr)) << 4;
346 }
347 }
348 return chunk_create(buf, len);
349 }
350
351 /** base 64 conversion digits */
352 static char b64digits[] =
353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
354
355 /**
356 * Described in header.
357 */
358 chunk_t chunk_to_base64(chunk_t chunk, char *buf)
359 {
360 int i, len;
361 char *pos;
362
363 len = chunk.len + ((3 - chunk.len % 3) % 3);
364 if (!buf)
365 {
366 buf = malloc(len * 4 / 3 + 1);
367 }
368 pos = buf;
369 for (i = 0; i < len; i+=3)
370 {
371 *pos++ = b64digits[chunk.ptr[i] >> 2];
372 if (i+1 >= chunk.len)
373 {
374 *pos++ = b64digits[(chunk.ptr[i] & 0x03) << 4];
375 *pos++ = '=';
376 *pos++ = '=';
377 break;
378 }
379 *pos++ = b64digits[((chunk.ptr[i] & 0x03) << 4) | (chunk.ptr[i+1] >> 4)];
380 if (i+2 >= chunk.len)
381 {
382 *pos++ = b64digits[(chunk.ptr[i+1] & 0x0F) << 2];
383 *pos++ = '=';
384 break;
385 }
386 *pos++ = b64digits[((chunk.ptr[i+1] & 0x0F) << 2) | (chunk.ptr[i+2] >> 6)];
387 *pos++ = b64digits[chunk.ptr[i+2] & 0x3F];
388 }
389 *pos = '\0';
390 return chunk_create(buf, len * 4 / 3);
391 }
392
393 /**
394 * convert a base 64 digit to its binary form (inversion of b64digits array)
395 */
396 static int b642bin(char b64)
397 {
398 switch (b64)
399 {
400 case 'A' ... 'Z':
401 return b64 - 'A';
402 case 'a' ... 'z':
403 return ('Z' - 'A' + 1) + b64 - 'a';
404 case '0' ... '9':
405 return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64 - '0';
406 case '+':
407 case '-':
408 return 62;
409 case '/':
410 case '_':
411 return 63;
412 case '=':
413 return 0;
414 default:
415 return -1;
416 }
417 }
418
419 /**
420 * Described in header.
421 */
422 chunk_t chunk_from_base64(chunk_t base64, char *buf)
423 {
424 u_char *pos, byte[4];
425 int i, j, len, outlen;
426
427 len = base64.len / 4 * 3;
428 if (!buf)
429 {
430 buf = malloc(len);
431 }
432 pos = base64.ptr;
433 outlen = 0;
434 for (i = 0; i < len; i+=3)
435 {
436 outlen += 3;
437 for (j = 0; j < 4; j++)
438 {
439 if (*pos == '=')
440 {
441 outlen--;
442 }
443 byte[j] = b642bin(*pos++);
444 }
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]);
448 }
449 return chunk_create(buf, outlen);
450 }
451
452 /** base 32 conversion digits */
453 static char b32digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
454
455 /**
456 * Described in header.
457 */
458 chunk_t chunk_to_base32(chunk_t chunk, char *buf)
459 {
460 int i, len;
461 char *pos;
462
463 len = chunk.len + ((5 - chunk.len % 5) % 5);
464 if (!buf)
465 {
466 buf = malloc(len * 8 / 5 + 1);
467 }
468 pos = buf;
469 for (i = 0; i < len; i+=5)
470 {
471 *pos++ = b32digits[chunk.ptr[i] >> 3];
472 if (i+1 >= chunk.len)
473 {
474 *pos++ = b32digits[(chunk.ptr[i] & 0x07) << 2];
475 memset(pos, '=', 6);
476 pos += 6;
477 break;
478 }
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)
483 {
484 *pos++ = b32digits[(chunk.ptr[i+1] & 0x01) << 4];
485 memset(pos, '=', 4);
486 pos += 4;
487 break;
488 }
489 *pos++ = b32digits[((chunk.ptr[i+1] & 0x01) << 4) |
490 (chunk.ptr[i+2] >> 4)];
491 if (i+3 >= chunk.len)
492 {
493 *pos++ = b32digits[(chunk.ptr[i+2] & 0x0F) << 1];
494 memset(pos, '=', 3);
495 pos += 3;
496 break;
497 }
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)
502 {
503 *pos++ = b32digits[(chunk.ptr[i+3] & 0x03) << 3];
504 *pos++ = '=';
505 break;
506 }
507 *pos++ = b32digits[((chunk.ptr[i+3] & 0x03) << 3) |
508 (chunk.ptr[i+4] >> 5)];
509 *pos++ = b32digits[chunk.ptr[i+4] & 0x1F];
510 }
511 *pos = '\0';
512 return chunk_create(buf, len * 8 / 5);
513 }
514
515 /**
516 * Described in header.
517 */
518 int chunk_compare(chunk_t a, chunk_t b)
519 {
520 int compare_len = a.len - b.len;
521 int len = (compare_len < 0)? a.len : b.len;
522
523 if (compare_len != 0 || len == 0)
524 {
525 return compare_len;
526 }
527 return memcmp(a.ptr, b.ptr, len);
528 };
529
530
531 /**
532 * Described in header.
533 */
534 bool chunk_increment(chunk_t chunk)
535 {
536 int i;
537
538 for (i = chunk.len - 1; i >= 0; i--)
539 {
540 if (++chunk.ptr[i] != 0)
541 {
542 return FALSE;
543 }
544 }
545 return TRUE;
546 }
547
548 /**
549 * Remove non-printable characters from a chunk.
550 */
551 bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace)
552 {
553 bool printable = TRUE;
554 int i;
555
556 if (sane)
557 {
558 *sane = chunk_clone(chunk);
559 }
560 for (i = 0; i < chunk.len; i++)
561 {
562 if (!isprint(chunk.ptr[i]))
563 {
564 if (sane)
565 {
566 sane->ptr[i] = replace;
567 }
568 printable = FALSE;
569 }
570 }
571 return printable;
572 }
573
574 /**
575 * Helper functions for chunk_mac()
576 */
577 static inline u_int64_t sipget(u_char *in)
578 {
579 u_int64_t v = 0;
580 int i;
581
582 for (i = 0; i < 64; i += 8, ++in)
583 {
584 v |= ((u_int64_t)*in) << i;
585 }
586 return v;
587 }
588
589 static inline u_int64_t siprotate(u_int64_t v, int shift)
590 {
591 return (v << shift) | (v >> (64 - shift));
592 }
593
594 static inline void sipround(u_int64_t *v0, u_int64_t *v1, u_int64_t *v2,
595 u_int64_t *v3)
596 {
597 *v0 += *v1;
598 *v1 = siprotate(*v1, 13);
599 *v1 ^= *v0;
600 *v0 = siprotate(*v0, 32);
601
602 *v2 += *v3;
603 *v3 = siprotate(*v3, 16);
604 *v3 ^= *v2;
605
606 *v2 += *v1;
607 *v1 = siprotate(*v1, 17);
608 *v1 ^= *v2;
609 *v2 = siprotate(*v2, 32);
610
611 *v0 += *v3;
612 *v3 = siprotate(*v3, 21);
613 *v3 ^= *v0;
614 }
615
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)
618 {
619 *v3 ^= m;
620 sipround(v0, v1, v2, v3);
621 sipround(v0, v1, v2, v3);
622 *v0 ^= m;
623 }
624
625 static inline u_int64_t siplast(size_t len, u_char *pos)
626 {
627 u_int64_t b;
628 int rem = len & 7;
629
630 b = ((u_int64_t)len) << 56;
631 switch (rem)
632 {
633 case 7:
634 b |= ((u_int64_t)pos[6]) << 48;
635 case 6:
636 b |= ((u_int64_t)pos[5]) << 40;
637 case 5:
638 b |= ((u_int64_t)pos[4]) << 32;
639 case 4:
640 b |= ((u_int64_t)pos[3]) << 24;
641 case 3:
642 b |= ((u_int64_t)pos[2]) << 16;
643 case 2:
644 b |= ((u_int64_t)pos[1]) << 8;
645 case 1:
646 b |= ((u_int64_t)pos[0]);
647 break;
648 case 0:
649 break;
650 }
651 return b;
652 }
653
654 /**
655 * Caculate SipHash-2-4 with an optional first block given as argument.
656 */
657 static u_int64_t chunk_mac_inc(chunk_t chunk, u_char *key, u_int64_t m)
658 {
659 u_int64_t v0, v1, v2, v3, k0, k1;
660 size_t len = chunk.len;
661 u_char *pos = chunk.ptr, *end;
662
663 end = chunk.ptr + len - (len % 8);
664
665 k0 = sipget(key);
666 k1 = sipget(key + 8);
667
668 v0 = k0 ^ 0x736f6d6570736575ULL;
669 v1 = k1 ^ 0x646f72616e646f6dULL;
670 v2 = k0 ^ 0x6c7967656e657261ULL;
671 v3 = k1 ^ 0x7465646279746573ULL;
672
673 if (m)
674 {
675 sipcompress(&v0, &v1, &v2, &v3, m);
676 }
677
678 /* compression with c = 2 */
679 for (; pos != end; pos += 8)
680 {
681 m = sipget(pos);
682 sipcompress(&v0, &v1, &v2, &v3, m);
683 }
684 sipcompress(&v0, &v1, &v2, &v3, siplast(len, pos));
685
686 /* finalization with d = 4 */
687 v2 ^= 0xff;
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;
693 }
694
695 /**
696 * Described in header.
697 */
698 u_int64_t chunk_mac(chunk_t chunk, u_char *key)
699 {
700 return chunk_mac_inc(chunk, key, 0);
701 }
702
703 /**
704 * Secret key allocated randomly during first use.
705 */
706 static u_char key[16];
707
708 /**
709 * Static key used in case predictable hash values are required.
710 */
711 static u_char static_key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
712 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
713
714 /**
715 * Only allocate the key once
716 */
717 static pthread_once_t key_allocated = PTHREAD_ONCE_INIT;
718
719 /**
720 * Allocate a key on first use, we do this manually to avoid dependencies on
721 * plugins.
722 */
723 static void allocate_key()
724 {
725 ssize_t len;
726 size_t done = 0;
727 int fd;
728
729 fd = open("/dev/urandom", O_RDONLY);
730 if (fd >= 0)
731 {
732 while (done < sizeof(key))
733 {
734 len = read(fd, key + done, sizeof(key) - done);
735 if (len < 0)
736 {
737 break;
738 }
739 done += len;
740 }
741 close(fd);
742 }
743 /* on error we use random() to generate the key (better than nothing) */
744 if (done < sizeof(key))
745 {
746 srandom(time(NULL) + getpid());
747 for (; done < sizeof(key); done++)
748 {
749 key[done] = (u_char)random();
750 }
751 }
752 }
753
754 /**
755 * Described in header.
756 */
757 u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
758 {
759 pthread_once(&key_allocated, allocate_key);
760 /* we could use a mac of the previous hash, but this is faster */
761 return chunk_mac_inc(chunk, key, ((u_int64_t)hash) << 32 | hash);
762 }
763
764 /**
765 * Described in header.
766 */
767 u_int32_t chunk_hash(chunk_t chunk)
768 {
769 pthread_once(&key_allocated, allocate_key);
770 return chunk_mac(chunk, key);
771 }
772
773 /**
774 * Described in header.
775 */
776 u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash)
777 { /* we could use a mac of the previous hash, but this is faster */
778 return chunk_mac_inc(chunk, static_key, ((u_int64_t)hash) << 32 | hash);
779 }
780
781 /**
782 * Described in header.
783 */
784 u_int32_t chunk_hash_static(chunk_t chunk)
785 {
786 return chunk_mac(chunk, static_key);
787 }
788
789 /**
790 * Described in header.
791 */
792 int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
793 const void *const *args)
794 {
795 chunk_t *chunk = *((chunk_t**)(args[0]));
796 bool first = TRUE;
797 chunk_t copy = *chunk;
798 int written = 0;
799
800 if (!spec->hash)
801 {
802 u_int chunk_len = chunk->len;
803 const void *new_args[] = {&chunk->ptr, &chunk_len};
804 return mem_printf_hook(data, spec, new_args);
805 }
806
807 while (copy.len > 0)
808 {
809 if (first)
810 {
811 first = FALSE;
812 }
813 else
814 {
815 written += print_in_hook(data, ":");
816 }
817 written += print_in_hook(data, "%02x", *copy.ptr++);
818 copy.len--;
819 }
820 return written;
821 }