diff options
Diffstat (limited to 'patches/0008-alpn.patch')
-rw-r--r-- | patches/0008-alpn.patch | 592 |
1 files changed, 0 insertions, 592 deletions
diff --git a/patches/0008-alpn.patch b/patches/0008-alpn.patch deleted file mode 100644 index 6fccbd31fa..0000000000 --- a/patches/0008-alpn.patch +++ /dev/null @@ -1,592 +0,0 @@ -From 5ebeb8b5d90f9f47418b6b8d898ace8f1b4d4104 Mon Sep 17 00:00:00 2001 -From: Adam Langley <agl@chromium.org> -Date: Mon, 15 Apr 2013 18:07:47 -0400 - -This change adds support for ALPN[1] in OpenSSL. ALPN is the IETF -blessed version of NPN and we'll be supporting both ALPN and NPN for -some time yet. - -[1] https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-00 ---- - apps/s_client.c | 40 +++++++++++++- - ssl/s3_lib.c | 13 +++++ - ssl/ssl.h | 45 +++++++++++++++ - ssl/ssl3.h | 10 ++++ - ssl/ssl_lib.c | 87 +++++++++++++++++++++++++++++ - ssl/t1_lib.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- - ssl/tls1.h | 3 + - 7 files changed, 362 insertions(+), 3 deletions(-) - -diff --git a/apps/s_client.c b/apps/s_client.c -index 791e277..cb1efcd 100644 ---- a/apps/s_client.c -+++ b/apps/s_client.c -@@ -359,6 +359,7 @@ static void sc_usage(void) - BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); - # ifndef OPENSSL_NO_NEXTPROTONEG - BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); -+ BIO_printf(bio_err," -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n"); - # endif - #endif - BIO_printf(bio_err," -cutthrough - enable 1-RTT full-handshake for strong ciphers\n"); -@@ -611,6 +612,7 @@ int MAIN(int argc, char **argv) - {NULL,0}; - # ifndef OPENSSL_NO_NEXTPROTONEG - const char *next_proto_neg_in = NULL; -+ const char *alpn_in = NULL; - # endif - #endif - char *sess_in = NULL; -@@ -883,6 +885,11 @@ int MAIN(int argc, char **argv) - if (--argc < 1) goto bad; - next_proto_neg_in = *(++argv); - } -+ else if (strcmp(*argv,"-alpn") == 0) -+ { -+ if (--argc < 1) goto bad; -+ alpn_in = *(++argv); -+ } - # endif - #endif - else if (strcmp(*argv,"-cutthrough") == 0) -@@ -1157,9 +1164,23 @@ bad: - */ - if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); - --#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) -+#if !defined(OPENSSL_NO_TLSEXT) -+# if !defined(OPENSSL_NO_NEXTPROTONEG) - if (next_proto.data) - SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); -+# endif -+ if (alpn_in) -+ { -+ unsigned short alpn_len; -+ unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in); -+ -+ if (alpn == NULL) -+ { -+ BIO_printf(bio_err, "Error parsing -alpn argument\n"); -+ goto end; -+ } -+ SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); -+ } - #endif - - /* Enable handshake cutthrough for client connections using -@@ -2077,7 +2098,8 @@ static void print_stuff(BIO *bio, SSL *s, int full) - } - #endif - --#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) -+#if !defined(OPENSSL_NO_TLSEXT) -+# if !defined(OPENSSL_NO_NEXTPROTONEG) - if (next_proto.status != -1) { - const unsigned char *proto; - unsigned int proto_len; -@@ -2086,6 +2108,20 @@ static void print_stuff(BIO *bio, SSL *s, int full) - BIO_write(bio, proto, proto_len); - BIO_write(bio, "\n", 1); - } -+ { -+ const unsigned char *proto; -+ unsigned int proto_len; -+ SSL_get0_alpn_selected(s, &proto, &proto_len); -+ if (proto_len > 0) -+ { -+ BIO_printf(bio, "ALPN protocol: "); -+ BIO_write(bio, proto, proto_len); -+ BIO_write(bio, "\n", 1); -+ } -+ else -+ BIO_printf(bio, "No ALPN negotiated\n"); -+ } -+# endif - #endif - - #ifndef OPENSSL_NO_SRTP -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 5e46393..2cd1654 100644 ---- a/ssl/s3_lib.c -+++ b/ssl/s3_lib.c -@@ -2996,6 +2996,11 @@ void ssl3_free(SSL *s) - BIO_free(s->s3->handshake_buffer); - } - if (s->s3->handshake_dgst) ssl3_free_digest_list(s); -+#ifndef OPENSSL_NO_TLSEXT -+ if (s->s3->alpn_selected) -+ OPENSSL_free(s->s3->alpn_selected); -+#endif -+ - #ifndef OPENSSL_NO_SRP - SSL_SRP_CTX_free(s); - #endif -@@ -3055,6 +3060,14 @@ void ssl3_clear(SSL *s) - if (s->s3->handshake_dgst) { - ssl3_free_digest_list(s); - } -+ -+#if !defined(OPENSSL_NO_TLSEXT) -+ if (s->s3->alpn_selected) -+ { -+ free(s->s3->alpn_selected); -+ s->s3->alpn_selected = NULL; -+ } -+#endif - memset(s->s3,0,sizeof *s->s3); - s->s3->rbuf.buf = rp; - s->s3->wbuf.buf = wp; -diff --git a/ssl/ssl.h b/ssl/ssl.h -index e8c73fa..612c7aa 100644 ---- a/ssl/ssl.h -+++ b/ssl/ssl.h -@@ -1019,6 +1019,31 @@ struct ssl_ctx_st - void *arg); - void *next_proto_select_cb_arg; - # endif -+ -+ /* ALPN information -+ * (we are in the process of transitioning from NPN to ALPN.) */ -+ -+ /* For a server, this contains a callback function that allows the -+ * server to select the protocol for the connection. -+ * out: on successful return, this must point to the raw protocol -+ * name (without the length prefix). -+ * outlen: on successful return, this contains the length of |*out|. -+ * in: points to the client's list of supported protocols in -+ * wire-format. -+ * inlen: the length of |in|. */ -+ int (*alpn_select_cb)(SSL *s, -+ const unsigned char **out, -+ unsigned char *outlen, -+ const unsigned char* in, -+ unsigned int inlen, -+ void *arg); -+ void *alpn_select_cb_arg; -+ -+ /* For a client, this contains the list of supported protocols in wire -+ * format. */ -+ unsigned char* alpn_client_proto_list; -+ unsigned alpn_client_proto_list_len; -+ - /* SRTP profiles we are willing to do from RFC 5764 */ - STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; - -@@ -1120,6 +1145,21 @@ void SSL_get0_next_proto_negotiated(const SSL *s, - #define OPENSSL_NPN_NO_OVERLAP 2 - #endif - -+int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, -+ unsigned protos_len); -+int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, -+ unsigned protos_len); -+void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, -+ int (*cb) (SSL *ssl, -+ const unsigned char **out, -+ unsigned char *outlen, -+ const unsigned char *in, -+ unsigned int inlen, -+ void *arg), -+ void *arg); -+void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, -+ unsigned *len); -+ - #ifndef OPENSSL_NO_PSK - /* the maximum length of the buffer given to callbacks containing the - * resulting identity/psk */ -@@ -1422,6 +1462,11 @@ struct ssl_st - char tlsext_channel_id_enabled; - /* The client's Channel ID private key. */ - EVP_PKEY *tlsext_channel_id_private; -+ -+ /* For a client, this contains the list of supported protocols in wire -+ * format. */ -+ unsigned char* alpn_client_proto_list; -+ unsigned alpn_client_proto_list_len; - #else - #define session_ctx ctx - #endif /* OPENSSL_NO_TLSEXT */ -diff --git a/ssl/ssl3.h b/ssl/ssl3.h -index 3229995..28c46d5 100644 ---- a/ssl/ssl3.h -+++ b/ssl/ssl3.h -@@ -551,6 +551,16 @@ typedef struct ssl3_state_st - * each are big-endian values. */ - unsigned char tlsext_channel_id[64]; - -+ /* ALPN information -+ * (we are in the process of transitioning from NPN to ALPN.) */ -+ -+ /* In a server these point to the selected ALPN protocol after the -+ * ClientHello has been processed. In a client these contain the -+ * protocol that the server selected once the ServerHello has been -+ * processed. */ -+ unsigned char *alpn_selected; -+ unsigned alpn_selected_len; -+ - /* These point to the digest function to use for signatures made with - * each type of public key. A NULL value indicates that the default - * digest should be used, which is SHA1 as of TLS 1.2. -diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c -index e360550..b472423 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -359,6 +359,17 @@ SSL *SSL_new(SSL_CTX *ctx) - # ifndef OPENSSL_NO_NEXTPROTONEG - s->next_proto_negotiated = NULL; - # endif -+ -+ if (s->ctx->alpn_client_proto_list) -+ { -+ s->alpn_client_proto_list = -+ OPENSSL_malloc(s->ctx->alpn_client_proto_list_len); -+ if (s->alpn_client_proto_list == NULL) -+ goto err; -+ memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list, -+ s->ctx->alpn_client_proto_list_len); -+ s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; -+ } - #endif - - s->verify_result=X509_V_OK; -@@ -564,6 +575,8 @@ void SSL_free(SSL *s) - OPENSSL_free(s->tlsext_ocsp_resp); - if (s->tlsext_channel_id_private) - EVP_PKEY_free(s->tlsext_channel_id_private); -+ if (s->alpn_client_proto_list) -+ OPENSSL_free(s->alpn_client_proto_list); - #endif - - if (s->client_CA != NULL) -@@ -1615,6 +1628,78 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned - ctx->next_proto_select_cb_arg = arg; - } - # endif -+ -+/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. -+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit -+ * length-prefixed strings). -+ * -+ * Returns 0 on success. */ -+int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, -+ unsigned protos_len) -+ { -+ if (ctx->alpn_client_proto_list) -+ OPENSSL_free(ctx->alpn_client_proto_list); -+ -+ ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len); -+ if (!ctx->alpn_client_proto_list) -+ return 1; -+ memcpy(ctx->alpn_client_proto_list, protos, protos_len); -+ ctx->alpn_client_proto_list_len = protos_len; -+ -+ return 0; -+ } -+ -+/* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. -+ * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit -+ * length-prefixed strings). -+ * -+ * Returns 0 on success. */ -+int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, -+ unsigned protos_len) -+ { -+ if (ssl->alpn_client_proto_list) -+ OPENSSL_free(ssl->alpn_client_proto_list); -+ -+ ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len); -+ if (!ssl->alpn_client_proto_list) -+ return 1; -+ memcpy(ssl->alpn_client_proto_list, protos, protos_len); -+ ssl->alpn_client_proto_list_len = protos_len; -+ -+ return 0; -+ } -+ -+/* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called -+ * during ClientHello processing in order to select an ALPN protocol from the -+ * client's list of offered protocols. */ -+void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, -+ int (*cb) (SSL *ssl, -+ const unsigned char **out, -+ unsigned char *outlen, -+ const unsigned char *in, -+ unsigned int inlen, -+ void *arg), -+ void *arg) -+ { -+ ctx->alpn_select_cb = cb; -+ ctx->alpn_select_cb_arg = arg; -+ } -+ -+/* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. -+ * On return it sets |*data| to point to |*len| bytes of protocol name (not -+ * including the leading length-prefix byte). If the server didn't respond with -+ * a negotiated protocol then |*len| will be zero. */ -+void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, -+ unsigned *len) -+ { -+ *data = NULL; -+ if (ssl->s3) -+ *data = ssl->s3->alpn_selected; -+ if (*data == NULL) -+ *len = 0; -+ else -+ *len = ssl->s3->alpn_selected_len; -+ } - #endif - - int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, -@@ -1955,6 +2040,8 @@ void SSL_CTX_free(SSL_CTX *a) - #ifndef OPENSSL_NO_TLSEXT - if (a->tlsext_channel_id_private) - EVP_PKEY_free(a->tlsext_channel_id_private); -+ if (a->alpn_client_proto_list != NULL) -+ OPENSSL_free(a->alpn_client_proto_list); - #endif - - OPENSSL_free(a); -diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c -index 1f93a6f..b2e049a 100644 ---- a/ssl/t1_lib.c -+++ b/ssl/t1_lib.c -@@ -659,6 +659,18 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha - s2n(0,ret); - } - -+ if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) -+ { -+ if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) -+ return NULL; -+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); -+ s2n(2 + s->alpn_client_proto_list_len,ret); -+ s2n(s->alpn_client_proto_list_len,ret); -+ memcpy(ret, s->alpn_client_proto_list, -+ s->alpn_client_proto_list_len); -+ ret += s->alpn_client_proto_list_len; -+ } -+ - #ifndef OPENSSL_NO_SRTP - if(SSL_get_srtp_profiles(s)) - { -@@ -879,6 +891,21 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha - s2n(0,ret); - } - -+ if (s->s3->alpn_selected) -+ { -+ const unsigned char *selected = s->s3->alpn_selected; -+ unsigned len = s->s3->alpn_selected_len; -+ -+ if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) -+ return NULL; -+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); -+ s2n(3 + len,ret); -+ s2n(1 + len,ret); -+ *ret++ = len; -+ memcpy(ret, selected, len); -+ ret += len; -+ } -+ - if ((extdatalen = ret-orig-2)== 0) - return p; - -@@ -966,6 +993,76 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsign - s->is_probably_safari = 1; - } - -+/* tls1_alpn_handle_client_hello is called to process the ALPN extension in a -+ * ClientHello. -+ * data: the contents of the extension, not including the type and length. -+ * data_len: the number of bytes in |data| -+ * al: a pointer to the alert value to send in the event of a non-zero -+ * return. -+ * -+ * returns: 0 on success. */ -+static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data, -+ unsigned data_len, int *al) -+ { -+ unsigned i; -+ unsigned proto_len; -+ const unsigned char *selected; -+ unsigned char selected_len; -+ int r; -+ -+ if (s->ctx->alpn_select_cb == NULL) -+ return 0; -+ -+ if (data_len < 2) -+ goto parse_error; -+ -+ /* data should contain a uint16 length followed by a series of 8-bit, -+ * length-prefixed strings. */ -+ i = ((unsigned) data[0]) << 8 | -+ ((unsigned) data[1]); -+ data_len -= 2; -+ data += 2; -+ if (data_len != i) -+ goto parse_error; -+ -+ if (data_len < 2) -+ goto parse_error; -+ -+ for (i = 0; i < data_len;) -+ { -+ proto_len = data[i]; -+ i++; -+ -+ if (proto_len == 0) -+ goto parse_error; -+ -+ if (i + proto_len < i || i + proto_len > data_len) -+ goto parse_error; -+ -+ i += proto_len; -+ } -+ -+ r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len, -+ s->ctx->alpn_select_cb_arg); -+ if (r == SSL_TLSEXT_ERR_OK) { -+ if (s->s3->alpn_selected) -+ OPENSSL_free(s->s3->alpn_selected); -+ s->s3->alpn_selected = OPENSSL_malloc(selected_len); -+ if (!s->s3->alpn_selected) -+ { -+ *al = SSL_AD_INTERNAL_ERROR; -+ return -1; -+ } -+ memcpy(s->s3->alpn_selected, selected, selected_len); -+ s->s3->alpn_selected_len = selected_len; -+ } -+ return 0; -+ -+parse_error: -+ *al = SSL_AD_DECODE_ERROR; -+ return -1; -+ } -+ - int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) - { - unsigned short type; -@@ -988,6 +1085,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in - s->s3->next_proto_neg_seen = 0; - #endif - -+ if (s->s3->alpn_selected) -+ { -+ OPENSSL_free(s->s3->alpn_selected); -+ s->s3->alpn_selected = NULL; -+ } -+ - #ifndef OPENSSL_NO_HEARTBEATS - s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | - SSL_TLSEXT_HB_DONT_SEND_REQUESTS); -@@ -1420,7 +1523,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in - #endif - #ifndef OPENSSL_NO_NEXTPROTONEG - else if (type == TLSEXT_TYPE_next_proto_neg && -- s->s3->tmp.finish_md_len == 0) -+ s->s3->tmp.finish_md_len == 0 && -+ s->s3->alpn_selected == NULL) - { - /* We shouldn't accept this extension on a - * renegotiation. -@@ -1444,6 +1548,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in - else if (type == TLSEXT_TYPE_channel_id && s->tlsext_channel_id_enabled) - s->s3->tlsext_channel_id_valid = 1; - -+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && -+ s->ctx->alpn_select_cb && -+ s->s3->tmp.finish_md_len == 0) -+ { -+ if (tls1_alpn_handle_client_hello(s, data, size, al) != 0) -+ return 0; -+ /* ALPN takes precedence over NPN. */ -+ s->s3->next_proto_neg_seen = 0; -+ } -+ - /* session ticket processed earlier */ - #ifndef OPENSSL_NO_SRTP - else if (type == TLSEXT_TYPE_use_srtp) -@@ -1508,6 +1622,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in - s->s3->next_proto_neg_seen = 0; - #endif - -+ if (s->s3->alpn_selected) -+ { -+ OPENSSL_free(s->s3->alpn_selected); -+ s->s3->alpn_selected = NULL; -+ } -+ - #ifndef OPENSSL_NO_HEARTBEATS - s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED | - SSL_TLSEXT_HB_DONT_SEND_REQUESTS); -@@ -1677,6 +1797,51 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in - else if (type == TLSEXT_TYPE_channel_id) - s->s3->tlsext_channel_id_valid = 1; - -+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) -+ { -+ unsigned len; -+ -+ /* We must have requested it. */ -+ if (s->alpn_client_proto_list == NULL) -+ { -+ *al = TLS1_AD_UNSUPPORTED_EXTENSION; -+ return 0; -+ } -+ if (size < 4) -+ { -+ *al = TLS1_AD_DECODE_ERROR; -+ return 0; -+ } -+ /* The extension data consists of: -+ * uint16 list_length -+ * uint8 proto_length; -+ * uint8 proto[proto_length]; */ -+ len = data[0]; -+ len <<= 8; -+ len |= data[1]; -+ if (len != (unsigned) size - 2) -+ { -+ *al = TLS1_AD_DECODE_ERROR; -+ return 0; -+ } -+ len = data[2]; -+ if (len != (unsigned) size - 3) -+ { -+ *al = TLS1_AD_DECODE_ERROR; -+ return 0; -+ } -+ if (s->s3->alpn_selected) -+ OPENSSL_free(s->s3->alpn_selected); -+ s->s3->alpn_selected = OPENSSL_malloc(len); -+ if (!s->s3->alpn_selected) -+ { -+ *al = TLS1_AD_INTERNAL_ERROR; -+ return 0; -+ } -+ memcpy(s->s3->alpn_selected, data + 3, len); -+ s->s3->alpn_selected_len = len; -+ } -+ - else if (type == TLSEXT_TYPE_renegotiate) - { - if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) -diff --git a/ssl/tls1.h b/ssl/tls1.h -index 8fc1ff4..c6670f4 100644 ---- a/ssl/tls1.h -+++ b/ssl/tls1.h -@@ -230,6 +230,9 @@ extern "C" { - /* ExtensionType value from RFC5620 */ - #define TLSEXT_TYPE_heartbeat 15 - -+/* ExtensionType value from draft-ietf-tls-applayerprotoneg-00 */ -+#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 -+ - /* ExtensionType value from RFC4507 */ - #define TLSEXT_TYPE_session_ticket 35 - --- -1.8.2.1 - |