diff --git a/apps/apps.c b/apps/apps.c
index e35f3c4..4e37306 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2953,6 +2953,50 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
 	}
 #endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+/* alpn_parse parses a comma separated list of strings into a string
+ * in a format suitable for passing to SSL_CTX_set_alpn_advertised.
+ *   outlen: (output) set to the length of the resulting buffer on success.
+ *   err: (maybe NULL) on failure, an error message line is written to this BIO.
+ *   in: a NUL terminated string like "abc,def,ghi"
+ *
+ *   returns: a malloced buffer or NULL on failure.
+ */
+unsigned char *alpn_parse(unsigned short *outlen, const char *in)
+	{
+	size_t len;
+	unsigned char *out;
+	size_t ii, start = 0;
+
+	len = strlen(in);
+	if (len >= 65535)
+		return NULL;
+
+	out = OPENSSL_malloc(strlen(in) + 1);
+	if (!out)
+		return NULL;
+
+	for (ii = 0; ii <= len; ++ii)
+		{
+		if (ii == len || in[ii] == ',')
+			{
+			if (ii - start > 255)
+				{
+				OPENSSL_free(out);
+				return NULL;
+				}
+			out[start] = ii - start;
+			start = ii + 1;
+			}
+		else
+			out[ii+1] = in[ii];
+		}
+
+	*outlen = len + 1;
+	return out;
+	}
+#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_ALPN */
+
 void print_cert_checks(BIO *bio, X509 *x,
 				const unsigned char *checkhost,
 				const unsigned char *checkemail,
diff --git a/apps/apps.h b/apps/apps.h
index 0a9d90b..4d0558a 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -339,6 +339,9 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret);
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
 unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
 #endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+unsigned char *alpn_parse(unsigned short *outlen, const char *in);
+#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_ALPN */
 
 void print_cert_checks(BIO *bio, X509 *x,
 				const unsigned char *checkhost,
diff --git a/apps/s_client.c b/apps/s_client.c
index 5fb5dff..2a0d46b 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -365,6 +365,9 @@ static void sc_usage(void)
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n");
 # endif
+# ifndef OPENSSL_NO_ALPN
+	BIO_printf(bio_err," -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n");
+# endif
 #ifndef OPENSSL_NO_TLSEXT
 	BIO_printf(bio_err," -serverinfo types - send empty ClientHello extensions (comma-separated numbers)\n");
 #endif
@@ -546,6 +549,41 @@ static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, con
 	}
 # endif  /* ndef OPENSSL_NO_NEXTPROTONEG */
 
+# ifndef OPENSSL_NO_ALPN
+/* This the context that we pass to alpn_cb */
+typedef struct tlsextalpnctx_st
+	{
+	unsigned char *data;
+	unsigned short len;
+	} tlsextalpnctx;
+
+static tlsextalpnctx alpnctx;
+
+static int alpn_adv_cb(SSL *ss, const unsigned char **data_out, unsigned int *size_out, void *arg)
+	{
+	tlsextalpnctx *ctx = arg;
+
+	if (!c_quiet)
+		{
+		unsigned ii;
+
+		BIO_printf(bio_c_out, "ALPN Protocols being advertised to the server: ");
+		for (ii = 0; ii < ctx->len; )
+			{
+			if (ii)
+				BIO_write(bio_c_out, ", ", 2);
+			BIO_write(bio_c_out, &ctx->data[ii + 1], ctx->data[ii]);
+			ii += ctx->data[ii] + 1;
+			}
+		BIO_write(bio_c_out, "\n", 1);
+		}
+
+	*data_out = ctx->data;
+	*size_out = ctx->len;
+	return SSL_TLSEXT_ERR_OK;
+	}
+# endif  /* ndef OPENSSL_NO_APLN */
+
 static int serverinfo_cli_cb(SSL* s, unsigned short ext_type,
 			     const unsigned char* in, unsigned short inlen, 
 			     int* al, void* arg)
