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