On Sun, Mar 08, 2026 at 06:53:42PM -0700, Shafiya Begum wrote:
> Several sites that recently upgraded from OpenSSL 1.1.1 to 3.x have
> incomplete certificate chains — the intermediate CA isn't being sent during
> the handshake. Modern browsers handle this silently via AIA fetching, but
> older clients (Android 7-9, some curl builds, IoT devices) fail with
> handshake errors.
I am somewhat sceptical that the issue is specifically related to the
software upgrade. I am not aware of any significant 1.1.1 -> 3.x
changes in how servers construct their certificate chains.
What a server operator puts into the server's certificate chain file is
up to that operator, OpenSSL software updates do not materially affect
those choices.
In terms of automatic augmentation of the server's certificate chain,
beyond what's in the configured chain file, the application can choose
to call SSL_CTX_build_cert_chain(), which is then calls the code in
ssl/ssl_cert.c:ssl_build_cert_chain(), which is underlies and remains
largely unchanged in 3.0.
> The typical cause: Nginx ssl_certificate only has the leaf cert, not the
> full chain. OpenSSL 1.1.1 seemed more forgiving, but 3.x appears stricter
> about only sending what's explicitly configured.
If so, the configured chain file does not contain the required
intermediate certificates (not related to the upgrade) and the
application did not call SSL_CTX_build_cert_chain(3):
SSL_CTX_build_cert_chain() builds the certificate chain for ctx.
Normally this uses the chain store or the verify store if the chain
store is not set. If the function is successful the built chain will
replace any existing chain. The flags parameter can be set to
SSL_BUILD_CHAIN_FLAG_UNTRUSTED to use existing chain certificates as
untrusted CAs, SSL_BUILD_CHAIN_FLAG_NO_ROOT to omit the root CA from
the built chain, SSL_BUILD_CHAIN_FLAG_CHECK to use all existing
chain certificates only to build the chain (effectively sanity
checking and rearranging them if necessary), the flag
SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR ignores any errors during
verification: if flag SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR is also set
verification errors are cleared from the error queue. Details of the
chain building process are described in "Certification Path
Building" in openssl-verification-options(1).
after specifying a "chain store" or "verify store" (a CA file) that
contains the requisite intermediate certificates.
> The fix is straightforward: cat server.crt intermediate.crt > fullchain.crt
Yes, that's best practice and standard operating procedure.
> Questions for the group:
>
> - Is there a way to make OpenSSL 3.x automatically fetch missing
> intermediates via AIA, similar to how browsers do it? I know
> s_client doesn't support this by default.
No, automatic download of "missing" certificates outside the scope of
OpenSSL. Applications can do that, but that's up to them.
> For anyone running OpenSSL 3.x in production: are you seeing more
> chain-related issues compared to 1.1.1?
I would not expect any difference except as a coincidence, perhaps over
time server operator habits have changed, or other software they deploy
along with a newer OpenSSL has also changed.
> - What's the recommended way to validate certificate chain
> completeness as part of a CI/CD pipeline? We're considering an
> openssl verify -CAfile step but want to catch all edge cases.
If you want more precise control over which trust anchors are required
and used during the verification, the "-trusted" option is more precise
thatn the "-CAfile" option, because in that case the system's default
CAfile and CApath are not used, and only the trust anchors in "-trusted"
are trusted. You can then augment that with "-untrusted", which makes
intermediate untrusted certificates available to the client and/or
server.
--
Viktor. 🇺🇦 Слава Україні!