Topic: [SOLVED] Certificate Validation requires both: root and intermediate

One more question, according to 7.3 section of your docs:

wolfSSL requires that only the top or “root” certificate in a chain to be loaded as a trusted certificate in order to verify a certificate chain. This means that if you have a certificate chain (A -> B -> C), where C is signed by B, and B is signed by A, wolfSSL only requires that certificate A be loaded as a trusted certificate in order to verify the entire chain (A->B->C).

it should be enough to load only root certificate, but in our case we should load both: root and intermediate certificate. Otherwise handshake procedure fails with -188 "ASN no signer error to confirm failure".

$ ~/wolfssl/examples/client/client -g -h devcomtest.buchi.digital -p 443 -A ~/root.pem
wolfSSL Entering wolfSSL_Init
wolfSSL Entering wolfCrypt_Init
wolfSSL Entering WOLFSSL_CTX_new_ex
wolfSSL Entering wolfSSL_CertManagerNew
wolfSSL Leaving WOLFSSL_CTX_new, return 0
wolfSSL Entering wolfSSL_CTX_use_certificate_chain_file
Getting dynamic buffer
wolfSSL Entering PemToDer
Checking cert signature type
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Not ECDSA cert signature
wolfSSL Entering wolfSSL_CTX_use_PrivateKey_file
Getting dynamic buffer
wolfSSL Entering PemToDer
wolfSSL Entering wolfSSL_CTX_load_verify_locations
Getting dynamic buffer
Processing CA PEM file
wolfSSL Entering PemToDer
Adding a CA
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
    Parsed new CA
    Freeing Parsed CA
    Freeing der CA
        OK Freeing der CA
wolfSSL Leaving AddCA, return 0
   Processed a CA
Processed at least one valid CA. Other stuff OK
wolfSSL Entering wolfSSL_CTX_load_verify_locations
Getting dynamic buffer
Processing CA PEM file
wolfSSL Entering PemToDer
Adding a CA
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetObjectId()
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeKeyUsage
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeExtKeyUsage
wolfSSL Entering GetObjectId()
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
    Parsed new CA
    Freeing Parsed CA
    Freeing der CA
        OK Freeing der CA
wolfSSL Leaving AddCA, return 0
   Processed a CA
Processed at least one valid CA. Other stuff OK
wolfSSL Entering SSL_new
wolfSSL Leaving SSL_new, return 0
wolfSSL Entering SSL_set_fd
wolfSSL Entering SSL_set_read_fd
wolfSSL Leaving SSL_set_read_fd, return 1
wolfSSL Entering SSL_set_write_fd
wolfSSL Leaving SSL_set_write_fd, return 1
wolfSSL Entering SSL_connect()
wolfSSL Entering SendClientHello
Adding signature algorithms extension
growing output buffer

Signature Algorithms extension to write
Point Formats extension to write
Supported Groups extension to write
Shrinking output buffer

wolfSSL Leaving SendClientHello, return 0
connect state: CLIENT_HELLO_SENT
growing input buffer

received record layer msg
wolfSSL Entering DoHandShakeMsg()
wolfSSL Entering DoHandShakeMsgType
processing server hello
wolfSSL Entering DoServerHello
Point Formats extension received
wolfSSL Entering VerifyClientSuite
wolfSSL Leaving DoServerHello, return 0
wolfSSL Leaving DoHandShakeMsgType(), return 0
wolfSSL Leaving DoHandShakeMsg(), return 0
growing input buffer

received record layer msg
wolfSSL Entering DoHandShakeMsg()
wolfSSL Entering DoHandShakeMsgType
processing certificate
wolfSSL Entering DoCertificate
wolfSSL Entering ProcessPeerCerts
Loading peer's cert chain
    Put another cert into chain
    Put another cert into chain
    Put another cert into chain
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
About to verify certificate signature
wolfSSL Entering ConfirmSignature
wolfSSL Leaving ConfirmSignature, return 0
Verified CA from chain and already had it
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
About to verify certificate signature
wolfSSL Entering ConfirmSignature
wolfSSL Leaving ConfirmSignature, return 0
Adding CA from chain
Adding a CA
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
    Parsed new CA
    Doesn't have key usage certificate signing
    Freeing Parsed CA
    Freeing der CA
        OK Freeing der CA
wolfSSL Leaving AddCA, return -357
Verifying Peer's cert
wolfSSL Entering GetExplicitVersion
wolfSSL Entering GetSerialNumber
Got Cert Header
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Algo ID
Getting Cert Name
Getting Cert Name
Got Subject Name
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
Got Key
Parsed Past Key
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering GetObjectId()
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering GetObjectId()
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering GetAlgoId
wolfSSL Entering GetObjectId()
About to verify certificate signature
No CA signer to verify with
Failed to verify Peer's cert
    No callback override available, fatal
