Skip to content

Commit 6f017a8

Browse files
Adam Langleybenlaurie
authored andcommitted
Support ALPN.
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 Conflicts: ssl/ssl3.h ssl/t1_lib.c
1 parent 584ac22 commit 6f017a8

File tree

8 files changed

+432
-7
lines changed

8 files changed

+432
-7
lines changed

apps/s_client.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ static void sc_usage(void)
364364
BIO_printf(bio_err," -proof_debug - request an audit proof and print its hex dump\n");
365365
# ifndef OPENSSL_NO_NEXTPROTONEG
366366
BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n");
367+
BIO_printf(bio_err," -alpn arg - enable ALPN extension, considering named protocols supported (comma-separated list)\n");
367368
# endif
368369
#ifndef OPENSSL_NO_TLSEXT
369370
BIO_printf(bio_err," -serverinfo types - send empty ClientHello extensions (comma-separated numbers)\n");
@@ -636,6 +637,7 @@ int MAIN(int argc, char **argv)
636637
{NULL,0};
637638
# ifndef OPENSSL_NO_NEXTPROTONEG
638639
const char *next_proto_neg_in = NULL;
640+
const char *alpn_in = NULL;
639641
# endif
640642
# define MAX_SI_TYPES 100
641643
unsigned short serverinfo_types[MAX_SI_TYPES];
@@ -993,6 +995,11 @@ static char *jpake_secret = NULL;
993995
if (--argc < 1) goto bad;
994996
next_proto_neg_in = *(++argv);
995997
}
998+
else if (strcmp(*argv,"-alpn") == 0)
999+
{
1000+
if (--argc < 1) goto bad;
1001+
alpn_in = *(++argv);
1002+
}
9961003
# endif
9971004
else if (strcmp(*argv,"-serverinfo") == 0)
9981005
{
@@ -1306,9 +1313,23 @@ static char *jpake_secret = NULL;
13061313
*/
13071314
if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
13081315

1309-
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
1316+
#if !defined(OPENSSL_NO_TLSEXT)
1317+
# if !defined(OPENSSL_NO_NEXTPROTONEG)
13101318
if (next_proto.data)
13111319
SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
1320+
# endif
1321+
if (alpn_in)
1322+
{
1323+
unsigned short alpn_len;
1324+
unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);
1325+
1326+
if (alpn == NULL)
1327+
{
1328+
BIO_printf(bio_err, "Error parsing -alpn argument\n");
1329+
goto end;
1330+
}
1331+
SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
1332+
}
13121333
#endif
13131334
#ifndef OPENSSL_NO_TLSEXT
13141335
if (serverinfo_types_count)
@@ -2265,7 +2286,8 @@ static void print_stuff(BIO *bio, SSL *s, int full)
22652286
}
22662287
#endif
22672288

2268-
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
2289+
#if !defined(OPENSSL_NO_TLSEXT)
2290+
# if !defined(OPENSSL_NO_NEXTPROTONEG)
22692291
if (next_proto.status != -1) {
22702292
const unsigned char *proto;
22712293
unsigned int proto_len;
@@ -2274,6 +2296,20 @@ static void print_stuff(BIO *bio, SSL *s, int full)
22742296
BIO_write(bio, proto, proto_len);
22752297
BIO_write(bio, "\n", 1);
22762298
}
2299+
{
2300+
const unsigned char *proto;
2301+
unsigned int proto_len;
2302+
SSL_get0_alpn_selected(s, &proto, &proto_len);
2303+
if (proto_len > 0)
2304+
{
2305+
BIO_printf(bio, "ALPN protocol: ");
2306+
BIO_write(bio, proto, proto_len);
2307+
BIO_write(bio, "\n", 1);
2308+
}
2309+
else
2310+
BIO_printf(bio, "No ALPN negotiated\n");
2311+
}
2312+
# endif
22772313
#endif
22782314

