From 15339a8c6b46d6aea4f5df0384c38a8aef15f986 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 21 Jan 2021 19:09:10 +0000 Subject: [PATCH] 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@ --- lib/libtls/Symbols.list | 1 + lib/libtls/tls.c | 84 +++++++++++++++++++++++++++++---------- lib/libtls/tls_config.c | 14 +++++-- lib/libtls/tls_internal.h | 4 +- 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 * @@ -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 * @@ -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 * Copyright (c) 2014 Joel Sing @@ -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 */ -- 2.20.1