@@ -637,6 +675,9 @@ int MAIN(int argc, char **argv)
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	const char *next_proto_neg_in = NULL;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	const char *alpn_in = NULL;
+# endif
 # define MAX_SI_TYPES 100
 	unsigned short serverinfo_types[MAX_SI_TYPES];
 	int serverinfo_types_count = 0;
@@ -994,6 +1035,13 @@ static char *jpake_secret = NULL;
 			next_proto_neg_in = *(++argv);
 			}
 # endif
+# ifndef OPENSSL_NO_ALPN
+		else if (strcmp(*argv,"-alpn") == 0)
+			{
+			if (--argc < 1) goto bad;
+			alpn_in = *(++argv);
+			}
+# endif
 		else if (strcmp(*argv,"-serverinfo") == 0)
 			{
 			char *c;
@@ -1134,6 +1182,20 @@ bad:
 		next_proto.data = NULL;
 #endif
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (alpn_in)
+		{
+		alpnctx.data = alpn_parse(&alpnctx.len, alpn_in);
+		if (alpnctx.data == NULL)
+			{
+			BIO_printf(bio_err, "Error parsing -alpn argument\n");
+			goto end;
+			}
+		}
+	else
+		alpnctx.data = NULL;
+#endif
+
 #ifndef OPENSSL_NO_ENGINE
         e = setup_engine(bio_err, engine_id, 1);
 	if (ssl_client_engine_id)
@@ -1310,6 +1372,26 @@ bad:
 	if (next_proto.data)
 		SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (alpnctx.data)
+		{
+		if (c_debug)
+			{
+			int ii = 0;
+			BIO_printf(bio_c_out, "ALPN argument parsed: ");
+			while (ii < alpnctx.len)
+				{
+				BIO_write(bio_c_out, &(alpnctx.data[ii+1]), alpnctx.data[ii]);
+				BIO_write(bio_c_out, " ", 1);
+				ii += (alpnctx.data[ii]+1);
+				}
+			BIO_write(bio_c_out, "\n", 1);
+			}
+		SSL_CTX_set_alpn_advertised_cb(ctx, alpn_adv_cb, &alpnctx);
+		if (c_debug)
+			BIO_printf(bio_c_out, "ALPN set callbacks\n");
+		}
+#endif
 #ifndef OPENSSL_NO_TLSEXT
 		if (serverinfo_types_count)
 			{
@@ -2082,6 +2164,10 @@ end:
 	if (next_proto.data)
 		OPENSSL_free(next_proto.data);
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (alpnctx.data)
+		OPENSSL_free(alpnctx.data);
+#endif
 	if (ctx != NULL) SSL_CTX_free(ctx);
 	if (cert)
 		X509_free(cert);
@@ -2275,6 +2361,22 @@ static void print_stuff(BIO *bio, SSL *s, int full)
 		BIO_write(bio, "\n", 1);
 	}
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (alpnctx.data)
+		{
+		const unsigned char *proto;
+		unsigned int proto_len;
+		SSL_get0_alpn_negotiated(s, &proto, &proto_len);
+		if (proto)
+			{
+			BIO_printf(bio, "ALPN protocol: ");
+			BIO_write(bio, proto, proto_len);
+			BIO_write(bio, "\n", 1);
+			}
+		else
+			BIO_printf(bio, "ALPN not negotiated\n");
+		}
+#endif
 
  	{
  	SRTP_PROTECTION_PROFILE *srtp_profile=SSL_get_selected_srtp_profile(s);
diff --git a/apps/s_server.c b/apps/s_server.c
index bf61a8d..82f07ac 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -577,6 +577,9 @@ static void sv_usage(void)
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n");
 # endif
+# ifndef OPENSSL_NO_ALPN
+	BIO_printf(bio_err," -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n");
+# endif
         BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
 #endif
 	BIO_printf(bio_err," -keymatexport label   - Export keying material using label\n");
@@ -932,6 +935,44 @@ static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
 	return SSL_TLSEXT_ERR_OK;
 	}
 # endif  /* ndef OPENSSL_NO_NEXTPROTONEG */
+
+# ifndef OPENSSL_NO_ALPN
+typedef struct tlsextalpnctx_st
+	{
+	unsigned char *data;
+	unsigned int len;
+	} tlsextalpnctx;
+
+static int alpn_cb(SSL *ss, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
+	{
+	tlsextalpnctx *ctx = arg;
+
+	if (!s_quiet)
+		{
+		unsigned ii;
+
+		BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
+		for (ii = 0; ii < inlen; )
+			{
+			if (ii)
+				BIO_write(bio_s_out, ", ", 2);
+			BIO_write(bio_s_out, &in[ii + 1], in[ii]);
+			ii += in[ii] + 1;
+			}
+		BIO_write(bio_s_out, "\n", 1);
+		}
+
+	if (SSL_select_alpn(out, outlen, ctx->data, ctx->len, in, inlen) == OPENSSL_ALPN_NO_OVERLAP)
+		return SSL_TLSEXT_ERR_ALERT_FATAL;
+	if (!s_quiet)
+		{
+		BIO_printf(bio_s_out, "ALPN protocol selected by the server: ");
+		BIO_write(bio_s_out, *out, *outlen);
+		BIO_write(bio_s_out, "\n", 1);
+		}
+	return SSL_TLSEXT_ERR_OK;
+	}
+# endif  /* ndef OPENSSL_NO_ALPN */
 #endif
 
 static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
@@ -989,6 +1030,10 @@ int MAIN(int argc, char *argv[])
 	const char *next_proto_neg_in = NULL;
 	tlsextnextprotoctx next_proto;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	const char *alpn_in = NULL;
+	tlsextalpnctx alpnctx;
+# endif
 #endif
 #ifndef OPENSSL_NO_PSK
 	/* by default do not send a PSK identity hint */
@@ -1439,6 +1484,13 @@ int MAIN(int argc, char *argv[])
 			next_proto_neg_in = *(++argv);
 			}
 # endif
+# ifndef OPENSSL_NO_ALPN
+		else if	(strcmp(*argv,"-alpn") == 0)
+			{
+			if (--argc < 1) goto bad;
+			alpn_in = *(++argv);
+			}
+# endif
 #endif
 #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
 		else if (strcmp(*argv,"-jpake") == 0)
@@ -1580,6 +1632,22 @@ bad:
 		}
 #endif
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN) 
+	if (alpn_in)
+		{
+		unsigned short len;
+		alpnctx.data = alpn_parse(&len, alpn_in);
+		if (alpnctx.data == NULL)
+			{
+			ERR_print_errors(bio_err);
+			goto end;
+			}
+		alpnctx.len = len;
+		}
+	else
+		alpnctx.data = NULL;
+#endif
+
 	if (crl_file)
 		{
 		X509_CRL *crl;
@@ -1812,6 +1880,10 @@ bad:
 	if (next_proto.data)
 		SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto);
 # endif