22792315
{

apps/s_server.c

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ static void sv_usage(void)
578578
BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n");
579579
# endif
580580
BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
581+
BIO_printf(bio_err," -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n");
581582
#endif
582583
BIO_printf(bio_err," -keymatexport label - Export keying material using label\n");
583584
BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n");
@@ -932,7 +933,48 @@ static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
932933
return SSL_TLSEXT_ERR_OK;
933934
}
934935
# endif /* ndef OPENSSL_NO_NEXTPROTONEG */
935-
#endif
936+
937+
/* This the context that we pass to alpn_cb */
938+
typedef struct tlsextalpnctx_st {
939+
unsigned char *data;
940+
unsigned short len;
941+
} tlsextalpnctx;
942+
943+
static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
944+
{
945+
tlsextalpnctx *alpn_ctx = arg;
946+
947+
if (!s_quiet)
948+
{
949+
/* We can assume that |in| is syntactically valid. */
950+
unsigned i;
951+
BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
952+
for (i = 0; i < inlen; )
953+
{
954+
if (i)
955+
BIO_write(bio_s_out, ", ", 2);
956+
BIO_write(bio_s_out, &in[i + 1], in[i]);
957+
i += in[i] + 1;
958+
}
959+
BIO_write(bio_s_out, "\n", 1);
960+
}
961+
962+
if (SSL_select_next_proto((unsigned char**) out, outlen, alpn_ctx->data, alpn_ctx->len, in, inlen) !=
963+
OPENSSL_NPN_NEGOTIATED)
964+
{
965+
return SSL_TLSEXT_ERR_NOACK;
966+
}
967+
968+
if (!s_quiet)
969+
{
970+
BIO_printf(bio_s_out, "ALPN protocols selected: ");
971+
BIO_write(bio_s_out, *out, *outlen);
972+
BIO_write(bio_s_out, "\n", 1);
973+
}
974+
975+
return SSL_TLSEXT_ERR_OK;
976+
}
977+
#endif /* ndef OPENSSL_NO_TLSEXT */
936978

937979
static int not_resumable_sess_cb(SSL *s, int is_forward_secure)
938980
{
@@ -988,6 +1030,8 @@ int MAIN(int argc, char *argv[])
9881030
# ifndef OPENSSL_NO_NEXTPROTONEG
9891031
const char *next_proto_neg_in = NULL;
9901032
tlsextnextprotoctx next_proto;
1033+
const char *alpn_in = NULL;
1034+
tlsextalpnctx alpn_ctx = { NULL, 0};
9911035
# endif
9921036
#endif
9931037
#ifndef OPENSSL_NO_PSK
@@ -1438,6 +1482,11 @@ int MAIN(int argc, char *argv[])
14381482
if (--argc < 1) goto bad;
14391483
next_proto_neg_in = *(++argv);
14401484
}
1485+
else if (strcmp(*argv,"-alpn") == 0)
1486+
{
1487+
if (--argc < 1) goto bad;
1488+
alpn_in = *(++argv);
1489+
}
14411490
# endif
14421491
#endif
14431492
#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
@@ -1565,7 +1614,8 @@ int MAIN(int argc, char *argv[])
15651614
#endif /* OPENSSL_NO_TLSEXT */
15661615
}
15671616

1568-
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
1617+
#if !defined(OPENSSL_NO_TLSEXT)
1618+
# if !defined(OPENSSL_NO_NEXTPROTONEG)
15691619
if (next_proto_neg_in)
15701620
{
15711621
unsigned short len;
@@ -1578,6 +1628,16 @@ int MAIN(int argc, char *argv[])
15781628
{
15791629
next_proto.data = NULL;
15801630
}
1631+
# endif
1632+
alpn_ctx.data = NULL;
1633+
if (alpn_in)
1634+
{
1635+
unsigned short len;
1636+
alpn_ctx.data = next_protos_parse(&len, alpn_in);
1637+
if (alpn_ctx.data == NULL)
1638+
goto end;
1639+
alpn_ctx.len = len;
1640+
}
15811641
#endif
15821642

15831643
if (crl_file)
@@ -1812,6 +1872,8 @@ int MAIN(int argc, char *argv[])
18121872
if (next_proto.data)
18131873
SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto);
18141874
# endif
1875+
if (alpn_ctx.data)
1876+
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
18151877
#endif
18161878

18171879
#ifndef OPENSSL_NO_DH
@@ -2047,6 +2109,10 @@ int MAIN(int argc, char *argv[])
20472109
BIO_free(authz_in);
20482110
if (serverinfo_in != NULL)
20492111
BIO_free(serverinfo_in);
2112+
if (next_proto.data)
2113+
OPENSSL_free(next_proto.data);
2114+
if (alpn_ctx.data)
2115+
OPENSSL_free(alpn_ctx.data);
20502116
#endif
20512117
ssl_excert_free(exc);
20522118
if (ssl_args)

