1 From 5ebeb8b5d90f9f47418b6b8d898ace8f1b4d4104 Mon Sep 17 00:00:00 2001 2 From: Adam Langley <agl (a] chromium.org> 3 Date: Mon, 15 Apr 2013 18:07:47 -0400 4 5 This change adds support for ALPN[1] in OpenSSL. ALPN is the IETF 6 blessed version of NPN and we'll be supporting both ALPN and NPN for 7 some time yet. 8 9 [1] https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-00 10 --- 11 apps/s_client.c | 40 +++++++++++++- 12 ssl/s3_lib.c | 13 +++++ 13 ssl/ssl.h | 45 +++++++++++++++ 14 ssl/ssl3.h | 10 ++++ 15 ssl/ssl_lib.c | 87 +++++++++++++++++++++++++++++ 16 ssl/t1_lib.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 17 ssl/tls1.h | 3 + 18 7 files changed, 362 insertions(+), 3 deletions(-) 19 20 diff --git a/apps/s_client.c b/apps/s_client.c 21 index 791e277..cb1efcd 100644 22 --- a/apps/s_client.c 23 +++ b/apps/s_client.c 24 @@ -359,6 +359,7 @@ static void sc_usage(void) 25 BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); 26 # ifndef OPENSSL_NO_NEXTPROTONEG 27 BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); 28 + BIO_printf(bio_err," -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n"); 29 # endif 30 #endif 31 BIO_printf(bio_err," -cutthrough - enable 1-RTT full-handshake for strong ciphers\n"); 32 @@ -611,6 +612,7 @@ int MAIN(int argc, char **argv) 33 {NULL,0}; 34 # ifndef OPENSSL_NO_NEXTPROTONEG 35 const char *next_proto_neg_in = NULL; 36 + const char *alpn_in = NULL; 37 # endif 38 #endif 39 char *sess_in = NULL; 40 @@ -883,6 +885,11 @@ int MAIN(int argc, char **argv) 41 if (--argc < 1) goto bad; 42 next_proto_neg_in = *(++argv); 43 } 44 + else if (strcmp(*argv,"-alpn") == 0) 45 + { 46 + if (--argc < 1) goto bad; 47 + alpn_in = *(++argv); 48 + } 49 # endif 50 #endif 51 else if (strcmp(*argv,"-cutthrough") == 0) 52 @@ -1157,9 +1164,23 @@ bad: 53 */ 54 if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); 55 56 -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) 57 +#if !defined(OPENSSL_NO_TLSEXT) 58 +# if !defined(OPENSSL_NO_NEXTPROTONEG) 59 if (next_proto.data) 60 SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); 61 +# endif 62 + if (alpn_in) 63 + { 64 + unsigned short alpn_len; 65 + unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in); 66 + 67 + if (alpn == NULL) 68 + { 69 + BIO_printf(bio_err, "Error parsing -alpn argument\n"); 70 + goto end; 71 + } 72 + SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); 73 + } 74 #endif 75 76 /* Enable handshake cutthrough for client connections using 77 @@ -2077,7 +2098,8 @@ static void print_stuff(BIO *bio, SSL *s, int full) 78 } 79 #endif 80 81 -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) 82 +#if !defined(OPENSSL_NO_TLSEXT) 83 +# if !defined(OPENSSL_NO_NEXTPROTONEG) 84 if (next_proto.status != -1) { 85 const unsigned char *proto; 86 unsigned int proto_len; 87 @@ -2086,6 +2108,20 @@ static void print_stuff(BIO *bio, SSL *s, int full) 88 BIO_write(bio, proto, proto_len); 89 BIO_write(bio, "\n", 1); 90 } 91 + { 92 + const unsigned char *proto; 93 + unsigned int proto_len; 94 + SSL_get0_alpn_selected(s, &proto, &proto_len); 95 + if (proto_len > 0) 96 + { 97 + BIO_printf(bio, "ALPN protocol: "); 98 + BIO_write(bio, proto, proto_len); 99 + BIO_write(bio, "\n", 1); 100 + } 101 + else 102 + BIO_printf(bio, "No ALPN negotiated\n"); 103 + } 104 +# endif 105 #endif 106 107 #ifndef OPENSSL_NO_SRTP 108 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c 109 index 5e46393..2cd1654 100644 110 --- a/ssl/s3_lib.c 111 +++ b/ssl/s3_lib.c 112 @@ -2996,6 +2996,11 @@ void ssl3_free(SSL *s) 113 BIO_free(s->s3->handshake_buffer); 114 } 115 if (s->s3->handshake_dgst) ssl3_free_digest_list(s); 116 +#ifndef OPENSSL_NO_TLSEXT 117 + if (s->s3->alpn_selected) 118 + OPENSSL_free(s->s3->alpn_selected); 119 +#endif 120 + 121 #ifndef OPENSSL_NO_SRP 122 SSL_SRP_CTX_free(s); 123 #endif 124 @@ -3055,6 +3060,14 @@ void ssl3_clear(SSL *s) 125 if (s->s3->handshake_dgst) { 126 ssl3_free_digest_list(s); 127 } 128 + 129 +#if !defined(OPENSSL_NO_TLSEXT) 130 + if (s->s3->alpn_selected) 131 + { 132 + free(s->s3->alpn_selected); 133 + s->s3->alpn_selected = NULL; 134 + } 135 +#endif 136 memset(s->s3,0,sizeof *s->s3); 137 s->s3->rbuf.buf = rp; 138 s->s3->wbuf.buf = wp; 139 diff --git a/ssl/ssl.h b/ssl/ssl.h 140 index e8c73fa..612c7aa 100644 141 --- a/ssl/ssl.h 142 +++ b/ssl/ssl.h 143 @@ -1019,6 +1019,31 @@ struct ssl_ctx_st 144 void *arg); 145 void *next_proto_select_cb_arg; 146 # endif 147 + 148 + /* ALPN information 149 + * (we are in the process of transitioning from NPN to ALPN.) */ 150 + 151 + /* For a server, this contains a callback function that allows the 152 + * server to select the protocol for the connection. 153 + * out: on successful return, this must point to the raw protocol 154 + * name (without the length prefix). 155 + * outlen: on successful return, this contains the length of |*out|. 156 + * in: points to the client's list of supported protocols in 157 + * wire-format. 158 + * inlen: the length of |in|. */ 159 + int (*alpn_select_cb)(SSL *s, 160 + const unsigned char **out, 161 + unsigned char *outlen, 162 + const unsigned char* in, 163 + unsigned int inlen, 164 + void *arg); 165 + void *alpn_select_cb_arg; 166 + 167 + /* For a client, this contains the list of supported protocols in wire 168 + * format. */ 169 + unsigned char* alpn_client_proto_list; 170 + unsigned alpn_client_proto_list_len; 171 + 172 /* SRTP profiles we are willing to do from RFC 5764 */ 173 STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; 174 175 @@ -1120,6 +1145,21 @@ void SSL_get0_next_proto_negotiated(const SSL *s, 176 #define OPENSSL_NPN_NO_OVERLAP 2 177 #endif 178 179 +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, 180 + unsigned protos_len); 181 +int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, 182 + unsigned protos_len); 183 +void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, 184 + int (*cb) (SSL *ssl, 185 + const unsigned char **out, 186 + unsigned char *outlen, 187 + const unsigned char *in, 188 + unsigned int inlen, 189 + void *arg), 190 + void *arg); 191 +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, 192 + unsigned *len); 193 + 194 #ifndef OPENSSL_NO_PSK 195 /* the maximum length of the buffer given to callbacks containing the 196 * resulting identity/psk */ 197 @@ -1422,6 +1462,11 @@ struct ssl_st 198 char tlsext_channel_id_enabled; 199 /* The client's Channel ID private key. */ 200 EVP_PKEY *tlsext_channel_id_private; 201 + 202 + /* For a client, this contains the list of supported protocols in wire 203 + * format. */ 204 + unsigned char* alpn_client_proto_list; 205 + unsigned alpn_client_proto_list_len; 206 #else 207 #define session_ctx ctx 208 #endif /* OPENSSL_NO_TLSEXT */ 209 diff --git a/ssl/ssl3.h b/ssl/ssl3.h 210 index 3229995..28c46d5 100644 211 --- a/ssl/ssl3.h 212 +++ b/ssl/ssl3.h 213 @@ -551,6 +551,16 @@ typedef struct ssl3_state_st 214 * each are big-endian values. */ 215 unsigned char tlsext_channel_id[64]; 216 217 + /* ALPN information 218 + * (we are in the process of transitioning from NPN to ALPN.) */ 219 + 220 + /* In a server these point to the selected ALPN protocol after the 221 + * ClientHello has been processed. In a client these contain the 222 + * protocol that the server selected once the ServerHello has been 223 + * processed. */ 224 + unsigned char *alpn_selected; 225 + unsigned alpn_selected_len; 226 + 227 /* These point to the digest function to use for signatures made with 228 * each type of public key. A NULL value indicates that the default 229 * digest should be used, which is SHA1 as of TLS 1.2. 230 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c 231 index e360550..b472423 100644 232 --- a/ssl/ssl_lib.c 233 +++ b/ssl/ssl_lib.c 234 @@ -359,6 +359,17 @@ SSL *SSL_new(SSL_CTX *ctx) 235 # ifndef OPENSSL_NO_NEXTPROTONEG 236 s->next_proto_negotiated = NULL; 237 # endif 238 + 239 + if (s->ctx->alpn_client_proto_list) 240 + { 241 + s->alpn_client_proto_list = 242 + OPENSSL_malloc(s->ctx->alpn_client_proto_list_len); 243 + if (s->alpn_client_proto_list == NULL) 244 + goto err; 245 + memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list, 246 + s->ctx->alpn_client_proto_list_len); 247 + s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; 248 + } 249 #endif 250 251 s->verify_result=X509_V_OK; 252 @@ -564,6 +575,8 @@ void SSL_free(SSL *s) 253 OPENSSL_free(s->tlsext_ocsp_resp); 254 if (s->tlsext_channel_id_private) 255 EVP_PKEY_free(s->tlsext_channel_id_private); 256 + if (s->alpn_client_proto_list) 257 + OPENSSL_free(s->alpn_client_proto_list); 258 #endif 259 260 if (s->client_CA != NULL) 261 @@ -1615,6 +1628,78 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned 262 ctx->next_proto_select_cb_arg = arg; 263 } 264 # endif 265 + 266 +/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. 267 + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit 268 + * length-prefixed strings). 269 + * 270 + * Returns 0 on success. */ 271 +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, 272 + unsigned protos_len) 273 + { 274 + if (ctx->alpn_client_proto_list) 275 + OPENSSL_free(ctx->alpn_client_proto_list); 276 + 277 + ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len); 278 + if (!ctx->alpn_client_proto_list) 279 + return 1; 280 + memcpy(ctx->alpn_client_proto_list, protos, protos_len); 281 + ctx->alpn_client_proto_list_len = protos_len; 282 + 283 + return 0; 284 + } 285 + 286 +/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. 287 + * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit 288 + * length-prefixed strings). 289 + * 290 + * Returns 0 on success. */ 291 +int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, 292 + unsigned protos_len) 293 + { 294 + if (ssl->alpn_client_proto_list) 295 + OPENSSL_free(ssl->alpn_client_proto_list); 296 + 297 + ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len); 298 + if (!ssl->alpn_client_proto_list) 299 + return 1; 300 + memcpy(ssl->alpn_client_proto_list, protos, protos_len); 301 + ssl->alpn_client_proto_list_len = protos_len; 302 + 303 + return 0; 304 + } 305 + 306 +/* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called 307 + * during ClientHello processing in order to select an ALPN protocol from the 308 + * client's list of offered protocols. */ 309 +void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, 310 + int (*cb) (SSL *ssl, 311 + const unsigned char **out, 312 + unsigned char *outlen, 313 + const unsigned char *in, 314 + unsigned int inlen, 315 + void *arg), 316 + void *arg) 317 + { 318 + ctx->alpn_select_cb = cb; 319 + ctx->alpn_select_cb_arg = arg; 320 + } 321 + 322 +/* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. 323 + * On return it sets |*data| to point to |*len| bytes of protocol name (not 324 + * including the leading length-prefix byte). If the server didn't respond with 325 + * a negotiated protocol then |*len| will be zero. */ 326 +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, 327 + unsigned *len) 328 + { 329 + *data = NULL; 330 + if (ssl->s3) 331 + *data = ssl->s3->alpn_selected; 332 + if (*data == NULL) 333 + *len = 0; 334 + else 335 + *len = ssl->s3->alpn_selected_len; 336 + } 337 #endif 338 339 int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, 340 @@ -1955,6 +2040,8 @@ void SSL_CTX_free(SSL_CTX *a) 341 #ifndef OPENSSL_NO_TLSEXT 342 if (a->tlsext_channel_id_private) 343 EVP_PKEY_free(a->tlsext_channel_id_private); 344 + if (a->alpn_client_proto_list != NULL) 345 + OPENSSL_free(a->alpn_client_proto_list); 346 #endif 347 348 OPENSSL_free(a); 349 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c 350 index 1f93a6f..b2e049a 100644 351 --- a/ssl/t1_lib.c 352 +++ b/ssl/t1_lib.c 353 @@ -659,6 +659,18 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha 354 s2n(0,ret); 355 } 356 357 + if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) 358 + { 359 + if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) 360 + return NULL; 361 + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); 362 + s2n(2 + s->alpn_client_proto_list_len,ret); 363 + s2n(s->alpn_client_proto_list_len,ret); 364 + memcpy(ret, s->alpn_client_proto_list, 365 + s->alpn_client_proto_list_len); 366 + ret += s->alpn_client_proto_list_len; 367 + } 368 + 369 #ifndef OPENSSL_NO_SRTP 370 if(SSL_get_srtp_profiles(s)) 371 { 372 @@ -879,6 +891,21 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha 373 s2n(0,ret); 374 } 375 376 + if (s->s3->alpn_selected) 377 + { 378 + const unsigned char *selected = s->s3->alpn_selected; 379 + unsigned len = s->s3->alpn_selected_len; 380 + 381 + if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) 382 + return NULL; 383 + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); 384 + s2n(3 + len,ret); 385 + s2n(1 + len,ret); 386 + *ret++ = len; 387 + memcpy(ret, selected, len); 388 + ret += len; 389 + } 390 + 391 if ((extdatalen = ret-orig-2)== 0) 392 return p; 393 394 @@ -966,6 +993,76 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsign 395 s->is_probably_safari = 1; 396 } 397 398 +/* tls1_alpn_handle_client_hello is called to process the ALPN extension in a 399 + * ClientHello. 400 + * data: the contents of the extension, not including the type and length. 401 + * data_len: the number of bytes in |data| 402 + * al: a pointer to the alert value to send in the event of a non-zero 403 + * return. 404 + * 405 + * returns: 0 on success. */ 406 +static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data, 407 + unsigned data_len, int *al) 408 + { 409 + unsigned i; 410 + unsigned proto_len; 411 + const unsigned char *selected; 412 + unsigned char selected_len; 413 + int r; 414 + 415 + if (s->ctx->alpn_select_cb == NULL) 416 + return 0; 417 + 418 + if (data_len < 2) 419 + goto parse_error; 420 + 421 + /* data should contain a uint16 length followed by a series of 8-bit, 422 + * length-prefixed strings. */ 423 + i = ((unsigned) data[0]) << 8 | 424 + ((unsigned) data[1]); 425 + data_len -= 2; 426 + data += 2; 427 + if (data_len != i) 428 + goto parse_error; 429 + 430 + if (data_len < 2) 431 + goto parse_error; 432 + 433 + for (i = 0; i < data_len;) 434 + { 435 + proto_len = data[i]; 436 + i++; 437 + 438 + if (proto_len == 0) 439 + goto parse_error; 440 + 441 + if (i + proto_len < i || i + proto_len > data_len) 442 + goto parse_error; 443 + 444 + i += proto_len; 445 + } 446 + 447 + r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len, 448 + s->ctx->alpn_select_cb_arg); 449 + if (r == SSL_TLSEXT_ERR_OK) { 450 + if (s->s3->alpn_selected) 451 + OPENSSL_free(s->s3->alpn_selected); 452 + s->s3->alpn_selected = OPENSSL_malloc(selected_len); 453 + if (!s->s3->alpn_selected) 454 + { 455 + *al = SSL_AD_INTERNAL_ERROR; 456 + return -1; 457 + } 458 + memcpy(s->s3->alpn_selected, selected, selected_len); 459 + s->s3->alpn_selected_len = selected_len; 460 + } 461 + return 0; 462 + 463 +parse_error: 464 + *al = SSL_AD_DECODE_ERROR; 465 + return -1; 466 + } 467 + 468 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) 469 { 470 unsigned short type; 471 @@ -988,6 +1085,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 472 s->s3->next_proto_neg_seen = 0; 473 #endif 474 475 + if (s->s3->alpn_selected) 476 + { 477 + OPENSSL_free(s->s3->alpn_selected); 478 + s->s3->alpn_selected = NULL; 479 + } 480 + 481 #ifndef OPENSSL_NO_HEARTBEATS 482 s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | 483 SSL_TLSEXT_HB_DONT_SEND_REQUESTS); 484 @@ -1420,7 +1523,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 485 #endif 486 #ifndef OPENSSL_NO_NEXTPROTONEG 487 else if (type == TLSEXT_TYPE_next_proto_neg && 488 - s->s3->tmp.finish_md_len == 0) 489 + s->s3->tmp.finish_md_len == 0 && 490 + s->s3->alpn_selected == NULL) 491 { 492 /* We shouldn't accept this extension on a 493 * renegotiation. 494 @@ -1444,6 +1548,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 495 else if (type == TLSEXT_TYPE_channel_id && s->tlsext_channel_id_enabled) 496 s->s3->tlsext_channel_id_valid = 1; 497 498 + else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && 499 + s->ctx->alpn_select_cb && 500 + s->s3->tmp.finish_md_len == 0) 501 + { 502 + if (tls1_alpn_handle_client_hello(s, data, size, al) != 0) 503 + return 0; 504 + /* ALPN takes precedence over NPN. */ 505 + s->s3->next_proto_neg_seen = 0; 506 + } 507 + 508 /* session ticket processed earlier */ 509 #ifndef OPENSSL_NO_SRTP 510 else if (type == TLSEXT_TYPE_use_srtp) 511 @@ -1508,6 +1622,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 512 s->s3->next_proto_neg_seen = 0; 513 #endif 514 515 + if (s->s3->alpn_selected) 516 + { 517 + OPENSSL_free(s->s3->alpn_selected); 518 + s->s3->alpn_selected = NULL; 519 + } 520 + 521 #ifndef OPENSSL_NO_HEARTBEATS 522 s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | 523 SSL_TLSEXT_HB_DONT_SEND_REQUESTS); 524 @@ -1677,6 +1797,51 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 525 else if (type == TLSEXT_TYPE_channel_id) 526 s->s3->tlsext_channel_id_valid = 1; 527 528 + else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) 529 + { 530 + unsigned len; 531 + 532 + /* We must have requested it. */ 533 + if (s->alpn_client_proto_list == NULL) 534 + { 535 + *al = TLS1_AD_UNSUPPORTED_EXTENSION; 536 + return 0; 537 + } 538 + if (size < 4) 539 + { 540 + *al = TLS1_AD_DECODE_ERROR; 541 + return 0; 542 + } 543 + /* The extension data consists of: 544 + * uint16 list_length 545 + * uint8 proto_length; 546 + * uint8 proto[proto_length]; */ 547 + len = data[0]; 548 + len <<= 8; 549 + len |= data[1]; 550 + if (len != (unsigned) size - 2) 551 + { 552 + *al = TLS1_AD_DECODE_ERROR; 553 + return 0; 554 + } 555 + len = data[2]; 556 + if (len != (unsigned) size - 3) 557 + { 558 + *al = TLS1_AD_DECODE_ERROR; 559 + return 0; 560 + } 561 + if (s->s3->alpn_selected) 562 + OPENSSL_free(s->s3->alpn_selected); 563 + s->s3->alpn_selected = OPENSSL_malloc(len); 564 + if (!s->s3->alpn_selected) 565 + { 566 + *al = TLS1_AD_INTERNAL_ERROR; 567 + return 0; 568 + } 569 + memcpy(s->s3->alpn_selected, data + 3, len); 570 + s->s3->alpn_selected_len = len; 571 + } 572 + 573 else if (type == TLSEXT_TYPE_renegotiate) 574 { 575 if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) 576 diff --git a/ssl/tls1.h b/ssl/tls1.h 577 index 8fc1ff4..c6670f4 100644 578 --- a/ssl/tls1.h 579 +++ b/ssl/tls1.h 580 @@ -230,6 +230,9 @@ extern "C" { 581 /* ExtensionType value from RFC5620 */ 582 #define TLSEXT_TYPE_heartbeat 15 583 584 +/* ExtensionType value from draft-ietf-tls-applayerprotoneg-00 */ 585 +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 586 + 587 /* ExtensionType value from RFC4507 */ 588 #define TLSEXT_TYPE_session_ticket 35 589 590 -- 591 1.8.2.1 592 593