+# ifndef OPENSSL_NO_ALPN
+	if (alpnctx.data)
+		SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpnctx);
+# endif
 #endif 
 
 #ifndef OPENSSL_NO_DH
@@ -2546,6 +2618,10 @@ static int init_ssl_connection(SSL *con)
 	const unsigned char *next_proto_neg;
 	unsigned next_proto_neg_len;
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	const unsigned char *alpn_proto;
+	unsigned alpn_len;
+#endif
 	unsigned char *exportedkeymat;
 
 
@@ -2616,6 +2692,20 @@ static int init_ssl_connection(SSL *con)
 		BIO_printf(bio_s_out, "\n");
 		}
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (s_debug)
+		BIO_printf(bio_s_out,"Calling alpn get negotatied\n");
+	SSL_get0_alpn_negotiated(con, &alpn_proto, &alpn_len);
+	if (alpn_proto)
+		{
+		BIO_printf(bio_s_out,"ALPN is ");
+		BIO_write(bio_s_out, alpn_proto, alpn_len);
+		BIO_printf(bio_s_out, "\n");
+		}
+	else
+		if (s_debug)
+			BIO_printf(bio_s_out,"ALPN not negotiated\n");
+#endif
 	{
 	SRTP_PROTECTION_PROFILE *srtp_profile
 	  = SSL_get_selected_srtp_profile(con);
diff --git a/makevms.com b/makevms.com
index d5a2526..5e0fe10 100755
--- a/makevms.com
+++ b/makevms.com
@@ -248,6 +248,7 @@ $! the following on a Unix system:
 $!   grep OPENSSL_NO_ crypto/*/*.h ssl/*.h engines/*.h engines/*/*.h|grep ':# *if'|sed -e 's/^.*def //'|sort|uniq
 $! For that reason, the list will also always end up in alphabetical order
 $ CONFIG_LOGICALS := AES,-
+		     ALPN,-
 		     ASM,INLINE_ASM,-
 		     BF,-
 		     BIO,-
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 67eb920..2ef92e0 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3122,6 +3122,14 @@ void ssl3_clear(SSL *s)
 		s->next_proto_negotiated_len = 0;
 		}
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (s->alpn_negotiated)
+		{
+		OPENSSL_free(s->alpn_negotiated);
+		s->alpn_negotiated = NULL;
+		s->alpn_negotiated_len = 0;
+		}
+#endif
 	}
 
 #ifndef OPENSSL_NO_SRP
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 9c19dc7..4fea63f 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1100,6 +1100,21 @@ struct ssl_ctx_st
 				    void *arg);
 	void *next_proto_select_cb_arg;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	/* For a client, this contains a callback function by which the set of
+	 * advertised protocols can be provided. */
+	int (*alpn_advertised_cb)(SSL *s, const unsigned char **buf,
+			                 unsigned int *len, void *arg);
+	void *alpn_advertised_cb_arg;
+	/* For a server, this contains a callback function that selects the
+	 * next protocol from the list provided by the client. */
+	int (*alpn_select_cb)(SSL *s, unsigned char **out,
+				    unsigned char *outlen,
+				    const unsigned char *in,
+				    unsigned int inlen,
+				    void *arg);
+	void *alpn_select_cb_arg;
+# endif
         /* SRTP profiles we are willing to do from RFC 5764 */
 	STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  
 #endif
