diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 10:00:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 10:00:10 +0000 |
commit | 3204e211a1e248154ff95b90b6a7e29cfa92069c (patch) | |
tree | 79f901498145b63bf34e9981a013f3d9b52eafc2 /modules/ssl/ssl_engine_pphrase.c | |
parent | Adding upstream version 2.4.61. (diff) | |
download | apache2-3204e211a1e248154ff95b90b6a7e29cfa92069c.tar.xz apache2-3204e211a1e248154ff95b90b6a7e29cfa92069c.zip |
Adding upstream version 2.4.62.upstream/2.4.62upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules/ssl/ssl_engine_pphrase.c')
-rw-r--r-- | modules/ssl/ssl_engine_pphrase.c | 159 |
1 files changed, 149 insertions, 10 deletions
diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c index 699019f..8a08ede 100644 --- a/modules/ssl/ssl_engine_pphrase.c +++ b/modules/ssl/ssl_engine_pphrase.c @@ -31,6 +31,9 @@ #include "ssl_private.h" #include <openssl/ui.h> +#if MODSSL_HAVE_OPENSSL_STORE +#include <openssl/store.h> +#endif typedef struct { server_rec *s; @@ -608,7 +611,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv) return (len); } -#if MODSSL_HAVE_ENGINE_API +#if MODSSL_HAVE_ENGINE_API || MODSSL_HAVE_OPENSSL_STORE /* OpenSSL UI implementation for passphrase entry; largely duplicated * from ssl_pphrase_Handle_CB but adjusted for UI API. TODO: Might be @@ -826,21 +829,32 @@ static UI_METHOD *get_passphrase_ui(apr_pool_t *p) } #endif +#if MODSSL_HAVE_ENGINE_API +static apr_status_t modssl_engine_cleanup(void *engine) +{ + ENGINE *e = engine; -apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p, - const char *vhostid, - const char *certid, const char *keyid, - X509 **pubkey, EVP_PKEY **privkey) + ENGINE_finish(e); + + return APR_SUCCESS; +} + +static apr_status_t modssl_load_keypair_engine(server_rec *s, apr_pool_t *pconf, + apr_pool_t *ptemp, + const char *vhostid, + const char *certid, + const char *keyid, + X509 **pubkey, + EVP_PKEY **privkey) { -#if MODSSL_HAVE_ENGINE_API const char *c, *scheme; ENGINE *e; - UI_METHOD *ui_method = get_passphrase_ui(p); + UI_METHOD *ui_method = get_passphrase_ui(ptemp); pphrase_cb_arg_t ppcb; memset(&ppcb, 0, sizeof ppcb); ppcb.s = s; - ppcb.p = p; + ppcb.p = ptemp; ppcb.bPassPhraseDialogOnce = TRUE; ppcb.key_id = vhostid; ppcb.pkey_file = keyid; @@ -853,7 +867,7 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p, return ssl_die(s); } - scheme = apr_pstrmemdup(p, keyid, c - keyid); + scheme = apr_pstrmemdup(ptemp, keyid, c - keyid); if (!(e = ENGINE_by_id(scheme))) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132) "Init: Failed to load engine for private key %s", @@ -902,11 +916,136 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p, return ssl_die(s); } - ENGINE_finish(e); + /* Release the functional reference obtained by ENGINE_init() only + * when after the ENGINE is no longer used. */ + apr_pool_cleanup_register(pconf, e, modssl_engine_cleanup, modssl_engine_cleanup); + + /* Release the structural reference obtained by ENGINE_by_id() + * immediately. */ ENGINE_free(e); return APR_SUCCESS; +} +#endif + +#if MODSSL_HAVE_OPENSSL_STORE +static OSSL_STORE_INFO *modssl_load_store_uri(server_rec *s, apr_pool_t *p, + const char *vhostid, + const char *uri, int info_type) +{ + OSSL_STORE_CTX *sctx; + UI_METHOD *ui_method = get_passphrase_ui(p); + pphrase_cb_arg_t ppcb; + OSSL_STORE_INFO *info = NULL; + + memset(&ppcb, 0, sizeof ppcb); + ppcb.s = s; + ppcb.p = p; + ppcb.bPassPhraseDialogOnce = TRUE; + ppcb.key_id = vhostid; + ppcb.pkey_file = uri; + + sctx = OSSL_STORE_open(uri, ui_method, &ppcb, NULL, NULL); + if (!sctx) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(10491) + "Init: OSSL_STORE_open failed for PKCS#11 URI `%s'", + uri); + return NULL; + } + + while (!OSSL_STORE_eof(sctx)) { + info = OSSL_STORE_load(sctx); + if (!info) + break; + + if (OSSL_STORE_INFO_get_type(info) == info_type) + break; + + OSSL_STORE_INFO_free(info); + info = NULL; + } + + OSSL_STORE_close(sctx); + + return info; +} + +static apr_status_t modssl_load_keypair_store(server_rec *s, apr_pool_t *p, + const char *vhostid, + const char *certid, + const char *keyid, + X509 **pubkey, + EVP_PKEY **privkey) +{ + OSSL_STORE_INFO *info = NULL; + + *privkey = NULL; + *pubkey = NULL; + + info = modssl_load_store_uri(s, p, vhostid, keyid, OSSL_STORE_INFO_PKEY); + if (!info) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10492) + "Init: OSSL_STORE_INFO_PKEY lookup failed for private key identifier `%s'", + keyid); + return ssl_die(s); + } + + *privkey = OSSL_STORE_INFO_get1_PKEY(info); + OSSL_STORE_INFO_free(info); + if (!*privkey) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10493) + "Init: OSSL_STORE_INFO_PKEY lookup failed for private key identifier `%s'", + keyid); + return ssl_die(s); + } + + if (certid) { + info = modssl_load_store_uri(s, p, vhostid, certid, OSSL_STORE_INFO_CERT); + if (!info) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10494) + "Init: OSSL_STORE_INFO_CERT lookup failed for certificate identifier `%s'", + keyid); + return ssl_die(s); + } + + *pubkey = OSSL_STORE_INFO_get1_CERT(info); + OSSL_STORE_INFO_free(info); + if (!*pubkey) { + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10495) + "Init: OSSL_STORE_INFO_CERT lookup failed for certificate identifier `%s'", + certid); + return ssl_die(s); + } + } + + return APR_SUCCESS; +} +#endif + +apr_status_t modssl_load_engine_keypair(server_rec *s, + apr_pool_t *pconf, apr_pool_t *ptemp, + const char *vhostid, + const char *certid, const char *keyid, + X509 **pubkey, EVP_PKEY **privkey) +{ +#if MODSSL_HAVE_ENGINE_API + SSLModConfigRec *mc = myModConfig(s); + + /* For OpenSSL 3.x, use the STORE-based API if either ENGINE + * support was not present compile-time, or if it's built but + * SSLCryptoDevice is not configured. */ + if (mc->szCryptoDevice) + return modssl_load_keypair_engine(s, pconf, ptemp, + vhostid, certid, keyid, + pubkey, privkey); +#endif +#if MODSSL_HAVE_OPENSSL_STORE + return modssl_load_keypair_store(s, ptemp, vhostid, certid, keyid, + pubkey, privkey); #else + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10496) + "Init: no method for loading keypair for %s (%s | %s)", + vhostid, certid ? certid : "no cert", keyid); return APR_ENOTIMPL; #endif } |