wolfSSL Leaving ProcessPeerCerts, return -188
wolfSSL Leaving DoCertificate, return -188
wolfSSL Leaving DoHandShakeMsgType(), return -188
wolfSSL Leaving DoHandShakeMsg(), return -188
wolfSSL error occurred, error = -188
wolfSSL Entering SSL_get_error
wolfSSL Leaving SSL_get_error, return -188
wolfSSL Entering SSL_get_error
wolfSSL Leaving SSL_get_error, return -188
wolfSSL Entering ERR_error_string
wolfSSL_connect error -188, ASN no signer error to confirm failure
wolfSSL Entering SSL_free
CTX ref count not 0 yet, no free
Shrinking input buffer

wolfSSL Leaving SSL_free, return 0
wolfSSL Entering SSL_CTX_free
CTX ref count down to 0, doing full free
wolfSSL Entering wolfSSL_CertManagerFree
wolfSSL Leaving SSL_CTX_free, return 0
wolfSSL error: wolfSSL_connect failed

At the same time the

$ ~/wolfssl/examples/client/client -g -h devcomtest.buchi.digital -p 443 -A ~/root_int.pem

works fine.

Where root.pem is the root certificate and root_int.pem file contains both: root and intermediate certificates.
So why we should provide both certificates in this case?

Thanks in advance.

Share

Re: [SOLVED] Certificate Validation requires both: root and intermediate

Hi Pilatuz,

That is an excellent question! Thank you for using the wolfSSL forums to seek an answer.

Unfortunately everyone does not follow the spec appropriately and sometimes exceptions have to be made for the rule-breakers.

You'll note in RFC 5246 https://tools.ietf.org/html/rfc5246 that server is SUPPOSED to send it's entire chain with the only exception being the root CA. It sounds like you have found a server that does not abide by the rules and leaves out another part of the chain too. (Excerpt below from the RFC):

7.4.2.  Server Certificate

   certificate_list
      This is a sequence (chain) of certificates.  The sender's
      certificate MUST come first in the list.  Each following
      certificate MUST directly certify the one preceding it.  Because
      certificate validation requires that root keys be distributed
      independently, the self-signed certificate that specifies the root
      certificate authority MAY be omitted from the chain, under the
      assumption that the remote end must already possess it in order to
      validate it in any case.

Please let us know if you have any other questions!

- Kaleb

Re: [SOLVED] Certificate Validation requires both: root and intermediate

Hi Kaleb, thank you for your reply.

As you noted,

the root certificate authority MAY be omitted from the chain

"MAY" assumes that both options are valid whatever server sends root certificate or not.
And it's not clear why verification works if both root+intermediate provided?

It seems that this issue is related to "Key Usage" TLS extension as noted here https://security.stackexchange.com/ques … rtificates
For the another server with "Key Usage" TLS extension enabled the root certificate only if enough to verify.

Share

Re: [SOLVED] Certificate Validation requires both: root and intermediate

Pilatuz,

Hi Kaleb, thank you for your reply.
As you noted,

the root certificate authority MAY be omitted from the chain

"MAY" assumes that both options are valid whatever server sends root certificate or not.
And it's not clear why verification works if both root+intermediate provided?
It seems that this issue is related to "Key Usage" TLS extension as noted here https://security.stackexchange.com/ques … rtificates
For the another server with "Key Usage" TLS extension enabled the root certificate only if enough to verify.

Correct! "MAY" indicating the ROOT CA may be omitted since the client presumably already has a copy loaded to validate the peer. This in no way implies an INTERMEDIATE CA may be omitted. Clients know about ROOT CA's, they do not always know, nor can they be expected to know about intermediate CA's. Conforming servers should not omit any cert from the chain except the root ca but like I mentioned not every server is a "conforming" server unfortunately.


Apologies for the delayed response on this one. The reason you had to provide both intermediate CA and root CA for verification to work is that wolfSSL checks the signatures and rebuilds the entire chain of trust. If a cert chain is composed of the certs A, B, C, and D let's say and the server only sends C and D during the handshake and wolfSSL side has only loaded A your chain is this:

A -> [MISSING] -> C-> D

wolfSSL will never validate this chain and it has nothing to do with the "Key Usage" extension.

In your case this is exactly what happened. wolfSSL did not have all the certs necessary to build the entire chain of trust so validation of the chain failed and the connection did not proceed. Once you loaded both A and B on the wolfSSL side and wolfSSL received cert C during the handshake it was able to rebuild the entire chain of trust and validate the authenticity of the peer.

Regards,

Kaleb