@@ -1202,6 +1217,33 @@ void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
 
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+void SSL_CTX_set_alpn_advertised_cb(SSL_CTX *s,
+					   int (*cb) (SSL *ssl,
+						      const unsigned char **out,
+						      unsigned int *outlen,
+						      void *arg),
+					   void *arg);
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *s,
+				      int (*cb) (SSL *ssl,
+						 unsigned char **out,
+						 unsigned char *outlen,
+						 const unsigned char *in,
+						 unsigned int inlen,
+						 void *arg),
+				      void *arg);
+
+int SSL_select_alpn(unsigned char **out, unsigned char *outlen,
+			  const unsigned char *in, unsigned int inlen,
+			  const unsigned char *client, unsigned int client_len);
+void SSL_get0_alpn_negotiated(const SSL *s,
+				    const unsigned char **data, unsigned *len);
+
+#define OPENSSL_ALPN_UNSUPPORTED	0
+#define OPENSSL_ALPN_NEGOTIATED		1
+#define OPENSSL_ALPN_NO_OVERLAP		2
+#endif
+
 #ifndef OPENSSL_NO_PSK
 /* the maximum length of the buffer given to callbacks containing the
  * resulting identity/psk */
@@ -1496,6 +1538,17 @@ struct ssl_st
 	unsigned char next_proto_negotiated_len;
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+	/* ALPN. For the server, this is the protocol that we chose
+	 * from the client's list when handling the ClientHello.
+	 *
+	 * For a client, this is the server's selected protocol from
+	 * the ServerHello.
+	 */
+	unsigned char *alpn_negotiated;
+	unsigned char alpn_negotiated_len;
+#endif
+
 #define session_ctx initial_ctx
 
 	STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  /* What we'll do */
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a48e09e..f3c355d 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -382,6 +382,9 @@ SSL *SSL_new(SSL_CTX *ctx)
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	s->next_proto_negotiated = NULL;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	s->alpn_negotiated = NULL;
+# endif
 #endif
 
 	s->verify_result=X509_V_OK;
