aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bottomley2020-05-28 15:59:18 -0700
committerGert Doering2020-06-06 20:06:24 +0200
commit8155f8aa0a8d801dd0d84e0ec844b9ca4c225df7 (patch)
treea7b3b3666b9f6566de3dfbc4498597025d91ecbb
parent7d65aad8973fa85a007a3de8907b9cbced20b2b4 (diff)
downloadopenvpn-8155f8aa0a8d801dd0d84e0ec844b9ca4c225df7.zip
openvpn-8155f8aa0a8d801dd0d84e0ec844b9ca4c225df7.tar.gz
openssl: add engine method for loading the key
As well as doing crypto acceleration, engines can also be used to load key files. If the engine is set, and the private key loading fails for bio methods, this patch makes openvpn try to get the engine to load the key. If that succeeds, we end up using an engine based key. This can be used with the openssl tpm engines to make openvpn use a TPM wrapped key file. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Acked-by: Arne Schwabe <arne@rfc2549.org> Message-Id: <20200528225920.6983-2-James.Bottomley@HansenPartnership.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg19937.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
-rw-r--r--src/openvpn/crypto_openssl.c56
-rw-r--r--src/openvpn/crypto_openssl.h12
-rw-r--r--src/openvpn/ssl_openssl.c5
3 files changed, 73 insertions, 0 deletions
diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
index a5b2c45..4ac77fd 100644
--- a/src/openvpn/crypto_openssl.c
+++ b/src/openvpn/crypto_openssl.c
@@ -63,6 +63,7 @@
#endif
#if HAVE_OPENSSL_ENGINE
+#include <openssl/ui.h>
#include <openssl/engine.h>
static bool engine_initialized = false; /* GLOBAL */
@@ -1070,4 +1071,59 @@ memcmp_constant_time(const void *a, const void *b, size_t size)
{
return CRYPTO_memcmp(a, b, size);
}
+
+#if HAVE_OPENSSL_ENGINE
+static int
+ui_reader(UI *ui, UI_STRING *uis)
+{
+ SSL_CTX *ctx = UI_get0_user_data(ui);
+
+ if (UI_get_string_type(uis) == UIT_PROMPT) {
+ pem_password_cb *cb = SSL_CTX_get_default_passwd_cb(ctx);
+ void *d = SSL_CTX_get_default_passwd_cb_userdata(ctx);
+ char password[64];
+
+ cb(password, sizeof(password), 0, d);
+ UI_set_result(ui, uis, password);
+
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+EVP_PKEY *
+engine_load_key(const char *file, SSL_CTX *ctx)
+{
+#if HAVE_OPENSSL_ENGINE
+ UI_METHOD *ui;
+ EVP_PKEY *pkey;
+
+ if (!engine_persist)
+ return NULL;
+
+ /* this will print out the error from BIO_read */
+ crypto_msg(M_INFO, "PEM_read_bio failed, now trying engine method to load private key");
+
+ ui = UI_create_method("openvpn");
+ if (!ui) {
+ crypto_msg(M_FATAL, "Engine UI creation failed");
+ return NULL;
+ }
+
+ UI_method_set_reader(ui, ui_reader);
+
+ ENGINE_init(engine_persist);
+ pkey = ENGINE_load_private_key(engine_persist, file, ui, ctx);
+ ENGINE_finish(engine_persist);
+ if (!pkey)
+ crypto_msg(M_FATAL, "Engine could not load key file");
+
+ UI_destroy_method(ui);
+ return pkey;
+#else
+ return NULL;
+#endif
+}
+
#endif /* ENABLE_CRYPTO_OPENSSL */
diff --git a/src/openvpn/crypto_openssl.h b/src/openvpn/crypto_openssl.h
index 6475448..7449fbd 100644
--- a/src/openvpn/crypto_openssl.h
+++ b/src/openvpn/crypto_openssl.h
@@ -107,4 +107,16 @@ cipher_kt_var_key_size(const cipher_kt_t *cipher)
return EVP_CIPHER_flags(cipher) & EVP_CIPH_VARIABLE_LENGTH;
}
+/**
+ * Load a key file from an engine
+ *
+ * @param file The engine file to load
+ * @param ui The UI method for the password prompt
+ * @param data The data to pass to the UI method
+ *
+ * @return The private key if successful or NULL if not
+ */
+EVP_PKEY *
+engine_load_key(const char *file, SSL_CTX *ctx);
+
#endif /* CRYPTO_OPENSSL_H_ */
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index 06c836d..a489053 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -1020,6 +1020,11 @@ tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
pkey = PEM_read_bio_PrivateKey(in, NULL,
SSL_CTX_get_default_passwd_cb(ctx->ctx),
SSL_CTX_get_default_passwd_cb_userdata(ctx->ctx));
+ if (!pkey)
+ {
+ pkey = engine_load_key(priv_key_file, ctx->ctx);
+ }
+
if (!pkey || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
{
#ifdef ENABLE_MANAGEMENT