xref: /openbsd-src/regress/lib/libssl/asn1/asn1test.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: asn1test.c,v 1.3 2014/12/07 20:00:13 bcook Exp $	*/
2 /*
3  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <err.h>
19 #include <stdlib.h>
20 
21 #include <openssl/bio.h>
22 #include <openssl/err.h>
23 #include <openssl/ssl.h>
24 #include <openssl/tls1.h>
25 
26 int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
27 SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
28     long length);
29 
30 struct ssl_asn1_test {
31 	SSL_SESSION session;
32 	const unsigned char asn1[512];
33 	int asn1_len;
34 };
35 
36 unsigned char tlsext_tick[] = {
37 	0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34,
38 	0x2d, 0x30, 0x31, 0x36, 0x30, 0x3a, 0x20, 0x37,
39 	0x74, 0x68, 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c,
40 	0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56,
41 	0x45, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x35,
42 	0x32, 0x39, 0x38, 0x3a, 0x20, 0x38, 0x74, 0x68,
43 	0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32,
44 	0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d,
45 	0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x39,
46 	0x38, 0x3a, 0x20, 0x32, 0x31, 0x73, 0x74, 0x20,
47 	0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30,
48 	0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32,
49 	0x30, 0x31, 0x34, 0x2d, 0x33, 0x34, 0x37, 0x30,
50 	0x3a, 0x20, 0x33, 0x30, 0x74, 0x68, 0x20, 0x4d,
51 	0x61, 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a,
52 	0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34,
53 	0x2d, 0x30, 0x31, 0x39, 0x35, 0x3a, 0x20, 0x35,
54 	0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20,
55 	0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45,
56 	0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x32,
57 	0x32, 0x31, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20,
58 	0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31,
59 	0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30,
60 	0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x34, 0x3a,
61 	0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e,
62 	0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a,
63 };
64 
65 struct ssl_asn1_test ssl_asn1_tests[] = {
66 	{
67 		{
68 			.cipher_id = 0x03000000L | 1,
69 			.ssl_version = TLS1_2_VERSION,
70 		},
71 		{
72 			0x30, 0x13, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03,
73 			0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x00, 0x04,
74 			0x00, 0xa4, 0x02, 0x04, 0x00,
75 		},
76 		21,
77 	},
78 	{
79 		{
80 			.cipher_id = 0x03000000L | 1,
81 			.ssl_version = TLS1_2_VERSION,
82 			.master_key_length = 26,
83 			.session_id = "0123456789",
84 			.session_id_length = 10,
85 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
86 			.sid_ctx_length = 26,
87 		},
88 		{
89 			0x30, 0x51, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03,
90 			0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x0a, 0x30,
91 			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
92 			0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
93 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 			0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x1c, 0x04,
96 			0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
97 			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
98 			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
99 			0x78, 0x79, 0x7a,
100 		},
101 		83,
102 	},
103 	{
104 		{
105 			.cipher_id = 0x03000000L | 1,
106 			.ssl_version = TLS1_2_VERSION,
107 			.master_key_length = 26,
108 			.session_id = "0123456789",
109 			.session_id_length = 10,
110 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
111 			.sid_ctx_length = 26,
112 			.time = 1405266069,
113 			.timeout = 5,
114 			.verify_result = 42,
115 			.tlsext_hostname = "libressl.openbsd.org",
116 			.tlsext_tick_lifetime_hint = 0x7abbccdd,
117 			.tlsext_tick = tlsext_tick,
118 			.tlsext_ticklen = 207,
119 		},
120 		{
121 			0x30, 0x82, 0x01, 0x58, 0x02, 0x01, 0x01, 0x02,
122 			0x02, 0x03, 0x03, 0x04, 0x02, 0x00, 0x01, 0x04,
123 			0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
124 			0x37, 0x38, 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00,
125 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1,
128 			0x06, 0x02, 0x04, 0x53, 0xc2, 0xa8, 0x95, 0xa2,
129 			0x03, 0x02, 0x01, 0x05, 0xa4, 0x1c, 0x04, 0x1a,
130 			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
131 			0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
132 			0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
133 			0x79, 0x7a, 0xa5, 0x03, 0x02, 0x01, 0x2a, 0xa6,
134 			0x16, 0x04, 0x14, 0x6c, 0x69, 0x62, 0x72, 0x65,
135 			0x73, 0x73, 0x6c, 0x2e, 0x6f, 0x70, 0x65, 0x6e,
136 			0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0xa9,
137 			0x06, 0x02, 0x04, 0x7a, 0xbb, 0xcc, 0xdd, 0xaa,
138 			0x81, 0xd2, 0x04, 0x81, 0xcf, 0x43, 0x56, 0x45,
139 			0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31,
140 			0x36, 0x30, 0x3a, 0x20, 0x37, 0x74, 0x68, 0x20,
141 			0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30,
142 			0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32,
143 			0x30, 0x31, 0x30, 0x2d, 0x35, 0x32, 0x39, 0x38,
144 			0x3a, 0x20, 0x38, 0x74, 0x68, 0x20, 0x41, 0x70,
145 			0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34,
146 			0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31,
147 			0x34, 0x2d, 0x30, 0x31, 0x39, 0x38, 0x3a, 0x20,
148 			0x32, 0x31, 0x73, 0x74, 0x20, 0x41, 0x70, 0x72,
149 			0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a,
150 			0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34,
151 			0x2d, 0x33, 0x34, 0x37, 0x30, 0x3a, 0x20, 0x33,
152 			0x30, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x79, 0x20,
153 			0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45,
154 			0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31,
155 			0x39, 0x35, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20,
156 			0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31,
157 			0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30,
158 			0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x31, 0x3a,
159 			0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e,
160 			0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43,
161 			0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d,
162 			0x30, 0x32, 0x32, 0x34, 0x3a, 0x20, 0x35, 0x74,
163 			0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32,
164 			0x30, 0x31, 0x34, 0x0a,
165 		},
166 		348,
167 	},
168 };
169 
170 #define N_SSL_ASN1_TESTS \
171     (sizeof(ssl_asn1_tests) / sizeof(*ssl_asn1_tests))
172 
173 static int
174 session_strcmp(const unsigned char *o1, const unsigned char *o2, size_t len)
175 {
176 	if (o1 == NULL && o2 == NULL)
177 		return (0);
178 	if (o1 == NULL || o2 == NULL)
179 		return (1);
180 	return memcmp(o1, o2, len);
181 }
182 
183 static int
184 session_cmp(SSL_SESSION *s1, SSL_SESSION *s2)
185 {
186 	/* Compare two sessions, from the perspective of ASN1. */
187 	if (s1->ssl_version != s2->ssl_version) {
188 		fprintf(stderr, "ssl_version differs: %i != %i\n",
189 		    s1->ssl_version, s2->ssl_version);
190 		return (1);
191 	}
192 	if (s1->cipher_id != s2->cipher_id) {
193 		fprintf(stderr, "cipher_id differs: %li != %li\n",
194 		    s1->cipher_id, s2->cipher_id);
195 		return (1);
196 	}
197 
198 	if (s1->master_key_length != s2->master_key_length) {
199 		fprintf(stderr, "master_key_length differs: %i != %i\n",
200 		    s1->master_key_length, s2->master_key_length);
201 		return (1);
202 	}
203 	if (session_strcmp(s1->master_key, s2->master_key,
204 	    s1->master_key_length) != 0) {
205 		fprintf(stderr, "master_key differs\n");
206 		return (1);
207 	}
208 
209 	if (s1->session_id_length != s2->session_id_length) {
210 		fprintf(stderr, "session_id_length differs: %i != %i\n",
211 		    s1->session_id_length, s2->session_id_length);
212 		return (1);
213 	}
214 	if (session_strcmp(s1->session_id, s2->session_id,
215 	    s1->session_id_length) != 0) {
216 		fprintf(stderr, "session_id differs\n");
217 		return (1);
218 	}
219 
220 	if (s1->sid_ctx_length != s2->sid_ctx_length) {
221 		fprintf(stderr, "sid_ctx_length differs: %i != %i\n",
222 		    s1->sid_ctx_length, s2->sid_ctx_length);
223 		return (1);
224 	}
225 	if (session_strcmp(s1->sid_ctx, s2->sid_ctx,
226 	    s1->sid_ctx_length) != 0) {
227 		fprintf(stderr, "sid_ctx differs\n");
228 		return (1);
229 	}
230 
231 	/* d2i_SSL_SESSION uses the current time if decoding a zero value. */
232 	if ((s1->time != s2->time) && s1->time != 0 && s2->time != 0) {
233 		fprintf(stderr, "time differs: %lli != %lli\n",
234 		    (long long)s1->time, (long long)s2->time);
235 		return (1);
236 	}
237 	/* d2i_SSL_SESSION uses a timeout of 3 if decoding a zero value. */
238 	if ((s1->timeout != s2->timeout) &&
239 	    s1->timeout != 3 && s2->timeout != 3) {
240 		fprintf(stderr, "timeout differs: %li != %li\n",
241 		    s1->timeout, s2->timeout);
242 		return (1);
243 	}
244 
245 	/* Ensure that a certificate is or is not present in both. */
246 	if ((s1->peer != NULL || s2->peer != NULL) &&
247 	    (s1->peer == NULL || s2->peer == NULL)) {
248 		fprintf(stderr, "peer differs\n");
249 		return (1);
250 	}
251 
252 	if (s1->verify_result != s2->verify_result) {
253 		fprintf(stderr, "verify_result differs: %li != %li\n",
254 		    s1->verify_result, s2->verify_result);
255 		return (1);
256 	}
257 
258 	if (session_strcmp(s1->tlsext_hostname, s2->tlsext_hostname,
259 	    (s1->tlsext_hostname ? strlen(s1->tlsext_hostname) : 0)) != 0) {
260 		fprintf(stderr, "sid_ctx differs\n");
261 		return (1);
262 	}
263 	if (s1->tlsext_tick_lifetime_hint != s2->tlsext_tick_lifetime_hint) {
264 		fprintf(stderr, "tlsext_tick_lifetime_hint differs: "
265 		    "%li != %li\n", s1->tlsext_tick_lifetime_hint,
266 		    s2->tlsext_tick_lifetime_hint);
267 		return (1);
268 	}
269 	if (s1->tlsext_ticklen != s2->tlsext_ticklen) {
270 		fprintf(stderr, "tlsext_ticklen differs: %zu != %zu\n",
271 		    s1->tlsext_ticklen, s2->tlsext_ticklen);
272 		return (1);
273 	}
274 	if (session_strcmp(s1->tlsext_tick, s2->tlsext_tick,
275 	    s1->tlsext_ticklen) != 0) {
276 		fprintf(stderr, "tlsext_tick differs\n");
277 		return (1);
278 	}
279 
280 	return (0);
281 }
282 
283 static int
284 do_ssl_asn1_test(int test_no, struct ssl_asn1_test *sat)
285 {
286 	SSL_SESSION session, *sp = NULL;
287 	unsigned char *ap, *asn1 = NULL;
288 	const unsigned char *pp;
289 	int i, len, rv = 1;
290 
291 	len = i2d_SSL_SESSION(&sat->session, NULL);
292 	if (len != sat->asn1_len) {
293 		fprintf(stderr, "FAIL: test %i returned ASN1 length %i, "
294 		    "want %i\n", test_no, len, sat->asn1_len);
295 		goto failed;
296 	}
297 
298 	if ((asn1 = malloc(len)) == NULL)
299 		errx(1, "failed to allocate memory");
300 
301 	ap = asn1;
302 	len = i2d_SSL_SESSION(&sat->session, &ap);
303 	if ((ap - asn1) > len) {
304 		fprintf(stderr, "FAIL: test %i overflowed ticket buffer "
305 		    "(%i > %i)\n", test_no, (int)(ap - asn1), len);
306 		goto failed;
307 	}
308 
309 	/*
310 	 * Length *should* be the same, but check it again since the code
311 	 * path is different.
312 	 */
313 	if (len != sat->asn1_len) {
314 		fprintf(stderr, "FAIL: test %i returned ASN1 length %i, "
315 		    "want %i\n", test_no, len, sat->asn1_len);
316 		goto failed;
317 	}
318 
319 	if (memcmp(asn1, &sat->asn1, len) != 0) {
320 		fprintf(stderr, "FAIL: test %i - encoding differs:\n", test_no);
321 		fprintf(stderr, "encoding:\n");
322 		for (i = 1; i <= len; i++) {
323 			fprintf(stderr, " 0x%02hhx,", asn1[i - 1]);
324 			if (i % 8 == 0)
325 				fprintf(stderr, "\n");
326 		}
327 		fprintf(stderr, "\n");
328 		fprintf(stderr, "test data:\n");
329 		for (i = 1; i <= sat->asn1_len; i++) {
330 			fprintf(stderr, " 0x%02hhx,", sat->asn1[i - 1]);
331 			if (i % 8 == 0)
332 				fprintf(stderr, "\n");
333 		}
334 		fprintf(stderr, "\n");
335 		goto failed;
336 	}
337 
338 	sp = &session;
339 	memset(sp, 0, sizeof(*sp));
340 	pp = sat->asn1;
341 
342 	if ((sp = d2i_SSL_SESSION(&sp, &pp, sat->asn1_len)) == NULL) {
343 		fprintf(stderr, "FAIL: test %i - decoding failed\n", test_no);
344 		goto failed;
345 	}
346 
347 	if (session_cmp(sp, &sat->session) != 0) {
348 		fprintf(stderr, "FAIL: test %i - decoding differs\n", test_no);
349 		goto failed;
350 	}
351 
352 	rv = 0;
353 
354 failed:
355 	ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
356 
357 	free(asn1);
358 
359 	return (rv);
360 }
361 
362 int
363 main(int argc, char **argv)
364 {
365 	int failed = 0;
366 	size_t i;
367 
368 	SSL_library_init();
369 	SSL_load_error_strings();
370 
371 	for (i = 0; i < N_SSL_ASN1_TESTS; i++)
372 		failed += do_ssl_asn1_test(i, &ssl_asn1_tests[i]);
373 
374 	return (failed);
375 }
376