diff options
author | Aleksei Bavshin <a.bavshin@nginx.com> | 2024-12-16 17:56:45 -0800 |
---|---|---|
committer | Aleksei Bavshin <a.bavshin@f5.com> | 2025-05-26 06:56:18 -0700 |
commit | 0fdbfc1ff45adb8e98e71004e5d147987e7d8974 (patch) | |
tree | 5785c5fc00cfb5e4fce1e04c8f92a685c2925648 /src | |
parent | 6a134dfd4888fc3850d22294687cfb3940994c69 (diff) | |
download | nginx-0fdbfc1ff45adb8e98e71004e5d147987e7d8974.tar.gz nginx-0fdbfc1ff45adb8e98e71004e5d147987e7d8974.zip |
SSL: support loading keys via OSSL_STORE.
A new "store:..." prefix for the "ssl_certificate_key" directive allows
loading keys via the OSSL_STORE API.
The change is required to support hardware backed keys in OpenSSL 3.x using
the new "provider(7ossl)" modules, such as "pkcs11-provider". While the
engine API is present in 3.x, some operating systems (notably, RHEL10)
have already disabled it in their builds of OpenSSL.
Related: https://trac.nginx.org/nginx/ticket/2449
Diffstat (limited to 'src')
-rw-r--r-- | src/event/ngx_event_openssl_cache.c | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/src/event/ngx_event_openssl_cache.c b/src/event/ngx_event_openssl_cache.c index d62b4c430..cbb05892f 100644 --- a/src/event/ngx_event_openssl_cache.c +++ b/src/event/ngx_event_openssl_cache.c @@ -8,10 +8,16 @@ #include <ngx_core.h> #include <ngx_event.h> +#ifdef ERR_R_OSSL_STORE_LIB +#include <openssl/store.h> +#include <openssl/ui.h> +#endif + #define NGX_SSL_CACHE_PATH 0 #define NGX_SSL_CACHE_DATA 1 #define NGX_SSL_CACHE_ENGINE 2 +#define NGX_SSL_CACHE_STORE 3 #define NGX_SSL_CACHE_DISABLED (ngx_array_t *) (uintptr_t) -1 @@ -444,6 +450,11 @@ ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index, ngx_str_t *path, { id->type = NGX_SSL_CACHE_ENGINE; + } else if (index == NGX_SSL_CACHE_PKEY + && ngx_strncmp(path->data, "store:", sizeof("store:") - 1) == 0) + { + id->type = NGX_SSL_CACHE_STORE; + } else { if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, path) != NGX_OK) @@ -714,11 +725,6 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data) #endif } - bio = ngx_ssl_cache_create_bio(id, err); - if (bio == NULL) { - return NULL; - } - cb_data.encrypted = 0; if (*passwords) { @@ -734,6 +740,76 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data) cb = NULL; } + if (id->type == NGX_SSL_CACHE_STORE) { + +#ifdef ERR_R_OSSL_STORE_LIB + + u_char *uri; + UI_METHOD *method; + OSSL_STORE_CTX *store; + OSSL_STORE_INFO *info; + + method = (cb != NULL) ? UI_UTIL_wrap_read_pem_callback(cb, 0) : NULL; + uri = id->data + sizeof("store:") - 1; + + store = OSSL_STORE_open((char *) uri, method, pwd, NULL, NULL); + + if (store == NULL) { + *err = "OSSL_STORE_open() failed"; + + if (method != NULL) { + UI_destroy_method(method); + } + + return NULL; + } + + pkey = NULL; + + while (pkey == NULL && !OSSL_STORE_eof(store)) { + info = OSSL_STORE_load(store); + + if (info == NULL) { + continue; + } + + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { + pkey = OSSL_STORE_INFO_get1_PKEY(info); + } + + OSSL_STORE_INFO_free(info); + } + + OSSL_STORE_close(store); + + if (method != NULL) { + UI_destroy_method(method); + } + + if (pkey == NULL) { + *err = "OSSL_STORE_load() failed"; + return NULL; + } + + if (cb_data.encrypted) { + *passwords = NGX_SSL_CACHE_DISABLED; + } + + return pkey; + +#else + + *err = "loading \"store:...\" certificate keys is not supported"; + return NULL; + +#endif + } + + bio = ngx_ssl_cache_create_bio(id, err); + if (bio == NULL) { + return NULL; + } + for ( ;; ) { pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd); |