@@ -624,6 +627,10 @@ void SSL_free(SSL *s)
 	if (s->next_proto_negotiated)
 		OPENSSL_free(s->next_proto_negotiated);
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (s->alpn_negotiated)
+		OPENSSL_free(s->alpn_negotiated);
+#endif
 
         if (s->srtp_profiles)
             sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
@@ -1698,6 +1705,116 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned
 	}
 # endif
 
+# ifndef OPENSSL_NO_ALPN
+/* SSL_select_alpn implements the standard protocol selection. It is
+ * expected that this function is called from the callback set by
+ * SSL_CTX_set_alpn_select_cb.
+ *
+ * The protocol data is assumed to be a vector of 8-bit, length
+ * prefixed byte strings. The length byte itself is not included in
+ * the length. A byte string of length 0 is invalid. No byte string
+ * may be truncated.
+ *
+ * It returns either
+ * OPENSSL_ALPN_NEGOTIATED if a common protocol was found, or
+ * OPENSSL_ALPN_NO_OVERLAP if the fallback case was reached.
+ */
+int SSL_select_alpn(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
+	{
+	unsigned int ii, jj;
+	const unsigned char *result;
+	int status = OPENSSL_ALPN_UNSUPPORTED;
+
+	/* For each protocol in server preference order, see if we support it. */
+	for (ii = 0; ii < server_len; )
+		{
+		for (jj = 0; jj < client_len; )
+			{
+			if (server[ii] == client[jj] &&
+			    memcmp(&server[ii+1], &client[jj+1], server[ii]) == 0)
+				{
+				/* We found a match */
+				result = &server[ii];
+				status = OPENSSL_ALPN_NEGOTIATED;
+				goto found;
+				}
+			jj += client[jj];
+			jj++;
+			}
+		ii += server[ii];
+		ii++;
+		}
+
+	/* There's no overlap between our protocols and the server's list. */
+	result = client;
+	status = OPENSSL_ALPN_NO_OVERLAP;
+
+	found:
+	*out = (unsigned char *) result + 1;
+	*outlen = result[0];
+	return status;
+	}
+
+/* SSL_get0_alpn_negotiated sets *data and *len to point to the
+ * servers's requested protocol for this connection. If the server
+ * didn't request any protocol, then *data is set to NULL.
+ *
+ * Note that the server can request any protocol it chooses. The value
+ * returned from this function need not be a member of the list of
+ * supported protocols provided by the callback.
+ */
+void SSL_get0_alpn_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+	{
+	*data = s->alpn_negotiated;
+	if (!*data)
+		*len = 0;
+	else
+		*len = s->alpn_negotiated_len;
+	}
+
+/* SSL_CTX_set_alpn_advertised_cb sets a callback that is called when
+ * a TLS client needs a list of supported protocols for ALPN. The list
+ * is returned by setting |out| to point to it and |outlen| to its
+ * length. This memory will not be modified, but one should assume
+ * that the SSL* keeps a reference to it.
+ *
+ * The protocol data is assumed to be a vector of 8-bit, length
+ * prefixed byte strings. The length byte itself is not included in
+ * the length. A byte string of length 0 is invalid. No byte string
+ * may be truncated.
+ *
+ * The callback should return SSL_TLSEXT_ERR_OK if it wishes to
+ * advertise. Otherwise, no such extension will be included in the
+ * ClientHello. */
+void SSL_CTX_set_alpn_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg)
+	{
+	ctx->alpn_advertised_cb = cb;
+	ctx->alpn_advertised_cb_arg = arg;
+	}
+
+/* SSL_CTX_set_alpn_select_cb sets a callback that is called when a
+ * server needs to select a protocol from the client's provided
+ * list. |out| must be set to point to the selected protocol (which
+ * may be within |in|).  The length of the protocol name must be
+ * written into |outlen|. The client's advertised protocols are
+ * provided in |in| and |inlen|. The callback can assume that |in| is
+ * syntactically valid.
+ * 
+ * The protocol data is assumed to be a vector of 8-bit, length
+ * prefixed byte strings. The length byte itself is not included in
+ * the length. A byte string of length 0 is invalid. No byte string
+ * may be truncated.
+ *
+ * If no match is found, the callback shall return
+ * SSL_TLSEXT_ERR_ALERT_FATAL
+ */
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, 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;
+	}
+# endif
+
 int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
 			       custom_cli_ext_first_cb_fn fn1, 
 			       custom_cli_ext_second_cb_fn fn2, void* arg)
