xref: /openbsd-src/regress/lib/libssl/unit/tls_ext_alpn.c (revision 7239aacce9efc97a6498c841bd23d200bc0642c9)
1 /*	$OpenBSD: tls_ext_alpn.c,v 1.1 2015/07/09 07:47:02 doug Exp $	*/
2 /*
3  * Copyright (c) 2015 Doug Hogan <doug@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 /*
19  * Test TLS extension Application-Layer Protocol Negotiation (RFC 7301).
20  */
21 #include <stdio.h>
22 #include <openssl/ssl.h>
23 
24 #include "tests.h"
25 
26 extern int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
27     unsigned char *d, int n, int *al);
28 extern int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p,
29     unsigned char *d, int n, int *al);
30 
31 /*
32  * In the ProtocolNameList, ProtocolNames must not include empty strings and
33  * byte strings must not be truncated.
34  *
35  * This uses some of the IANA approved protocol names from:
36  * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
37  */
38 
39 /* Valid for client and server since it only has one name. */
40 static uint8_t proto_single[] = {
41 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
42 	0x00, 0x0f, /* len */
43 	/* ExtensionType extension_type */
44 	0x00, 0x10, /* ALPN */
45 	/* opaque extension_data<0..2^16-1> */
46 	0x00, 0x0b, /* len */
47 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
48 	0x00, 0x09, /* len of all names */
49 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
50 	0x08, /* len */
51 	0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31
52 };
53 
54 /* Valid for client, but NOT server.  Server must have exactly one name. */
55 static uint8_t proto_multiple1[] = {
56 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
57 	0x00, 0x19, /* len */
58 	/* ExtensionType extension_type */
59 	0x00, 0x10, /* ALPN */
60 	/* opaque extension_data<0..2^16-1> */
61 	0x00, 0x15, /* len */
62 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
63 	0x00, 0x13, /* len of all names */
64 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
65 	0x08, /* len */
66 	0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
67 	/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
68 	0x09, /* len */
69 	0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
70 };
71 
72 /* Valid for client, but NOT server.  Server must have exactly one name. */
73 static uint8_t proto_multiple2[] = {
74 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
75 	0x00, 0x1c, /* len */
76 	/* ExtensionType extension_type */
77 	0x00, 0x10, /* ALPN */
78 	/* opaque extension_data<0..2^16-1> */
79 	0x00, 0x18, /* len */
80 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
81 	0x00, 0x16, /* len of all names */
82 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
83 	0x08, /* len */
84 	0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
85 	/* opaque ProtocolName<1..2^8-1> -- 'h2' */
86 	0x02, /* len */
87 	0x68, 0x32,
88 	/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
89 	0x09, /* len */
90 	0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
91 };
92 
93 /* Valid for client, but NOT server.  Server must have exactly one name. */
94 static uint8_t proto_multiple3[] = {
95 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
96 	0x00, 0x20, /* len */
97 	/* ExtensionType extension_type */
98 	0x00, 0x10, /* ALPN */
99 	/* opaque extension_data<0..2^16-1> */
100 	0x00, 0x1c, /* len */
101 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
102 	0x00, 0x1a, /* len of all names */
103 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
104 	0x08, /* len */
105 	0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
106 	/* opaque ProtocolName<1..2^8-1> -- 'h2' */
107 	0x02, /* len */
108 	0x68, 0x32,
109 	/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
110 	0x09, /* len */
111 	0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e,
112 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
113 	0x03, /* len */
114 	0x68, 0x32, 0x63
115 };
116 
117 static uint8_t proto_empty[] = {
118 	/* Extension extensions<0..2^16-1> -- All TLS extensions. */
119 	0x00, 0x00, /* none present. */
120 };
121 
122 /* Invalid for both client and server.  Length is wrong. */
123 static uint8_t proto_invalid_len1[] = {
124 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
125 	0x00, 0x0a, /* len */
126 	/* ExtensionType extension_type */
127 	0x00, 0x10, /* ALPN */
128 	/* opaque extension_data<0..2^16-1> */
129 	0x00, 0x06, /* len */
130 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
131 	0x00, 0x04, /* len of all names */
132 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
133 	0x04, /* XXX len too large */
134 	0x68, 0x32, 0x63
135 };
136 static uint8_t proto_invalid_len2[] = {
137 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
138 	0x00, 0x0a, /* len */
139 	/* ExtensionType extension_type */
140 	0x00, 0x10, /* ALPN */
141 	/* opaque extension_data<0..2^16-1> */
142 	0x00, 0x06, /* len */
143 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
144 	0x00, 0x04, /* len of all names */
145 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
146 	0x02, /* XXX len too small */
147 	0x68, 0x32, 0x63
148 };
149 static uint8_t proto_invalid_len3[] = {
150 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
151 	0x00, 0x0a, /* len */
152 	/* ExtensionType extension_type */
153 	0x00, 0x10, /* ALPN */
154 	/* opaque extension_data<0..2^16-1> */
155 	0x00, 0x06, /* len */
156 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
157 	0x00, 0x03, /* XXX len too small */
158 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
159 	0x03, /* len */
160 	0x68, 0x32, 0x63
161 };
162 static uint8_t proto_invalid_len4[] = {
163 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
164 	0x00, 0x0a, /* len */
165 	/* ExtensionType extension_type */
166 	0x00, 0x10, /* ALPN */
167 	/* opaque extension_data<0..2^16-1> */
168 	0x00, 0x06, /* len */
169 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
170 	0x00, 0x06, /* XXX len too large */
171 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
172 	0x03, /* len */
173 	0x68, 0x32, 0x63
174 };
175 static uint8_t proto_invalid_len5[] = {
176 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
177 	0x00, 0x0a, /* len */
178 	/* ExtensionType extension_type */
179 	0x00, 0x10, /* ALPN */
180 	/* opaque extension_data<0..2^16-1> */
181 	0x01, 0x08, /* XXX len too large */
182 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
183 	0x00, 0x04, /* len */
184 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
185 	0x03, /* len */
186 	0x68, 0x32, 0x63
187 };
188 static uint8_t proto_invalid_len6[] = {
189 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
190 	0x00, 0x0a, /* len */
191 	/* ExtensionType extension_type */
192 	0x00, 0x10, /* ALPN */
193 	/* opaque extension_data<0..2^16-1> */
194 	0x00, 0x05, /* XXX len too small */
195 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
196 	0x00, 0x04, /* len */
197 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
198 	0x03, /* len */
199 	0x68, 0x32, 0x63
200 };
201 static uint8_t proto_invalid_len7[] = {
202 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
203 	0x00, 0x06, /* XXX len too small */
204 	/* ExtensionType extension_type */
205 	0x00, 0x10, /* ALPN */
206 	/* opaque extension_data<0..2^16-1> */
207 	0x00, 0x06, /* len */
208 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
209 	0x00, 0x04, /* len */
210 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
211 	0x03, /* len */
212 	0x68, 0x32, 0x63
213 };
214 static uint8_t proto_invalid_len8[] = {
215 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
216 	0x00, 0x0b, /* XXX len too large */
217 	/* ExtensionType extension_type */
218 	0x00, 0x10, /* ALPN */
219 	/* opaque extension_data<0..2^16-1> */
220 	0x00, 0x06, /* len */
221 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
222 	0x00, 0x04, /* len */
223 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
224 	0x03, /* len */
225 	0x68, 0x32, 0x63
226 };
227 
228 /* Invalid for client and server since it is missing data. */
229 static uint8_t proto_invalid_missing1[] = {
230 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
231 	0x00, 0x0a, /* len */
232 	/* ExtensionType extension_type */
233 	0x00, 0x10, /* ALPN */
234 	/* opaque extension_data<0..2^16-1> */
235 	0x00, 0x06, /* len */
236 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
237 	0x00, 0x04, /* len of all names */
238 	/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
239 	/* XXX missing */
240 };
241 static uint8_t proto_invalid_missing2[] = {
242 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
243 	0x00, 0x0a, /* len */
244 	/* ExtensionType extension_type */
245 	0x00, 0x10, /* ALPN */
246 	/* opaque extension_data<0..2^16-1> */
247 	0x00, 0x00, /* XXX missing name list */
248 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
249 };
250 static uint8_t proto_invalid_missing3[] = {
251 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
252 	0x00, 0x0a, /* len */
253 	/* ExtensionType extension_type */
254 	0x00, 0x10, /* ALPN */
255 	/* opaque extension_data<0..2^16-1> */
256 	0x00, 0x02, /* XXX size is sufficient but missing data for name list */
257 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
258 };
259 static uint8_t proto_invalid_missing4[] = {
260 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
261 	0x00, 0x0a, /* len */
262 	/* ExtensionType extension_type */
263 	0x00, 0x10, /* ALPN */
264 	/* opaque extension_data<0..2^16-1> */
265 	/* XXX missing */
266 };
267 static uint8_t proto_invalid_missing5[] = {
268 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
269 	0x00, 0x1c, /* len */
270 	/* ExtensionType extension_type */
271 	0x00, 0x10, /* ALPN */
272 	/* opaque extension_data<0..2^16-1> */
273 	0x00, 0x18, /* len */
274 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
275 	0x00, 0x16, /* len of all names */
276 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
277 	0x08, /* len */
278 	0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
279 	/* opaque ProtocolName<1..2^8-1> -- 'h2' */
280 	0x02, /* len */
281 	0x68, 0x32,
282 	/* XXX missing name */
283 };
284 static uint8_t proto_invalid_missing6[] = {
285 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
286 	0x00, 0x07, /* len */
287 	/* ExtensionType extension_type */
288 	0x00, 0x10, /* ALPN */
289 	/* opaque extension_data<0..2^16-1> */
290 	0x00, 0x03, /* len */
291 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
292 	0x00, 0x01, /* XXX len must be at least 2 */
293 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
294 	0x00, /* XXX len cannot be 0 */
295 };
296 static uint8_t proto_invalid_missing7[] = {
297 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
298 	0x00, 0x07, /* len */
299 	/* ExtensionType extension_type */
300 	0x00, 0x10, /* ALPN */
301 	/* opaque extension_data<0..2^16-1> */
302 	0x00, 0x03, /* len */
303 	/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
304 	0x00, 0x02, /* XXX len is at least 2 but not correct. */
305 	/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
306 	0x00, /* XXX len cannot be 0 */
307 };
308 static uint8_t proto_invalid_missing8[] = {
309 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
310 	0x00, 0x01, /* len */
311 	/* ExtensionType extension_type */
312 	0x00, /* XXX need a 2 byte type */
313 };
314 static uint8_t proto_invalid_missing9[] = {
315 	/* Extension extensions<0..2^16-1> -- All TLS extensions */
316 	0x0a, /* XXX need a 2 byte len */
317 };
318 
319 
320 #define CHECK_BOTH(c_val,s_val,proto) do {				\
321 	{								\
322 		unsigned char *p = proto;				\
323 		int al;							\
324 		CHECK(c_val == ssl_parse_clienthello_tlsext(s, &p,	\
325 		    proto, sizeof(proto), &al));			\
326 		p = proto;						\
327 		CHECK(s_val == ssl_parse_serverhello_tlsext(s, &p,	\
328 		    proto, sizeof(proto), &al));			\
329 	}								\
330 } while (0)
331 
332 static int dummy_alpn_cb(SSL *ssl, const unsigned char **out,
333     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
334     void *arg);
335 
336 static int
337 check_valid_alpn(SSL *s)
338 {
339 	const uint8_t str[] = {
340 		0x08, /* len */
341 		0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */
342 	};
343 
344 	/* Setup in order to test ALPN. */
345 	CHECK(! SSL_set_alpn_protos(s, str, 9));
346 	SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL);
347 
348 	/* Prerequisites to test these. */
349 	CHECK(s->alpn_client_proto_list != NULL);
350 	CHECK(s->ctx->alpn_select_cb != NULL);
351 	CHECK(s->s3->tmp.finish_md_len == 0);
352 
353 	CHECK_BOTH(1, 1, proto_single);
354 	CHECK_BOTH(1, 1, proto_empty);
355 
356 	/* Multiple protocol names are only valid for client */
357 	CHECK_BOTH(1, 0, proto_multiple1);
358 	CHECK_BOTH(1, 0, proto_multiple2);
359 	CHECK_BOTH(1, 0, proto_multiple3);
360 
361 	return 1;
362 }
363 
364 /*
365  * Some of the IANA approved IDs from:
366  * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
367  */
368 static int
369 check_invalid_alpn(SSL *s)
370 {
371 	const uint8_t str[] = {
372 		0x08, /* len */
373 		0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */
374 	};
375 
376 	/* Setup in order to test ALPN. */
377 	CHECK(! SSL_set_alpn_protos(s, str, 9));
378 	SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL);
379 
380 	/* Prerequisites to test these. */
381 	CHECK(s->alpn_client_proto_list != NULL);
382 	CHECK(s->ctx->alpn_select_cb != NULL);
383 	CHECK(s->s3->tmp.finish_md_len == 0);
384 
385 	/* None of these are valid for client or server */
386 	CHECK_BOTH(0, 0, proto_invalid_len1);
387 	CHECK_BOTH(0, 0, proto_invalid_len2);
388 	CHECK_BOTH(0, 0, proto_invalid_len3);
389 	CHECK_BOTH(0, 0, proto_invalid_len4);
390 	CHECK_BOTH(0, 0, proto_invalid_len5);
391 	CHECK_BOTH(0, 0, proto_invalid_len6);
392 	CHECK_BOTH(0, 0, proto_invalid_len7);
393 	CHECK_BOTH(0, 0, proto_invalid_len8);
394 	CHECK_BOTH(0, 0, proto_invalid_missing1);
395 	CHECK_BOTH(0, 0, proto_invalid_missing2);
396 	CHECK_BOTH(0, 0, proto_invalid_missing3);
397 	CHECK_BOTH(0, 0, proto_invalid_missing4);
398 	CHECK_BOTH(0, 0, proto_invalid_missing5);
399 	CHECK_BOTH(0, 0, proto_invalid_missing6);
400 	CHECK_BOTH(0, 0, proto_invalid_missing7);
401 	CHECK_BOTH(0, 0, proto_invalid_missing8);
402 	CHECK_BOTH(0, 0, proto_invalid_missing9);
403 
404 	return 1;
405 }
406 
407 int
408 dummy_alpn_cb(SSL *ssl __attribute__((unused)), const unsigned char **out,
409     unsigned char *outlen, const unsigned char *in, unsigned int inlen,
410     void *arg __attribute__((unused)))
411 {
412 	*out = in;
413 	*outlen = (unsigned char)inlen;
414 
415 	return 0;
416 }
417 
418 int
419 main(void)
420 {
421 	SSL_CTX *ctx = NULL;
422 	SSL *s = NULL;
423 	int rv = 1;
424 
425 	SSL_library_init();
426 
427 	CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL);
428 	CHECK_GOTO((s = SSL_new(ctx)) != NULL);
429 
430 	if (!check_valid_alpn(s))
431 		goto err;
432 	if (!check_invalid_alpn(s))
433 		goto err;
434 
435 	rv = 0;
436 
437 err:
438 	SSL_CTX_free(ctx);
439 	SSL_free(s);
440 
441 	if (!rv)
442 		printf("PASS %s\n", __FILE__);
443 	return rv;
444 }
445