소스 검색

tls: basic OpenSSL 3 support of provider keys (replaces ENGINE)

- initial support for v3 provider keys (replaces ENGINE from 1.1.1)
- can be disabled behind build flag -DOPENSSL_NO_PROVIDER
- provider keys start with /uri: e.g
  private_key = /uri:pkcs11:token=NSS%20Certificate%20DB;type=private;object=Fork-Test-c67cc0e0
- global config:
  provider_quirks: 0 | 1
  - 0 - default
  - 1 - create a new OSS_LIB_CTX* in the child

This integration does not load any providers itself and depends on
the usual

export OPENSSL_CONF=my-openssl.cnf

to configure providers.
S-P Chan 1 년 전
부모
커밋
69883dd381
2개의 변경된 파일119개의 추가작업 그리고 30개의 파일을 삭제
  1. 24 16
      src/modules/tls/tls_domain.c
  2. 95 14
      src/modules/tls/tls_mod.c

+ 24 - 16
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 <openssl/engine.h>
+extern EVP_PKEY *tls_engine_private_key(const char *key_id);
 #endif
 
-#ifdef KSR_SSL_ENGINE
-#include <openssl/engine.h>
+#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 <openssl/ui.h>
@@ -1227,7 +1235,7 @@ err:
 #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 @@ err:
  * 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
  *

+ 95 - 14
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 <openssl/store.h>
+#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 <openssl/conf.h>
-#include <openssl/engine.h>
-
-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 <openssl/conf.h>
+#include <openssl/engine.h>
+
+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 @@ error:
 }
 
 
-#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 <openssl/store.h>
+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