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