OpenSSL server sending certificate chain(inc. root cert) during handshake

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

OpenSSL server sending certificate chain(inc. root cert) during handshake

Jason Schultz
I believe this behavior is common among all supported versions of OpenSSL, but most of my testing has been with OpenSSL 1.0.2, the latest LTS release.

My application using OpenSSL is acting as a server. I have a server certificate configured that has been signed by a self-signed/root certificate, so the chain is only the server certificate and the root certificate. The certificates were created using OpenSSL, for non-production use only. The server application is calling SSL_CTX_use_certificate_file() to load the server cert, residing in /etc/ssl/certs. 

Depending on what's in /etc/ssl/certs, the handshake behavior will show 1 of 2 things:

  1. If only the server certificate (and NOT the self-signed root cert) is in /etc/ssl/certs/, only the server certificate will be presented in the handshake.
  2. If the server AND self-signed root certificates are in /etc/ssl/certs/, the entire chain will be presented during the handshake. 
My questions deal with #2: Why does OpenSSL include the root cert in the certificate chain? Will the root cert be included in the chain any time it's in the same directory as the server cert? Is there a way, via API call, configuration, etc, to force OpenSSL to NOT send the root certificate as part of the chain in this case? Or is there something more basic I'm missing? Googling for answers has not proved fruitful as there are a lot of results, none of which pertain to my situation...although my google fu may be lacking.

Thanks in advance.

Reply | Threaded
Open this post in threaded view
|

Re: OpenSSL server sending certificate chain(inc. root cert) during handshake

Sam Roberts
The root cert is not used for validation, so it doesn't have to be
sent. However, sending it does no harm, and it is useful for humans
who are attempting to diagnose problems, it allows them to see what
what root cert they are expected to have locally for sucessful cert
chain validation.
Reply | Threaded
Open this post in threaded view
|

Re: OpenSSL server sending certificate chain(inc. root cert) during handshake

Jason Schultz
Right, I realize it doesn't have to be sent, my questions are why is it sent and is there a way to force OpenSSL to not send it?

You may have answered the first question as to "why?". But is OpenSSL doing this just to make problems easier to diagnose? Are there other reasons?

More importantly, can I force OpenSSL to not send the root cert?

Thanks,

Jason



From: Sam Roberts <[hidden email]>
Sent: Friday, May 31, 2019 7:32 PM
To: Jason Schultz
Cc: [hidden email]
Subject: Re: OpenSSL server sending certificate chain(inc. root cert) during handshake
 
The root cert is not used for validation, so it doesn't have to be
sent. However, sending it does no harm, and it is useful for humans
who are attempting to diagnose problems, it allows them to see what
what root cert they are expected to have locally for sucessful cert
chain validation.
Reply | Threaded
Open this post in threaded view
|

Re: OpenSSL server sending certificate chain(inc. root cert) during handshake

Viktor Dukhovni
In reply to this post by Jason Schultz
> On May 31, 2019, at 3:20 PM, Jason Schultz <[hidden email]> wrote:
>
> My questions deal with #2: Why does OpenSSL include the root cert in the certificate chain?

The OpenSSL SSL_CTX_build_cert_chain(3) function constructs a complete
chain of trust for your certificate chain, based on the configured trust
stores (CAfile and/or CApath).  If you call this function, then you can
control how your certificates chain is augmented.

But if your EE certificate is the entire chain, then the internal automatic
chain construction code will assume that the chain was not built, and will
try to augment it unless you set the SSL_MODE_NO_AUTO_CHAIN flag via:

  SSL_CTX_set_mode(3), or
  SSL_set_mode(3)

[ Which really ought to also document SSL_MODE_NO_AUTO_CHAIN ]

> Will the root cert be included in the chain any time it's in the same directory
> as the server cert?

No, the chain is augmented based on the configured trust stores, and does
not directly consider the directory holding the chain file.

> Is there a way, via API call, configuration, etc, to force OpenSSL to NOT send the
> root certificate as part of the chain in this case?

You can set a CAfile/CApath that do not include the location of the root
cert, or disable automatic chain construction, and build the chain just
the way you like it via SSL_CTX_build_cert_chain(3), possibly passing the
SSL_BUILD_CHAIN_FLAG_NO_ROOT flag.

--
        Viktor.

Reply | Threaded
Open this post in threaded view
|

Re: OpenSSL server sending certificate chain(inc. root cert) during handshake

Jason Schultz
I apologize for bringing this old subject back up, but I'm running into something I wanted to poll the list on.

Based on Victor's email below, I am doing the following in my application to set up my server to send a certificate chain *excluding* the root certificate during a handshake.

status = SSL_CTX_set_mode(ctx, SSL_MODE_NO_AUTO_CHAIN);
status = SSL_CTX_build_cert_chain(ctx, SSL_BUILD_CHAIN_FLAG_NO_ROOT);

When I configure a certificate chain, the server sends the chain, excluding the root. The call to SSL_CTX_build_cert_chain() accomplishes this, with the "no root" flag. This works as expected.

