What might cause System.Net Error:AcquireCredentialsHandle() failed with error 0X8009030D?

0

I have a simple piece of https connection code that works well with one ssl host, connecting even though the root certificate authority is untrusted (this is a sandbox environment, so we're not worried about the security hole this creates, for now), and loading the certificate and key from text files, using the Nuget package OpenSSL.X509Certificate2Provider:

    public async Task<string> Register()
    {
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;

        using (var handler = new HttpClientHandler())
        {
            var rawcert = File.ReadAllText(@"C:\OpenSSL\bin\certTransport.pem");
            var rawkey = File.ReadAllText(@"C:\OpenSSL\bin\privateKeyTransport.key");

            var provider = new CertificateFromFileProvider(rawcert, rawkey);
            var cert = provider.Certificate;
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ServerCertificateCustomValidationCallback +=
                (HttpRequestMessage req, X509Certificate2 cert2, X509Chain chain, SslPolicyErrors err) =>
                {
                    return true;
                };

            handler.ClientCertificates.Add(cert);

            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = new Uri("https://{uri}/");
                var response = await client.GetStringAsync("register");
                return response;
            }
        }
    }

When I point this code to another host, that should be secured in precisely the same manner, I get the following error: System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.

And digging into the logs, I discover: System.Net Information: 0 : [35036] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential) System.Net Error: 0 : [35036] AcquireCredentialsHandle() failed with error 0X8009030D.

Searching stack for this, I find many errors related to certificate store permissions, but the client certificate in this case isn't loaded from the store.

I also find many issues relating to SecurityProtocolType. I have verified that the server is using Tls1.2 (only).

I'm calling the code from a unit test within VS 2017 Enterprise running with Administrative privileges on Win10 x64. The code is contained in a .Net 4.7 Class Library, not hosted in IIS.

What could be causing this issue?

UPDATE Following @Jeroen Mostert's useful comments below, I tried a basic connection test with OpenSSL. Slightly anonymised results:

OpenSSL> s_client -connect {REMOVED}:443 -CAfile C:\OpenSSL\bin\archive-ii\transport-production-new\certTransport.pem
CONNECTED(000001F0)
depth=2 C = GB, O = OK, CN = {REMOVED} Root CA
verify error:num=19:self signed certificate in certificate chain
---
Certificate chain
0 s:/C=GB/O={REMOVED}/OU={REMOVED}/CN={REMOVED}
i:/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
1 s:/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
i:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
2 s:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
i:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
{REMOVED}
-----END CERTIFICATE-----
subject=/C=GB/O={REMOVED}/OU={REMOVED}/CN={REMOVED}
issuer=/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
---
Acceptable client certificate CA names
/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
/C=GB/O={REMOVED}/CN={REMOVED} Root CA
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms:     RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5155 bytes and written 446 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID:
    Session-ID-ctx:
    Master-Key: {REMOVED}
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1527164830
    Timeout   : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
---

Is there anything amiss there?

I've also looked in the CAPI2 log (as suggested in the comments). This shows errors relating to the root certificate not being trusted, like this: enter image description here

Does this mean my validation callbacks aren't working - and if so, any idea why that would be?

Further Update:

If I remove the line of code which attaches the certificate, then the error goes away - I get through to the MTLS test endpoint (but, of course, fail the MTLS test that is conducted there).

What does this suggest? A problem with the certificate itself?

c#
ssl
x509certificate
dotnet-httpclient
tls1.2
asked on Stack Overflow May 24, 2018 by Jude Fisher • edited May 29, 2018 by Jude Fisher

1 Answer

0

The problem here in the end was with the output of the CertificateFromFileProvider method of the OpenSSL.X509Certificate2Provider NuGet package.

For whatever reason, the certificate created would not work correctly. Taking the same input files and generating a .pfx with OpenSSL resulted in an X509Certificate2 that worked fine.

answered on Stack Overflow Jun 28, 2018 by Jude Fisher

User contributions licensed under CC BY-SA 3.0