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