SSL_CTX_set_verify uses the "wrong" certificate chain (cross signed certificate )

Viktor Dukhovni openssl-users at
Sun Oct 3 20:25:36 UTC 2021

On Sun, Oct 03, 2021 at 09:33:29PM +0200, Alex Robuchon wrote:

> > Not quite, a candidate chain is constructed from whatever certificates the
> > peer (server in your case) provided, and then passed to the callback with
> > "preverify_ok" set to false (for the top certificate), because the chain is
> > not trusted.
> This confuses me a little bit because I thought the callback function set
> with *SSL_set_verify* would have the "trusted first" valid chain.

But there is no trust store configured, so trust first is a no-op.
The constructed chain consists entirely of certificates from the
peer, and last certificate in the chain (the ultimate issuing CA)
is still not trusted, so preverify_ok = 0.

> Are you sure you are not speaking as if eventmachine was using the
> *SSL_CTX_set_cert_verify_callback* ?

I rewrote the OpenSSL chain construction code for OpenSSL 1.1.0.  Yes, I
am sure.

> - *build_chain* that will apply the trusted first algorithm and replace the
> certificate chain passed by the server with the valid one ( if found ).

The code in eventmachine does not configure any trusted certificates for
the SSL_CTX handles used to create the SSL connections.  So
trusted-first is a no-op.

> - *internal_verify *which now has the new chain and will call *verify_callback
> *( the callback function passed to SSL_set_verify ) for every certificate
> in this new chain in reverse order.

You don't have to explain the code to me. :-)

> > But given all the evidence before me, I'd want to delete that code and
> > never see it again.
> I hear you :).

That code is beyond repair, it needs to be thrown out, and replaced with
ground up by the book TLS connection establishment.

#1. No compiled in private keys

#2. Configure the SSL_CTX with the desired list of trust anchors

#3. Reuse the SSL_CTX for multiple connections that share the same
    trust and other general settings

#4. Prior to SSL_connect(), tell the SSL library what hostname you want
    to verify via SSL_set1_host(3).  Let OpenSSL do all the heavy
    lifting of certificate and name checks.

#5. DO NOT attempt to override certificate chain verifiction in the
    verify callback.  Use the verify callback only for logging or
    similar diagnostic purposes.

#6. Return "preverify_ok" unmodified, unless your application is doing
    opportunistic unauthenticated TLS, or wants to complete the
    handshake even on verification failure, and then gracefully tear
    down the application-layer session with the peer (after checking the
    verification status at connection completion).

    If preverify_ok is false (0), OpenSSL chain verification failed,
    your application is unlikely to do better.  Return 0, and the
    TLS handshake will be aborted, you can log the error reason,
    chain depth, ... in the verify callback.


More information about the openssl-users mailing list