utils: Add a constant time chunk_equals() variant for cryptographic purposes
[strongswan.git] / src / libstrongswan / tests / suites / test_chunk.c
1 /*
2 * Copyright (C) 2013 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "test_suite.h"
18
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <errno.h>
24
25 #include <utils/chunk.h>
26 #include <threading/thread.h>
27
28 /*******************************************************************************
29 * utilities
30 */
31
32 static void assert_chunk_empty(chunk_t chunk)
33 {
34 ck_assert(chunk.len == 0 && chunk.ptr == NULL);
35 }
36
37 /*******************************************************************************
38 * equals
39 */
40
41 START_TEST(test_chunk_equals)
42 {
43 chunk_t chunk = chunk_from_str("chunk");
44 chunk_t chunk_a, chunk_b;
45
46 chunk_a = chunk_empty;
47 chunk_b = chunk_empty;
48 ck_assert(!chunk_equals(chunk_a, chunk_b));
49
50 chunk_a = chunk;
51 ck_assert(!chunk_equals(chunk_a, chunk_b));
52 chunk_b = chunk;
53 ck_assert(chunk_equals(chunk_a, chunk_b));
54
55 chunk_b = chunk_from_str("asdf");
56 ck_assert(!chunk_equals(chunk_a, chunk_b));
57
58 chunk_b = chunk_from_str("chunk");
59 ck_assert(chunk_equals(chunk_a, chunk_b));
60 }
61 END_TEST
62
63 /*******************************************************************************
64 * equals_const
65 */
66
67 START_TEST(test_chunk_equals_const)
68 {
69 chunk_t chunk = chunk_from_str("chunk");
70 chunk_t chunk_a, chunk_b;
71
72 chunk_a = chunk_empty;
73 chunk_b = chunk_empty;
74 ck_assert(!chunk_equals_const(chunk_a, chunk_b));
75
76 chunk_a = chunk;
77 ck_assert(!chunk_equals_const(chunk_a, chunk_b));
78 chunk_b = chunk;
79 ck_assert(chunk_equals_const(chunk_a, chunk_b));
80
81 chunk_b = chunk_from_str("asdf");
82 ck_assert(!chunk_equals_const(chunk_a, chunk_b));
83
84 chunk_b = chunk_from_str("chunk");
85 ck_assert(chunk_equals_const(chunk_a, chunk_b));
86 }
87 END_TEST
88
89 /*******************************************************************************
90 * chunk_compare test
91 */
92
93 static struct {
94 int result;
95 chunk_t a;
96 chunk_t b;
97 } compare_data[] = {
98 { 0, { NULL, 0 }, { NULL, 0 }},
99 { 0, chunk_from_chars(0x00), chunk_from_chars(0x00)},
100 {-1, chunk_from_chars(0x00), chunk_from_chars(0x01)},
101 { 1, chunk_from_chars(0x01), chunk_from_chars(0x00)},
102 { 0, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x00)},
103 {-1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x01)},
104 { 1, chunk_from_chars(0x00, 0x01), chunk_from_chars(0x00, 0x00)},
105 {-1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x01, 0x00)},
106 { 1, chunk_from_chars(0x01, 0x00), chunk_from_chars(0x00, 0x00)},
107 {-1, chunk_from_chars(0xff), chunk_from_chars(0x00, 0x00)},
108 { 1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0xff)},
109 };
110
111 START_TEST(test_compare)
112 {
113 int result, expected;
114
115 result = chunk_compare(compare_data[_i].a, compare_data[_i].b);
116 expected = compare_data[_i].result;
117 ck_assert((result == 0 && expected == 0) ||
118 (result < 0 && expected < 0) ||
119 (result > 0 && expected > 0));
120 }
121 END_TEST
122
123 /*******************************************************************************
124 * clear
125 */
126
127 START_TEST(test_chunk_clear)
128 {
129 chunk_t chunk;
130 u_char *ptr;
131 int i;
132 bool cleared = TRUE;
133
134 chunk = chunk_empty;
135 chunk_clear(&chunk);
136 chunk_free(&chunk);
137
138 chunk = chunk_alloc(64);
139 ptr = chunk.ptr;
140 for (i = 0; i < 64; i++)
141 {
142 chunk.ptr[i] = i;
143 }
144 chunk_clear(&chunk);
145 /* check memory area of freed chunk. We can't use ck_assert() for this
146 * test directly, as it might allocate data at the freed area. comparing
147 * two bytes at once reduces the chances of conflicts if memory got
148 * overwritten already */
149 for (i = 0; i < 64; i += 2)
150 {
151 if (ptr[i] != 0 && ptr[i] == i &&
152 ptr[i+1] != 0 && ptr[i+1] == i+1)
153 {
154 cleared = FALSE;
155 break;
156 }
157 }
158 assert_chunk_empty(chunk);
159 ck_assert(cleared);
160 }
161 END_TEST
162
163 /*******************************************************************************
164 * chunk_length
165 */
166
167 START_TEST(test_chunk_length)
168 {
169 chunk_t a, b, c;
170 size_t len;
171
172 a = chunk_empty;
173 b = chunk_empty;
174 c = chunk_empty;
175 len = chunk_length("ccc", a, b, c);
176 ck_assert_int_eq(len, 0);
177
178 a = chunk_from_str("foo");
179 b = chunk_from_str("bar");
180 len = chunk_length("ccc", a, b, c);
181 ck_assert_int_eq(len, 6);
182
183 len = chunk_length("zcc", a, b, c);
184 ck_assert_int_eq(len, 0);
185
186 len = chunk_length("czc", a, b, c);
187 ck_assert_int_eq(len, 3);
188
189 a = chunk_from_str("foo");
190 b = chunk_from_str("bar");
191 c = chunk_from_str("baz");
192 len = chunk_length("ccc", a, b, c);
193 ck_assert_int_eq(len, 9);
194 }
195 END_TEST
196
197 /*******************************************************************************
198 * chunk_create_cat
199 */
200
201 START_TEST(test_chunk_create_cat)
202 {
203 chunk_t foo, bar;
204 chunk_t a, b, c;
205 u_char *ptra, *ptrb;
206
207 foo = chunk_from_str("foo");
208 bar = chunk_from_str("bar");
209
210 /* to simplify things we use the chunk_cata macro */
211
212 a = chunk_empty;
213 b = chunk_empty;
214 c = chunk_cata("cc", a, b);
215 ck_assert_int_eq(c.len, 0);
216 ck_assert(c.ptr != NULL);
217
218 a = foo;
219 b = bar;
220 c = chunk_cata("cc", a, b);
221 ck_assert_int_eq(c.len, 6);
222 ck_assert(chunk_equals(c, chunk_from_str("foobar")));
223
224 a = chunk_clone(foo);
225 b = chunk_clone(bar);
226 c = chunk_cata("mm", a, b);
227 ck_assert_int_eq(c.len, 6);
228 ck_assert(chunk_equals(c, chunk_from_str("foobar")));
229
230 a = chunk_clone(foo);
231 b = chunk_clone(bar);
232 ptra = a.ptr;
233 ptrb = b.ptr;
234 c = chunk_cata("ss", a, b);
235 ck_assert_int_eq(c.len, 6);
236 ck_assert(chunk_equals(c, chunk_from_str("foobar")));
237 /* check memory area of cleared chunk */
238 ck_assert(!chunk_equals(foo, chunk_create(ptra, 3)));
239 ck_assert(!chunk_equals(bar, chunk_create(ptrb, 3)));
240 }
241 END_TEST
242
243 /*******************************************************************************
244 * chunk_split
245 */
246
247 static bool mem_in_chunk(u_char *ptr, chunk_t chunk)
248 {
249 return ptr >= chunk.ptr && ptr < (chunk.ptr + chunk.len);
250 }
251
252 START_TEST(test_chunk_split)
253 {
254 chunk_t foo, bar, foobar;
255 chunk_t a, b, c;
256 u_char *ptra, *ptrb;
257
258 foo = chunk_from_str("foo");
259 bar = chunk_from_str("bar");
260 foobar = chunk_from_str("foobar");
261
262 chunk_split(foobar, "aa", 3, &a, 3, &b);
263 ck_assert(chunk_equals(a, foo));
264 ck_assert(chunk_equals(b, bar));
265 ck_assert(!mem_in_chunk(a.ptr, foobar));
266 ck_assert(!mem_in_chunk(b.ptr, foobar));
267 chunk_free(&a);
268 chunk_free(&b);
269
270 chunk_split(foobar, "mm", 3, &a, 3, &b);
271 ck_assert(chunk_equals(a, foo));
272 ck_assert(chunk_equals(b, bar));
273 ck_assert(mem_in_chunk(a.ptr, foobar));
274 ck_assert(mem_in_chunk(b.ptr, foobar));
275
276 chunk_split(foobar, "am", 3, &a, 3, &b);
277 ck_assert(chunk_equals(a, foo));
278 ck_assert(chunk_equals(b, bar));
279 ck_assert(!mem_in_chunk(a.ptr, foobar));
280 ck_assert(mem_in_chunk(b.ptr, foobar));
281 chunk_free(&a);
282
283 a = chunk_alloca(3);
284 ptra = a.ptr;
285 b = chunk_alloca(3);
286 ptrb = b.ptr;
287 chunk_split(foobar, "cc", 3, &a, 3, &b);
288 ck_assert(chunk_equals(a, foo));
289 ck_assert(chunk_equals(b, bar));
290 ck_assert(a.ptr == ptra);
291 ck_assert(b.ptr == ptrb);
292
293 chunk_split(foobar, "mm", 1, NULL, 2, &a, 2, NULL, 1, &b);
294 ck_assert(chunk_equals(a, chunk_from_str("oo")));
295 ck_assert(chunk_equals(b, chunk_from_str("r")));
296
297 chunk_split(foobar, "mm", 6, &a, 6, &b);
298 ck_assert(chunk_equals(a, foobar));
299 assert_chunk_empty(b);
300
301 chunk_split(foobar, "mac", 12, &a, 12, &b, 12, &c);
302 ck_assert(chunk_equals(a, foobar));
303 assert_chunk_empty(b);
304 assert_chunk_empty(c);
305 }
306 END_TEST
307
308 /*******************************************************************************
309 * chunk_skip[_zero]
310 */
311
312 START_TEST(test_chunk_skip)
313 {
314 chunk_t foobar, a;
315
316 foobar = chunk_from_str("foobar");
317 a = foobar;
318 a = chunk_skip(a, 0);
319 ck_assert(chunk_equals(a, foobar));
320 a = chunk_skip(a, 1);
321 ck_assert(chunk_equals(a, chunk_from_str("oobar")));
322 a = chunk_skip(a, 2);
323 ck_assert(chunk_equals(a, chunk_from_str("bar")));
324 a = chunk_skip(a, 3);
325 assert_chunk_empty(a);
326
327 a = foobar;
328 a = chunk_skip(a, 6);
329 assert_chunk_empty(a);
330
331 a = foobar;
332 a = chunk_skip(a, 10);
333 assert_chunk_empty(a);
334 }
335 END_TEST
336
337 START_TEST(test_chunk_skip_zero)
338 {
339 chunk_t foobar, a;
340
341 a = chunk_empty;
342 a = chunk_skip_zero(a);
343 assert_chunk_empty(a);
344
345 foobar = chunk_from_str("foobar");
346 a = foobar;
347 a = chunk_skip_zero(a);
348 ck_assert(chunk_equals(a, foobar));
349
350 a = chunk_from_chars(0x00, 0xaa, 0xbb, 0xcc);
351 a = chunk_skip_zero(a);
352 ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc)));
353 a = chunk_skip_zero(a);
354 ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc)));
355 }
356 END_TEST
357
358 /*******************************************************************************
359 * BASE16 encoding test
360 */
361
362 START_TEST(test_base16)
363 {
364 /* test vectors from RFC 4648:
365 *
366 * BASE16("") = ""
367 * BASE16("f") = "66"
368 * BASE16("fo") = "666F"
369 * BASE16("foo") = "666F6F"
370 * BASE16("foob") = "666F6F62"
371 * BASE16("fooba") = "666F6F6261"
372 * BASE16("foobar") = "666F6F626172"
373 */
374 typedef struct {
375 bool upper;
376 char *in;
377 char *out;
378 } testdata_t;
379
380 testdata_t test[] = {
381 {TRUE, "", ""},
382 {TRUE, "f", "66"},
383 {TRUE, "fo", "666F"},
384 {TRUE, "foo", "666F6F"},
385 {TRUE, "foob", "666F6F62"},
386 {TRUE, "fooba", "666F6F6261"},
387 {TRUE, "foobar", "666F6F626172"},
388 {FALSE, "", ""},
389 {FALSE, "f", "66"},
390 {FALSE, "fo", "666f"},
391 {FALSE, "foo", "666f6f"},
392 {FALSE, "foob", "666f6f62"},
393 {FALSE, "fooba", "666f6f6261"},
394 {FALSE, "foobar", "666f6f626172"},
395 };
396 testdata_t test_colon[] = {
397 {TRUE, "", ""},
398 {TRUE, "f", "66"},
399 {TRUE, "fo", "66:6F"},
400 {TRUE, "foo", "66:6F:6F"},
401 {FALSE, "foob", "66:6f:6f:62"},
402 {FALSE, "fooba", "66:6f:6f:62:61"},
403 {FALSE, "foobar", "66:6f:6f:62:61:72"},
404 {FALSE, "foobar", "66:6f6f:6261:72"},
405 };
406 int i;
407
408 for (i = 0; i < countof(test); i++)
409 {
410 chunk_t out;
411
412 out = chunk_to_hex(chunk_create(test[i].in, strlen(test[i].in)), NULL,
413 test[i].upper);
414 ck_assert_str_eq(out.ptr, test[i].out);
415 free(out.ptr);
416 }
417
418 for (i = 0; i < countof(test); i++)
419 {
420 chunk_t out;
421
422 out = chunk_from_hex(chunk_create(test[i].out, strlen(test[i].out)), NULL);
423 fail_unless(strneq(out.ptr, test[i].in, out.len),
424 "base16 conversion error - should '%s', is %#B",
425 test[i].in, &out);
426 free(out.ptr);
427 }
428
429 for (i = 0; i < countof(test_colon); i++)
430 {
431 chunk_t out;
432
433 out = chunk_from_hex(chunk_create(test_colon[i].out, strlen(test_colon[i].out)), NULL);
434 fail_unless(strneq(out.ptr, test_colon[i].in, out.len),
435 "base16 conversion error - should '%s', is %#B",
436 test_colon[i].in, &out);
437 free(out.ptr);
438 }
439 }
440 END_TEST
441
442 /*******************************************************************************
443 * BASE64 encoding test
444 */
445
446 START_TEST(test_base64)
447 {
448 /* test vectors from RFC 4648:
449 *
450 * BASE64("") = ""
451 * BASE64("f") = "Zg=="
452 * BASE64("fo") = "Zm8="
453 * BASE64("foo") = "Zm9v"
454 * BASE64("foob") = "Zm9vYg=="
455 * BASE64("fooba") = "Zm9vYmE="
456 * BASE64("foobar") = "Zm9vYmFy"
457 */
458 typedef struct {
459 char *in;
460 char *out;
461 } testdata_t;
462
463 testdata_t test[] = {
464 {"", ""},
465 {"f", "Zg=="},
466 {"fo", "Zm8="},
467 {"foo", "Zm9v"},
468 {"foob", "Zm9vYg=="},
469 {"fooba", "Zm9vYmE="},
470 {"foobar", "Zm9vYmFy"},
471 };
472 int i;
473
474 for (i = 0; i < countof(test); i++)
475 {
476 chunk_t out;
477
478 out = chunk_to_base64(chunk_create(test[i].in, strlen(test[i].in)), NULL);
479 ck_assert_str_eq(out.ptr, test[i].out);
480 free(out.ptr);
481 }
482
483 for (i = 0; i < countof(test); i++)
484 {
485 chunk_t out;
486
487 out = chunk_from_base64(chunk_create(test[i].out, strlen(test[i].out)), NULL);
488 fail_unless(strneq(out.ptr, test[i].in, out.len),
489 "base64 conversion error - should '%s', is %#B",
490 test[i].in, &out);
491 free(out.ptr);
492 }
493 }
494 END_TEST
495
496 /*******************************************************************************
497 * BASE32 encoding test
498 */
499
500 START_TEST(test_base32)
501 {
502 /* test vectors from RFC 4648:
503 *
504 * BASE32("") = ""
505 * BASE32("f") = "MY======"
506 * BASE32("fo") = "MZXQ===="
507 * BASE32("foo") = "MZXW6==="
508 * BASE32("foob") = "MZXW6YQ="
509 * BASE32("fooba") = "MZXW6YTB"
510 * BASE32("foobar") = "MZXW6YTBOI======"
511 */
512 typedef struct {
513 char *in;
514 char *out;
515 } testdata_t;
516
517 testdata_t test[] = {
518 {"", ""},
519 {"f", "MY======"},
520 {"fo", "MZXQ===="},
521 {"foo", "MZXW6==="},
522 {"foob", "MZXW6YQ="},
523 {"fooba", "MZXW6YTB"},
524 {"foobar", "MZXW6YTBOI======"},
525 };
526 int i;
527
528 for (i = 0; i < countof(test); i++)
529 {
530 chunk_t out;
531
532 out = chunk_to_base32(chunk_create(test[i].in, strlen(test[i].in)), NULL);
533 ck_assert_str_eq(out.ptr, test[i].out);
534 free(out.ptr);
535 }
536 }
537 END_TEST
538
539 /*******************************************************************************
540 * chunk_increment test
541 */
542
543 static struct {
544 bool overflow;
545 chunk_t in;
546 chunk_t out;
547 } increment_data[] = {
548 {TRUE, { NULL, 0 }, { NULL, 0 }},
549 {FALSE, chunk_from_chars(0x00), chunk_from_chars(0x01)},
550 {FALSE, chunk_from_chars(0xfe), chunk_from_chars(0xff)},
551 {TRUE, chunk_from_chars(0xff), chunk_from_chars(0x00)},
552 {FALSE, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x01)},
553 {FALSE, chunk_from_chars(0x00, 0xff), chunk_from_chars(0x01, 0x00)},
554 {FALSE, chunk_from_chars(0xfe, 0xff), chunk_from_chars(0xff, 0x00)},
555 {TRUE, chunk_from_chars(0xff, 0xff), chunk_from_chars(0x00, 0x00)},
556 };
557
558 START_TEST(test_increment)
559 {
560 chunk_t chunk;
561 bool overflow;
562
563 chunk = chunk_clonea(increment_data[_i].in);
564 overflow = chunk_increment(chunk);
565 ck_assert(overflow == increment_data[_i].overflow);
566 ck_assert(!increment_data[_i].out.ptr ||
567 chunk_equals(chunk, increment_data[_i].out));
568 }
569 END_TEST
570
571 /*******************************************************************************
572 * chunk_printable tests
573 */
574
575 static struct {
576 bool printable;
577 chunk_t in;
578 char *out;
579 } printable_data[] = {
580 {TRUE, chunk_from_chars(0x31), "1"},
581 {FALSE, chunk_from_chars(0x00), "?"},
582 {FALSE, chunk_from_chars(0x31, 0x00), "1?"},
583 {FALSE, chunk_from_chars(0x00, 0x31), "?1"},
584 {TRUE, chunk_from_chars(0x3f, 0x31), "?1"},
585 {FALSE, chunk_from_chars(0x00, 0x31, 0x00), "?1?"},
586 {FALSE, chunk_from_chars(0x00, 0x31, 0x00, 0x32), "?1?2"},
587 };
588
589 START_TEST(test_printable)
590 {
591 bool printable;
592
593 printable = chunk_printable(printable_data[_i].in, NULL, ' ');
594 ck_assert(printable == printable_data[_i].printable);
595 }
596 END_TEST
597
598 START_TEST(test_printable_sanitize)
599 {
600 chunk_t sane, expected;
601 bool printable;
602
603 printable = chunk_printable(printable_data[_i].in, &sane, '?');
604 ck_assert(printable == printable_data[_i].printable);
605 expected = chunk_from_str(printable_data[_i].out);
606 ck_assert(chunk_equals(sane, expected));
607 chunk_free(&sane);
608 }
609 END_TEST
610
611 START_TEST(test_printable_empty)
612 {
613 chunk_t sane;
614 bool printable;
615
616 printable = chunk_printable(chunk_empty, NULL, ' ');
617 ck_assert(printable);
618
619 sane.ptr = (void*)1;
620 sane.len = 1;
621 printable = chunk_printable(chunk_empty, &sane, ' ');
622 ck_assert(printable);
623 assert_chunk_empty(sane);
624 }
625 END_TEST
626
627 /*******************************************************************************
628 * test for chunk_mac(), i.e. SipHash-2-4
629 */
630
631 /**
632 * SipHash-2-4 output with
633 * k = 00 01 02 ...
634 * and
635 * in = (empty string)
636 * in = 00 (1 byte)
637 * in = 00 01 (2 bytes)
638 * in = 00 01 02 (3 bytes)
639 * ...
640 * in = 00 01 02 ... 3e (63 bytes)
641 */
642 static const u_char sip_vectors[64][8] =
643 {
644 { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
645 { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
646 { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
647 { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
648 { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
649 { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
650 { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
651 { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
652 { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
653 { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
654 { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
655 { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
656 { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
657 { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
658 { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
659 { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
660 { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
661 { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
662 { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
663 { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
664 { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
665 { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
666 { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
667 { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
668 { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
669 { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
670 { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
671 { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
672 { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
673 { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
674 { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
675 { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
676 { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
677 { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
678 { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
679 { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
680 { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
681 { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
682 { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
683 { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
684 { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
685 { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
686 { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
687 { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
688 { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
689 { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
690 { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
691 { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
692 { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
693 { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
694 { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
695 { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
696 { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
697 { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
698 { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
699 { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
700 { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
701 { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
702 { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
703 { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
704 { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
705 { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
706 { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
707 { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
708 };
709
710 /**
711 * Our SipHash-2-4 implementation returns the result in host order, which
712 * doesn't matter for practical purposes and even avoids a byte swap. But
713 * because the test vectors are in little-endian we have to account for this
714 * with this custom comparison function.
715 */
716 static inline bool sipeq(const void *a, const void *b, size_t n)
717 {
718 u_char *ap = (u_char*)a, *bp = (u_char*)b;
719 int i;
720
721 for (i = 0; i < n; i++)
722 {
723 #ifdef WORDS_BIGENDIAN
724 if (ap[i] != bp[n - i - 1])
725 #else
726 if (ap[i] != bp[i])
727 #endif
728 {
729 return FALSE;
730 }
731 }
732 return TRUE;
733 }
734
735 START_TEST(test_chunk_mac)
736 {
737 chunk_t in;
738 u_char key[16];
739 u_int64_t out;
740 int i, count;
741
742 count = countof(sip_vectors);
743 in = chunk_alloca(count);
744
745 for (i = 0; i < 16; ++i)
746 {
747 key[i] = i;
748 }
749
750 for (i = 0; i < count; ++i)
751 {
752 in.ptr[i] = i;
753 in.len = i;
754 out = chunk_mac(in, key);
755 fail_unless(sipeq(&out, sip_vectors[i], 8),
756 "test vector failed for %d bytes", i);
757 }
758 }
759 END_TEST
760
761 /*******************************************************************************
762 * test for chunk_hash[_inc]()
763 */
764
765 START_TEST(test_chunk_hash)
766 {
767 chunk_t chunk;
768 u_int32_t hash_a, hash_b, hash_c;
769
770 chunk = chunk_from_str("asdf");
771
772 /* output is randomized, so there are no test-vectors we could use */
773 hash_a = chunk_hash(chunk);
774 hash_b = chunk_hash(chunk);
775 ck_assert(hash_a == hash_b);
776 hash_b = chunk_hash_inc(chunk, hash_a);
777 ck_assert(hash_a != hash_b);
778 hash_c = chunk_hash_inc(chunk, hash_a);
779 ck_assert(hash_b == hash_c);
780 }
781 END_TEST
782
783 /*******************************************************************************
784 * test for chunk_hash_static[_inc]()
785 */
786
787 START_TEST(test_chunk_hash_static)
788 {
789 chunk_t in;
790 u_int32_t out, hash_a, hash_b, hash_inc = 0x7b891a95;
791 int i, count;
792
793 count = countof(sip_vectors);
794 in = chunk_alloca(count);
795
796 for (i = 0; i < count; ++i)
797 {
798 in.ptr[i] = i;
799 in.len = i;
800 /* compared to chunk_mac() we only get half the value back */
801 out = chunk_hash_static(in);
802 fail_unless(sipeq(&out, sip_vectors[i], 4),
803 "test vector failed for %d bytes", i);
804 }
805 hash_a = chunk_hash_static_inc(in, out);
806 ck_assert_int_eq(hash_a, hash_inc);
807 hash_b = chunk_hash_static_inc(in, out);
808 ck_assert_int_eq(hash_a, hash_b);
809 }
810 END_TEST
811
812 /*******************************************************************************
813 * test for chunk_internet_checksum[_inc]()
814 */
815
816 static inline u_int16_t compensate_alignment(u_int16_t val)
817 {
818 return ((val & 0xff) << 8) | (val >> 8);
819 }
820
821 START_TEST(test_chunk_internet_checksum)
822 {
823 chunk_t chunk;
824 u_int16_t sum;
825
826 chunk = chunk_from_chars(0x45,0x00,0x00,0x30,0x44,0x22,0x40,0x00,0x80,0x06,
827 0x00,0x00,0x8c,0x7c,0x19,0xac,0xae,0x24,0x1e,0x2b);
828
829 sum = chunk_internet_checksum(chunk);
830 ck_assert_int_eq(0x442e, ntohs(sum));
831
832 sum = chunk_internet_checksum(chunk_create(chunk.ptr, 10));
833 sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+10, 10), sum);
834 ck_assert_int_eq(0x442e, ntohs(sum));
835
836 /* need to compensate for even/odd alignment */
837 sum = chunk_internet_checksum(chunk_create(chunk.ptr, 9));
838 sum = compensate_alignment(sum);
839 sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+9, 11), sum);
840 sum = compensate_alignment(sum);
841 ck_assert_int_eq(0x442e, ntohs(sum));
842
843 chunk = chunk_from_chars(0x45,0x00,0x00,0x30,0x44,0x22,0x40,0x00,0x80,0x06,
844 0x00,0x00,0x8c,0x7c,0x19,0xac,0xae,0x24,0x1e);
845
846 sum = chunk_internet_checksum(chunk);
847 ck_assert_int_eq(0x4459, ntohs(sum));
848
849 sum = chunk_internet_checksum(chunk_create(chunk.ptr, 10));
850 sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+10, 9), sum);
851 ck_assert_int_eq(0x4459, ntohs(sum));
852
853 /* need to compensate for even/odd alignment */
854 sum = chunk_internet_checksum(chunk_create(chunk.ptr, 9));
855 sum = compensate_alignment(sum);
856 sum = chunk_internet_checksum_inc(chunk_create(chunk.ptr+9, 10), sum);
857 sum = compensate_alignment(sum);
858 ck_assert_int_eq(0x4459, ntohs(sum));
859 }
860 END_TEST
861
862 /*******************************************************************************
863 * test for chunk_map and friends
864 */
865
866 START_TEST(test_chunk_map)
867 {
868 chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05);
869 #ifdef WIN32
870 char *path = "C:\\Windows\\Temp\\strongswan-chunk-map-test";
871 #else
872 char *path = "/tmp/strongswan-chunk-map-test";
873 #endif
874
875 ck_assert(chunk_write(contents, path, 022, TRUE));
876
877 /* read */
878 map = chunk_map(path, FALSE);
879 ck_assert(map != NULL);
880 ck_assert_msg(chunk_equals(*map, contents), "%B", map);
881 /* altering mapped chunk should not hurt */
882 *map = chunk_empty;
883 ck_assert(chunk_unmap(map));
884
885 /* write */
886 map = chunk_map(path, TRUE);
887 ck_assert(map != NULL);
888 ck_assert_msg(chunk_equals(*map, contents), "%B", map);
889 map->ptr[0] = 0x06;
890 ck_assert(chunk_unmap(map));
891
892 /* verify write */
893 contents.ptr[0] = 0x06;
894 map = chunk_map(path, FALSE);
895 ck_assert(map != NULL);
896 ck_assert_msg(chunk_equals(*map, contents), "%B", map);
897 ck_assert(chunk_unmap(map));
898
899 unlink(path);
900 }
901 END_TEST
902
903 /*******************************************************************************
904 * test for chunk_from_fd
905 */
906
907 START_TEST(test_chunk_from_fd_file)
908 {
909 chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05);
910 #ifdef WIN32
911 char *path = "C:\\Windows\\Temp\\strongswan-chunk-fd-test";
912 #else
913 char *path = "/tmp/strongswan-chunk-fd-test";
914 #endif
915 int fd;
916
917 ck_assert(chunk_write(contents, path, 022, TRUE));
918
919 fd = open(path, O_RDONLY);
920 ck_assert(fd != -1);
921
922 ck_assert(chunk_from_fd(fd, &in));
923 close(fd);
924 ck_assert_msg(chunk_equals(in, contents), "%B", &in);
925 unlink(path);
926 free(in.ptr);
927 }
928 END_TEST
929
930 START_TEST(test_chunk_from_fd_skt)
931 {
932 chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05);
933 int s[2];
934
935 ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
936 ck_assert_int_eq(send(s[1], contents.ptr, contents.len, 0), contents.len);
937 close(s[1]);
938 ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno));
939 close(s[0]);
940 ck_assert_msg(chunk_equals(in, contents), "%B", &in);
941 free(in.ptr);
942 }
943 END_TEST
944
945 #define FROM_FD_COUNT 8192
946
947 void *chunk_from_fd_run(void *data)
948 {
949 int i, fd = (uintptr_t)data;
950
951 for (i = 0; i < FROM_FD_COUNT; i++)
952 {
953 ck_assert(send(fd, &i, sizeof(i), 0) == sizeof(i));
954 }
955 close(fd);
956 return NULL;
957 }
958
959 START_TEST(test_chunk_from_fd_huge)
960 {
961 thread_t *thread;
962 chunk_t in;
963 int s[2], i;
964
965 ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
966
967 thread = thread_create(chunk_from_fd_run, (void*)(uintptr_t)s[1]);
968 ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno));
969 ck_assert_int_eq(in.len, FROM_FD_COUNT * sizeof(i));
970 for (i = 0; i < FROM_FD_COUNT; i++)
971 {
972 ck_assert_int_eq(((int*)in.ptr)[i], i);
973 }
974 thread->join(thread);
975 close(s[0]);
976 free(in.ptr);
977 }
978 END_TEST
979
980 /*******************************************************************************
981 * printf_hook tests
982 */
983
984 static struct {
985 chunk_t in;
986 char *out;
987 char *out_plus;
988 } printf_hook_data[] = {
989 {chunk_from_chars(), "", ""},
990 {chunk_from_chars(0x00), "00", "00"},
991 {chunk_from_chars(0x00, 0x01), "00:01", "0001"},
992 {chunk_from_chars(0x00, 0x01, 0x02), "00:01:02", "000102"},
993 };
994
995 START_TEST(test_printf_hook_hash)
996 {
997 char buf[16];
998 int len;
999
1000 len = snprintf(buf, sizeof(buf), "%#B", &printf_hook_data[_i].in);
1001 ck_assert(len >= 0 && len < sizeof(buf));
1002 ck_assert_str_eq(buf, printf_hook_data[_i].out);
1003 }
1004 END_TEST
1005
1006 START_TEST(test_printf_hook_plus)
1007 {
1008 char buf[16];
1009 int len;
1010
1011 len = snprintf(buf, sizeof(buf), "%+B", &printf_hook_data[_i].in);
1012 ck_assert(len >= 0 && len < sizeof(buf));
1013 ck_assert_str_eq(buf, printf_hook_data[_i].out_plus);
1014 }
1015 END_TEST
1016
1017 START_TEST(test_printf_hook)
1018 {
1019 char buf[128], mem[128];
1020 int len;
1021
1022 /* %B should be the same as %b, which is what we check, comparing the
1023 * acutal result could be tricky as %b prints the chunk's memory address */
1024 len = snprintf(buf, sizeof(buf), "%B", &printf_hook_data[_i].in);
1025 ck_assert(len >= 0 && len < sizeof(buf));
1026 len = snprintf(mem, sizeof(mem), "%b", printf_hook_data[_i].in.ptr,
1027 (u_int)printf_hook_data[_i].in.len);
1028 ck_assert(len >= 0 && len < sizeof(mem));
1029 ck_assert_str_eq(buf, mem);
1030 }
1031 END_TEST
1032
1033 Suite *chunk_suite_create()
1034 {
1035 Suite *s;
1036 TCase *tc;
1037
1038 s = suite_create("chunk");
1039
1040 tc = tcase_create("equals");
1041 tcase_add_test(tc, test_chunk_equals);
1042 tcase_add_test(tc, test_chunk_equals_const);
1043 suite_add_tcase(s, tc);
1044
1045 tc = tcase_create("chunk_compare");
1046 tcase_add_loop_test(tc, test_compare, 0, countof(compare_data));
1047 suite_add_tcase(s, tc);
1048
1049 tc = tcase_create("clear");
1050 tcase_add_test(tc, test_chunk_clear);
1051 suite_add_tcase(s, tc);
1052
1053 tc = tcase_create("chunk_length");
1054 tcase_add_test(tc, test_chunk_length);
1055 suite_add_tcase(s, tc);
1056
1057 tc = tcase_create("chunk_create_cat");
1058 tcase_add_test(tc, test_chunk_create_cat);
1059 suite_add_tcase(s, tc);
1060
1061 tc = tcase_create("chunk_split");
1062 tcase_add_test(tc, test_chunk_split);
1063 suite_add_tcase(s, tc);
1064
1065 tc = tcase_create("chunk_skip");
1066 tcase_add_test(tc, test_chunk_skip);
1067 tcase_add_test(tc, test_chunk_skip_zero);
1068 suite_add_tcase(s, tc);
1069
1070 tc = tcase_create("chunk_increment");
1071 tcase_add_loop_test(tc, test_increment, 0, countof(increment_data));
1072 suite_add_tcase(s, tc);
1073
1074 tc = tcase_create("chunk_printable");
1075 tcase_add_loop_test(tc, test_printable, 0, countof(printable_data));
1076 tcase_add_loop_test(tc, test_printable_sanitize, 0, countof(printable_data));
1077 tcase_add_test(tc, test_printable_empty);
1078 suite_add_tcase(s, tc);
1079
1080 tc = tcase_create("baseXX");
1081 tcase_add_test(tc, test_base64);
1082 tcase_add_test(tc, test_base32);
1083 tcase_add_test(tc, test_base16);
1084 suite_add_tcase(s, tc);
1085
1086 tc = tcase_create("chunk_mac");
1087 tcase_add_test(tc, test_chunk_mac);
1088 suite_add_tcase(s, tc);
1089
1090 tc = tcase_create("chunk_hash");
1091 tcase_add_test(tc, test_chunk_hash);
1092 suite_add_tcase(s, tc);
1093
1094 tc = tcase_create("chunk_hash_static");
1095 tcase_add_test(tc, test_chunk_hash_static);
1096 suite_add_tcase(s, tc);
1097
1098 tc = tcase_create("chunk_internet_checksum");
1099 tcase_add_test(tc, test_chunk_internet_checksum);
1100 suite_add_tcase(s, tc);
1101
1102 tc = tcase_create("chunk_map");
1103 tcase_add_test(tc, test_chunk_map);
1104 suite_add_tcase(s, tc);
1105
1106 tc = tcase_create("chunk_from_fd");
1107 tcase_add_test(tc, test_chunk_from_fd_file);
1108 tcase_add_test(tc, test_chunk_from_fd_skt);
1109 tcase_add_test(tc, test_chunk_from_fd_huge);
1110 suite_add_tcase(s, tc);
1111
1112 tc = tcase_create("printf_hook");
1113 tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data));
1114 tcase_add_loop_test(tc, test_printf_hook_plus, 0, countof(printf_hook_data));
1115 tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_hook_data));
1116 suite_add_tcase(s, tc);
1117
1118 return s;
1119 }