Skip to content

Commit 8155f8a

Browse files
James Bottomleycron2
James Bottomley
authored andcommitted
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>
1 parent 7d65aad commit 8155f8a

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/openvpn/crypto_openssl.c

+56
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#endif
6464

6565
#if HAVE_OPENSSL_ENGINE
66+
#include <openssl/ui.h>
6667
#include <openssl/engine.h>
6768

6869
static bool engine_initialized = false; /* GLOBAL */
@@ -1070,4 +1071,59 @@ memcmp_constant_time(const void *a, const void *b, size_t size)
10701071
{
10711072
return CRYPTO_memcmp(a, b, size);
10721073
}
1074+
1075+
#if HAVE_OPENSSL_ENGINE
1076+
static int
1077+
ui_reader(UI *ui, UI_STRING *uis)
1078+
{
1079+
SSL_CTX *ctx = UI_get0_user_data(ui);
1080+
1081+
if (UI_get_string_type(uis) == UIT_PROMPT) {
1082+
pem_password_cb *cb = SSL_CTX_get_default_passwd_cb(ctx);
1083+
void *d = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1084+
char password[64];
1085+
1086+
cb(password, sizeof(password), 0, d);
1087+
UI_set_result(ui, uis, password);
1088+
1089+
return 1;
1090+
}
1091+
return 0;
1092+
}
1093+
#endif
1094+
1095+
EVP_PKEY *
1096+
engine_load_key(const char *file, SSL_CTX *ctx)
1097+
{
1098+
#if HAVE_OPENSSL_ENGINE
1099+
UI_METHOD *ui;
1100+
EVP_PKEY *pkey;
1101+
1102+
if (!engine_persist)
1103+
return NULL;
1104+
1105+
/* this will print out the error from BIO_read */
1106+
crypto_msg(M_INFO, "PEM_read_bio failed, now trying engine method to load private key");
1107+
1108+
ui = UI_create_method("openvpn");
1109+
if (!ui) {
1110+
crypto_msg(M_FATAL, "Engine UI creation failed");
1111+
return NULL;
1112+
}
1113+
1114+
UI_method_set_reader(ui, ui_reader);
1115+
1116+
ENGINE_init(engine_persist);
1117+
pkey = ENGINE_load_private_key(engine_persist, file, ui, ctx);
1118+
ENGINE_finish(engine_persist);
1119+
if (!pkey)
1120+
crypto_msg(M_FATAL, "Engine could not load key file");
1121+
1122+
UI_destroy_method(ui);
1123+
return pkey;
1124+
#else
1125+
return NULL;
1126+
#endif
1127+
}
1128+
10731129
#endif /* ENABLE_CRYPTO_OPENSSL */

src/openvpn/crypto_openssl.h

+12
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,16 @@ cipher_kt_var_key_size(const cipher_kt_t *cipher)
107107
return EVP_CIPHER_flags(cipher) & EVP_CIPH_VARIABLE_LENGTH;
108108
}
109109

110+
/**
111+
* Load a key file from an engine
112+
*
113+
* @param file The engine file to load
114+
* @param ui The UI method for the password prompt
115+
* @param data The data to pass to the UI method
116+
*
117+
* @return The private key if successful or NULL if not
118+
*/
119+
EVP_PKEY *
120+
engine_load_key(const char *file, SSL_CTX *ctx);
121+
110122
#endif /* CRYPTO_OPENSSL_H_ */

src/openvpn/ssl_openssl.c

+5
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,11 @@ tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
10201020
pkey = PEM_read_bio_PrivateKey(in, NULL,
10211021
SSL_CTX_get_default_passwd_cb(ctx->ctx),
10221022
SSL_CTX_get_default_passwd_cb_userdata(ctx->ctx));
1023+
if (!pkey)
1024+
{
1025+
pkey = engine_load_key(priv_key_file, ctx->ctx);
1026+
}
1027+
10231028
if (!pkey || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
10241029
{
10251030
#ifdef ENABLE_MANAGEMENT

0 commit comments

Comments
 (0)