Can't connect to the SSL server that use only ephemeral ciphersuites (The Local Security Authority cannot be contacted)
Asked Answered
H

1

5

I'm trying to connect to the test server started with openssl (this limited ciphersuite combination is intended):

openssl s_server -accept 443 -www -tls1_2 -cipher ECDHE:DHE:EDH -cert selfsignedcert.pem -key sskey.pem

The code I use is similar to msdn's

public static bool ValidateServerCertificate(
      object sender,
      X509Certificate certificate,
      X509Chain chain,
      SslPolicyErrors sslPolicyErrors)
{
        return true;
}

...

var client = new TcpClient(target, port);
SslStream sslStream = new SslStream(client.GetStream(), false,ValidateServerCertificate,null);
sslStream.AuthenticateAsClient(target, null, SslProtocols.Tls12, false);

But I'm getting an exception at the last line: A call to SSPI failed, see inner exception., where inner exception says: The Local Security Authority cannot be contacted. By looking at wireshark I can say that the TLS handshake ends with Server Hello, Certificate, Server Key Exchange, Server Hello Done and the chosen ciphersuite is TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f).

I can acces the url with Firefox, but not with IE (it just says "This page can’t be displayed") so it looks like schannel issue.

Everything works fine (IE and the code) when I start the server with all ciphersuites (-cipher ALL). Is there a way to make it work without modifying server's config?

Stacktrace just in case

    at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)

I'm using Windows 8.1 with latest updates.

Hypoderma answered 27/5, 2015 at 9:5 Comment(4)
Try to give your own DH param with at least 1024 bit. The default for s_server are a weak 512 bit which might not be acceptable by IE.Ataraxia
@SteffenUllrich thanks, using custom 1024bit params helped. But my question is how to connect to this server without changing it's config ie. how to bypass this safeguard in schannelHypoderma
I don't think it is a good idea to bypass this check, see weakdh.org. And expect the other browsers and libraries to get this limit too. The OpenSSL forks BoringSSL and LibreSSL have a 1024 bit limit for a while already too, without a way to bypass it. But you might use a newer OpenSSL version (after 1.02) where they don't use the 512 bit DH default in s_server any longer.Ataraxia
I'm aware of that. The thing is I'm using my program to verify SSL/TLS configuration of remote servers (bad certificates, weak ciphersuites etc.) so I need it to connect even to the unsafe services. So far it looks like schannel is not for this job.Hypoderma
H
6

I've managed to set the minimum key length for schannel using windows registry.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200

But it's not the desired solution, because it changes the setting for the whole system and I would like to set it temporarily and only in the scope of my application.

Hypoderma answered 27/5, 2015 at 10:17 Comment(1)
Sort of. Instead of using schannel I went with openssl, managed wrapper to be precise openssl-net.Hypoderma

© 2022 - 2024 — McMap. All rights reserved.