xref: /freebsd/crypto/heimdal/lib/asn1/check-der.c (revision b528cefc6b8f9670b31a865051741d946cb37085)
1b528cefcSMark Murray /*
2b528cefcSMark Murray  * Copyright (c) 1999 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #ifdef HAVE_CONFIG_H
35b528cefcSMark Murray #include <config.h>
36b528cefcSMark Murray #endif
37b528cefcSMark Murray #include <stdio.h>
38b528cefcSMark Murray #include <string.h>
39b528cefcSMark Murray #include <err.h>
40b528cefcSMark Murray #include <roken.h>
41b528cefcSMark Murray 
42b528cefcSMark Murray #include <libasn1.h>
43b528cefcSMark Murray 
44b528cefcSMark Murray RCSID("$Id: check-der.c,v 1.7 1999/12/02 17:05:01 joda Exp $");
45b528cefcSMark Murray 
46b528cefcSMark Murray static void
47b528cefcSMark Murray print_bytes (unsigned const char *buf, size_t len)
48b528cefcSMark Murray {
49b528cefcSMark Murray     int i;
50b528cefcSMark Murray 
51b528cefcSMark Murray     for (i = 0; i < len; ++i)
52b528cefcSMark Murray 	printf ("%02x ", buf[i]);
53b528cefcSMark Murray }
54b528cefcSMark Murray 
55b528cefcSMark Murray struct test_case {
56b528cefcSMark Murray     void *val;
57b528cefcSMark Murray     int byte_len;
58b528cefcSMark Murray     const unsigned char *bytes;
59b528cefcSMark Murray     char *name;
60b528cefcSMark Murray };
61b528cefcSMark Murray 
62b528cefcSMark Murray static int
63b528cefcSMark Murray generic_test (const struct test_case *tests,
64b528cefcSMark Murray 	      unsigned ntests,
65b528cefcSMark Murray 	      size_t data_size,
66b528cefcSMark Murray 	      int (*encode)(unsigned char *, size_t, void *, size_t *),
67b528cefcSMark Murray 	      int (*length)(void *),
68b528cefcSMark Murray 	      int (*decode)(unsigned char *, size_t, void *, size_t *),
69b528cefcSMark Murray 	      int (*cmp)(void *a, void *b))
70b528cefcSMark Murray {
71b528cefcSMark Murray     unsigned char buf[4711];
72b528cefcSMark Murray     int i;
73b528cefcSMark Murray     int failures = 0;
74b528cefcSMark Murray     void *val = malloc (data_size);
75b528cefcSMark Murray 
76b528cefcSMark Murray     if (data_size != 0 && val == NULL)
77b528cefcSMark Murray 	err (1, "malloc");
78b528cefcSMark Murray 
79b528cefcSMark Murray     for (i = 0; i < ntests; ++i) {
80b528cefcSMark Murray 	int ret;
81b528cefcSMark Murray 	size_t sz, consumed_sz, length_sz;
82b528cefcSMark Murray 	unsigned char *beg;
83b528cefcSMark Murray 
84b528cefcSMark Murray 	ret = (*encode) (buf + sizeof(buf) - 1, sizeof(buf),
85b528cefcSMark Murray 			 tests[i].val, &sz);
86b528cefcSMark Murray 	beg = buf + sizeof(buf) - sz;
87b528cefcSMark Murray 	if (ret != 0) {
88b528cefcSMark Murray 	    printf ("encoding of %s failed\n", tests[i].name);
89b528cefcSMark Murray 	    ++failures;
90b528cefcSMark Murray 	}
91b528cefcSMark Murray 	if (sz != tests[i].byte_len) {
92b528cefcSMark Murray 	    printf ("encoding of %s has wrong len (%lu != %lu)\n",
93b528cefcSMark Murray 		    tests[i].name,
94b528cefcSMark Murray 		    (unsigned long)sz, (unsigned long)tests[i].byte_len);
95b528cefcSMark Murray 	    ++failures;
96b528cefcSMark Murray 	}
97b528cefcSMark Murray 
98b528cefcSMark Murray 	length_sz = (*length) (tests[i].val);
99b528cefcSMark Murray 	if (sz != length_sz) {
100b528cefcSMark Murray 	    printf ("length for %s is bad (%lu != %lu)\n",
101b528cefcSMark Murray 		    tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
102b528cefcSMark Murray 	    ++failures;
103b528cefcSMark Murray 	}
104b528cefcSMark Murray 
105b528cefcSMark Murray 	if (memcmp (beg, tests[i].bytes, tests[i].byte_len) != 0) {
106b528cefcSMark Murray 	    printf ("encoding of %s has bad bytes:\n"
107b528cefcSMark Murray 		    "correct: ", tests[i].name);
108b528cefcSMark Murray 	    print_bytes (tests[i].bytes, tests[i].byte_len);
109b528cefcSMark Murray 	    printf ("\nactual:  ");
110b528cefcSMark Murray 	    print_bytes (beg, sz);
111b528cefcSMark Murray 	    printf ("\n");
112b528cefcSMark Murray 	    ++failures;
113b528cefcSMark Murray 	}
114b528cefcSMark Murray 	ret = (*decode) (beg, sz, val, &consumed_sz);
115b528cefcSMark Murray 	if (ret != 0) {
116b528cefcSMark Murray 	    printf ("decoding of %s failed\n", tests[i].name);
117b528cefcSMark Murray 	    ++failures;
118b528cefcSMark Murray 	}
119b528cefcSMark Murray 	if (sz != consumed_sz) {
120b528cefcSMark Murray 	    printf ("different length decoding %s (%ld != %ld)\n",
121b528cefcSMark Murray 		    tests[i].name,
122b528cefcSMark Murray 		    (unsigned long)sz, (unsigned long)consumed_sz);
123b528cefcSMark Murray 	    ++failures;
124b528cefcSMark Murray 	}
125b528cefcSMark Murray 	if ((*cmp)(val, tests[i].val) != 0) {
126b528cefcSMark Murray 	    printf ("%s: comparison failed\n", tests[i].name);
127b528cefcSMark Murray 	    ++failures;
128b528cefcSMark Murray 	}
129b528cefcSMark Murray     }
130b528cefcSMark Murray     free (val);
131b528cefcSMark Murray     return failures;
132b528cefcSMark Murray }
133b528cefcSMark Murray 
134b528cefcSMark Murray static int
135b528cefcSMark Murray cmp_integer (void *a, void *b)
136b528cefcSMark Murray {
137b528cefcSMark Murray     int *ia = (int *)a;
138b528cefcSMark Murray     int *ib = (int *)b;
139b528cefcSMark Murray 
140b528cefcSMark Murray     return *ib - *ia;
141b528cefcSMark Murray }
142b528cefcSMark Murray 
143b528cefcSMark Murray static int
144b528cefcSMark Murray test_integer (void)
145b528cefcSMark Murray {
146b528cefcSMark Murray     struct test_case tests[] = {
147b528cefcSMark Murray 	{NULL, 3, "\x02\x01\x00"},
148b528cefcSMark Murray 	{NULL, 3, "\x02\x01\x7f"},
149b528cefcSMark Murray 	{NULL, 4, "\x02\x02\x00\x80"},
150b528cefcSMark Murray 	{NULL, 4, "\x02\x02\x01\x00"},
151b528cefcSMark Murray 	{NULL, 3, "\x02\x01\x80"},
152b528cefcSMark Murray 	{NULL, 4, "\x02\x02\xff\x7f"},
153b528cefcSMark Murray 	{NULL, 3, "\x02\x01\xff"},
154b528cefcSMark Murray 	{NULL, 4, "\x02\x02\xff\x01"},
155b528cefcSMark Murray 	{NULL, 4, "\x02\x02\x00\xff"},
156b528cefcSMark Murray 	{NULL, 6, "\x02\x04\x80\x00\x00\x00"},
157b528cefcSMark Murray 	{NULL, 6, "\x02\x04\x7f\xff\xff\xff"}
158b528cefcSMark Murray     };
159b528cefcSMark Murray 
160b528cefcSMark Murray     int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
161b528cefcSMark Murray 		    0x80000000, 0x7fffffff};
162b528cefcSMark Murray     int i;
163b528cefcSMark Murray     int ntests = sizeof(tests) / sizeof(*tests);
164b528cefcSMark Murray 
165b528cefcSMark Murray     for (i = 0; i < ntests; ++i) {
166b528cefcSMark Murray 	tests[i].val = &values[i];
167b528cefcSMark Murray 	asprintf (&tests[i].name, "integer %d", values[i]);
168b528cefcSMark Murray     }
169b528cefcSMark Murray 
170b528cefcSMark Murray     return generic_test (tests, ntests, sizeof(int),
171b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
172b528cefcSMark Murray 				  void *, size_t *))encode_integer,
173b528cefcSMark Murray 			 (int (*)(void *))length_integer,
174b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
175b528cefcSMark Murray 				  void *, size_t *))decode_integer,
176b528cefcSMark Murray 			 cmp_integer);
177b528cefcSMark Murray }
178b528cefcSMark Murray 
179b528cefcSMark Murray static int
180b528cefcSMark Murray cmp_octet_string (void *a, void *b)
181b528cefcSMark Murray {
182b528cefcSMark Murray     octet_string *oa = (octet_string *)a;
183b528cefcSMark Murray     octet_string *ob = (octet_string *)b;
184b528cefcSMark Murray 
185b528cefcSMark Murray     if (oa->length != ob->length)
186b528cefcSMark Murray 	return ob->length - oa->length;
187b528cefcSMark Murray 
188b528cefcSMark Murray     return (memcmp (oa->data, ob->data, oa->length));
189b528cefcSMark Murray }
190b528cefcSMark Murray 
191b528cefcSMark Murray static int
192b528cefcSMark Murray test_octet_string (void)
193b528cefcSMark Murray {
194b528cefcSMark Murray     octet_string s1 = {8, "\x01\x23\x45\x67\x89\xab\xcd\xef"};
195b528cefcSMark Murray 
196b528cefcSMark Murray     struct test_case tests[] = {
197b528cefcSMark Murray 	{NULL, 10, "\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef"}
198b528cefcSMark Murray     };
199b528cefcSMark Murray     int ntests = sizeof(tests) / sizeof(*tests);
200b528cefcSMark Murray 
201b528cefcSMark Murray     tests[0].val = &s1;
202b528cefcSMark Murray     asprintf (&tests[0].name, "a octet string");
203b528cefcSMark Murray 
204b528cefcSMark Murray     return generic_test (tests, ntests, sizeof(octet_string),
205b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
206b528cefcSMark Murray 				  void *, size_t *))encode_octet_string,
207b528cefcSMark Murray 			 (int (*)(void *))length_octet_string,
208b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
209b528cefcSMark Murray 				  void *, size_t *))decode_octet_string,
210b528cefcSMark Murray 			 cmp_octet_string);
211b528cefcSMark Murray }
212b528cefcSMark Murray 
213b528cefcSMark Murray static int
214b528cefcSMark Murray cmp_general_string (void *a, void *b)
215b528cefcSMark Murray {
216b528cefcSMark Murray     unsigned char **sa = (unsigned char **)a;
217b528cefcSMark Murray     unsigned char **sb = (unsigned char **)b;
218b528cefcSMark Murray 
219b528cefcSMark Murray     return strcmp (*sa, *sb);
220b528cefcSMark Murray }
221b528cefcSMark Murray 
222b528cefcSMark Murray static int
223b528cefcSMark Murray test_general_string (void)
224b528cefcSMark Murray {
225b528cefcSMark Murray     unsigned char *s1 = "Test User 1";
226b528cefcSMark Murray 
227b528cefcSMark Murray     struct test_case tests[] = {
228b528cefcSMark Murray 	{NULL, 13, "\x1b\x0b\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31"}
229b528cefcSMark Murray     };
230b528cefcSMark Murray     int ntests = sizeof(tests) / sizeof(*tests);
231b528cefcSMark Murray 
232b528cefcSMark Murray     tests[0].val = &s1;
233b528cefcSMark Murray     asprintf (&tests[0].name, "the string \"%s\"", s1);
234b528cefcSMark Murray 
235b528cefcSMark Murray     return generic_test (tests, ntests, sizeof(unsigned char *),
236b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
237b528cefcSMark Murray 				  void *, size_t *))encode_general_string,
238b528cefcSMark Murray 			 (int (*)(void *))length_general_string,
239b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
240b528cefcSMark Murray 				  void *, size_t *))decode_general_string,
241b528cefcSMark Murray 			 cmp_general_string);
242b528cefcSMark Murray }
243b528cefcSMark Murray 
244b528cefcSMark Murray static int
245b528cefcSMark Murray cmp_generalized_time (void *a, void *b)
246b528cefcSMark Murray {
247b528cefcSMark Murray     time_t *ta = (time_t *)a;
248b528cefcSMark Murray     time_t *tb = (time_t *)b;
249b528cefcSMark Murray 
250b528cefcSMark Murray     return *tb - *ta;
251b528cefcSMark Murray }
252b528cefcSMark Murray 
253b528cefcSMark Murray static int
254b528cefcSMark Murray test_generalized_time (void)
255b528cefcSMark Murray {
256b528cefcSMark Murray     struct test_case tests[] = {
257b528cefcSMark Murray 	{NULL, 17, "\x18\x0f""19700101000000Z"},
258b528cefcSMark Murray 	{NULL, 17, "\x18\x0f""19851106210627Z"}
259b528cefcSMark Murray     };
260b528cefcSMark Murray     time_t values[] = {0, 500159187};
261b528cefcSMark Murray     int i;
262b528cefcSMark Murray     int ntests = sizeof(tests) / sizeof(*tests);
263b528cefcSMark Murray 
264b528cefcSMark Murray     for (i = 0; i < ntests; ++i) {
265b528cefcSMark Murray 	tests[i].val = &values[i];
266b528cefcSMark Murray 	asprintf (&tests[i].name, "time %d", (int)values[i]);
267b528cefcSMark Murray     }
268b528cefcSMark Murray 
269b528cefcSMark Murray     return generic_test (tests, ntests, sizeof(time_t),
270b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
271b528cefcSMark Murray 				  void *, size_t *))encode_generalized_time,
272b528cefcSMark Murray 			 (int (*)(void *))length_generalized_time,
273b528cefcSMark Murray 			 (int (*)(unsigned char *, size_t,
274b528cefcSMark Murray 				  void *, size_t *))decode_generalized_time,
275b528cefcSMark Murray 			 cmp_generalized_time);
276b528cefcSMark Murray }
277b528cefcSMark Murray 
278b528cefcSMark Murray int
279b528cefcSMark Murray main(int argc, char **argv)
280b528cefcSMark Murray {
281b528cefcSMark Murray     int ret = 0;
282b528cefcSMark Murray 
283b528cefcSMark Murray     ret += test_integer ();
284b528cefcSMark Murray     ret += test_octet_string ();
285b528cefcSMark Murray     ret += test_general_string ();
286b528cefcSMark Murray     ret += test_generalized_time ();
287b528cefcSMark Murray 
288b528cefcSMark Murray     return ret;
289b528cefcSMark Murray }
290