The interesting part comes in when I am configuring a self-signed certificate as the server cert.

** NOTE **: I know this isn't recommended, this is ONLY for test purposes, and our users will configure servers in this way, also ONLY for test purposes. This is why I'm testing the operation of this configuration.

As Victor indicated, my EE certificate is also the entire chain; of 1 self-signed certificate. Setting the SSL_MODE_AUTO_CHAIN flag allowed me to configure a self-signed certificate on the server, the two calls above succeed, and my server sends that single, self-signed cert in the handshake. This is true for version 3 self-signed certificates, with the CA bit set.

If I have a version 1 *RSA* certificate, with the CA bit NOT set(so CA:FALSE), the call to SSL_CTX_build_cert_chain() errors. I think this is the expected behavior. Does everyone agree with that? Since OpenSSL 1.1.1 is more strict regarding the CA bit, the building of the "chain" will fail because a self-signed cert MUST have CA:TRUE.

The incorrect behavior I think I'm seeing is when configuring a self-signed ECDSA certificate. I'll paste the certificate below, but I would think this version 1 certificate that does NOT have CA:TRUE would error in the same was the similar RSA certificate did above. Does anyone know what could be the result of the (seemingly) different behavior? Are there any other tests I could try to lead me to an answer?

Thanks,

Jason


TEST:/etc/ssl # openssl x509 -text -noout -in certs/ecdsacert.pem
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            de:6e:db:59:3a:03:e5:ac
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=State, L=City, O=Company, OU=Networking, CN=COMMON-NAME/emailAddress=[hidden email]
        Validity
            Not Before: Mar 17 18:23:09 2020 GMT
            Not After : Mar 17 18:23:09 2021 GMT
        Subject: C=US, ST=State, L=City, O=Company, OU=Networking, CN=COMMON-NAME/emailAddress=[hidden email]
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:dc:67:d3:f5:53:0b:c9:3c:13:e9:d9:52:17:60:
                    fb:a2:f6:ad:98:74:a4:1b:6d:57:52:81:d3:e5:8f:
                    e9:0f:a6:32:81:8f:f6:6d:3f:f2:1c:1c:6b:a7:c6:
                    3a:59:a3:c8:ce:12:08:ee:5c:8c:3e:4f:52:cb:35:
                    dc:6b:1a:de:59
                ASN1 OID: prime256v1
                NIST CURVE: P-256
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:66:d8:35:06:98:38:0a:88:57:c4:8d:30:02:97:
         3a:e7:4f:34:4a:50:d2:5c:e7:16:61:80:b3:43:41:7f:71:42:
         02:21:00:82:c2:39:b5:52:d4:e9:aa:21:d5:d1:fb:e8:01:e2:
         aa:81:16:75:cb:0d:2c:33:f6:34:5b:54:80:ac:82:66:4f




From: openssl-users <[hidden email]> on behalf of Viktor Dukhovni <[hidden email]>
Sent: Friday, May 31, 2019 9:44 PM
To: [hidden email] <[hidden email]>
Subject: Re: OpenSSL server sending certificate chain(inc. root cert) during handshake
 
> On May 31, 2019, at 3:20 PM, Jason Schultz <[hidden email]> wrote:
>
> My questions deal with #2: Why does OpenSSL include the root cert in the certificate chain?

The OpenSSL SSL_CTX_build_cert_chain(3) function constructs a complete
chain of trust for your certificate chain, based on the configured trust
stores (CAfile and/or CApath).  If you call this function, then you can
control how your certificates chain is augmented.

But if your EE certificate is the entire chain, then the internal automatic
chain construction code will assume that the chain was not built, and will
try to augment it unless you set the SSL_MODE_NO_AUTO_CHAIN flag via:

  SSL_CTX_set_mode(3), or
  SSL_set_mode(3)

[ Which really ought to also document SSL_MODE_NO_AUTO_CHAIN ]

> Will the root cert be included in the chain any time it's in the same directory
> as the server cert?

No, the chain is augmented based on the configured trust stores, and does
not directly consider the directory holding the chain file.

> Is there a way, via API call, configuration, etc, to force OpenSSL to NOT send the
> root certificate as part of the chain in this case?

You can set a CAfile/CApath that do not include the location of the root
cert, or disable automatic chain construction, and build the chain just
the way you like it via SSL_CTX_build_cert_chain(3), possibly passing the
SSL_BUILD_CHAIN_FLAG_NO_ROOT flag.

--
        Viktor.

Reply | Threaded
Open this post in threaded view
|

SSL_CTX_build_cert_chain() and SSL_CTX_set_mode()

Jason Schultz
Changing the subject to be more relevant to my questions. Just wanted to ping the list again.



From: openssl-users <[hidden email]> on behalf of Jason Schultz <[hidden email]>
Sent: Friday, March 20, 2020 3:21 PM
To: [hidden email] <[hidden email]>
Subject: Re: OpenSSL server sending certificate chain(inc. root cert) during handshake
 
I apologize for bringing this old subject back up, but I'm running into something I wanted to poll the list on.

