summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2016-04-28 17:06:00 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2016-04-28 17:06:00 +0000
commitb2daa22e54e25c4f73060dc598119941bda99041 (patch)
tree1cb15c42c85e6d58f078339292b1ce634994a536
parenteb65459604e2a7010ecdda143c94d347c8f4bacf (diff)
Factor our the keypair handling in libtls. This results in more readable
and self-contained code, while preparing for the ability to handle multiple keypairs. Also provide two additional functions that allow a public certificate and private key to be set with a single function call. ok beck@
-rw-r--r--lib/libtls/tls.c45
-rw-r--r--lib/libtls/tls.h6
-rw-r--r--lib/libtls/tls_client.c4
-rw-r--r--lib/libtls/tls_config.c114
-rw-r--r--lib/libtls/tls_init.320
-rw-r--r--lib/libtls/tls_internal.h23
-rw-r--r--lib/libtls/tls_server.c4
7 files changed, 164 insertions, 52 deletions
diff --git a/lib/libtls/tls.c b/lib/libtls/tls.c
index 661aa6ad0ad..d067309cd30 100644
--- a/lib/libtls/tls.c
+++ b/lib/libtls/tls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.c,v 1.36 2016/04/28 16:48:44 jsing Exp $ */
+/* $OpenBSD: tls.c,v 1.37 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -179,40 +179,41 @@ tls_configure(struct tls *ctx, struct tls_config *config)
}
int
-tls_configure_keypair(struct tls *ctx, int required)
+tls_configure_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
+ struct tls_keypair *keypair, int required)
{
EVP_PKEY *pkey = NULL;
X509 *cert = NULL;
BIO *bio = NULL;
if (!required &&
- ctx->config->cert_mem == NULL &&
- ctx->config->key_mem == NULL &&
- ctx->config->cert_file == NULL &&
- ctx->config->key_file == NULL)
+ keypair->cert_mem == NULL &&
+ keypair->key_mem == NULL &&
+ keypair->cert_file == NULL &&
+ keypair->key_file == NULL)
return(0);
- if (ctx->config->cert_mem != NULL) {
- if (ctx->config->cert_len > INT_MAX) {
+ if (keypair->cert_mem != NULL) {
+ if (keypair->cert_len > INT_MAX) {
tls_set_errorx(ctx, "certificate too long");
goto err;
}
- if (SSL_CTX_use_certificate_chain_mem(ctx->ssl_ctx,
- ctx->config->cert_mem, ctx->config->cert_len) != 1) {
+ if (SSL_CTX_use_certificate_chain_mem(ssl_ctx,
+ keypair->cert_mem, keypair->cert_len) != 1) {
tls_set_errorx(ctx, "failed to load certificate");
goto err;
}
cert = NULL;
}
- if (ctx->config->key_mem != NULL) {
- if (ctx->config->key_len > INT_MAX) {
+ if (keypair->key_mem != NULL) {
+ if (keypair->key_len > INT_MAX) {
tls_set_errorx(ctx, "key too long");
goto err;
}
- if ((bio = BIO_new_mem_buf(ctx->config->key_mem,
- ctx->config->key_len)) == NULL) {
+ if ((bio = BIO_new_mem_buf(keypair->key_mem,
+ keypair->key_len)) == NULL) {
tls_set_errorx(ctx, "failed to create buffer");
goto err;
}
@@ -221,7 +222,7 @@ tls_configure_keypair(struct tls *ctx, int required)
tls_set_errorx(ctx, "failed to read private key");
goto err;
}
- if (SSL_CTX_use_PrivateKey(ctx->ssl_ctx, pkey) != 1) {
+ if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) {
tls_set_errorx(ctx, "failed to load private key");
goto err;
}
@@ -231,22 +232,22 @@ tls_configure_keypair(struct tls *ctx, int required)
pkey = NULL;
}
- if (ctx->config->cert_file != NULL) {
- if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx,
- ctx->config->cert_file) != 1) {
+ if (keypair->cert_file != NULL) {
+ if (SSL_CTX_use_certificate_chain_file(ssl_ctx,
+ keypair->cert_file) != 1) {
tls_set_errorx(ctx, "failed to load certificate file");
goto err;
}
}
- if (ctx->config->key_file != NULL) {
- if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx,
- ctx->config->key_file, SSL_FILETYPE_PEM) != 1) {
+ if (keypair->key_file != NULL) {
+ if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
+ keypair->key_file, SSL_FILETYPE_PEM) != 1) {
tls_set_errorx(ctx, "failed to load private key file");
goto err;
}
}
- if (SSL_CTX_check_private_key(ctx->ssl_ctx) != 1) {
+ if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
tls_set_errorx(ctx, "private/public key mismatch");
goto err;
}
diff --git a/lib/libtls/tls.h b/lib/libtls/tls.h
index da229d1feed..6994f1417b9 100644
--- a/lib/libtls/tls.h
+++ b/lib/libtls/tls.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.h,v 1.27 2016/04/28 16:48:44 jsing Exp $ */
+/* $OpenBSD: tls.h,v 1.28 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -66,6 +66,10 @@ int tls_config_set_ecdhecurve(struct tls_config *_config, const char *_name);
int tls_config_set_key_file(struct tls_config *_config, const char *_key_file);
int tls_config_set_key_mem(struct tls_config *_config, const uint8_t *_key,
size_t _len);
+int tls_config_set_keypair_file(struct tls_config *_config,
+ const char *_cert_file, const char *_key_file);
+int tls_config_set_keypair_mem(struct tls_config *_config, const uint8_t *_cert,
+ size_t _cert_len, const uint8_t *_key, size_t _key_len);
void tls_config_set_protocols(struct tls_config *_config, uint32_t _protocols);
void tls_config_set_verify_depth(struct tls_config *_config, int _verify_depth);
diff --git a/lib/libtls/tls_client.c b/lib/libtls/tls_client.c
index 6bb24cd512f..3847f4c46cd 100644
--- a/lib/libtls/tls_client.c
+++ b/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_client.c,v 1.32 2015/10/09 04:13:34 deraadt Exp $ */
+/* $OpenBSD: tls_client.c,v 1.33 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -195,7 +195,7 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
if (tls_configure_ssl(ctx) != 0)
goto err;
- if (tls_configure_keypair(ctx, 0) != 0)
+ if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 0) != 0)
goto err;
if (ctx->config->verify_name) {
diff --git a/lib/libtls/tls_config.c b/lib/libtls/tls_config.c
index 9c2b5810f68..b395337f498 100644
--- a/lib/libtls/tls_config.c
+++ b/lib/libtls/tls_config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_config.c,v 1.15 2016/04/28 16:48:44 jsing Exp $ */
+/* $OpenBSD: tls_config.c,v 1.16 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -57,6 +57,63 @@ set_mem(char **dest, size_t *destlen, const void *src, size_t srclen)
return 0;
}
+static struct tls_keypair *
+tls_keypair_new()
+{
+ return calloc(1, sizeof(struct tls_keypair));
+}
+
+static int
+tls_keypair_set_cert_file(struct tls_keypair *keypair, const char *cert_file)
+{
+ return set_string(&keypair->cert_file, cert_file);
+}
+
+static int
+tls_keypair_set_cert_mem(struct tls_keypair *keypair, const uint8_t *cert,
+ size_t len)
+{
+ return set_mem(&keypair->cert_mem, &keypair->cert_len, cert, len);
+}
+
+static int
+tls_keypair_set_key_file(struct tls_keypair *keypair, const char *key_file)
+{
+ return set_string(&keypair->key_file, key_file);
+}
+
+static int
+tls_keypair_set_key_mem(struct tls_keypair *keypair, const uint8_t *key,
+ size_t len)
+{
+ if (keypair->key_mem != NULL)
+ explicit_bzero(keypair->key_mem, keypair->key_len);
+ return set_mem(&keypair->key_mem, &keypair->key_len, key, len);
+}
+
+static void
+tls_keypair_clear(struct tls_keypair *keypair)
+{
+ tls_keypair_set_cert_mem(keypair, NULL, 0);
+ tls_keypair_set_key_mem(keypair, NULL, 0);
+}
+
+static void
+tls_keypair_free(struct tls_keypair *keypair)
+{
+ if (keypair == NULL)
+ return;
+
+ tls_keypair_clear(keypair);
+
+ free((char *)keypair->cert_file);
+ free(keypair->cert_mem);
+ free((char *)keypair->key_file);
+ free(keypair->key_mem);
+
+ free(keypair);
+}
+
struct tls_config *
tls_config_new(void)
{
@@ -65,6 +122,9 @@ tls_config_new(void)
if ((config = calloc(1, sizeof(*config))) == NULL)
return (NULL);
+ if ((config->keypair = tls_keypair_new()) == NULL)
+ goto err;
+
/*
* Default configuration.
*/
@@ -94,20 +154,21 @@ tls_config_new(void)
void
tls_config_free(struct tls_config *config)
{
+ struct tls_keypair *kp, *nkp;
+
if (config == NULL)
return;
- tls_config_clear_keys(config);
+ for (kp = config->keypair; kp != NULL; kp = nkp) {
+ nkp = kp->next;
+ tls_keypair_free(kp);
+ }
free(config->error.msg);
free((char *)config->ca_file);
free((char *)config->ca_path);
- free((char *)config->cert_file);
- free(config->cert_mem);
free((char *)config->ciphers);
- free((char *)config->key_file);
- free(config->key_mem);
free(config);
}
@@ -121,9 +182,12 @@ tls_config_error(struct tls_config *config)
void
tls_config_clear_keys(struct tls_config *config)
{
+ struct tls_keypair *kp;
+
+ for (kp = config->keypair; kp != NULL; kp = kp->next)
+ tls_keypair_clear(kp);
+
tls_config_set_ca_mem(config, NULL, 0);
- tls_config_set_cert_mem(config, NULL, 0);
- tls_config_set_key_mem(config, NULL, 0);
}
int
@@ -205,14 +269,14 @@ tls_config_set_ca_mem(struct tls_config *config, const uint8_t *ca, size_t len)
int
tls_config_set_cert_file(struct tls_config *config, const char *cert_file)
{
- return set_string(&config->cert_file, cert_file);
+ return tls_keypair_set_cert_file(config->keypair, cert_file);
}
int
tls_config_set_cert_mem(struct tls_config *config, const uint8_t *cert,
size_t len)
{
- return set_mem(&config->cert_mem, &config->cert_len, cert, len);
+ return tls_keypair_set_cert_mem(config->keypair, cert, len);
}
int
@@ -272,16 +336,38 @@ tls_config_set_ecdhecurve(struct tls_config *config, const char *name)
int
tls_config_set_key_file(struct tls_config *config, const char *key_file)
{
- return set_string(&config->key_file, key_file);
+ return tls_keypair_set_key_file(config->keypair, key_file);
}
int
tls_config_set_key_mem(struct tls_config *config, const uint8_t *key,
size_t len)
{
- if (config->key_mem)
- explicit_bzero(config->key_mem, config->key_len);
- return set_mem(&config->key_mem, &config->key_len, key, len);
+ return tls_keypair_set_key_mem(config->keypair, key, len);
+}
+
+int
+tls_config_set_keypair_file(struct tls_config *config,
+ const char *cert_file, const char *key_file)
+{
+ if (tls_config_set_cert_file(config, cert_file) != 0)
+ return (-1);
+ if (tls_config_set_key_file(config, key_file) != 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+tls_config_set_keypair_mem(struct tls_config *config, const uint8_t *cert,
+ size_t cert_len, const uint8_t *key, size_t key_len)
+{
+ if (tls_config_set_cert_mem(config, cert, cert_len) != 0)
+ return (-1);
+ if (tls_config_set_key_mem(config, key, key_len) != 0)
+ return (-1);
+
+ return (0);
}
void
diff --git a/lib/libtls/tls_init.3 b/lib/libtls/tls_init.3
index 48662e08683..da8565a248d 100644
--- a/lib/libtls/tls_init.3
+++ b/lib/libtls/tls_init.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tls_init.3,v 1.57 2016/04/28 16:48:44 jsing Exp $
+.\" $OpenBSD: tls_init.3,v 1.58 2016/04/28 17:05:59 jsing Exp $
.\"
.\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
.\"
@@ -34,6 +34,8 @@
.Nm tls_config_set_ecdhecurve ,
.Nm tls_config_set_key_file ,
.Nm tls_config_set_key_mem ,
+.Nm tls_config_set_keypair_file ,
+.Nm tls_config_set_keypair_mem ,
.Nm tls_config_set_protocols ,
.Nm tls_config_set_verify_depth ,
.Nm tls_config_prefer_ciphers_client ,
@@ -105,6 +107,10 @@
.Fn tls_config_set_key_file "struct tls_config *config" "const char *key_file"
.Ft "int"
.Fn tls_config_set_key_mem "struct tls_config *config" "const uint8_t *key" "size_t len"
+.Ft "int"
+.Fn tls_config_set_keypair_file "struct tls_config *config" "const char *cert_file" "const char *key_file"
+.Ft "int"
+.Fn tls_config_set_keypair_mem "struct tls_config *config" "const uint8_t *cert" "size_t cert_len" "const uint8_t *key" "size_t key_len"
.Ft "void"
.Fn tls_config_set_protocols "struct tls_config *config" "uint32_t protocols"
.Ft "void"
@@ -327,11 +333,19 @@ permitted names are:
.It
.Fn tls_config_set_key_file
sets the file from which the private key will be read.
-.Em (Server)
+.Em (Client and server)
.It
.Fn tls_config_set_key_mem
directly sets the private key from memory.
-.Em (Server)
+.Em (Client and server)
+.It
+.Fn tls_config_set_keypair_file
+sets the files from which the public certificate and private key will be read.
+.Em (Client and server)
+.It
+.Fn tls_config_set_keypair_mem
+directly sets the public certifcate and private key from memory.
+.Em (Client and server)
.It
.Fn tls_config_set_protocols
sets which versions of the protocol may be used.
diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h
index 21bf2b46130..cb5d90f5427 100644
--- a/lib/libtls/tls_internal.h
+++ b/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.27 2016/04/28 16:48:44 jsing Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.28 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -39,6 +39,17 @@ struct tls_error {
int num;
};
+struct tls_keypair {
+ struct tls_keypair *next;
+
+ const char *cert_file;
+ char *cert_mem;
+ size_t cert_len;
+ const char *key_file;
+ char *key_mem;
+ size_t key_len;
+};
+
struct tls_config {
struct tls_error error;
@@ -46,16 +57,11 @@ struct tls_config {
const char *ca_path;
char *ca_mem;
size_t ca_len;
- const char *cert_file;
- char *cert_mem;
- size_t cert_len;
const char *ciphers;
int ciphers_server;
int dheparams;
int ecdhecurve;
- const char *key_file;
- char *key_mem;
- size_t key_len;
+ struct tls_keypair *keypair;
uint32_t protocols;
int verify_cert;
int verify_client;
@@ -103,7 +109,8 @@ struct tls *tls_new(void);
struct tls *tls_server_conn(struct tls *ctx);
int tls_check_name(struct tls *ctx, X509 *cert, const char *servername);
-int tls_configure_keypair(struct tls *ctx, int);
+int tls_configure_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
+ struct tls_keypair *keypair, int required);
int tls_configure_server(struct tls *ctx);
int tls_configure_ssl(struct tls *ctx);
int tls_configure_ssl_verify(struct tls *ctx, int verify);
diff --git a/lib/libtls/tls_server.c b/lib/libtls/tls_server.c
index ad98cf3d7e8..1d94c99bc01 100644
--- a/lib/libtls/tls_server.c
+++ b/lib/libtls/tls_server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_server.c,v 1.18 2015/09/29 10:17:04 deraadt Exp $ */
+/* $OpenBSD: tls_server.c,v 1.19 2016/04/28 17:05:59 jsing Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -61,7 +61,7 @@ tls_configure_server(struct tls *ctx)
if (tls_configure_ssl(ctx) != 0)
goto err;
- if (tls_configure_keypair(ctx, 1) != 0)
+ if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 1) != 0)
goto err;
if (ctx->config->verify_client != 0) {
int verify = SSL_VERIFY_PEER;