@@ -1944,6 +2061,10 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 	ret->next_protos_advertised_cb = 0;
 	ret->next_proto_select_cb = 0;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	ret->alpn_advertised_cb = 0;
+	ret->alpn_select_cb = 0;
+# endif
 #endif
 #ifndef OPENSSL_NO_PSK
 	ret->psk_identity_hint=NULL;
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index 1be60c0..3193117 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -295,7 +295,7 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
 static BIO *bio_err=NULL;
 static BIO *bio_stdout=NULL;
 
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 /* Note that this code assumes that this is only a one element list: */
 static const char NEXT_PROTO_STRING[] = "\x09testproto";
 int npn_client = 0;
@@ -680,7 +680,7 @@ static void sv_usage(void)
 	               "                 (default is sect163r2).\n");
 #endif
 	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	fprintf(stderr," -npn_client - have client side offer NPN\n");
 	fprintf(stderr," -npn_server - have server side offer NPN\n");
 	fprintf(stderr," -npn_server_reject - have server reject NPN\n");
@@ -1087,7 +1087,7 @@ int main(int argc, char *argv[])
 			{
 			test_cipherlist = 1;
 			}
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 		else if (strcmp(*argv,"-npn_client") == 0)
 			{
 			npn_client = 1;
@@ -1423,7 +1423,7 @@ bad:
 		}
 #endif
 
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (npn_client)
 		{
 		SSL_CTX_set_next_proto_select_cb(c_ctx, cb_client_npn, NULL);
@@ -1937,7 +1937,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
 
 	if (verbose)
 		print_details(c_ssl, "DONE via BIO pair: ");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (verify_npn(c_ssl, s_ssl) < 0)
 		{
 		ret = 1;
@@ -2251,7 +2251,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
 
 	if (verbose)
 		print_details(c_ssl, "DONE: ");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (verify_npn(c_ssl, s_ssl) < 0)
 		{
 		ret = 1;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 07cb096..97c9173 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1404,6 +1404,30 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
 		}
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+	if (s->ctx->alpn_advertised_cb && !s->s3->tmp.finish_md_len)
+		{
+		/* Here in send clienthello, we send the list of
+		 * supported ALPN protos */
+		const unsigned char *alpn_protos;
+		unsigned int alpn_protos_len;
+		unsigned short alpn_ext_len;
+		int rv;
+
+		rv = s->ctx->alpn_advertised_cb(s, &alpn_protos, &alpn_protos_len, s->ctx->alpn_advertised_cb_arg);
+		if (rv == SSL_TLSEXT_ERR_OK)
+			{
+			alpn_ext_len = alpn_protos_len + 2; /* Add size for the list length */
+			if ((long)(limit - ret - 4 - alpn_ext_len) < 0) return NULL;
+			s2n(TLSEXT_TYPE_alpn,ret);
+			s2n(alpn_ext_len,ret); /* Size of the whole extension */
+			s2n(alpn_protos_len,ret); /* Size of the list */
+			memcpy(ret, alpn_protos, alpn_protos_len);
+			ret += alpn_protos_len;
+			}
+		}
+#endif /* OPENSSL_NO_ALPN */
+
         if(SSL_get_srtp_profiles(s))
                 {
                 int el;
@@ -1784,6 +1808,22 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 			}
 		}
 
+#ifndef OPENSSL_NO_ALPN
+	if (s->alpn_negotiated)
+		{
+		/* Here in send serverhello, we want to send the ALPN
+		 * proto we selected in the scan clienthello */
+		unsigned int alpn_size = s->alpn_negotiated_len + 1 + 2; /* Add for the list size and string size. */
+		if ((long)(limit - ret - 4 - alpn_size) < 0) return NULL;
+		s2n(TLSEXT_TYPE_alpn,ret);
+		s2n(alpn_size,ret); /* Extension size */
+		s2n((s->alpn_negotiated_len + 1),ret); /* List size */
+		*(ret++) = (unsigned char)(s->alpn_negotiated_len); /* String size */
+		memcpy(ret, s->alpn_negotiated, s->alpn_negotiated_len);
+		ret += s->alpn_negotiated_len;
+		}
+#endif
+
 	if ((extdatalen = ret-p-2)== 0) 
 		return p;
 
@@ -1791,6 +1831,26 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 	return ret;
 	}
 
