From 73d0add4b5d2e01d460eb9eaa91dd531da22e21c Mon Sep 17 00:00:00 2001 From: jsing <> Date: Wed, 10 Dec 2014 14:58:56 +0000 Subject: Add support for ALPN. Based on OpenSSL and BoringSSL. ok bcook@ --- src/lib/libssl/ssl_lib.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) (limited to 'src/lib/libssl/ssl_lib.c') diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index bdd47ff87f..a03ee735ad 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.90 2014/11/16 14:12:47 jsing Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.91 2014/12/10 14:58:56 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -337,6 +337,18 @@ SSL_new(SSL_CTX *ctx) s->next_proto_negotiated = NULL; # endif + if (s->ctx->alpn_client_proto_list != NULL) { + s->alpn_client_proto_list = + 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; + } + s->verify_result = X509_V_OK; s->method = ctx->method; @@ -551,6 +563,7 @@ SSL_free(SSL *s) #ifndef OPENSSL_NO_NEXTPROTONEG free(s->next_proto_negotiated); #endif + free(s->alpn_client_proto_list); #ifndef OPENSSL_NO_SRTP if (s->srtp_profiles) @@ -1629,6 +1642,75 @@ SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, } # endif +/* + * SSL_CTX_set_alpn_protos sets the ALPN protocol list to the specified + * protocols, which 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 int protos_len) +{ + free(ctx->alpn_client_proto_list); + if ((ctx->alpn_client_proto_list = malloc(protos_len)) == NULL) + 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 to the specified + * protocols, which 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 int protos_len) +{ + free(ssl->alpn_client_proto_list); + if ((ssl->alpn_client_proto_list = malloc(protos_len)) == NULL) + 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 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). 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; + *len = 0; + + if (ssl->s3 != NULL) { + *data = ssl->s3->alpn_selected; + *len = ssl->s3->alpn_selected_len; + } +} + int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, const char *label, size_t llen, const unsigned char *p, size_t plen, @@ -1894,6 +1976,8 @@ SSL_CTX_free(SSL_CTX *a) ENGINE_finish(a->client_cert_engine); #endif + free(a->alpn_client_proto_list); + free(a); } -- cgit v1.2.3-55-g6feb