xref: /openbsd/regress/lib/libssl/asn1/asn1test.c (revision a6445c1d)
1 /*	$OpenBSD: asn1test.c,v 1.2 2014/07/16 17:38:19 miod 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 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
83 			.master_key_length = 26,
84 			.session_id = "0123456789",
85 			.session_id_length = 10,
86 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
87 			.sid_ctx_length = 26,
88 		},
89 		{
90 			0x30, 0x51, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03,
91 			0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x0a, 0x30,
92 			0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
93 			0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
94 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 			0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x1c, 0x04,
97 			0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
98 			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
99 			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
100 			0x78, 0x79, 0x7a,
101 		},
102 		83,
103 	},
104 	{
105 		{
106 			.cipher_id = 0x03000000L | 1,
107 			.ssl_version = TLS1_2_VERSION,
108 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
109 			.master_key_length = 26,
110 			.session_id = "0123456789",
111 			.session_id_length = 10,
112 			.sid_ctx = "abcdefghijklmnopqrstuvwxyz",
113 			.sid_ctx_length = 26,
114 			.time = 1405266069,
115 			.timeout = 5,
116 			.verify_result = 42,
117 			.tlsext_hostname = "libressl.openbsd.org",
118 			.tlsext_tick_lifetime_hint = 0x7abbccdd,
119 			.tlsext_tick = tlsext_tick,
120 			.tlsext_ticklen = 207,
121 		},
122 		{
123 			0x30, 0x82, 0x01, 0x58, 0x02, 0x01, 0x01, 0x02,
124 			0x02, 0x03, 0x03, 0x04, 0x02, 0x00, 0x01, 0x04,
125 			0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
126 			0x37, 0x38, 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00,
127 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1,
130 			0x06, 0x02, 0x04, 0x53, 0xc2, 0xa8, 0x95, 0xa2,
131 			0x03, 0x02, 0x01, 0x05, 0xa4, 0x1c, 0x04, 0x1a,
132 			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
133 			0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
134 			0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
135 			0x79, 0x7a, 0xa5, 0x03, 0x02, 0x01, 0x2a, 0xa6,
136 			0x16, 0x04, 0x14, 0x6c, 0x69, 0x62, 0x72, 0x65,
137 			0x73, 0x73, 0x6c, 0x2e, 0x6f, 0x70, 0x65, 0x6e,
138 			0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0xa9,
139 			0x06, 0x02, 0x04, 0x7a, 0xbb, 0xcc, 0xdd, 0xaa,
140 			0x81, 0xd2, 0x04, 0x81, 0xcf, 0x43, 0x56, 0x45,
141 			0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31,
142 			0x36, 0x30, 0x3a, 0x20, 0x37, 0x74, 0x68, 0x20,
143 			0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30,
144 			0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32,
145 			0x30, 0x31, 0x30, 0x2d, 0x35, 0x32, 0x39, 0x38,
146 			0x3a, 0x20, 0x38, 0x74, 0x68, 0x20, 0x41, 0x70,
147 			0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34,
148 			0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31,
149 			0x34, 0x2d, 0x30, 0x31, 0x39, 0x38, 0x3a, 0x20,
150 			0x32, 0x31, 0x73, 0x74, 0x20, 0x41, 0x70, 0x72,
151 			0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a,
152 			0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34,
153 			0x2d, 0x33, 0x34, 0x37, 0x30, 0x3a, 0x20, 0x33,
154 			0x30, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x79, 0x20,
155 			0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45,
156 			0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31,
157 			0x39, 0x35, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20,
158 			0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31,
159 			0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30,
160 			0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x31, 0x3a,
161 			0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e,
162 			0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43,
163 			0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d,
164 			0x30, 0x32, 0x32, 0x34, 0x3a, 0x20, 0x35, 0x74,
165 			0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32,
166 			0x30, 0x31, 0x34, 0x0a,
167 		},
168 		348,
169 	},
170 };
171 
172 #define N_SSL_ASN1_TESTS \
173     (sizeof(ssl_asn1_tests) / sizeof(*ssl_asn1_tests))
174 
175 static int
176 session_strcmp(const unsigned char *o1, const unsigned char *o2, size_t len)
177 {
178 	if (o1 == NULL && o2 == NULL)
179 		return (0);
180 	if (o1 == NULL || o2 == NULL)
181 		return (1);
182 	return memcmp(o1, o2, len);
183 }
184 
185 static int
186 session_cmp(SSL_SESSION *s1, SSL_SESSION *s2)
187 {
188 	/* Compare two sessions, from the perspective of ASN1. */
189 	if (s1->ssl_version != s2->ssl_version) {
190 		fprintf(stderr, "ssl_version differs: %i != %i\n",
191 		    s1->ssl_version, s2->ssl_version);
192 		return (1);
193 	}
194 	if (s1->cipher_id != s2->cipher_id) {
195 		fprintf(stderr, "cipher_id differs: %li != %li\n",
196 		    s1->cipher_id, s2->cipher_id);
197 		return (1);
198 	}
199 
200 	if (s1->master_key_length != s2->master_key_length) {
201 		fprintf(stderr, "master_key_length differs: %i != %i\n",
202 		    s1->master_key_length, s2->master_key_length);
203 		return (1);
204 	}
205 	if (session_strcmp(s1->master_key, s2->master_key,
206 	    s1->master_key_length) != 0) {
207 		fprintf(stderr, "master_key differs\n");
208 		return (1);
209 	}
210 
211 	if (s1->session_id_length != s2->session_id_length) {
212 		fprintf(stderr, "session_id_length differs: %i != %i\n",
213 		    s1->session_id_length, s2->session_id_length);
214 		return (1);
215 	}
216 	if (session_strcmp(s1->session_id, s2->session_id,
217 	    s1->session_id_length) != 0) {
218 		fprintf(stderr, "session_id differs\n");
219 		return (1);
220 	}
221 
222 	if (s1->sid_ctx_length != s2->sid_ctx_length) {
223 		fprintf(stderr, "sid_ctx_length differs: %i != %i\n",
224 		    s1->sid_ctx_length, s2->sid_ctx_length);
225 		return (1);
226 	}
227 	if (session_strcmp(s1->sid_ctx, s2->sid_ctx,
228 	    s1->sid_ctx_length) != 0) {
229 		fprintf(stderr, "sid_ctx differs\n");
230 		return (1);
231 	}
232 
233 	/* d2i_SSL_SESSION uses the current time if decoding a zero value. */
234 	if ((s1->time != s2->time) && s1->time != 0 && s2->time != 0) {
235 		fprintf(stderr, "time differs: %lli != %lli\n",
236 		    (long long)s1->time, (long long)s2->time);
237 		return (1);
238 	}
239 	/* d2i_SSL_SESSION uses a timeout of 3 if decoding a zero value. */
240 	if ((s1->timeout != s2->timeout) &&
241 	    s1->timeout != 3 && s2->timeout != 3) {
242 		fprintf(stderr, "timeout differs: %li != %li\n",
243 		    s1->timeout, s2->timeout);
244 		return (1);
245 	}
246 
247 	/* Ensure that a certificate is or is not present in both. */
248 	if ((s1->peer != NULL || s2->peer != NULL) &&
249 	    (s1->peer == NULL || s2->peer == NULL)) {
250 		fprintf(stderr, "peer differs\n");
251 		return (1);
252 	}
253 
254 	if (s1->verify_result != s2->verify_result) {
255 		fprintf(stderr, "verify_result differs: %li != %li\n",
256 		    s1->verify_result, s2->verify_result);
257 		return (1);
258 	}
259 
260 	if (session_strcmp(s1->tlsext_hostname, s2->tlsext_hostname,
261 	    (s1->tlsext_hostname ? strlen(s1->tlsext_hostname) : 0)) != 0) {
262 		fprintf(stderr, "sid_ctx differs\n");
263 		return (1);
264 	}
265 	if (s1->tlsext_tick_lifetime_hint != s2->tlsext_tick_lifetime_hint) {
266 		fprintf(stderr, "tlsext_tick_lifetime_hint differs: "
267 		    "%li != %li\n", s1->tlsext_tick_lifetime_hint,
268 		    s2->tlsext_tick_lifetime_hint);
269 		return (1);
270 	}
271 	if (s1->tlsext_ticklen != s2->tlsext_ticklen) {
272 		fprintf(stderr, "tlsext_ticklen differs: %zu != %zu\n",
273 		    s1->tlsext_ticklen, s2->tlsext_ticklen);
274 		return (1);
275 	}
276 	if (session_strcmp(s1->tlsext_tick, s2->tlsext_tick,
277 	    s1->tlsext_ticklen) != 0) {
278 		fprintf(stderr, "tlsext_tick differs\n");
279 		return (1);
280 	}
281 
282 	return (0);
283 }
284 
285 static int
286 do_ssl_asn1_test(int test_no, struct ssl_asn1_test *sat)
287 {
288 	SSL_SESSION session, *sp = NULL;
289 	unsigned char *ap, *asn1 = NULL;
290 	const unsigned char *pp;
291 	int i, len, rv = 1;
292 
293 	len = i2d_SSL_SESSION(&sat->session, NULL);
294 	if (len != sat->asn1_len) {
295 		fprintf(stderr, "FAIL: test %i returned ASN1 length %i, "
296 		    "want %i\n", test_no, len, sat->asn1_len);
297 		goto failed;
298 	}
299 
300 	if ((asn1 = malloc(len)) == NULL)
301 		errx(1, "failed to allocate memory");
302 
303 	ap = asn1;
304 	len = i2d_SSL_SESSION(&sat->session, &ap);
305 	if ((ap - asn1) > len) {
306 		fprintf(stderr, "FAIL: test %i overflowed ticket buffer "
307 		    "(%i > %i)\n", test_no, (int)(ap - asn1), len);
308 		goto failed;
309 	}
310 
311 	/*
312 	 * Length *should* be the same, but check it again since the code
313 	 * path is different.
314 	 */
315 	if (len != sat->asn1_len) {
316 		fprintf(stderr, "FAIL: test %i returned ASN1 length %i, "
317 		    "want %i\n", test_no, len, sat->asn1_len);
318 		goto failed;
319 	}
320 
321 	if (memcmp(asn1, &sat->asn1, len) != 0) {
322 		fprintf(stderr, "FAIL: test %i - encoding differs:\n", test_no);
323 		fprintf(stderr, "encoding:\n");
324 		for (i = 1; i <= len; i++) {
325 			fprintf(stderr, " 0x%02hhx,", asn1[i - 1]);
326 			if (i % 8 == 0)
327 				fprintf(stderr, "\n");
328 		}
329 		fprintf(stderr, "\n");
330 		fprintf(stderr, "test data:\n");
331 		for (i = 1; i <= sat->asn1_len; i++) {
332 			fprintf(stderr, " 0x%02hhx,", sat->asn1[i - 1]);
333 			if (i % 8 == 0)
334 				fprintf(stderr, "\n");
335 		}
336 		fprintf(stderr, "\n");
337 		goto failed;
338 	}
339 
340 	sp = &session;
341 	memset(sp, 0, sizeof(*sp));
342 	pp = sat->asn1;
343 
344 	if ((sp = d2i_SSL_SESSION(&sp, &pp, sat->asn1_len)) == NULL) {
345 		fprintf(stderr, "FAIL: test %i - decoding failed\n", test_no);
346 		goto failed;
347 	}
348 
349 	if (session_cmp(sp, &sat->session) != 0) {
350 		fprintf(stderr, "FAIL: test %i - decoding differs\n", test_no);
351 		goto failed;
352 	}
353 
354 	rv = 0;
355 
356 failed:
357 	ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
358 
359 	free(asn1);
360 
361 	return (rv);
362 }
363 
364 int
365 main(int argc, char **argv)
366 {
367 	int failed = 0;
368 	size_t i;
369 
370 	SSL_library_init();
371 	SSL_load_error_strings();
372 
373 	for (i = 0; i < N_SSL_ASN1_TESTS; i++)
374 		failed += do_ssl_asn1_test(i, &ssl_asn1_tests[i]);
375 
376 	return (failed);
377 }
378