ssl/s3_lib.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,6 +3020,11 @@ void ssl3_free(SSL *s)
30203020
BIO_free(s->s3->handshake_buffer);
30213021
}
30223022
if (s->s3->handshake_dgst) ssl3_free_digest_list(s);
3023+
#ifndef OPENSSL_NO_TLSEXT
3024+
if (s->s3->alpn_selected)
3025+
OPENSSL_free(s->s3->alpn_selected);
3026+
#endif
3027+
30233028
#ifndef OPENSSL_NO_SRP
30243029
SSL_SRP_CTX_free(s);
30253030
#endif
@@ -3098,6 +3103,14 @@ void ssl3_clear(SSL *s)
30983103
if (s->s3->handshake_dgst) {
30993104
ssl3_free_digest_list(s);
31003105
}
3106+
3107+
#if !defined(OPENSSL_NO_TLSEXT)
3108+
if (s->s3->alpn_selected)
3109+
{
3110+
free(s->s3->alpn_selected);
3111+
s->s3->alpn_selected = NULL;
3112+
}
3113+
#endif
31013114
memset(s->s3,0,sizeof *s->s3);
31023115
s->s3->rbuf.buf = rp;
31033116
s->s3->wbuf.buf = wp;

ssl/ssl.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,31 @@ struct ssl_ctx_st
11001100
void *arg);
11011101
void *next_proto_select_cb_arg;
11021102
# endif
1103+
1104+
/* ALPN information
1105+
* (we are in the process of transitioning from NPN to ALPN.) */
1106+
1107+
/* For a server, this contains a callback function that allows the
1108+
* server to select the protocol for the connection.
1109+
* out: on successful return, this must point to the raw protocol
1110+
* name (without the length prefix).
1111+
* outlen: on successful return, this contains the length of |*out|.
1112+
* in: points to the client's list of supported protocols in
1113+
* wire-format.
1114+
* inlen: the length of |in|. */
1115+
int (*alpn_select_cb)(SSL *s,
1116+
const unsigned char **out,
1117+
unsigned char *outlen,
1118+
const unsigned char* in,
1119+
unsigned int inlen,
1120+
void *arg);
1121+
void *alpn_select_cb_arg;
1122+
1123+
/* For a client, this contains the list of supported protocols in wire
1124+
* format. */
1125+
unsigned char* alpn_client_proto_list;
1126+
unsigned alpn_client_proto_list_len;
1127+
11031128
/* SRTP profiles we are willing to do from RFC 5764 */
11041129
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
11051130
#endif
@@ -1202,6 +1227,21 @@ void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
12021227

12031228
#endif
12041229

1230+
int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos,
1231+
unsigned protos_len);
1232+
int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos,
1233+
unsigned protos_len);
1234+
void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx,
1235+
int (*cb) (SSL *ssl,
1236+
const unsigned char **out,
1237+
unsigned char *outlen,
1238+
const unsigned char *in,
1239+
unsigned int inlen,
1240+
void *arg),
1241+
void *arg);
1242+
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
1243+
unsigned *len);
1244+
12051245
#ifndef OPENSSL_NO_PSK
12061246
/* the maximum length of the buffer given to callbacks containing the
12071247
* resulting identity/psk */
@@ -1508,6 +1548,11 @@ struct ssl_st
15081548
*/
15091549
unsigned int tlsext_hb_pending; /* Indicates if a HeartbeatRequest is in flight */
15101550
unsigned int tlsext_hb_seq; /* HeartbeatRequest sequence number */
1551+
1552+
/* For a client, this contains the list of supported protocols in wire
1553+
* format. */
1554+
unsigned char* alpn_client_proto_list;
1555+
unsigned alpn_client_proto_list_len;
15111556
#else
15121557
#define session_ctx ctx
15131558
#endif /* OPENSSL_NO_TLSEXT */

ssl/ssl3.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,17 @@ typedef struct ssl3_state_st
586586
* as the types were received in the client hello. */
587587
unsigned short *tlsext_custom_types;
588588
size_t tlsext_custom_types_count; /* how many tlsext_custom_types */
589-
#endif
589+
590+
/* ALPN information
591+
* (we are in the process of transitioning from NPN to ALPN.) */
592+
593+
/* In a server these point to the selected ALPN protocol after the
594+
* ClientHello has been processed. In a client these contain the
595+
* protocol that the server selected once the ServerHello has been
596+
* processed. */
597+
unsigned char *alpn_selected;
598+
unsigned alpn_selected_len;
599+
#endif /* OPENSSL_NO_TLSEXT */
590600
} SSL3_STATE;
591601

592602
#endif

0 commit comments

Comments
 (0)