1/*	$NetBSD: check-der.c,v 1.3 2023/06/19 21:41:42 christos Exp $	*/
2
3/*
4 * Copyright (c) 1999 - 2007 Kungliga Tekniska H��gskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * 3. Neither the name of the Institute nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include "der_locl.h"
39#include <err.h>
40#include <krb5/roken.h>
41
42#include <krb5/asn1-common.h>
43#include <krb5/asn1_err.h>
44#include <krb5/der.h>
45
46#include "check-common.h"
47
48__RCSID("$NetBSD: check-der.c,v 1.3 2023/06/19 21:41:42 christos Exp $");
49
50static int
51cmp_integer (void *a, void *b)
52{
53    int *ia = (int *)a;
54    int *ib = (int *)b;
55
56    return *ib - *ia;
57}
58
59static int
60test_integer (void)
61{
62    struct test_case tests[] = {
63	{NULL, 1, "\x00", 		NULL },
64	{NULL, 1, "\x7f", 		NULL },
65	{NULL, 2, "\x00\x80", 		NULL },
66	{NULL, 2, "\x01\x00", 		NULL },
67	{NULL, 1, "\x80", 		NULL },
68	{NULL, 2, "\xff\x7f", 		NULL },
69	{NULL, 1, "\xff", 		NULL },
70	{NULL, 2, "\xff\x01", 		NULL },
71	{NULL, 2, "\x00\xff", 		NULL },
72	{NULL, 2, "\xfe\x01", 		NULL },
73	{NULL, 4, "\x7f\xff\xff\xff", 	NULL }
74    };
75
76    int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
77		    -511, 0x7fffffff};
78    int i, ret;
79    int ntests = sizeof(tests) / sizeof(*tests);
80
81    for (i = 0; i < ntests; ++i) {
82	tests[i].val = &values[i];
83	if (asprintf (&tests[i].name, "integer %d", values[i]) < 0)
84	    errx(1, "malloc");
85	if (tests[i].name == NULL)
86	    errx(1, "malloc");
87    }
88
89    ret = generic_test (tests, ntests, sizeof(int),
90			(generic_encode)der_put_integer,
91			(generic_length) der_length_integer,
92			(generic_decode)der_get_integer,
93			(generic_free)NULL,
94			cmp_integer,
95			NULL);
96
97    for (i = 0; i < ntests; ++i)
98	free (tests[i].name);
99    return ret;
100}
101
102static int
103test_one_int(int val)
104{
105    int ret, dval;
106    unsigned char *buf;
107    size_t len_len, len;
108
109    len = _heim_len_int(val);
110
111    buf = emalloc(len + 2);
112
113    buf[0] = '\xff';
114    buf[len + 1] = '\xff';
115    memset(buf + 1, 0, len);
116
117    ret = der_put_integer(buf + 1 + len - 1, len, &val, &len_len);
118    if (ret) {
119	printf("integer %d encode failed %d\n", val, ret);
120	return 1;
121    }
122    if (len != len_len) {
123	printf("integer %d encode fail with %d len %lu, result len %lu\n",
124	       val, ret, (unsigned long)len, (unsigned long)len_len);
125	return 1;
126    }
127
128    ret = der_get_integer(buf + 1, len, &dval, &len_len);
129    if (ret) {
130	printf("integer %d decode failed %d\n", val, ret);
131	return 1;
132    }
133    if (len != len_len) {
134	printf("integer %d decoded diffrent len %lu != %lu",
135	       val, (unsigned long)len, (unsigned long)len_len);
136	return 1;
137    }
138    if (val != dval) {
139	printf("decode decoded to diffrent value %d != %d",
140	       val, dval);
141	return 1;
142    }
143
144    if (buf[0] != (unsigned char)'\xff') {
145	printf("precanary dead %d\n", val);
146	return 1;
147    }
148    if (buf[len + 1] != (unsigned char)'\xff') {
149	printf("postecanary dead %d\n", val);
150	return 1;
151    }
152    free(buf);
153    return 0;
154}
155
156static int
157test_integer_more (void)
158{
159    int64_t i, n1, n2, n3, n4, n5, n6;
160
161    n2 = 0;
162    for (i = 0; i < (sizeof(int) * 8); i++) {
163	n1 = 0x01LL << i;
164	n2 = n2 | n1;
165	n3 = ~n1;
166	n4 = ~n2;
167	n5 = (-1LL) & ~(0x3fLL << i);
168	n6 = (-1LL) & ~(0x7fLL << i);
169
170	test_one_int(n1);
171	test_one_int(n2);
172	test_one_int(n3);
173	test_one_int(n4);
174	test_one_int(n5);
175	test_one_int(n6);
176    }
177    return 0;
178}
179
180static int
181cmp_unsigned (void *a, void *b)
182{
183    return *(unsigned int*)b - *(unsigned int*)a;
184}
185
186static int
187test_unsigned (void)
188{
189    struct test_case tests[] = {
190	{NULL, 1, "\x00", 			NULL },
191	{NULL, 1, "\x7f", 			NULL },
192	{NULL, 2, "\x00\x80", 			NULL },
193	{NULL, 2, "\x01\x00", 			NULL },
194	{NULL, 2, "\x02\x00", 			NULL },
195	{NULL, 3, "\x00\x80\x00", 		NULL },
196	{NULL, 5, "\x00\x80\x00\x00\x00",	NULL },
197	{NULL, 4, "\x7f\xff\xff\xff", 		NULL }
198    };
199
200    unsigned int values[] = {0, 127, 128, 256, 512, 32768,
201			     0x80000000, 0x7fffffff};
202    int i, ret;
203    int ntests = sizeof(tests) / sizeof(*tests);
204
205    for (i = 0; i < ntests; ++i) {
206	tests[i].val = &values[i];
207	if (asprintf (&tests[i].name, "unsigned %u", values[i]) < 0)
208	    errx(1, "malloc");
209	if (tests[i].name == NULL)
210	    errx(1, "malloc");
211    }
212
213    ret = generic_test (tests, ntests, sizeof(int),
214			(generic_encode)der_put_unsigned,
215			(generic_length)der_length_unsigned,
216			(generic_decode)der_get_unsigned,
217			(generic_free)NULL,
218			cmp_unsigned,
219			NULL);
220    for (i = 0; i < ntests; ++i)
221	free (tests[i].name);
222    return ret;
223}
224
225static int
226cmp_octet_string (void *a, void *b)
227{
228    return der_heim_octet_string_cmp(a, b);
229}
230
231static int
232test_octet_string (void)
233{
234    heim_octet_string s1 = {8, "\x01\x23\x45\x67\x89\xab\xcd\xef"};
235
236    struct test_case tests[] = {
237	{NULL, 8, "\x01\x23\x45\x67\x89\xab\xcd\xef", NULL }
238    };
239    int ntests = sizeof(tests) / sizeof(*tests);
240    int ret;
241
242    tests[0].val = &s1;
243    if (asprintf (&tests[0].name, "a octet string") < 0)
244	errx(1, "malloc");
245    if (tests[0].name == NULL)
246	errx(1, "malloc");
247
248    ret = generic_test (tests, ntests, sizeof(heim_octet_string),
249			(generic_encode)der_put_octet_string,
250			(generic_length)der_length_octet_string,
251			(generic_decode)der_get_octet_string,
252			(generic_free)der_free_octet_string,
253			cmp_octet_string,
254			NULL);
255    free(tests[0].name);
256    return ret;
257}
258
259static int
260cmp_bmp_string (void *a, void *b)
261{
262    heim_bmp_string *oa = (heim_bmp_string *)a;
263    heim_bmp_string *ob = (heim_bmp_string *)b;
264
265    return der_heim_bmp_string_cmp(oa, ob);
266}
267
268static uint16_t bmp_d1[] = { 32 };
269static uint16_t bmp_d2[] = { 32, 32 };
270
271static int
272test_bmp_string (void)
273{
274    heim_bmp_string s1 = { 1, bmp_d1 };
275    heim_bmp_string s2 = { 2, bmp_d2 };
276
277    struct test_case tests[] = {
278	{NULL, 2, "\x00\x20", 		NULL },
279	{NULL, 4, "\x00\x20\x00\x20", 	NULL }
280    };
281    int ntests = sizeof(tests) / sizeof(*tests);
282    int ret;
283
284    tests[0].val = &s1;
285    if (asprintf (&tests[0].name, "a bmp string") < 0)
286	errx(1, "malloc");
287    if (tests[0].name == NULL)
288	errx(1, "malloc");
289    tests[1].val = &s2;
290    if (asprintf (&tests[1].name, "second bmp string") < 0)
291	errx(1, "malloc");
292    if (tests[1].name == NULL)
293	errx(1, "malloc");
294
295    ret = generic_test (tests, ntests, sizeof(heim_bmp_string),
296			(generic_encode)der_put_bmp_string,
297			(generic_length)der_length_bmp_string,
298			(generic_decode)der_get_bmp_string,
299			(generic_free)der_free_bmp_string,
300			cmp_bmp_string,
301			NULL);
302    free(tests[0].name);
303    free(tests[1].name);
304    return ret;
305}
306
307static int
308cmp_universal_string (void *a, void *b)
309{
310    heim_universal_string *oa = (heim_universal_string *)a;
311    heim_universal_string *ob = (heim_universal_string *)b;
312
313    return der_heim_universal_string_cmp(oa, ob);
314}
315
316static uint32_t universal_d1[] = { 32 };
317static uint32_t universal_d2[] = { 32, 32 };
318
319static int
320test_universal_string (void)
321{
322    heim_universal_string s1 = { 1, universal_d1 };
323    heim_universal_string s2 = { 2, universal_d2 };
324
325    struct test_case tests[] = {
326	{NULL, 4, "\x00\x00\x00\x20", 			NULL },
327	{NULL, 8, "\x00\x00\x00\x20\x00\x00\x00\x20", 	NULL }
328    };
329    int ntests = sizeof(tests) / sizeof(*tests);
330    int ret;
331
332    tests[0].val = &s1;
333    if (asprintf (&tests[0].name, "a universal string") < 0)
334	errx(1, "malloc");
335    if (tests[0].name == NULL)
336	errx(1, "malloc");
337    tests[1].val = &s2;
338    if (asprintf (&tests[1].name, "second universal string") < 0)
339	errx(1, "malloc");
340    if (tests[1].name == NULL)
341	errx(1, "malloc");
342
343    ret = generic_test (tests, ntests, sizeof(heim_universal_string),
344			(generic_encode)der_put_universal_string,
345			(generic_length)der_length_universal_string,
346			(generic_decode)der_get_universal_string,
347			(generic_free)der_free_universal_string,
348			cmp_universal_string,
349			NULL);
350    free(tests[0].name);
351    free(tests[1].name);
352    return ret;
353}
354
355static int
356cmp_general_string (void *a, void *b)
357{
358    char **sa = (char **)a;
359    char **sb = (char **)b;
360
361    return strcmp (*sa, *sb);
362}
363
364static int
365test_general_string (void)
366{
367    char *s1 = "Test User 1";
368
369    struct test_case tests[] = {
370	{NULL, 11, "\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31", NULL }
371    };
372    int ret, ntests = sizeof(tests) / sizeof(*tests);
373
374    tests[0].val = &s1;
375    if (asprintf (&tests[0].name, "the string \"%s\"", s1) < 0)
376	errx(1, "malloc");
377    if (tests[0].name == NULL)
378	errx(1, "malloc");
379
380    ret = generic_test (tests, ntests, sizeof(unsigned char *),
381			(generic_encode)der_put_general_string,
382			(generic_length)der_length_general_string,
383			(generic_decode)der_get_general_string,
384			(generic_free)der_free_general_string,
385			cmp_general_string,
386			NULL);
387    free(tests[0].name);
388    return ret;
389}
390
391static int
392cmp_generalized_time (void *a, void *b)
393{
394    time_t *ta = (time_t *)a;
395    time_t *tb = (time_t *)b;
396
397    return (int)(*tb - *ta);
398}
399
400static int
401test_generalized_time (void)
402{
403    struct test_case tests[] = {
404	{NULL, 15, "19700101000000Z", 		NULL },
405	{NULL, 15, "19851106210627Z", 		NULL }
406    };
407    time_t values[] = {0, 500159187};
408    int i, ret;
409    int ntests = sizeof(tests) / sizeof(*tests);
410
411    for (i = 0; i < ntests; ++i) {
412	tests[i].val = &values[i];
413	if (asprintf (&tests[i].name, "time %d", (int)values[i]) < 0)
414	    errx(1, "malloc");
415	if (tests[i].name == NULL)
416	    errx(1, "malloc");
417    }
418
419    ret = generic_test (tests, ntests, sizeof(time_t),
420			(generic_encode)der_put_generalized_time,
421			(generic_length)der_length_generalized_time,
422			(generic_decode)der_get_generalized_time,
423			(generic_free)NULL,
424			cmp_generalized_time,
425			NULL);
426    for (i = 0; i < ntests; ++i)
427	free(tests[i].name);
428    return ret;
429}
430
431static int
432test_cmp_oid (void *a, void *b)
433{
434    return der_heim_oid_cmp((heim_oid *)a, (heim_oid *)b);
435}
436
437static unsigned oid_comp1[] = { 1, 1, 1 };
438static unsigned oid_comp2[] = { 1, 1 };
439static unsigned oid_comp3[] = { 6, 15, 1 };
440static unsigned oid_comp4[] = { 6, 15 };
441
442static int
443test_oid (void)
444{
445    struct test_case tests[] = {
446	{NULL, 2, "\x29\x01", 		NULL },
447	{NULL, 1, "\x29", 		NULL },
448	{NULL, 2, "\xff\x01", 		NULL },
449	{NULL, 1, "\xff", 		NULL }
450    };
451    heim_oid values[] = {
452	{ 3, oid_comp1 },
453	{ 2, oid_comp2 },
454	{ 3, oid_comp3 },
455	{ 2, oid_comp4 }
456    };
457    int i, ret;
458    int ntests = sizeof(tests) / sizeof(*tests);
459
460    for (i = 0; i < ntests; ++i) {
461	tests[i].val = &values[i];
462	if (asprintf (&tests[i].name, "oid %d", i) < 0)
463	    errx(1, "malloc");
464	if (tests[i].name == NULL)
465	    errx(1, "malloc");
466    }
467
468    ret = generic_test (tests, ntests, sizeof(heim_oid),
469			(generic_encode)der_put_oid,
470			(generic_length)der_length_oid,
471			(generic_decode)der_get_oid,
472			(generic_free)der_free_oid,
473			test_cmp_oid,
474			NULL);
475    for (i = 0; i < ntests; ++i)
476	free(tests[i].name);
477    return ret;
478}
479
480static int
481test_cmp_bit_string (void *a, void *b)
482{
483    return der_heim_bit_string_cmp((heim_bit_string *)a, (heim_bit_string *)b);
484}
485
486static int
487test_bit_string (void)
488{
489    struct test_case tests[] = {
490	{NULL, 1, "\x00", 		NULL }
491    };
492    heim_bit_string values[] = {
493	{ 0, "" }
494    };
495    int i, ret;
496    int ntests = sizeof(tests) / sizeof(*tests);
497
498    for (i = 0; i < ntests; ++i) {
499	tests[i].val = &values[i];
500	if (asprintf (&tests[i].name, "bit_string %d", i) < 0)
501	    errx(1, "malloc");
502	if (tests[i].name == NULL)
503	    errx(1, "malloc");
504    }
505
506    ret = generic_test (tests, ntests, sizeof(heim_bit_string),
507			(generic_encode)der_put_bit_string,
508			(generic_length)der_length_bit_string,
509			(generic_decode)der_get_bit_string,
510			(generic_free)der_free_bit_string,
511			test_cmp_bit_string,
512			NULL);
513    for (i = 0; i < ntests; ++i)
514	free(tests[i].name);
515    return ret;
516}
517
518static int
519test_cmp_heim_integer (void *a, void *b)
520{
521    return der_heim_integer_cmp((heim_integer *)a, (heim_integer *)b);
522}
523
524static int
525test_heim_integer (void)
526{
527    struct test_case tests[] = {
528	{NULL, 1, "\xff", 		NULL },
529	{NULL, 2, "\xff\x01", 		NULL },
530	{NULL, 2, "\xfe\x01", 		NULL },
531	{NULL, 2, "\xef\x01", 		NULL },
532	{NULL, 3, "\xff\x00\xff", 	NULL },
533	{NULL, 3, "\xff\x01\x00", 	NULL },
534	{NULL, 1, "\x00", 		NULL },
535	{NULL, 1, "\x01", 		NULL },
536	{NULL, 2, "\x00\x80", 		NULL },
537    };
538
539    heim_integer values[] = {
540	{ 1, "\x01", 1 },
541	{ 1, "\xff", 1 },
542	{ 2, "\x01\xff", 1 },
543	{ 2, "\x10\xff", 1 },
544	{ 2, "\xff\x01", 1 },
545	{ 2, "\xff\x00", 1 },
546	{ 0, "", 0 },
547	{ 1, "\x01", 0 },
548	{ 1, "\x80", 0 },
549    };
550    int i, ret;
551    int ntests = sizeof(tests) / sizeof(tests[0]);
552    size_t size;
553    heim_integer i2;
554
555    for (i = 0; i < ntests; ++i) {
556	tests[i].val = &values[i];
557	if (asprintf (&tests[i].name, "heim_integer %d", i) < 0)
558	    errx(1, "malloc");
559	if (tests[i].name == NULL)
560	    errx(1, "malloc");
561    }
562
563    ret = generic_test (tests, ntests, sizeof(heim_integer),
564			(generic_encode)der_put_heim_integer,
565			(generic_length)der_length_heim_integer,
566			(generic_decode)der_get_heim_integer,
567			(generic_free)der_free_heim_integer,
568			test_cmp_heim_integer,
569			NULL);
570    for (i = 0; i < ntests; ++i)
571	free (tests[i].name);
572    if (ret)
573	return ret;
574
575    /* test zero length integer (BER format) */
576    ret = der_get_heim_integer(NULL, 0, &i2, &size);
577    if (ret)
578	errx(1, "der_get_heim_integer");
579    if (i2.length != 0)
580	errx(1, "der_get_heim_integer wrong length");
581    der_free_heim_integer(&i2);
582
583    return 0;
584}
585
586static int
587test_cmp_boolean (void *a, void *b)
588{
589    return !!*(int *)a != !!*(int *)b;
590}
591
592static int
593test_boolean (void)
594{
595    struct test_case tests[] = {
596	{NULL, 1, "\xff", 		NULL },
597	{NULL, 1, "\x00", 		NULL }
598    };
599
600    int values[] = { 1, 0 };
601    int i, ret;
602    int ntests = sizeof(tests) / sizeof(tests[0]);
603    size_t size;
604    heim_integer i2;
605
606    for (i = 0; i < ntests; ++i) {
607	tests[i].val = &values[i];
608	if (asprintf (&tests[i].name, "heim_boolean %d", i) < 0)
609	    errx(1, "malloc");
610	if (tests[i].name == NULL)
611	    errx(1, "malloc");
612    }
613
614    ret = generic_test (tests, ntests, sizeof(int),
615			(generic_encode)der_put_boolean,
616			(generic_length)der_length_boolean,
617			(generic_decode)der_get_boolean,
618			(generic_free)NULL,
619			test_cmp_boolean,
620			NULL);
621    for (i = 0; i < ntests; ++i)
622	free (tests[i].name);
623    if (ret)
624	return ret;
625
626    /* test zero length integer (BER format) */
627    ret = der_get_heim_integer(NULL, 0, &i2, &size);
628    if (ret)
629	errx(1, "der_get_heim_integer");
630    if (i2.length != 0)
631	errx(1, "der_get_heim_integer wrong length");
632    der_free_heim_integer(&i2);
633
634    return 0;
635}
636
637static int
638check_fail_unsigned(void)
639{
640    struct test_case tests[] = {
641	{NULL, sizeof(unsigned) + 1,
642	 "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" }
643    };
644    int ntests = sizeof(tests) / sizeof(*tests);
645
646    return generic_decode_fail(tests, ntests, sizeof(unsigned),
647			       (generic_decode)der_get_unsigned);
648}
649
650static int
651check_fail_integer(void)
652{
653    struct test_case tests[] = {
654	{NULL, sizeof(int) + 1,
655	 "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" }
656    };
657    int ntests = sizeof(tests) / sizeof(*tests);
658
659    return generic_decode_fail(tests, ntests, sizeof(int),
660			       (generic_decode)der_get_integer);
661}
662
663static int
664check_fail_length(void)
665{
666    struct test_case tests[] = {
667	{NULL, 0, "", "empty input data"},
668	{NULL, 1, "\x82", "internal length overrun" }
669    };
670    int ntests = sizeof(tests) / sizeof(*tests);
671
672    return generic_decode_fail(tests, ntests, sizeof(size_t),
673			       (generic_decode)der_get_length);
674}
675
676static int
677check_fail_boolean(void)
678{
679    struct test_case tests[] = {
680	{NULL, 0, "", "empty input data"}
681    };
682    int ntests = sizeof(tests) / sizeof(*tests);
683
684    return generic_decode_fail(tests, ntests, sizeof(int),
685			       (generic_decode)der_get_boolean);
686}
687
688static int
689check_fail_general_string(void)
690{
691    struct test_case tests[] = {
692	{ NULL, 3, "A\x00i", "NUL char in string"}
693    };
694    int ntests = sizeof(tests) / sizeof(*tests);
695
696    return generic_decode_fail(tests, ntests, sizeof(heim_general_string),
697			       (generic_decode)der_get_general_string);
698}
699
700static int
701check_fail_bmp_string(void)
702{
703    struct test_case tests[] = {
704	{NULL, 1, "\x00", "odd (1) length bmpstring"},
705	{NULL, 3, "\x00\x00\x00", "odd (3) length bmpstring"}
706    };
707    int ntests = sizeof(tests) / sizeof(*tests);
708
709    return generic_decode_fail(tests, ntests, sizeof(heim_bmp_string),
710			       (generic_decode)der_get_bmp_string);
711}
712
713static int
714check_fail_universal_string(void)
715{
716    struct test_case tests[] = {
717	{NULL, 1, "\x00", "x & 3 == 1 universal string"},
718	{NULL, 2, "\x00\x00", "x & 3 == 2 universal string"},
719	{NULL, 3, "\x00\x00\x00", "x & 3 == 3 universal string"},
720	{NULL, 5, "\x00\x00\x00\x00\x00", "x & 3 == 1 universal string"},
721	{NULL, 6, "\x00\x00\x00\x00\x00\x00", "x & 3 == 2 universal string"},
722	{NULL, 7, "\x00\x00\x00\x00\x00\x00\x00", "x & 3 == 3 universal string"}
723    };
724    int ntests = sizeof(tests) / sizeof(*tests);
725
726    return generic_decode_fail(tests, ntests, sizeof(heim_universal_string),
727			       (generic_decode)der_get_universal_string);
728}
729
730static int
731check_fail_heim_integer(void)
732{
733#if 0
734    struct test_case tests[] = {
735    };
736    int ntests = sizeof(tests) / sizeof(*tests);
737
738    return generic_decode_fail(tests, ntests, sizeof(heim_integer),
739			       (generic_decode)der_get_heim_integer);
740#else
741    return 0;
742#endif
743}
744
745static int
746check_fail_generalized_time(void)
747{
748    struct test_case tests[] = {
749	{NULL, 1, "\x00", "no time"}
750    };
751    int ntests = sizeof(tests) / sizeof(*tests);
752
753    return generic_decode_fail(tests, ntests, sizeof(time_t),
754			       (generic_decode)der_get_generalized_time);
755}
756
757static int
758check_fail_oid(void)
759{
760    struct test_case tests[] = {
761	{NULL, 0, "", "empty input data"},
762	{NULL, 2, "\x00\x80", "last byte continuation" },
763	{NULL, 11, "\x00\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00",
764	"oid element overflow" }
765    };
766    int ntests = sizeof(tests) / sizeof(*tests);
767
768    return generic_decode_fail(tests, ntests, sizeof(heim_oid),
769			       (generic_decode)der_get_oid);
770}
771
772static int
773check_fail_bitstring(void)
774{
775    struct test_case tests[] = {
776	{NULL, 0, "", "empty input data"},
777	{NULL, 1, "\x08", "larger then 8 bits trailer"},
778	{NULL, 1, "\x01", "to few bytes for bits"},
779	{NULL, -2, "\x00", "length overrun"},
780	{NULL, -1, "", "length to short"}
781    };
782    int ntests = sizeof(tests) / sizeof(*tests);
783
784    return generic_decode_fail(tests, ntests, sizeof(heim_bit_string),
785			       (generic_decode)der_get_bit_string);
786}
787
788static int
789check_heim_integer_same(const char *p, const char *norm_p, heim_integer *i)
790{
791    heim_integer i2;
792    char *str;
793    int ret;
794
795    ret = der_print_hex_heim_integer(i, &str);
796    if (ret)
797	errx(1, "der_print_hex_heim_integer: %d", ret);
798
799    if (strcmp(str, norm_p) != 0)
800	errx(1, "der_print_hex_heim_integer: %s != %s", str, p);
801
802    ret = der_parse_hex_heim_integer(str, &i2);
803    if (ret)
804	errx(1, "der_parse_hex_heim_integer: %d", ret);
805
806    if (der_heim_integer_cmp(i, &i2) != 0)
807	errx(1, "der_heim_integer_cmp: p %s", p);
808
809    der_free_heim_integer(&i2);
810    free(str);
811
812    ret = der_parse_hex_heim_integer(p, &i2);
813    if (ret)
814	errx(1, "der_parse_hex_heim_integer: %d", ret);
815
816    if (der_heim_integer_cmp(i, &i2) != 0)
817	errx(1, "der_heim_integer_cmp: norm");
818
819    der_free_heim_integer(&i2);
820
821    return 0;
822}
823
824static int
825test_heim_int_format(void)
826{
827    heim_integer i = { 1, "\x10", 0 };
828    heim_integer i2 = { 1, "\x10", 1 };
829    heim_integer i3 = { 1, "\01", 0 };
830    char *p =
831	"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
832	"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
833	"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
834	"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
835	"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
836	"FFFFFFFF" "FFFFFFFF";
837    heim_integer bni = {
838	128,
839	"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2"
840	"\x21\x68\xC2\x34\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1"
841	"\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE\xA6"
842	"\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD"
843	"\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D"
844	"\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2\x45"
845	"\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9"
846	"\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED"
847	"\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11"
848	"\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE6\x53\x81"
849	"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
850	0
851    };
852    heim_integer f;
853    int ret = 0;
854
855    ret += check_heim_integer_same(p, p, &bni);
856    ret += check_heim_integer_same("10", "10", &i);
857    ret += check_heim_integer_same("00000010", "10", &i);
858    ret += check_heim_integer_same("-10", "-10", &i2);
859    ret += check_heim_integer_same("-00000010", "-10", &i2);
860    ret += check_heim_integer_same("01", "01", &i3);
861    ret += check_heim_integer_same("1", "01", &i3);
862
863    {
864	int r;
865	r = der_parse_hex_heim_integer("-", &f);
866	if (r == 0) {
867	    der_free_heim_integer(&f);
868	    ret++;
869	}
870	/* used to cause UMR */
871	r = der_parse_hex_heim_integer("00", &f);
872	if (r == 0)
873	    der_free_heim_integer(&f);
874	else
875	    ret++;
876    }
877
878    return ret;
879}
880
881static int
882test_heim_oid_format_same(const char *str, const heim_oid *oid)
883{
884    int ret;
885    char *p;
886    heim_oid o2;
887
888    ret = der_print_heim_oid(oid, ' ', &p);
889    if (ret) {
890	printf("fail to print oid: %s\n", str);
891	return 1;
892    }
893    ret = strcmp(p, str);
894    if (ret) {
895	printf("oid %s != formated oid %s\n", str, p);
896	free(p);
897	return ret;
898    }
899
900    ret = der_parse_heim_oid(p, " ", &o2);
901    if (ret) {
902	printf("failed to parse %s\n", p);
903	free(p);
904	return ret;
905    }
906    free(p);
907    ret = der_heim_oid_cmp(&o2, oid);
908    der_free_oid(&o2);
909
910    return ret;
911}
912
913static unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
914
915static int
916test_heim_oid_format(void)
917{
918    heim_oid sha1 = { 6, sha1_oid_tree };
919    int ret = 0;
920
921    ret += test_heim_oid_format_same("1 3 14 3 2 26", &sha1);
922
923    return ret;
924}
925
926static int
927check_trailing_nul(void)
928{
929    int i, ret;
930    struct {
931	int fail;
932	const unsigned char *p;
933	size_t len;
934	const char *s;
935	size_t size;
936    } foo[] = {
937	{ 1, (const unsigned char *)"foo\x00o", 5, NULL, 0 },
938	{ 1, (const unsigned char *)"\x00o", 2, NULL, 0 },
939	{ 0, (const unsigned char *)"\x00\x00\x00\x00\x00", 5, "", 5 },
940	{ 0, (const unsigned char *)"\x00", 1, "", 1 },
941	{ 0, (const unsigned char *)"", 0, "", 0 },
942	{ 0, (const unsigned char *)"foo\x00\x00", 5, "foo", 5 },
943	{ 0, (const unsigned char *)"foo\0", 4, "foo", 4 },
944	{ 0, (const unsigned char *)"foo", 3, "foo", 3 }
945    };
946
947    for (i = 0; i < sizeof(foo)/sizeof(foo[0]); i++) {
948	char *s;
949	size_t size;
950	ret = der_get_general_string(foo[i].p, foo[i].len, &s, &size);
951	if (foo[i].fail) {
952	    if (ret == 0)
953		errx(1, "check %d NULL didn't fail", i);
954	    continue;
955	}
956	if (ret)
957	    errx(1, "NULL check %d der_get_general_string failed", i);
958	if (foo[i].size != size)
959	    errx(1, "NUL check i = %d size failed", i);
960	if (strcmp(foo[i].s, s) != 0)
961	    errx(1, "NUL check i = %d content failed", i);
962	free(s);
963    }
964    return 0;
965}
966
967static int
968test_misc_cmp(void)
969{
970    int ret;
971
972    /* diffrent lengths are diffrent */
973    {
974	const heim_octet_string os1 = { 1, "a" } , os2 = { 0, NULL };
975	ret = der_heim_octet_string_cmp(&os1, &os2);
976	if (ret == 0)
977	    return 1;
978    }
979    /* diffrent data are diffrent */
980    {
981	const heim_octet_string os1 = { 1, "a" } , os2 = { 1, "b" };
982	ret = der_heim_octet_string_cmp(&os1, &os2);
983	if (ret == 0)
984	    return 1;
985    }
986    /* diffrent lengths are diffrent */
987    {
988	const heim_bit_string bs1 = { 8, "a" } , bs2 = { 7, "a" };
989	ret = der_heim_bit_string_cmp(&bs1, &bs2);
990	if (ret == 0)
991	    return 1;
992    }
993    /* diffrent data are diffrent */
994    {
995	const heim_bit_string bs1 = { 7, "\x0f" } , bs2 = { 7, "\x02" };
996	ret = der_heim_bit_string_cmp(&bs1, &bs2);
997	if (ret == 0)
998	    return 1;
999    }
1000    /* diffrent lengths are diffrent */
1001    {
1002	uint16_t data = 1;
1003	heim_bmp_string bs1 = { 1, NULL } , bs2 = { 0, NULL };
1004	bs1.data = &data;
1005	ret = der_heim_bmp_string_cmp(&bs1, &bs2);
1006	if (ret == 0)
1007	    return 1;
1008    }
1009    /* diffrent lengths are diffrent */
1010    {
1011	uint32_t data;
1012	heim_universal_string us1 = { 1, NULL } , us2 = { 0, NULL };
1013	us1.data = &data;
1014	ret = der_heim_universal_string_cmp(&us1, &us2);
1015	if (ret == 0)
1016	    return 1;
1017    }
1018    /* same */
1019    {
1020	uint32_t data = (uint32_t)'a';
1021	heim_universal_string us1 = { 1, NULL } , us2 = { 1, NULL };
1022	us1.data = &data;
1023	us2.data = &data;
1024	ret = der_heim_universal_string_cmp(&us1, &us2);
1025	if (ret != 0)
1026	    return 1;
1027    }
1028
1029    return 0;
1030}
1031
1032static int
1033corner_generalized_time(void)
1034{
1035    const char *str = "760520140000Z";
1036    size_t size;
1037    time_t t;
1038    int ret;
1039
1040    ret = der_get_generalized_time((const unsigned char*)str, strlen(str),
1041				   &t, &size);
1042    if (ret)
1043	return 1;
1044    return 0;
1045}
1046
1047static int
1048corner_tag(void)
1049{
1050    struct {
1051	int ok;
1052	const char *ptr;
1053	size_t len;
1054    } tests[] = {
1055	{ 1, "\x00", 1 },
1056	{ 0, "\xff", 1 },
1057	{ 0, "\xff\xff\xff\xff\xff\xff\xff\xff", 8 }
1058    };
1059    int i, ret;
1060    Der_class cl;
1061    Der_type ty;
1062    unsigned int tag;
1063    size_t size;
1064
1065    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
1066	ret = der_get_tag((const unsigned char*)tests[i].ptr,
1067			  tests[i].len, &cl, &ty, &tag, &size);
1068	if (ret) {
1069	    if (tests[i].ok)
1070		errx(1, "failed while shouldn't");
1071	} else {
1072	    if (!tests[i].ok)
1073		errx(1, "passed while shouldn't");
1074	}
1075    }
1076    return 0;
1077}
1078
1079struct randomcheck {
1080    asn1_type_decode decoder;
1081    asn1_type_release release;
1082    size_t typesize;
1083    size_t inputsize;
1084} randomcheck[] = {
1085#define el(name, type, maxlen) {			\
1086	(asn1_type_decode)der_get_##name,		\
1087	(asn1_type_release)der_free_##name,		\
1088	sizeof(type), 					\
1089	maxlen						\
1090    }
1091    el(integer, int, 6),
1092    el(heim_integer, heim_integer, 12),
1093    el(integer, int, 6),
1094    el(unsigned, unsigned, 6),
1095    el(general_string, heim_general_string, 12),
1096    el(octet_string, heim_octet_string, 12),
1097    { (asn1_type_decode)der_get_octet_string_ber,
1098      (asn1_type_release)der_free_octet_string,
1099      sizeof(heim_octet_string), 20 },
1100    el(generalized_time, time_t, 20),
1101    el(utctime, time_t, 20),
1102    el(bit_string, heim_bit_string, 10),
1103    el(oid, heim_oid, 10),
1104    { NULL, NULL, 0, 0 }
1105#undef el
1106};
1107
1108static void
1109asn1rand(uint8_t *randbytes, size_t len)
1110{
1111    while (len) {
1112	*randbytes++ = rk_random();
1113	len--;
1114    }
1115}
1116
1117static int
1118check_random(void)
1119{
1120    struct randomcheck *r = randomcheck;
1121    uint8_t *input;
1122    void *type;
1123    size_t size, insize;
1124    int ret;
1125
1126    while (r->decoder) {
1127	type = emalloc(r->typesize);
1128	memset(type, 0, r->typesize);
1129
1130	input = emalloc(r->inputsize);
1131
1132	/* try all zero first */
1133	memset(input, 0, r->inputsize);
1134
1135	ret = r->decoder(input, r->inputsize, type, &size);
1136	if (ret)
1137	    r->release(type);
1138
1139	/* try all one first */
1140	memset(input, 0xff, r->inputsize);
1141	ret = r->decoder(input, r->inputsize, type, &size);
1142	if (ret)
1143	    r->release(type);
1144
1145	/* try 0x41 too */
1146	memset(input, 0x41, r->inputsize);
1147	ret = r->decoder(input, r->inputsize, type, &size);
1148	if (ret)
1149	    r->release(type);
1150
1151	/* random */
1152	asn1rand(input, r->inputsize);
1153	ret = r->decoder(input, r->inputsize, type, &size);
1154	if (ret)
1155	    r->release(type);
1156
1157	/* let make buffer smaller */
1158	insize = r->inputsize;
1159	do {
1160	    insize--;
1161	    asn1rand(input, insize);
1162
1163	    ret = r->decoder(input, insize, type, &size);
1164	    if (ret == 0)
1165		r->release(type);
1166	} while(insize > 0);
1167
1168	free(type);
1169
1170	r++;
1171    }
1172    return 0;
1173}
1174
1175
1176
1177int
1178main(int argc, char **argv)
1179{
1180    int ret = 0;
1181
1182    ret += test_integer ();
1183    ret += test_integer_more();
1184    ret += test_unsigned ();
1185    ret += test_octet_string ();
1186    ret += test_bmp_string ();
1187    ret += test_universal_string ();
1188    ret += test_general_string ();
1189    ret += test_generalized_time ();
1190    ret += test_oid ();
1191    ret += test_bit_string();
1192    ret += test_heim_integer();
1193    ret += test_boolean();
1194
1195    ret += check_fail_unsigned();
1196    ret += check_fail_integer();
1197    ret += check_fail_length();
1198    ret += check_fail_boolean();
1199    ret += check_fail_general_string();
1200    ret += check_fail_bmp_string();
1201    ret += check_fail_universal_string();
1202    ret += check_fail_heim_integer();
1203    ret += check_fail_generalized_time();
1204    ret += check_fail_oid();
1205    ret += check_fail_bitstring();
1206    ret += test_heim_int_format();
1207    ret += test_heim_oid_format();
1208    ret += check_trailing_nul();
1209    ret += test_misc_cmp();
1210    ret += corner_generalized_time();
1211    ret += corner_tag();
1212    ret += check_random();
1213
1214    return ret;
1215}
1216