+#ifndef OPENSSL_NO_ALPN
+/* ssl_alpn_validate validates a ALPN block. No elements of zero
+ * length are allowed and the set of elements must exactly fill the
+ * length of the block. */
+static char ssl_alpn_validate(unsigned char *data, unsigned short len)
+	{
+	unsigned int off = 2;	/* Skip the length of the list */
+
+	while (off < len)
+		{
+		if (data[off] == 0)
+			return 0;
+		off += data[off];
+		off++;
+		}
+
+	return off == len;
+	}
+#endif
+
 static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) 
 	{	
 	unsigned short type;
@@ -2281,6 +2341,53 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
+#ifndef OPENSSL_NO_ALPN
+		else if (type == TLSEXT_TYPE_alpn &&
+			 s->ctx->alpn_select_cb &&
+			 s->s3->tmp.finish_md_len == 0)
+			{
+			/* Here in scan clienthello, we get the
+			 * clients list, select the proto, and save it
+			 * off */
+			/* If the client sends alpn, but the server is
+			 * not expecting it, just ignore. */
+			unsigned char *selected;
+			unsigned char selected_len;
+			int rv;
+
+			/* The data must be valid */
+			if (!ssl_alpn_validate(data, size))
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			/* Skip the list length when sending to callback */
+			rv = s->ctx->alpn_select_cb(s, &selected, &selected_len, data + 2, size - 2,
+						    s->ctx->alpn_select_cb_arg);
+			if (rv == SSL_TLSEXT_ERR_OK)
+				{
+				s->alpn_negotiated = OPENSSL_malloc(selected_len);
+				if (!s->alpn_negotiated)
+					{
+					*al = TLS1_AD_INTERNAL_ERROR;
+					return 0;
+					}
+				memcpy(s->alpn_negotiated, selected, selected_len);
+				s->alpn_negotiated_len = selected_len;
+				}
+			else if (rv == SSL_TLSEXT_ERR_ALERT_FATAL)
+				{
+				/* No match, send alert. */
+				*al = TLS1_AD_NO_APPLICATION_PROTOCOL;
+				return 0;
+				}
+			else
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			}
+#endif /* OPENSSL_NO_ALPN */
 
 		/* session ticket processed earlier */
 		else if (type == TLSEXT_TYPE_use_srtp)
@@ -2400,6 +2507,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 		data+=size;
 		}
 
+#if !defined(OPENSSL_NO_ALPN) && !defined(OPENSSL_NO_NEXTPROTONEG)
+	if (s->alpn_negotiated)
+		{
+		/* If alpn was successful, ignore npn */
+		s->s3->next_proto_neg_seen = 0;
+		}
+#endif
 	*p = data;
 
 	ri_check:
