0

I'm currently working on a project where I need to validate Https Requests based on known TLSA records. The steps are:

  1. I perform a DNS lookup and obtain all TLSA records of the domain
  2. I perform the Https request and use the ServicePointManager.ServerCertificateValidationCallback to perform the validation
  3. On receiving the validation the certificate, I follow the DANE rfc to validate the HTTPS request:
  4. Based on the TLSA record's CertificateUsage, the correct certificate in the chain is selected.

At this step I'm having the following issue. In section 5 of the rfc it is stated that for different kind of certificate usages (i.e. PKIX-TA(0), PKIX-EE(1), DANE-TA(2) and DANE-EE(3)), the certificate chain needs to be authenticated in different ways.

From what I understand, this authentication is based on the SSLPolicyErrors, but I'm struggling to translate the rfc's language into the SSLPolicyErrors. I've currently implemented it as follows, based on a combination of ARSoft.Tools.Net and the rfc:

  • For both PKIX values (0 and 1), any kind of policy errors will imply that the the certificate is invalid.
  • For Dane-TA(2), it is stated that With usage DANE-TA(2), the server certificates will need to have names that match one of the client's reference identifiers. I have translated this into: the name mismatch enum value is not allowed
  • For Dane-EE(3), it is stated that Authentication via certificate usage DANE-EE(3) TLSA records involves simply checking that the server's leaf certificate matches the TLSA record.. I have translated this into: Any type of SSL policy error is allowed.

This brings me to the following code:

        public IEnumerable<SystemX509Certificates.X509Certificate> GetCorrectCertificate(SystemX509Certificates.X509Certificate certificate, X509Chain certificateChain, SslPolicyErrors sslPolicyErrors)
        {
            switch (_tlsaRecord.CertificateUsage)
            {
                case 0: // PKIX-TA, the full certificate chain needs to be valid
                    if(sslPolicyErrors == SslPolicyErrors.None)
                    {
                        // use any certificate
                        return certificateChain.ChainElements.Cast<X509ChainElement>().Select(x => x.Certificate);
                    }
                    else
                    {
                        return null;
                    }
                case 1: //PKIX-EE, the full certificate chain needs to be valid
                    if (sslPolicyErrors == SslPolicyErrors.None)
                    {
                        // use end entity certificate
                        return Enumerable.AsEnumerable(new List<SystemX509Certificates.X509Certificate> { certificate });
                    }
                    else
                    {
                        return null;
                    }
                case 2: //DANE-TA, only name mismatch is not allowed
                    if ((sslPolicyErrors | SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
                    {
                        // use any certificate
                        return certificateChain.ChainElements.Cast<X509ChainElement>().Select(x => x.Certificate);
                    }
                    else
                    {
                        return null;
                    }
                case 3: //DANE-EE, only compare leaf certificate with TLSA record
                        // use end entity certificate
                        return Enumerable.AsEnumerable(new List<SystemX509Certificates.X509Certificate> { certificate });
                default:
                    return Enumerable.Empty<X509Certificate2>();
            }
        }

However, I have no idea whether my interpretation of the rfc, and the implementation in C#, are correct. Can anybody tell me whether I'm doing the correct SSL policy check for the different kind of TLSA certificate usages?

der Bomber
  • 41
  • 5

0 Answers0