Welcome! Log In Create A New Profile


[PATCH] Add ssl_provider directive (ticket #2449)

Nick Bogdanov
March 14, 2023 11:30AM
# HG changeset patch
# User Nick Bogdanov <nickrbogdanov@gmail.com>
# Date 1677975659 28800
# Sat Mar 04 16:20:59 2023 -0800
# Node ID a00302750c65e122292da5094093e45f2f644600
# Parent cffaf3f2eec8fd33605c2a37814f5ffc30371989
Add ssl_provider directive (ticket #2449).

This change allows nginx to load modules that use the new OpenSSL
Provider interface. My primary use case involves securing the
webserver's private TLS key using a TPM2 chip, so it can't be stolen
if the server is compromised. The way I tested this is as follows:

1. Install basic TPM2 support. On Ubuntu 22.04 I used

apt install tpm2-tools tpm2-abrmd libtss2-tcti-tabrmd0

2. Install https://github.com/tpm2-software/tpm2-openssl . Version
1.2.0-rc0 or higher is required. At the time of this writing, it's
likely you'll have to build from source.

3. Generate a parent key on your TPM (one-time setup):

tpm2_createprimary -C o -g sha256 -G ecc -c primary_sh.ctx

tpm2_evictcontrol -C o -c 0x81000001 || true

tpm2_evictcontrol -C o -c primary_sh.ctx 0x81000001

4. Generate a TPM-backed RSA privkey and a corresponding self-signed
x509 cert:

openssl genpkey -provider tpm2 -algorithm RSA
-pkeyopt parent:0x81000001 -out rsakey.pem

openssl req -provider tpm2 -provider default -x509
-subj "/C=GB/CN=foo" -key rsakey.pem -out rsacert.pem

rsakey.pem will start with "-----BEGIN TSS2 PRIVATE KEY-----" to indicate
that the key material is encrypted with a key that is only available inside
the TPM chip.

5. At the start of nginx.conf, tell nginx to use the tpm2 provider
first, and then fall back to the default provider for unsupported

ssl_provider tpm2;
ssl_provider default;

6. Inside a "server {" section for an existing TLS server, point nginx
to the new TPM-backed cert and key:

ssl_certificate /tmp/rsacert.pem;
ssl_certificate_key /tmp/rsakey.pem;

If the ssl_provider option took effect, it will be able to recognize
the new TSS2 rsakey.pem and instruct the TPM chip to handle the signing
operation during the TLS handshake.

In my setup, the initial handshake time increased from 5ms->67ms after
enabling TPM2. More details here:

diff -r cffaf3f2eec8 -r a00302750c65 contrib/vim/syntax/nginx.vim
--- a/contrib/vim/syntax/nginx.vim Thu Feb 02 23:38:48 2023 +0300
+++ b/contrib/vim/syntax/nginx.vim Sat Mar 04 16:20:59 2023 -0800
@@ -620,6 +620,7 @@
syn keyword ngxDirective contained ssl_prefer_server_ciphers
syn keyword ngxDirective contained ssl_preread
syn keyword ngxDirective contained ssl_protocols
+syn keyword ngxDirective contained ssl_provider
syn keyword ngxDirective contained ssl_reject_handshake
syn keyword ngxDirective contained ssl_session_cache
syn keyword ngxDirective contained ssl_session_ticket_key
diff -r cffaf3f2eec8 -r a00302750c65 src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c Thu Feb 02 23:38:48 2023 +0300
+++ b/src/event/ngx_event_openssl.c Sat Mar 04 16:20:59 2023 -0800
@@ -90,6 +90,7 @@

static void *ngx_openssl_create_conf(ngx_cycle_t *cycle);
static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_openssl_provider(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void ngx_openssl_exit(ngx_cycle_t *cycle);

@@ -102,6 +103,13 @@

+ { ngx_string("ssl_provider"),
+ ngx_openssl_provider,
+ 0,
+ 0,
+ NULL },

@@ -5939,6 +5947,26 @@

+static char *
+ngx_openssl_provider(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ ngx_str_t *value = cf->args->elts;
+ if (OSSL_PROVIDER_load(NULL, (char *)value[1].data) == NULL) {
+ ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
+ "OSSL_PROVIDER_load(\"%V\") failed", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+ return NGX_CONF_OK;
+ return "is not supported";

static void
ngx_openssl_exit(ngx_cycle_t *cycle)
diff -r cffaf3f2eec8 -r a00302750c65 src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h Thu Feb 02 23:38:48 2023 +0300
+++ b/src/event/ngx_event_openssl.h Sat Mar 04 16:20:59 2023 -0800
@@ -28,6 +28,10 @@
#include <openssl/ocsp.h>
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+#include <openssl/provider.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
nginx-devel mailing list
Subject Author Views Posted

[PATCH] Add ssl_provider directive (ticket #2449)

Nick Bogdanov 407 March 14, 2023 11:30AM

Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 115
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready