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