summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2021-01-21 19:09:11 +0000
committerEric Faurot <eric@cvs.openbsd.org>2021-01-21 19:09:11 +0000
commit84d709d1a3c107dd95b802d688a9898c224be5f7 (patch)
treeddbd7db8c7d1899c0f7312e4ce1c68d093e48554
parent5bfa6f2cfdee0e1f7c735df379ca53da8b240710 (diff)
Allow setting a keypair on a tls context without specifying the private
key, and fake it internally with the certificate public key instead. It makes it easier for privsep engines like relayd that don't have to use bogus keys anymore. ok beck@ tb@ jsing@
-rw-r--r--lib/libtls/Symbols.list1
-rw-r--r--lib/libtls/tls.c84
-rw-r--r--lib/libtls/tls_config.c14
-rw-r--r--lib/libtls/tls_internal.h4
4 files changed, 77 insertions, 26 deletions
diff --git a/lib/libtls/Symbols.list b/lib/libtls/Symbols.list
index e3fcb67fb3f..42c039d2945 100644
--- a/lib/libtls/Symbols.list
+++ b/lib/libtls/Symbols.list
@@ -45,6 +45,7 @@ tls_config_set_session_lifetime
tls_config_set_session_fd
tls_config_set_verify_depth
tls_config_skip_private_key_check
+tls_config_use_fake_private_key
tls_config_verify
tls_config_verify_client
tls_config_verify_client_optional
diff --git a/lib/libtls/tls.c b/lib/libtls/tls.c
index 3d6723bbd9c..02ddf447fb3 100644
--- a/lib/libtls/tls.c
+++ b/lib/libtls/tls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls.c,v 1.85 2020/05/24 15:12:54 jsing Exp $ */
+/* $OpenBSD: tls.c,v 1.86 2021/01/21 19:09:10 eric Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -326,12 +326,69 @@ tls_cert_pubkey_hash(X509 *cert, char **hash)
return (rv);
}
+static int
+tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pkey)
+{
+ BIO *bio = NULL;
+ X509 *x509 = NULL;
+ char *mem;
+ size_t len;
+ int ret = -1;
+
+ *pkey = NULL;
+
+ if (ctx->config->use_fake_private_key) {
+ mem = keypair->cert_mem;
+ len = keypair->cert_len;
+ } else {
+ mem = keypair->key_mem;
+ len = keypair->key_len;
+ }
+
+ if (mem == NULL)
+ return (0);
+
+ if (len > INT_MAX) {
+ tls_set_errorx(ctx, ctx->config->use_fake_private_key ?
+ "cert too long" : "key too long");
+ goto err;
+ }
+
+ if ((bio = BIO_new_mem_buf(mem, len)) == NULL) {
+ tls_set_errorx(ctx, "failed to create buffer");
+ goto err;
+ }
+
+ if (ctx->config->use_fake_private_key) {
+ if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
+ NULL)) == NULL) {
+ tls_set_errorx(ctx, "failed to read X509 certificate");
+ goto err;
+ }
+ if ((*pkey = X509_get_pubkey(x509)) == NULL) {
+ tls_set_errorx(ctx, "failed to retrieve pubkey");
+ goto err;
+ }
+ } else {
+ if ((*pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
+ NULL)) == NULL) {
+ tls_set_errorx(ctx, "failed to read private key");
+ goto err;
+ }
+ }
+
+ ret = 0;
+ err:
+ BIO_free(bio);
+ X509_free(x509);
+ return (ret);
+}
+
int
tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
struct tls_keypair *keypair, int required)
{
EVP_PKEY *pkey = NULL;
- BIO *bio = NULL;
if (!required &&
keypair->cert_mem == NULL &&
@@ -351,23 +408,9 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
}
}
- 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(keypair->key_mem,
- keypair->key_len)) == NULL) {
- tls_set_errorx(ctx, "failed to create buffer");
- goto err;
- }
- if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
- NULL)) == NULL) {
- tls_set_errorx(ctx, "failed to read private key");
- goto err;
- }
-
+ if (tls_keypair_to_pkey(ctx, keypair, &pkey) == -1)
+ goto err;
+ if (pkey != NULL) {
if (keypair->pubkey_hash != NULL) {
RSA *rsa;
/* XXX only RSA for now for relayd privsep */
@@ -381,8 +424,6 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
tls_set_errorx(ctx, "failed to load private key");
goto err;
}
- BIO_free(bio);
- bio = NULL;
EVP_PKEY_free(pkey);
pkey = NULL;
}
@@ -397,7 +438,6 @@ tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
err:
EVP_PKEY_free(pkey);
- BIO_free(bio);
return (1);
}
diff --git a/lib/libtls/tls_config.c b/lib/libtls/tls_config.c
index 7a0d6d8adf2..e3e90aaa007 100644
--- a/lib/libtls/tls_config.c
+++ b/lib/libtls/tls_config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_config.c,v 1.61 2020/12/22 13:07:54 bcook Exp $ */
+/* $OpenBSD: tls_config.c,v 1.62 2021/01/21 19:09:10 eric Exp $ */
/*
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
*
@@ -353,7 +353,8 @@ tls_config_add_keypair_file_internal(struct tls_config *config,
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)
+ if (key_file != NULL &&
+ tls_keypair_set_key_file(keypair, &config->error, key_file) != 0)
goto err;
if (ocsp_file != NULL &&
tls_keypair_set_ocsp_staple_file(keypair, &config->error,
@@ -380,7 +381,8 @@ tls_config_add_keypair_mem_internal(struct tls_config *config, const uint8_t *ce
return (-1);
if (tls_keypair_set_cert_mem(keypair, &config->error, cert, cert_len) != 0)
goto err;
- if (tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0)
+ if (key != NULL &&
+ tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0)
goto err;
if (staple != NULL &&
tls_keypair_set_ocsp_staple_mem(keypair, &config->error, staple,
@@ -805,6 +807,12 @@ tls_config_skip_private_key_check(struct tls_config *config)
config->skip_private_key_check = 1;
}
+void
+tls_config_use_fake_private_key(struct tls_config *config)
+{
+ config->use_fake_private_key = 1;
+}
+
int
tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file)
{
diff --git a/lib/libtls/tls_internal.h b/lib/libtls/tls_internal.h
index 1dd5f45dddb..5487b123ec6 100644
--- a/lib/libtls/tls_internal.h
+++ b/lib/libtls/tls_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.77 2019/11/16 21:39:52 beck Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.78 2021/01/21 19:09:10 eric Exp $ */
/*
* Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
* Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
@@ -111,6 +111,7 @@ struct tls_config {
int verify_name;
int verify_time;
int skip_private_key_check;
+ int use_fake_private_key;
};
struct tls_conninfo {
@@ -294,5 +295,6 @@ __END_HIDDEN_DECLS
/* XXX this function is not fully hidden so relayd can use it */
void tls_config_skip_private_key_check(struct tls_config *config);
+void tls_config_use_fake_private_key(struct tls_config *config);
#endif /* HEADER_TLS_INTERNAL_H */