Based on Victor's email below, I am doing the following in my application to set up my server to send a certificate chain *excluding* the root certificate during a handshake.

status = SSL_CTX_set_mode(ctx, SSL_MODE_NO_AUTO_CHAIN);
status = SSL_CTX_build_cert_chain(ctx, SSL_BUILD_CHAIN_FLAG_NO_ROOT);

When I configure a certificate chain, the server sends the chain, excluding the root. The call to SSL_CTX_build_cert_chain() accomplishes this, with the "no root" flag. This works as expected.

The interesting part comes in when I am configuring a self-signed certificate as the server cert.

** NOTE **: I know this isn't recommended, this is ONLY for test purposes, and our users will configure servers in this way, also ONLY for test purposes. This is why I'm testing the operation of this configuration.

As Victor indicated, my EE certificate is also the entire chain; of 1 self-signed certificate. Setting the SSL_MODE_AUTO_CHAIN flag allowed me to configure a self-signed certificate on the server, the two calls above succeed, and my server sends that single, self-signed cert in the handshake. This is true for version 3 self-signed certificates, with the CA bit set.

If I have a version 1 *RSA* certificate, with the CA bit NOT set(so CA:FALSE), the call to SSL_CTX_build_cert_chain() errors. I think this is the expected behavior. Does everyone agree with that? Since OpenSSL 1.1.1 is more strict regarding the CA bit, the building of the "chain" will fail because a self-signed cert MUST have CA:TRUE.

The incorrect behavior I think I'm seeing is when configuring a self-signed ECDSA certificate. I'll paste the certificate below, but I would think this version 1 certificate that does NOT have CA:TRUE would error in the same was the similar RSA certificate did above. Does anyone know what could be the result of the (seemingly) different behavior? Are there any other tests I could try to lead me to an answer?

Thanks,

Jason


TEST:/etc/ssl # openssl x509 -text -noout -in certs/ecdsacert.pem
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            de:6e:db:59:3a:03:e5:ac
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=State, L=City, O=Company, OU=Networking, CN=COMMON-NAME/emailAddress=[hidden email]
        Validity
            Not Before: Mar 17 18:23:09 2020 GMT
            Not After : Mar 17 18:23:09 2021 GMT
        Subject: C=US, ST=State, L=City, O=Company, OU=Networking, CN=COMMON-NAME/emailAddress=[hidden email]
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:dc:67:d3:f5:53:0b:c9:3c:13:e9:d9:52:17:60:
                    fb:a2:f6:ad:98:74:a4:1b:6d:57:52:81:d3:e5:8f:
                    e9:0f:a6:32:81:8f:f6:6d:3f:f2:1c:1c:6b:a7:c6:
                    3a:59:a3:c8:ce:12:08:ee:5c:8c:3e:4f:52:cb:35:
                    dc:6b:1a:de:59
                ASN1 OID: prime256v1
                NIST CURVE: P-256
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:66:d8:35:06:98:38:0a:88:57:c4:8d:30:02:97:
         3a:e7:4f:34:4a:50:d2:5c:e7:16:61:80:b3:43:41:7f:71:42:
         02:21:00:82:c2:39:b5:52:d4:e9:aa:21:d5:d1:fb:e8:01:e2:
         aa:81:16:75:cb:0d:2c:33:f6:34:5b:54:80:ac:82:66:4f




From: openssl-users <[hidden email]> on behalf of Viktor Dukhovni <[hidden email]>
Sent: Friday, May 31, 2019 9:44 PM
To: [hidden email] <[hidden email]>
Subject: Re: OpenSSL server sending certificate chain(inc. root cert) during handshake
 
> On May 31, 2019, at 3:20 PM, Jason Schultz <[hidden email]> wrote:
>
> My questions deal with #2: Why does OpenSSL include the root cert in the certificate chain?

The OpenSSL SSL_CTX_build_cert_chain(3) function constructs a complete
chain of trust for your certificate chain, based on the configured trust
stores (CAfile and/or CApath).  If you call this function, then you can
control how your certificates chain is augmented.

But if your EE certificate is the entire chain, then the internal automatic
chain construction code will assume that the chain was not built, and will
try to augment it unless you set the SSL_MODE_NO_AUTO_CHAIN flag via:

  SSL_CTX_set_mode(3), or
  SSL_set_mode(3)

[ Which really ought to also document SSL_MODE_NO_AUTO_CHAIN ]

> Will the root cert be included in the chain any time it's in the same directory
> as the server cert?

No, the chain is augmented based on the configured trust stores, and does
not directly consider the directory holding the chain file.

> Is there a way, via API call, configuration, etc, to force OpenSSL to NOT send the
> root certificate as part of the chain in this case?

You can set a CAfile/CApath that do not include the location of the root
cert, or disable automatic chain construction, and build the chain just
the way you like it via SSL_CTX_build_cert_chain(3), possibly passing the
SSL_BUILD_CHAIN_FLAG_NO_ROOT flag.

--
        Viktor.