Opened 4 months ago
Last modified 4 months ago
#2449 new enhancement
Allow using OpenSSL 3.0 "provider" API instead of deprecated "engine" API
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.23.x |
Keywords: | openssl, provider, tpm, pkcs11, engine | Cc: | |
uname -a: | Linux www 5.15.0-58-generic #64-Ubuntu SMP Thu Jan 5 11:43:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 3.0.2 15 Mar 2022 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-d8gVax/nginx-1.18.0=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --add-dynamic-module=/build/nginx-d8gVax/nginx-1.18.0/debian/modules/http-geoip2 --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module |
Description
I would like to use hardware encryption to protect my webserver's TLS privkey from theft. My server has a TPM 2.0 chip which supports this, but it's unnecessarily difficult to configure it in nginx. I'm proposing a change to make the process more user-friendly.
For background: old versions of OpenSSL supported HSMs and hardware offloading through the ENGINE API. In nginx this is enabled through the ssl_engine
directive: hxxps://github.com/Infineon/optiga-tpm-cheatsheet#nginx--curl
(Please s/hxxps/https/ due to Trac spam filter)
In OpenSSL 3.0 the authors introduced a "Provider API" which is intended to replace the old ENGINE API. It works in a similar way. When using the CLI to sign or create TPM-backed keys, you add -provider tpm2 -provider base
to the arguments: hxxps://github.com/Infineon/optiga-tpm-cheatsheet#pem-encoded-key-object-2
I'm running Ubuntu 22.04 LTS on this webserver. This Linux distribution has a tpm2-openssl package ( hxxps://github.com/tpm2-software/tpm2-openssl ) which conforms to the new OpenSSL 3.0 Provider API. The CLI examples on the optiga-tpm-cheatsheet work right out of the box, with no extra configuration. This makes it quick and easy to set up hardware-backed keys, just by installing a single package. For instance, anyone running this distro on an x86 Linux PC can do:
sudo apt install tpm2-openssl
openssl genpkey -provider tpm2 -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out testkey.priv
echo "test" | openssl pkeyutl -provider tpm2 -provider base -digest sha256 -inkey testkey.priv -sign -rawin -hexdump
But unfortunately, at this time nginx only supports the ENGINE API, not the Provider API. In order to use hardware backed keys with nginx, users would need to compile, install, and configure the legacy tpm2tss ENGINE implementation, and keep it up to date themselves without help from the Debian/Ubuntu package maintainers.
I believe that with a small tweak to nginx, it would be possible for users to specify e.g.
ssl_provider tpm2,base
to tell OpenSSL 3.x to use the tpm2-openssl Provider to support hardware-backed private keys in nginx.
Change History (3)
comment:1 by , 4 months ago
comment:2 by , 4 months ago
What I found when enabling the tpm2+base providers globally in openssl.cnf, is that applications could utilize the encrypted TSS2 privkeys but they lost the ability to sign using standard non-TPM-backed privkeys. Thus forcing me to choose between "all TPM2" or "all default," systemwide.
I think that if nginx called SSL_CTX_config(ctx, "nginx") then I could add an nginx-specific provider configuration to openssl.cnf and that would largely avoid this downside? But maybe there's a better way to do this without an nginx code change.
comment:3 by , 4 months ago
It is certainly possible to provide an nginx-specific OpenSSL configuration file via the OPENSSL_CONF
environment variable.
Note that it should be possible to load OpenSSL providers using the configuration file, see README-PROVIDERS.md in OpenSSL sources for an example.
Support for loading providers directly from nginx configuration might still be useful from simplicity point of view, though it does not look like something required to use tpm2-openssl provider.