From 55272e791e8761e9e22ccec7985f6a67b353362d Mon Sep 17 00:00:00 2001 From: jsing Date: Mon, 22 Aug 2016 14:55:59 +0000 Subject: [PATCH] Provide an API that enables server side SNI support - add the ability to provide additional keypairs (via tls_config_add_keypair_{file,mem}()) and allow the server to determine what servername the client requested (via tls_conn_servername()). ok beck@ --- lib/libtls/tls.h | 8 +++++- lib/libtls/tls_config.c | 58 ++++++++++++++++++++++++++++++++++++++- lib/libtls/tls_conninfo.c | 15 +++++++++- lib/libtls/tls_init.3 | 29 ++++++++++++++++++-- lib/libtls/tls_internal.h | 3 +- 5 files changed, 107 insertions(+), 6 deletions(-) diff --git a/lib/libtls/tls.h b/lib/libtls/tls.h index 13df43f0461..7a68c3d0d36 100644 --- a/lib/libtls/tls.h +++ b/lib/libtls/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.33 2016/08/12 15:10:59 jsing Exp $ */ +/* $OpenBSD: tls.h,v 1.34 2016/08/22 14:55:59 jsing Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -52,6 +52,11 @@ const char *tls_error(struct tls *_ctx); struct tls_config *tls_config_new(void); void tls_config_free(struct tls_config *_config); +int tls_config_add_keypair_file(struct tls_config *_config, + const char *_cert_file, const char *_key_file); +int tls_config_add_keypair_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); + int tls_config_set_alpn(struct tls_config *_config, const char *_alpn); int tls_config_set_ca_file(struct tls_config *_config, const char *_ca_file); int tls_config_set_ca_path(struct tls_config *_config, const char *_ca_path); @@ -119,6 +124,7 @@ time_t tls_peer_cert_notafter(struct tls *_ctx); const char *tls_conn_alpn_selected(struct tls *_ctx); const char *tls_conn_cipher(struct tls *_ctx); +const char *tls_conn_servername(struct tls *_ctx); const char *tls_conn_version(struct tls *_ctx); uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); diff --git a/lib/libtls/tls_config.c b/lib/libtls/tls_config.c index 0d52704aa81..c07621acaf2 100644 --- a/lib/libtls/tls_config.c +++ b/lib/libtls/tls_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_config.c,v 1.27 2016/08/13 13:15:53 jsing Exp $ */ +/* $OpenBSD: tls_config.c,v 1.28 2016/08/22 14:55:59 jsing Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -227,6 +227,18 @@ tls_config_free(struct tls_config *config) free(config); } +static void +tls_config_keypair_add(struct tls_config *config, struct tls_keypair *keypair) +{ + struct tls_keypair *kp; + + kp = config->keypair; + while (kp->next != NULL) + kp = kp->next; + + kp->next = keypair; +} + const char * tls_config_error(struct tls_config *config) { @@ -369,6 +381,50 @@ tls_config_set_alpn(struct tls_config *config, const char *alpn) &config->alpn_len); } +int +tls_config_add_keypair_file(struct tls_config *config, + const char *cert_file, const char *key_file) +{ + struct tls_keypair *keypair; + + if ((keypair = tls_keypair_new()) == NULL) + return (-1); + if (tls_keypair_set_cert_file(keypair, &config->error, cert_file) != 0) + goto err; + if (tls_keypair_set_key_file(keypair, &config->error, key_file) != 0) + goto err; + + tls_config_keypair_add(config, keypair); + + return (0); + + err: + tls_keypair_free(keypair); + return (-1); +} + +int +tls_config_add_keypair_mem(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len) +{ + struct tls_keypair *keypair; + + if ((keypair = tls_keypair_new()) == NULL) + return (-1); + if (tls_keypair_set_cert_mem(keypair, cert, cert_len) != 0) + goto err; + if (tls_keypair_set_key_mem(keypair, key, key_len) != 0) + goto err; + + tls_config_keypair_add(config, keypair); + + return (0); + + err: + tls_keypair_free(keypair); + return (-1); +} + int tls_config_set_ca_file(struct tls_config *config, const char *ca_file) { diff --git a/lib/libtls/tls_conninfo.c b/lib/libtls/tls_conninfo.c index 523b2798d36..281af798665 100644 --- a/lib/libtls/tls_conninfo.c +++ b/lib/libtls/tls_conninfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_conninfo.c,v 1.9 2016/08/15 14:47:41 jsing Exp $ */ +/* $OpenBSD: tls_conninfo.c,v 1.10 2016/08/22 14:55:59 jsing Exp $ */ /* * Copyright (c) 2015 Joel Sing * Copyright (c) 2015 Bob Beck @@ -199,6 +199,11 @@ tls_get_conninfo(struct tls *ctx) goto err; if (tls_conninfo_alpn_proto(ctx) == -1) goto err; + if (ctx->servername != NULL) { + if ((ctx->conninfo->servername = + strdup(ctx->servername)) == NULL) + goto err; + } return (0); err: @@ -241,6 +246,14 @@ tls_conn_cipher(struct tls *ctx) return (ctx->conninfo->cipher); } +const char * +tls_conn_servername(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->servername); +} + const char * tls_conn_version(struct tls *ctx) { diff --git a/lib/libtls/tls_init.3 b/lib/libtls/tls_init.3 index cd984500355..4d7367408be 100644 --- a/lib/libtls/tls_init.3 +++ b/lib/libtls/tls_init.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tls_init.3,v 1.66 2016/08/18 15:43:12 jsing Exp $ +.\" $OpenBSD: tls_init.3,v 1.67 2016/08/22 14:55:59 jsing Exp $ .\" .\" Copyright (c) 2014 Ted Unangst .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: August 18 2016 $ +.Dd $Mdocdate: August 22 2016 $ .Dt TLS_INIT 3 .Os .Sh NAME @@ -24,6 +24,8 @@ .Nm tls_config_new , .Nm tls_config_free , .Nm tls_config_parse_protocols , +.Nm tls_config_add_keypair_file , +.Nm tls_config_add_keypair_mem , .Nm tls_config_set_alpn , .Nm tls_config_set_ca_file , .Nm tls_config_set_ca_path , @@ -57,6 +59,7 @@ .Nm tls_peer_cert_notafter , .Nm tls_conn_alpn_selected , .Nm tls_conn_cipher , +.Nm tls_conn_servername , .Nm tls_conn_version , .Nm tls_load_file , .Nm tls_client , @@ -90,6 +93,10 @@ .Ft "int" .Fn tls_config_parse_protocols "uint32_t *protocols" "const char *protostr" .Ft "int" +.Fn tls_config_add_keypair_file "struct tls_config *config" "const char *cert_file" "const char *key_file" +.Ft "int" +.Fn tls_config_add_keypair_mem "struct tls_config *config" "const uint8_t *cert" "size_t cert_len" "const uint8_t *key" "size_t key_len" +.Ft "int" .Fn tls_config_set_alpn "struct tls_config *config" "const char *alpn" .Ft "int" .Fn tls_config_set_ca_file "struct tls_config *config" "const char *ca_file" @@ -156,6 +163,8 @@ .Ft "const char *" .Fn tls_conn_cipher "struct tls *ctx" .Ft "const char *" +.Fn tls_conn_servername "struct tls *ctx" +.Ft "const char *" .Fn tls_conn_version "struct tls *ctx" .Ft "uint8_t *" .Fn tls_load_file "const char *file" "size_t *len" "char *password" @@ -301,6 +310,16 @@ The following functions modify a configuration by setting parameters (the configuration options may only apply to clients, to servers or to both): .Bl -bullet -offset four .It +.Fn tls_config_add_keypair_file +adds an additional public certificate and private key from the specified files, +used as an alternative certificate for Server Name Indication. +.Em (Server) +.It +.Fn tls_config_set_keypair_mem +adds an additional public certificate and private key from memory, +used as an alternative certificate for Server Name Indication. +.Em (Server) +.It .Fn tls_config_set_alpn sets the ALPN protocols that are supported. The alpn string is a comma separated list of protocols, in order of preference. @@ -445,6 +464,12 @@ connected to .Ar ctx . .Em (Server and client) .It +.Fn tls_conn_servername +returns a string corresponding to the servername that the client connected to +.Ar ctx +requested by sending a TLS Server Name Indication extension. +.Em (Server) +.It .Fn tls_conn_version returns a string corresponding to a TLS version negotiated with the peer connected to diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h index 428e29c8577..3fcc7a021fa 100644 --- a/lib/libtls/tls_internal.h +++ b/lib/libtls/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.40 2016/08/22 14:51:37 jsing Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.41 2016/08/22 14:55:59 jsing Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * Copyright (c) 2014 Joel Sing @@ -74,6 +74,7 @@ struct tls_config { struct tls_conninfo { char *alpn; char *cipher; + char *servername; char *version; char *hash; -- 2.20.1