diff --git a/src/modules/tls/tls_domain.c b/src/modules/tls/tls_domain.c index dde5fe08afd..e056a70b504 100644 --- a/src/modules/tls/tls_domain.c +++ b/src/modules/tls/tls_domain.c @@ -32,13 +32,21 @@ /* only OpenSSL <= 1.1.1 */ #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER < 0x030000000L +#define KSR_SSL_COMMON #define KSR_SSL_ENGINE +#define KEY_PREFIX "/engine:" +#define KEY_PREFIX_LEN (strlen(KEY_PREFIX)) +#include +extern EVP_PKEY *tls_engine_private_key(const char *key_id); #endif -#ifdef KSR_SSL_ENGINE -#include +#if !defined(OPENSSL_NO_PROVIDER) && OPENSSL_VERSION_NUMBER >= 0x030000000L +#define KSR_SSL_COMMON +#define KSR_SSL_PROVIDER +#define KEY_PREFIX "/uri:" +#define KEY_PREFIX_LEN (strlen(KEY_PREFIX)) extern EVP_PKEY *tls_engine_private_key(const char *key_id); -#endif /* KSR_SSL_ENGINE */ +#endif #if OPENSSL_VERSION_NUMBER >= 0x00907000L #include @@ -1227,7 +1235,7 @@ static int passwd_cb(char *buf, int size, int rwflag, void *filename) #endif } -#ifdef KSR_SSL_ENGINE +#ifdef KSR_SSL_COMMON /** * @brief Load a private key from an OpenSSL engine * @param d TLS domain @@ -1237,7 +1245,7 @@ static int passwd_cb(char *buf, int size, int rwflag, void *filename) * to be fork() safe * * private_key setting which starts with /engine: is assumed to be - * an HSM key and not a file-based key + * an HSM key and not a file-based key (/uri: for OpenSSL 3 key URIs) * * We store the private key in a local memory hash table as * HSM keys must be process-local. We use the SSL_CTX* address @@ -1253,13 +1261,13 @@ static int load_engine_private_key(tls_domain_t *d) DBG("%s: No private key specified\n", tls_domain_str(d)); return 0; } - if(strncmp(d->pkey_file.s, "/engine:", 8) != 0) + if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) != 0) return 0; do { i = process_no; for(idx = 0, ret_pwd = 0; idx < 3; idx++) { - pkey = tls_engine_private_key(d->pkey_file.s + 8); + pkey = tls_engine_private_key(d->pkey_file.s + KEY_PREFIX_LEN); if(pkey) { ret_pwd = SSL_CTX_use_PrivateKey(d->ctx[i], pkey); } else { @@ -1295,7 +1303,7 @@ static int load_engine_private_key(tls_domain_t *d) d->pkey_file.s); return 0; } -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_COMMON */ /** * @brief Load a private key from a file * @param d TLS domain @@ -1319,10 +1327,10 @@ static int load_private_key(tls_domain_t *d) SSL_CTX_set_default_passwd_cb_userdata(d->ctx[i], d->pkey_file.s); for(idx = 0, ret_pwd = 0; idx < 3; idx++) { -#ifdef KSR_SSL_ENGINE +#ifdef KSR_SSL_COMMON // in PROC_INIT skip loading HSM keys due to // fork() issues with PKCS#11 libraries - if(strncmp(d->pkey_file.s, "/engine:", 8) != 0) { + if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) != 0) { ret_pwd = SSL_CTX_use_PrivateKey_file( d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM); } else { @@ -1331,7 +1339,7 @@ static int load_private_key(tls_domain_t *d) #else ret_pwd = SSL_CTX_use_PrivateKey_file( d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM); -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_COMMON */ if(ret_pwd) { break; } else { @@ -1348,12 +1356,12 @@ static int load_private_key(tls_domain_t *d) TLS_ERR("load_private_key:"); return -1; } -#ifdef KSR_SSL_ENGINE - if(strncmp(d->pkey_file.s, "/engine:", 8) == 0) { +#ifdef KSR_SSL_COMMON + if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) == 0) { // skip private key validity check for HSM keys continue; } -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_COMMON */ if(!SSL_CTX_check_private_key(d->ctx[i])) { ERR("%s: Key '%s' does not match the public key of the" " certificate\n", @@ -1369,7 +1377,7 @@ static int load_private_key(tls_domain_t *d) } -#ifdef KSR_SSL_ENGINE +#ifdef KSR_SSL_COMMON /** * @brief Initialize engine private keys * @@ -1401,7 +1409,7 @@ int tls_fix_engine_keys(tls_domains_cfg_t *cfg, tls_domain_t *srv_defaults, return 0; } -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_COMMON */ /** * @brief Initialize attributes of all domains from default domains if necessary * diff --git a/src/modules/tls/tls_mod.c b/src/modules/tls/tls_mod.c index 20ac304af1e..1dc9357f56a 100644 --- a/src/modules/tls/tls_mod.c +++ b/src/modules/tls/tls_mod.c @@ -93,9 +93,21 @@ MODULE_VERSION /* Engine is deprecated in OpenSSL 3 */ #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER < 0x030000000L +#define KSR_SSL_COMMON #define KSR_SSL_ENGINE +#define KEY_PREFIX "/engine:" +#define KEY_PREFIX_LEN (strlen(KEY_PREFIX)) #endif +#if !defined(OPENSSL_NO_PROVIDER) && OPENSSL_VERSION_NUMBER >= 0x030000000L +#define KSR_SSL_COMMON +#define KSR_SSL_PROVIDER +#include +#define KEY_PREFIX "/uri:" +#define KEY_PREFIX_LEN (strlen(KEY_PREFIX)) +#endif + + extern str sr_tls_event_callback; str sr_tls_xavp_cfg = {0, 0}; /* @@ -151,23 +163,28 @@ tls_domain_t srv_defaults = { #ifdef KSR_SSL_ENGINE - typedef struct tls_engine { str engine; str engine_config; str engine_algorithms; } tls_engine_t; -#include -#include - -static ENGINE *ksr_tls_engine; static tls_engine_t tls_engine_settings = { STR_STATIC_INIT("NONE"), STR_STATIC_INIT("NONE"), STR_STATIC_INIT("ALL"), }; -#endif /* KSR_SSL_ENGINE */ + +#include +#include + +static ENGINE *ksr_tls_engine; +#endif + +#ifdef KSR_SSL_PROVIDER +static int tls_provider_quirks; +#endif + /* * Default settings for client domains when using external config file */ @@ -238,6 +255,10 @@ static param_export_t params[] = { {"engine_algorithms", PARAM_STR, &tls_engine_settings.engine_algorithms}, #endif /* KSR_SSL_ENGINE */ +#ifdef KSR_SSL_PROVIDER + {"provider_quirks", PARAM_INT, + &tls_provider_quirks}, /* OpenSSL 3 provider that needs new OSSL_LIB_CTX in child */ +#endif /* KSR_SSL_PROVIDER */ {"tls_log", PARAM_INT, &default_tls_cfg.log}, {"tls_debug", PARAM_INT, &default_tls_cfg.debug}, {"session_cache", PARAM_INT, &default_tls_cfg.session_cache}, @@ -316,7 +337,6 @@ static tls_domains_cfg_t* tls_use_modparams(void) } #endif - static int mod_init(void) { int method; @@ -433,10 +453,10 @@ static int mod_init(void) } -#ifdef KSR_SSL_ENGINE +#ifdef KSR_SSL_COMMON static int tls_engine_init(); int tls_fix_engine_keys(tls_domains_cfg_t *, tls_domain_t *, tls_domain_t *); -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_COMMON */ /* * OpenSSL 1.1.1+: SSL_CTX is repeated in each worker @@ -450,9 +470,10 @@ int tls_fix_engine_keys(tls_domains_cfg_t *, tls_domain_t *, tls_domain_t *); */ static int mod_child_hook(int *rank, void *dummy) { - LM_DBG("Loading SSL_CTX in process_no=%d rank=%d " - "ksr_tls_threads_mode=%d\n", + LM_INFO("Loading SSL_CTX in process_no=%d rank=%d " + "ksr_tls_threads_mode=%d\n", process_no, *rank, ksr_tls_threads_mode); + if(cfg_get(tls, tls_cfg, config_file).s) { if(tls_fix_domains_cfg(*tls_domains_cfg, &srv_defaults, &cli_defaults) < 0) @@ -464,6 +485,10 @@ static int mod_child_hook(int *rank, void *dummy) return 0; } +#ifdef KSR_SSL_PROVIDER +static OSSL_LIB_CTX *orig_ctx; +static OSSL_LIB_CTX *new_ctx; +#endif static int mod_child(int rank) { if(tls_disable || (tls_domains_cfg == 0)) @@ -477,23 +502,32 @@ static int mod_child(int rank) return run_thread4PP((_thread_proto4PP)mod_child_hook, &rank, NULL); } -#ifdef KSR_SSL_ENGINE +#ifdef KSR_SSL_COMMON /* * after the child is fork()ed we go through the TLS domains * and fix up private keys from engine */ +#ifdef KSR_SSL_ENGINE if(!strncmp(tls_engine_settings.engine.s, "NONE", 4)) return 0; +#endif /* KSR_SSL_ENGINE */ if(rank > 0) { +#ifdef KSR_SSL_PROVIDER + if(tls_provider_quirks & 1) { + new_ctx = OSSL_LIB_CTX_new(); + orig_ctx = OSSL_LIB_CTX_set0_default(new_ctx); + CONF_modules_load_file(CONF_get1_default_config_file(), NULL, 0L); + } +#endif /* KSR_SSL_PROVIDER */ if(tls_engine_init() < 0) return -1; if(tls_fix_engine_keys(*tls_domains_cfg, &srv_defaults, &cli_defaults) < 0) return -1; - LM_INFO("OpenSSL Engine loaded private keys in child: %d\n", rank); + LM_INFO("OpenSSL loaded private keys in child: %d\n", rank); } -#endif /* KSR_SSL_ENGINE */ +#endif /* KSR_SSL_PROVIDER */ return 0; } @@ -798,3 +832,50 @@ EVP_PKEY *tls_engine_private_key(const char *key_id) return ENGINE_load_private_key(ksr_tls_engine, key_id, NULL, NULL); } #endif /* KSR_SSL_ENGINE */ + +#ifdef KSR_SSL_PROVIDER +#include +static int tls_engine_init() +{ + return 0; +} +EVP_PKEY *tls_engine_private_key(const char *key_id) +{ + OSSL_STORE_CTX *ctx; + EVP_PKEY *pkey = NULL; + + ctx = OSSL_STORE_open_ex(key_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if(!ctx) { + LM_ERR("[ERR] could not load URI %s\n", key_id); + goto error; + } + + OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY); + + while(!(OSSL_STORE_eof(ctx))) { + OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); + + int type; + type = OSSL_STORE_INFO_get_type(info); + + switch(type) { + case OSSL_STORE_INFO_PKEY: + pkey = OSSL_STORE_INFO_get1_PKEY(info); + break; + default: + continue; + break; + } + OSSL_STORE_INFO_free(info); + if(pkey) + break; + } + + LM_INFO("Loaded private key = %p\n", pkey); + +error: + OSSL_STORE_close(ctx); + + return pkey; +} +#endif