This bug proposes a solution to a problem. But the problem is not due to any violation of any specification, so I am reluctant to call it a bug. So I am filing this as an RFE. The problem is this. While trying to construct a cert chain for an SSL server, NSS may construct a chain that includes an expired CA cert found in the cert DB, even when the server has sent a cert chain with a newer unexpired cert for that same CA, whose expired cert is in the cert DB. The reason for this is that that CA has issued certs with Authority Key ID (AKID) extensions that include the Issuer name and Serial number of the CA's own cert. Then when that CA cert expires or is replaced, the certs previously issued by that CA still contain the issuer name and serial number of the old CA cert. Following the RFC to the letter, NSS will choose the old CA cert, rather than the newer one, because that is exactly what the AKID instructs it to do. This is not a bug in NSS, per se'. It is correct for NSS to construct the chain with the old CA cert under the circumstances where: a) the cert under test specifies that old cert by its issuer name and serial number, and b) that old cert is available to NSS among the certs for that CA from which NSS must choose when constructing the chain. The problem arises when the old cert is locally retained past its expiration date. The problem would not be experienced if the old cert was no longer retained in the cert DB after its expiration. I propose that PSM adopt the following strategy. When an attempt to validate a cert (SSL server cert or SMIME cert or any cert for which it calls one of NSS's cert validation functions) fails (the cert validation function returns SECFailure) with the error SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE (-8162), then PSM should find and delete the expired issuer cert IF (and only if) it is known to be stored in the internal token (in the cert DB). To do that, PSM would ask NSS to return the chain with the expired cert, and then PSM would walk the chain returned by NSS until it found the expired cert. Then PSM would examine the cert to see if it is stored in the internal token, and delete it if so. Then PSM would try AGAIN to validate the server's cert chain. This proposed approach to dealing with expired CA certs depends on NSS's ability to output the cert chain containing the expired cert. I am certain that the old cert DB code in NSS can and will do that. I am not certain that the new libPKIX-based code can do it. (Alexei?)
I specifically did NOT propose the following alternative strategy: - Once per PSM startup, PSM will traverse all the certs in the cert DB, looking for expired CA certs, and delete any it finds. I suspect that would be simpler to implement than the strategy proposed in comment 0, but it would have the undesirable side effect of deleting CA certs for which that deletion solves no problem, and that the user may still be using (e.g. to validate cert chains on old emails). Ideally, PSM would only delete certs that it had formerly saved in the course of validating cert chains, and would not delete certs that had been imported by the user (including those imported as part of a PKCS#12 file). But I suspect that we have no way to know how or why a cert was imported, after the fact. So I propose that we delete only expired CA certs that are known to be causing a problem. As a further refinement (which might complicate this even more), PSM might only delete a CA cert if it was expired *AND* if its subordinate cert contains an AKID extension that specifies the CA cert by issuer name and serial number.
(In reply to comment #0) ... > This proposed approach to dealing with expired CA certs depends on NSS's > ability to output the cert chain containing the expired cert. I am certain > that the old cert DB code in NSS can and will do that. I am not certain > that the new libPKIX-based code can do it. (Alexei?) NSS legacy cert validation function does not return cert chain at all. CERT_CertChainFromCert should be used to construct the chain. The function does filter found cert issuers by key ID: certificate.c:407 Libpkix does not return partially built chain in case when validation failed. But, it returns CERTVerifyLog that potentially can be used to find expired cert with correct AKID. Also libpkix can be modified to return a partially built chain. One thing I noticed though, is that libpkix code relies on underlying nss to filter out certs that do not have proper key id. But, libpkix also uses other cert fetching mechanisms and it may end up build chain with mismatched or absent subject keyid on an issuer cert. Will file a bug on this matter against libpkix.
(In reply to comment #2) > NSS legacy cert validation function does not return cert chain at all. Yes it does. It's the "log" output.
I meant that CERT_Verify* functions are the public function that does not return an address to a built chain as one of its argument. We can not return partially built chain to a caller of these functions. The log that returned by legacy and libpkix code, has a pointer to a cert and the reason code. But it is questionable that psm can effectively use it, as it will need to find things like: issued subordinate certs that have AKID with appropriate data; make sure, that the CA cert can not be used to verify cert on old email; there is another CA issuer of cert(s) with AKID which public key can be used to verify their signatures.
The CERT_Verify public functions have a log argument that returns a partial chain of certs in the error case.
Automatic deletion based on time? Would need to consider possibility of incorrect system clock.
The switch to mozilla::pkix made this bug unnecessary.