John,

On 12/21/2013 12:16, John Dennis wrote:
I'm trying to debug a validation failure when using
CERT_VerifyCertificate(). The cert being validated is a SSL Server Cert,
it is signed by a root cert. I have confirmed the server cert validates
using CERT_VerifyCertificate() in a stand alone program an the root cert
imported and trusted into an NSS database. I've also confirms it
validates with openssl verify.



The problem seems to come when the cert is used in an SSL handshake (in
this particular instance when the openldap libary is making a TLS
connection to an openldap server (the openldap library is using NSS,
e.g. tls_m.c).

Stepping through CERT_VerifyCertificate as called by the openldap
library I have found where verification failure occurs. First also let
me say that I've also run the connection through the NSS ssltap tool and
I can see that the server is sending the client 2 certs, the server cert
and the root ca cert that signed it. Hence during the connection attempt
there is cert chain of length 2.

The verify failure occurs cert_VerifyCertChainOld() in this code:

There are 2 PKIX implementations in NSS . The "old" implementation is not so smart and does not properly handle cases for which there are multiple matches in the cert chain.

See http://lxr.mozilla.org/nss/source/lib/certhigh/certvfy.c#692

Please make sure your application is using the newest implementation.
You can do so by calling
CERT_SetUsePKIXForValidation(PR_TRUE);


        /* make sure that the issuer is not self signed.  If it is, then
         * stop here to prevent looping.
         */
        if (issuerCert->isRoot) {
            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
            LOG_ERROR(log, issuerCert, count+1, 0);
            goto loser;
        }
This suggests to me that NSS will not accept a cert chain with the root
cert in it. Is that correct?
No, it should accept such a chain.
But problems can occur if you have similar roots sent locally and over the wire. For example, if your root was renewed, and you have an old one installed and trusted locally, only that one is trusted. If the remote server is sending over a newer root, then that one won't be trusted. The old PKIX implementation only explores one certification path and this is probably what's causing your failure. If the root cert installed and trusted locally and sent over the wire are really the same cert, then either the old or new implementation should work.

My understanding (and verified via some additional research) is that
while it's not optimal/common to include the root cert in the chain it
is in fact permissible. The basic idea I believe is the root cert in the
chain is ignored and previous cert in the chain is validated by finding
the root issuer in the trust store. Yes/No/Comments?
It is permissible.

The stand alone validation succeeds apparently because there is no chain
to traverse with a root cert in it.

Is NSS behaving incorrectly by rejecting a chain with a root cert?
Depends if that identical DER cert is locally trusted or not.

Is the server behaving incorrectly by sending a chain with a root cert?
No. But my guess is that the root certs sent over the wire and the one you have locally trusted are not identical. They may be similar in terms of public key and key ID, but other elements like the NotBefore/NotAfter date probably differ. They must actually be the same cert if you want to use the old PKIX implementation. The newer PKIX implementation is more flexible. But that will only help if your cert truly can chain back to the locally-installed root cert.

What causes a root cert to be included in a chain?
Something in your server configuration. You should be able to remove the root from the server config, and then it should stop sending it. This is specific to your server and the security library it uses.

Julien

--
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to