@@ -2633,6 +2747,37 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
+#ifndef OPENSSL_NO_ALPN
+		else if (type == TLSEXT_TYPE_alpn && s->s3->tmp.finish_md_len == 0)
+			{
+			/* Here in scan serverhello, we get the
+			 * selected ALPN proto and save it off */
+
+			/* The Server should not have sent alpn if we
+			 * didn't send our list in our clienthello */
+			if ((s->ctx->alpn_advertised_cb == NULL))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			/* The data must be valid */
+			if (!ssl_alpn_validate(data, size))
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			/* Ignore the first 3 bytes. The size of the
+			 * list and size the protocol string. */
+			s->alpn_negotiated = OPENSSL_malloc(size - 3);
+			if (!s->alpn_negotiated)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			memcpy(s->alpn_negotiated, data + 3, size - 3);
+			s->alpn_negotiated_len = size - 3;
+			}
+#endif
 		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 c59a02f..865ab41 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -196,6 +196,8 @@ extern "C" {
 #define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
 #define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
 #define TLS1_AD_UNKNOWN_PSK_IDENTITY	115	/* fatal */
+/* draft-ietf-tls-applayerprotoneg-01 */
+#define TLS1_AD_NO_APPLICATION_PROTOCOL	120	/* fatal */
 
 /* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */
 #define TLSEXT_TYPE_server_name			0
@@ -248,6 +250,9 @@ extern "C" {
 #define TLSEXT_TYPE_next_proto_neg		13172
 #endif
 
+/* draft-ietf-tls-applayerprotoneg-01 */
+#define TLSEXT_TYPE_alpn			16
+
 /* NameType value from RFC 3546 */
 #define TLSEXT_NAMETYPE_host_name 0
 /* status request value from RFC 3546 */
diff --git a/util/mkdef.pl b/util/mkdef.pl
index 8d74eaa..76d625f 100755
--- a/util/mkdef.pl
+++ b/util/mkdef.pl
@@ -112,6 +112,8 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
 			 "JPAKE",
 			 # NEXTPROTONEG
 			 "NEXTPROTONEG",
+			 # ALPN
+			 "ALPN",
 			 # Deprecated functions
 			 "DEPRECATED",
 			 # Hide SSL internals
@@ -139,7 +141,7 @@ my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw;
 my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
 my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
 my $no_jpake; my $no_ssl2; my $no_ec2m; my $no_nextprotoneg;
-my $no_srp; my $no_nistp_gcc; my $no_sctp; my $no_ssl_trace;
+my $no_srp; my $no_nistp_gcc; my $no_sctp; my $no_ssl_trace; my $no_alpn;
 
 my $fips;
 
@@ -233,6 +235,7 @@ foreach (@ARGV, split(/ /, $options))
 	elsif (/^no-ec2m$/)	{ $no_ec2m=1; }
  	elsif (/^no-ec-nistp224-64-gcc-128$/)	{ $no_nistp_gcc=1; }
 	elsif (/^no-nextprotoneg$/)	{ $no_nextprotoneg=1; }
+	elsif (/^no-alpn$/)	{ $no_alpn=1; }
 	elsif (/^no-ssl2$/)	{ $no_ssl2=1; }
 	elsif (/^no-ssl-trace$/) { $no_ssl_trace=1; }
 	elsif (/^no-capieng$/)	{ $no_capieng=1; }
@@ -1202,6 +1205,7 @@ sub is_valid
 					{ return 0; }
 			if ($keyword eq "EC2M" && $no_ec2m) { return 0; }
 			if ($keyword eq "NEXTPROTONEG" && $no_nextprotoneg) { return 0; }
+			if ($keyword eq "ALPN" && $no_alpn) { return 0; }
 			if ($keyword eq "SSL2" && $no_ssl2) { return 0; }
 			if ($keyword eq "SSL_TRACE" && $no_ssl_trace) { return 0; }
 			if ($keyword eq "CAPIENG" && $no_capieng) { return 0; }
