Specific nginx variables not returning values using BoringSSL

My issue: Specific nginx variables not returning values using BoringSSL

How I encountered the problem:

I tested a number variables with two different versions of nginx 1.31.2. One built with OpenSSL 4.0.1 and the other with BoringSSL 0.20260616.0. Of the tested variables, the following ones only seem to work when using OpenSSL:

  • $ssl_sigalg
  • $ssl_sigalgs
  • $ssl_ciphers
  • $ssl_curves

Nginx built with OpenSSL returns values like:

ssl-sigalg
ecdsa_secp384r1_sha384
ssl-sigalgs
ecdsa_secp256r1_sha256:ecdsa_secp384r1_sha384:ecdsa_secp521r1_sha512:ecdsa_sha1:rsa_pss_rsae_sha256:rsa_pss_rsae_sha384:rsa_pss_rsae_sha512:rsa_pkcs1_sha256:rsa_pkcs1_sha384:rsa_pkcs1_sha512:rsa_pkcs1_sha1
ssl-ciphers
TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384
ssl-curves
X25519MLKEM768:X25519:prime256v1:secp384r1:secp521r1

While nginx built with BoringSSL returns empty values for those variables.

My question is if this is a case of “working as designed” or if this behaviour is related to one or more bugs in nginx. Can you please clarify? Thanks in advance!

For those that are interested. In the mean time I created an issue on github: Specific nginx variables not returning values using BoringSSL · Issue #1496 · nginx/nginx · GitHub

Working as designed — not an nginx bug. All four variables depend on OpenSSL introspection APIs that BoringSSL deliberately doesn’t ship, and nginx feature-detects each one and returns an empty string when the API is absent.

Look at the source in src/event/ngx_event_openssl.c

$ssl_curvesngx_ssl_get_curves

In OpnenSSL #ifdef SSL_CTRL_GET_CURVES → uses SSL_get1_curves()

In BoringSSL macro and function both absent, thus falls to #elses->len = 0

$ssl_ciphers → ngx_ssl_get_ciphers

In OpnenSSL #ifdef SSL_CTRL_GET_RAW_CIPHERLIST → else SSL_get_shared_ciphers()

In BoringSSL SSL_get0_raw_cipherlist/SSL_CIPHER_find absent; falls to SSL_get_shared_ciphers, which BoringSSL stubs to write buf[0]='\0' and return

thus, ngx_strlen(buf) == 0

$ssl_sigalg → ngx_ssl_get_sigalg

In OpnenSSL #ifdef SSL_get0_signature_name

In BoringSSL absent, thus guard false → s->len = 0

$ssl_sigalgs → ngx_ssl_get_sigalgs

In OpnenSSL #if OPENSSL_VERSION_NUMBER >= 0x40000000L (SSL_get0_sigalg) / #elif SSL_CTRL_SET_SIGALGS (SSL_get_sigalgs)

In BoringSSL reports OPENSSL_VERSION_NUMBER 0x1010107f (pretends to be 1.1.1g), and SSL_CTRL_SET_SIGALGS absent, thus both branches false → #else s->len = 0

And for reference, BoringSSL provides what’s needed to operate the handshake (which group did we land on) but omits the introspection APIs for enumerating what the client offered — exactly the ones used for fingerprinting/logging, which is what ssl_curves, $ssl_ciphers, and the sigalg list variables are.

Hi bit_warrior,

First let me thank you for taking the time to reply to my question. Much appreciated!

In the mean time I also got the answers I was looking for on github (Specific nginx variables not returning values using BoringSSL · Issue #1496 · nginx/nginx · GitHub). For now, that issue has been given the label “enhancement”. Not that I expect things to change soon(ish), but hey, who knows … :grinning_face:

At least it does not stop me from playing around with nginx, openssl and boringssl.

Best regards.