Search code examples
c#windowscertificatepkix509certificate2

Using C#, how to programmatically determine if a certificate in a Windows certificate store has been disabled


I'm currently working on refining communications between mutually authenticated client/server applications using HTTPS. I am currently building validation logic into a C# client to help identify configuration issues when a TLS connection fails. In verifying the connection, I validate that the root CA certificate presented by the server is installed on the client, in the appropriate store, and is valid. I'm using X509Store to pull the X509Certificate2, and validating it using X509Chain.

My issue is that the certificate will report as valid even if the certificate has been disabled via MMC. So the TLS connection will fail, despite the chain reporting as valid.

Certificate Properties

It's an unlikely case, but one I'd like to handle by reporting something like "Could not connect because root CA is disabled."

Could anyone point me in the direction of a .NET or Win32 call that could be made to determine the value of "Certificate Purposes" for a certificate? Or to read the "Certificate Status" for a cert?

Certificate Status

I read through MSDN's listing of what's in the System.Security.Cryptography namespace, and started looking into CryptoAPI and CNG, but didn't find anything so far.

Thanks!


Solution

  • That dialog does not "disable" a certificate it disables it "for all purposes". What this means is it counts as having an empty Enhanced Key Usage extension for purposes of EKU validation.

    Normally a root certificate (or an intermediate CA certificate) will not have an EKU extension, so if you do a chain build with any ApplicationPolicy value it will be a match. Once you set it to Disable for all purposes you'll get a chain error X509ChainStatusFlags.NotValidForUsage.

    If you want to build something for validating TLS you'd check either the Server Authentication or Client Authentication EKUs (depending on what you're checking):

    // Server EKU or Client EKU
    Oid eku = forServer ? new Oid("1.3.6.1.5.5.7.3.1") : new Oid("1.3.6.1.5.5.7.3.2");
    
    // Test if it's valid for that purpose
    chain.ChainPolicy.ApplicationPolicy.Add(eku);
    

    If you want to "Disable" a root CA altogether, add a copy of the certificate to the Disallowed store (called "Untrusted Certificates" in the UI). That will result in a chain build producing X509ChainStatusFlags.ExplicitDistrust.