summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2013-06-26 10:25:44 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2013-06-26 10:25:44 -0700
commit0613b7a7a289f883d9d1f7465fea8d024a82a55b (patch)
treea56046f94a7cf3e0ba40fbf889038e287f4990c7
parentd1175680fa9036ea776aaa4134b337e4c57c5b79 (diff)
parent7b972f1aa23172c4430ada7f3236fa1fd9b31756 (diff)
downloadreplicant_openssl-0613b7a7a289f883d9d1f7465fea8d024a82a55b.zip
replicant_openssl-0613b7a7a289f883d9d1f7465fea8d024a82a55b.tar.gz
replicant_openssl-0613b7a7a289f883d9d1f7465fea8d024a82a55b.tar.bz2
am 7b972f1a: Merge changes I556b1ee8,I11b74472
* commit '7b972f1aa23172c4430ada7f3236fa1fd9b31756': Add ALPN support patch Add TLS 1.2 digests patch
-rw-r--r--apps/s_client.c40
-rw-r--r--include/openssl/ssl.h45
-rw-r--r--include/openssl/ssl3.h21
-rw-r--r--include/openssl/tls1.h3
-rw-r--r--openssl.config21
-rw-r--r--patches/README11
-rw-r--r--patches/alpn.patch592
-rw-r--r--patches/tls12_digests.patch411
-rw-r--r--ssl/s3_clnt.c26
-rw-r--r--ssl/s3_lib.c13
-rw-r--r--ssl/ssl.h45
-rw-r--r--ssl/ssl3.h21
-rw-r--r--ssl/ssl_cert.c20
-rw-r--r--ssl/ssl_lib.c122
-rw-r--r--ssl/ssl_locl.h4
-rw-r--r--ssl/t1_lib.c271
-rw-r--r--ssl/tls1.h3
17 files changed, 1559 insertions, 110 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/include/openssl/ssl.h b/include/openssl/ssl.h
index 61b110f..dac9c3e 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -979,6 +979,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;
@@ -1075,6 +1100,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 */
@@ -1365,6 +1405,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/include/openssl/ssl3.h b/include/openssl/ssl3.h
index fee9671..4729868 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -550,6 +550,26 @@ typedef struct ssl3_state_st
* verified Channel ID from the client: a P256 point, (x,y), where
* 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.
+ *
+ * (These should be in the tmp member, but we have to put them here to
+ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
+ const EVP_MD *digest_rsa;
+ const EVP_MD *digest_dsa;
+ const EVP_MD *digest_ecdsa;
} SSL3_STATE;
#endif
@@ -699,4 +719,3 @@ typedef struct ssl3_state_st
}
#endif
#endif
-
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 8fc1ff4..c6670f4 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/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
diff --git a/openssl.config b/openssl.config
index d5c0aa4..00e4ff9 100644
--- a/openssl.config
+++ b/openssl.config
@@ -991,6 +991,8 @@ jsse.patch \
channelid.patch \
eng_dyn_dirs.patch \
fix_clang_build.patch \
+tls12_digests.patch \
+alpn.patch \
"
OPENSSL_PATCHES_progs_SOURCES="\
@@ -1047,3 +1049,22 @@ crypto/bio/b_sock.c \
crypto/x509v3/v3_utl.c \
"
+OPENSSL_PATCHES_tls12_digests_SOURCES="\
+ssl/s3_clnt.c \
+ssl/ssl3.h \
+ssl/ssl_cert.c \
+ssl/ssl_lib.c \
+ssl/ssl_locl.h \
+ssl/t1_lib.c \
+"
+
+OPENSSL_PATCHES_alpn_SOURCES="\
+apps/s_client.c \
+ssl/s3_lib.c \
+ssl/ssl.h \
+ssl/ssl3.h \
+ssl/ssl_lib.c \
+ssl/t1_lib.c \
+ssl/tls1.h \
+"
+
diff --git a/patches/README b/patches/README
index 5d9ef03..0859abe 100644
--- a/patches/README
+++ b/patches/README
@@ -26,3 +26,14 @@ Fixes the case of having multiple DIR_ADD commands sent to eng_dyn
fix_clang_build.patch
Fixes the Clang based build.
+
+tls12_digests.patch
+
+Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA
+keys.
+
+alpn.patch
+
+This change adds support for ALPN in OpenSSL. ALPN is the IETF
+blessed version of NPN and we'll be supporting both ALPN and NPN for
+some time yet.
diff --git a/patches/alpn.patch b/patches/alpn.patch
new file mode 100644
index 0000000..084ac32
--- /dev/null
+++ b/patches/alpn.patch
@@ -0,0 +1,592 @@
+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-p-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
+
diff --git a/patches/tls12_digests.patch b/patches/tls12_digests.patch
new file mode 100644
index 0000000..11f7c27
--- /dev/null
+++ b/patches/tls12_digests.patch
@@ -0,0 +1,411 @@
+From 3a8c7b1a08b2766a7f8a388eee14442281b4e295 Mon Sep 17 00:00:00 2001
+From: Adam Langley <agl@chromium.org>
+Date: Thu, 24 Jan 2013 16:27:14 -0500
+Subject: [PATCH 19/36] tls12_digests
+
+Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA
+keys.
+---
+ ssl/s3_clnt.c | 26 +++++++++++++--
+ ssl/ssl3.h | 11 +++++-
+ ssl/ssl_cert.c | 20 -----------
+ ssl/ssl_lib.c | 35 +++++++++++--------
+ ssl/ssl_locl.h | 4 +--
+ ssl/t1_lib.c | 104 ++++++++++++++++++++-------------------------------------
+ 6 files changed, 94 insertions(+), 106 deletions(-)
+
+diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
+index c9196b3..1f3b376 100644
+--- a/ssl/s3_clnt.c
++++ b/ssl/s3_clnt.c
+@@ -1990,12 +1990,13 @@ int ssl3_get_certificate_request(SSL *s)
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+- if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
++ if (llen & 1)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ goto err;
+ }
++ tls1_process_sigalgs(s, p, llen);
+ p += llen;
+ }
+
+@@ -3017,7 +3018,28 @@ int ssl3_send_client_verify(SSL *s)
+ {
+ long hdatalen = 0;
+ void *hdata;
+- const EVP_MD *md = s->cert->key->digest;
++ const EVP_MD *md;
++ switch (ssl_cert_type(NULL, pkey))
++ {
++ case SSL_PKEY_RSA_ENC:
++ md = s->s3->digest_rsa;
++ break;
++ case SSL_PKEY_DSA_SIGN:
++ md = s->s3->digest_dsa;
++ break;
++ case SSL_PKEY_ECC:
++ md = s->s3->digest_ecdsa;
++ break;
++ default:
++ md = NULL;
++ }
++ if (!md)
++ /* Unlike with the SignatureAlgorithm extension (sent by clients),
++ * there are no default algorithms for the CertificateRequest message
++ * (sent by servers). However, now that we've sent a certificate
++ * for which we don't really know what hash to use for signing, the
++ * best we can do is try a default algorithm. */
++ md = EVP_sha1();
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
+ &hdata);
+ if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
+diff --git a/ssl/ssl3.h b/ssl/ssl3.h
+index 29098e4..3229995 100644
+--- a/ssl/ssl3.h
++++ b/ssl/ssl3.h
+@@ -550,6 +550,16 @@ typedef struct ssl3_state_st
+ * verified Channel ID from the client: a P256 point, (x,y), where
+ * each are big-endian values. */
+ unsigned char tlsext_channel_id[64];
++
++ /* 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.
++ *
++ * (These should be in the tmp member, but we have to put them here to
++ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
++ const EVP_MD *digest_rsa;
++ const EVP_MD *digest_dsa;
++ const EVP_MD *digest_ecdsa;
+ } SSL3_STATE;
+
+ #endif
+@@ -700,4 +710,3 @@ typedef struct ssl3_state_st
+ }
+ #endif
+ #endif
+-
+diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
+index 5123a89..bc4150b 100644
+--- a/ssl/ssl_cert.c
++++ b/ssl/ssl_cert.c
+@@ -160,21 +160,6 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+ return ssl_x509_store_ctx_idx;
+ }
+
+-static void ssl_cert_set_default_md(CERT *cert)
+- {
+- /* Set digest values to defaults */
+-#ifndef OPENSSL_NO_DSA
+- cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_RSA
+- cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+- cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_ECDSA
+- cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
+-#endif
+- }
+-
+ CERT *ssl_cert_new(void)
+ {
+ CERT *ret;
+@@ -189,7 +174,6 @@ CERT *ssl_cert_new(void)
+
+ ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
+ ret->references=1;
+- ssl_cert_set_default_md(ret);
+ return(ret);
+ }
+
+@@ -322,10 +306,6 @@ CERT *ssl_cert_dup(CERT *cert)
+ * chain is held inside SSL_CTX */
+
+ ret->references=1;
+- /* Set digests to defaults. NB: we don't copy existing values as they
+- * will be set during handshake.
+- */
+- ssl_cert_set_default_md(ret);
+
+ return(ret);
+
+diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
+index 5f8b0b0..e360550 100644
+--- a/ssl/ssl_lib.c
++++ b/ssl/ssl_lib.c
+@@ -2345,32 +2345,41 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
+ {
+ unsigned long alg_a;
+ CERT *c;
+- int idx = -1;
+
+ alg_a = cipher->algorithm_auth;
+ c=s->cert;
+
++ /* SHA1 is the default for all signature algorithms up to TLS 1.2,
++ * except RSA which is handled specially in s3_srvr.c */
++ if (pmd)
++ *pmd = EVP_sha1();
++
+ if ((alg_a & SSL_aDSS) &&
+- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+- idx = SSL_PKEY_DSA_SIGN;
++ (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
++ {
++ if (pmd && s->s3 && s->s3->digest_dsa)
++ *pmd = s->s3->digest_dsa;
++ return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey;
++ }
+ else if (alg_a & SSL_aRSA)
+ {
++ if (pmd && s->s3 && s->s3->digest_rsa)
++ *pmd = s->s3->digest_rsa;
+ if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
+- idx = SSL_PKEY_RSA_SIGN;
+- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+- idx = SSL_PKEY_RSA_ENC;
++ return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey;
++ if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
++ return c->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+ }
+ else if ((alg_a & SSL_aECDSA) &&
+ (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
+- idx = SSL_PKEY_ECC;
+- if (idx == -1)
+ {
+- SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
+- return(NULL);
++ if (pmd && s->s3 && s->s3->digest_ecdsa)
++ *pmd = s->s3->digest_ecdsa;
++ return c->pkeys[SSL_PKEY_ECC].privatekey;
+ }
+- if (pmd)
+- *pmd = c->pkeys[idx].digest;
+- return c->pkeys[idx].privatekey;
++
++ SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
++ return(NULL);
+ }
+
+ void ssl_update_cache(SSL *s,int mode)
+diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
+index 6d38f0f..3e89fcb 100644
+--- a/ssl/ssl_locl.h
++++ b/ssl/ssl_locl.h
+@@ -485,8 +485,6 @@ typedef struct cert_pkey_st
+ {
+ X509 *x509;
+ EVP_PKEY *privatekey;
+- /* Digest to use when signing */
+- const EVP_MD *digest;
+ } CERT_PKEY;
+
+ typedef struct cert_st
+@@ -1142,7 +1140,7 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+ int *al);
+ long ssl_get_algorithm2(SSL *s);
+-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
++void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
+ int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
+
+ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
+diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
+index 26805e4..6af51a9 100644
+--- a/ssl/t1_lib.c
++++ b/ssl/t1_lib.c
+@@ -897,6 +897,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
+
+ s->servername_done = 0;
+ s->tlsext_status_type = -1;
++
++ /* Reset TLS 1.2 digest functions to defaults because they don't carry
++ * over to a renegotiation. */
++ s->s3->digest_rsa = NULL;
++ s->s3->digest_dsa = NULL;
++ s->s3->digest_ecdsa = NULL;
++
+ #ifndef OPENSSL_NO_NEXTPROTONEG
+ s->s3->next_proto_neg_seen = 0;
+ #endif
+@@ -1198,11 +1205,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+- if (!tls1_process_sigalgs(s, data, dsize))
+- {
+- *al = SSL_AD_DECODE_ERROR;
+- return 0;
+- }
++ tls1_process_sigalgs(s, data, dsize);
+ }
+ else if (type == TLSEXT_TYPE_status_request &&
+ s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+@@ -2354,18 +2357,6 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
+ }
+ return -1;
+ }
+-#if 0
+-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
+- {
+- size_t i;
+- for (i = 0; i < tlen; i++)
+- {
+- if (table[i].id == id)
+- return table[i].nid;
+- }
+- return -1;
+- }
+-#endif
+
+ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+ {
+@@ -2384,6 +2375,8 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+ return 1;
+ }
+
++/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding
++ * to the given public key, or -1 if not known. */
+ int tls12_get_sigid(const EVP_PKEY *pk)
+ {
+ return tls12_find_id(pk->type, tls12_sig,
+@@ -2403,47 +2396,49 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+ return EVP_md5();
+ #endif
+ #ifndef OPENSSL_NO_SHA
+- case TLSEXT_hash_sha1:
++ case TLSEXT_hash_sha1:
+ return EVP_sha1();
+ #endif
+ #ifndef OPENSSL_NO_SHA256
+- case TLSEXT_hash_sha224:
++ case TLSEXT_hash_sha224:
+ return EVP_sha224();
+
+- case TLSEXT_hash_sha256:
++ case TLSEXT_hash_sha256:
+ return EVP_sha256();
+ #endif
+ #ifndef OPENSSL_NO_SHA512
+- case TLSEXT_hash_sha384:
++ case TLSEXT_hash_sha384:
+ return EVP_sha384();
+
+- case TLSEXT_hash_sha512:
++ case TLSEXT_hash_sha512:
+ return EVP_sha512();
+ #endif
+- default:
++ default:
+ return NULL;
+
+ }
+ }
+
+-/* Set preferred digest for each key type */
+-
+-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
++/* tls1_process_sigalgs processes a signature_algorithms extension and sets the
++ * digest functions accordingly for each key type.
++ *
++ * See RFC 5246, section 7.4.1.4.1.
++ *
++ * data: points to the content of the extension, not including type and length
++ * headers.
++ * dsize: the number of bytes of |data|. Must be even.
++ */
++void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+ {
+- int i, idx;
+- const EVP_MD *md;
+- CERT *c = s->cert;
++ int i;
++ const EVP_MD *md, **digest_ptr;
+ /* Extension ignored for TLS versions below 1.2 */
+ if (TLS1_get_version(s) < TLS1_2_VERSION)
+- return 1;
+- /* Should never happen */
+- if (!c)
+- return 0;
++ return;
+
+- c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
+- c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
+- c->pkeys[SSL_PKEY_ECC].digest = NULL;
++ s->s3->digest_rsa = NULL;
++ s->s3->digest_dsa = NULL;
++ s->s3->digest_ecdsa = NULL;
+
+ for (i = 0; i < dsize; i += 2)
+ {
+@@ -2453,56 +2448,31 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+ {
+ #ifndef OPENSSL_NO_RSA
+ case TLSEXT_signature_rsa:
+- idx = SSL_PKEY_RSA_SIGN;
++ digest_ptr = &s->s3->digest_rsa;
+ break;
+ #endif
+ #ifndef OPENSSL_NO_DSA
+ case TLSEXT_signature_dsa:
+- idx = SSL_PKEY_DSA_SIGN;
++ digest_ptr = &s->s3->digest_dsa;
+ break;
+ #endif
+ #ifndef OPENSSL_NO_ECDSA
+ case TLSEXT_signature_ecdsa:
+- idx = SSL_PKEY_ECC;
++ digest_ptr = &s->s3->digest_ecdsa;
+ break;
+ #endif
+ default:
+ continue;
+ }
+
+- if (c->pkeys[idx].digest == NULL)
++ if (*digest_ptr == NULL)
+ {
+ md = tls12_get_hash(hash_alg);
+ if (md)
+- {
+- c->pkeys[idx].digest = md;
+- if (idx == SSL_PKEY_RSA_SIGN)
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+- }
++ *digest_ptr = md;
+ }
+
+ }
+-
+-
+- /* Set any remaining keys to default values. NOTE: if alg is not
+- * supported it stays as NULL.
+- */
+-#ifndef OPENSSL_NO_DSA
+- if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
+- c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
+-#endif
+-#ifndef OPENSSL_NO_RSA
+- if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
+- {
+- c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+- c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+- }
+-#endif
+-#ifndef OPENSSL_NO_ECDSA
+- if (!c->pkeys[SSL_PKEY_ECC].digest)
+- c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
+-#endif
+- return 1;
+ }
+
+ #endif
+--
+1.8.2.1
+
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 1d40a2e..88077ea 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2014,12 +2014,13 @@ int ssl3_get_certificate_request(SSL *s)
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
- if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
+ if (llen & 1)
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
goto err;
}
+ tls1_process_sigalgs(s, p, llen);
p += llen;
}
@@ -3041,7 +3042,28 @@ int ssl3_send_client_verify(SSL *s)
{
long hdatalen = 0;
void *hdata;
- const EVP_MD *md = s->cert->key->digest;
+ const EVP_MD *md;
+ switch (ssl_cert_type(NULL, pkey))
+ {
+ case SSL_PKEY_RSA_ENC:
+ md = s->s3->digest_rsa;
+ break;
+ case SSL_PKEY_DSA_SIGN:
+ md = s->s3->digest_dsa;
+ break;
+ case SSL_PKEY_ECC:
+ md = s->s3->digest_ecdsa;
+ break;
+ default:
+ md = NULL;
+ }
+ if (!md)
+ /* Unlike with the SignatureAlgorithm extension (sent by clients),
+ * there are no default algorithms for the CertificateRequest message
+ * (sent by servers). However, now that we've sent a certificate
+ * for which we don't really know what hash to use for signing, the
+ * best we can do is try a default algorithm. */
+ md = EVP_sha1();
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
&hdata);
if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 0be87e8..1d3af82 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 61b110f..dac9c3e 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -979,6 +979,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;
@@ -1075,6 +1100,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 */
@@ -1365,6 +1405,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 fee9671..4729868 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -550,6 +550,26 @@ typedef struct ssl3_state_st
* verified Channel ID from the client: a P256 point, (x,y), where
* 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.
+ *
+ * (These should be in the tmp member, but we have to put them here to
+ * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
+ const EVP_MD *digest_rsa;
+ const EVP_MD *digest_dsa;
+ const EVP_MD *digest_ecdsa;
} SSL3_STATE;
#endif
@@ -699,4 +719,3 @@ typedef struct ssl3_state_st
}
#endif
#endif
-
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 5123a89..bc4150b 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -160,21 +160,6 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
return ssl_x509_store_ctx_idx;
}
-static void ssl_cert_set_default_md(CERT *cert)
- {
- /* Set digest values to defaults */
-#ifndef OPENSSL_NO_DSA
- cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_RSA
- cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
- cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_ECDSA
- cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
- }
-
CERT *ssl_cert_new(void)
{
CERT *ret;
@@ -189,7 +174,6 @@ CERT *ssl_cert_new(void)
ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
ret->references=1;
- ssl_cert_set_default_md(ret);
return(ret);
}
@@ -322,10 +306,6 @@ CERT *ssl_cert_dup(CERT *cert)
* chain is held inside SSL_CTX */
ret->references=1;
- /* Set digests to defaults. NB: we don't copy existing values as they
- * will be set during handshake.
- */
- ssl_cert_set_default_md(ret);
return(ret);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 65b2ef8..1a3ceea 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -360,6 +360,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;
@@ -581,6 +592,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)
@@ -1658,6 +1671,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,
@@ -2010,6 +2095,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);
@@ -2400,32 +2487,41 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
{
unsigned long alg_a;
CERT *c;
- int idx = -1;
alg_a = cipher->algorithm_auth;
c=s->cert;
+ /* SHA1 is the default for all signature algorithms up to TLS 1.2,
+ * except RSA which is handled specially in s3_srvr.c */
+ if (pmd)
+ *pmd = EVP_sha1();
+
if ((alg_a & SSL_aDSS) &&
- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
- idx = SSL_PKEY_DSA_SIGN;
+ (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
+ {
+ if (pmd && s->s3 && s->s3->digest_dsa)
+ *pmd = s->s3->digest_dsa;
+ return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey;
+ }
else if (alg_a & SSL_aRSA)
{
+ if (pmd && s->s3 && s->s3->digest_rsa)
+ *pmd = s->s3->digest_rsa;
if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
- idx = SSL_PKEY_RSA_SIGN;
- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
- idx = SSL_PKEY_RSA_ENC;
+ return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey;
+ if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
+ return c->pkeys[SSL_PKEY_RSA_ENC].privatekey;
}
else if ((alg_a & SSL_aECDSA) &&
(c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
- idx = SSL_PKEY_ECC;
- if (idx == -1)
{
- SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
- return(NULL);
+ if (pmd && s->s3 && s->s3->digest_ecdsa)
+ *pmd = s->s3->digest_ecdsa;
+ return c->pkeys[SSL_PKEY_ECC].privatekey;
}
- if (pmd)
- *pmd = c->pkeys[idx].digest;
- return c->pkeys[idx].privatekey;
+
+ SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
+ return(NULL);
}
void ssl_update_cache(SSL *s,int mode)
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 5f21726..917c9f3 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -483,8 +483,6 @@ typedef struct cert_pkey_st
X509 *x509;
STACK_OF(X509) *cert_chain;
EVP_PKEY *privatekey;
- /* Digest to use when signing */
- const EVP_MD *digest;
} CERT_PKEY;
typedef struct cert_st
@@ -1140,7 +1138,7 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
int *al);
long ssl_get_algorithm2(SSL *s);
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
+void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 28d45b3..f170056 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-p-2)== 0)
return p;
@@ -886,6 +913,76 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
return ret;
}
+/* 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;
@@ -897,10 +994,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
s->servername_done = 0;
s->tlsext_status_type = -1;
+
+ /* Reset TLS 1.2 digest functions to defaults because they don't carry
+ * over to a renegotiation. */
+ s->s3->digest_rsa = NULL;
+ s->s3->digest_dsa = NULL;
+ s->s3->digest_ecdsa = NULL;
+
#ifndef OPENSSL_NO_NEXTPROTONEG
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);
@@ -1194,11 +1304,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!tls1_process_sigalgs(s, data, dsize))
- {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ tls1_process_sigalgs(s, data, dsize);
}
else if (type == TLSEXT_TYPE_status_request &&
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
@@ -1331,7 +1437,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.
@@ -1355,6 +1462,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)
@@ -1419,6 +1536,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);
@@ -1588,6 +1711,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))
@@ -2350,18 +2518,6 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
}
return -1;
}
-#if 0
-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
- {
- size_t i;
- for (i = 0; i < tlen; i++)
- {
- if (table[i].id == id)
- return table[i].nid;
- }
- return -1;
- }
-#endif
int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
{
@@ -2380,6 +2536,8 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
return 1;
}
+/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding
+ * to the given public key, or -1 if not known. */
int tls12_get_sigid(const EVP_PKEY *pk)
{
return tls12_find_id(pk->type, tls12_sig,
@@ -2399,47 +2557,49 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
return EVP_md5();
#endif
#ifndef OPENSSL_NO_SHA
- case TLSEXT_hash_sha1:
+ case TLSEXT_hash_sha1:
return EVP_sha1();
#endif
#ifndef OPENSSL_NO_SHA256
- case TLSEXT_hash_sha224:
+ case TLSEXT_hash_sha224:
return EVP_sha224();
- case TLSEXT_hash_sha256:
+ case TLSEXT_hash_sha256:
return EVP_sha256();
#endif
#ifndef OPENSSL_NO_SHA512
- case TLSEXT_hash_sha384:
+ case TLSEXT_hash_sha384:
return EVP_sha384();
- case TLSEXT_hash_sha512:
+ case TLSEXT_hash_sha512:
return EVP_sha512();
#endif
- default:
+ default:
return NULL;
}
}
-/* Set preferred digest for each key type */
-
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+/* tls1_process_sigalgs processes a signature_algorithms extension and sets the
+ * digest functions accordingly for each key type.
+ *
+ * See RFC 5246, section 7.4.1.4.1.
+ *
+ * data: points to the content of the extension, not including type and length
+ * headers.
+ * dsize: the number of bytes of |data|. Must be even.
+ */
+void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
- int i, idx;
- const EVP_MD *md;
- CERT *c = s->cert;
+ int i;
+ const EVP_MD *md, **digest_ptr;
/* Extension ignored for TLS versions below 1.2 */
if (TLS1_get_version(s) < TLS1_2_VERSION)
- return 1;
- /* Should never happen */
- if (!c)
- return 0;
+ return;
- c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
- c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
- c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
- c->pkeys[SSL_PKEY_ECC].digest = NULL;
+ s->s3->digest_rsa = NULL;
+ s->s3->digest_dsa = NULL;
+ s->s3->digest_ecdsa = NULL;
for (i = 0; i < dsize; i += 2)
{
@@ -2449,56 +2609,31 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
- idx = SSL_PKEY_RSA_SIGN;
+ digest_ptr = &s->s3->digest_rsa;
break;
#endif
#ifndef OPENSSL_NO_DSA
case TLSEXT_signature_dsa:
- idx = SSL_PKEY_DSA_SIGN;
+ digest_ptr = &s->s3->digest_dsa;
break;
#endif
#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
- idx = SSL_PKEY_ECC;
+ digest_ptr = &s->s3->digest_ecdsa;
break;
#endif
default:
continue;
}
- if (c->pkeys[idx].digest == NULL)
+ if (*digest_ptr == NULL)
{
md = tls12_get_hash(hash_alg);
if (md)
- {
- c->pkeys[idx].digest = md;
- if (idx == SSL_PKEY_RSA_SIGN)
- c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
- }
+ *digest_ptr = md;
}
}
-
-
- /* Set any remaining keys to default values. NOTE: if alg is not
- * supported it stays as NULL.
- */
-#ifndef OPENSSL_NO_DSA
- if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
- c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
-#endif
-#ifndef OPENSSL_NO_RSA
- if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
- {
- c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
- c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
- }
-#endif
-#ifndef OPENSSL_NO_ECDSA
- if (!c->pkeys[SSL_PKEY_ECC].digest)
- c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
- return 1;
}
#endif
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