2

I have a simple C# application that talks to a remote server over TLS. When I attempt to "AuthenticateAsClient," I immediately receive the dreaded "the client and the server cannot communicated, because they do not possess a common algorithm."

So, I broke out a wire trace and observe that the "Client Hello" completes and serves up a cipher suite list. The "Server Hello" completes with a certificate and a selected cipher suite from the list provided in the "Client Hello". However, I then expect to see a "CIPHER CHANGE SPEC" next, but instead, the client resets/acks the connection, and fails, and I have no idea why. The server is sending down TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xC014).

What I've tried:

I suspected a problem with the server certificate, but verified that it has a KeySpec of 1 and validates properly. Its cert chain validates. Even when exported from the server and moved to my client box (sans private key), the validation chain seems OK.

I've verified via the IISCrypto tool that AES_256 is enabled and available on both the server and the client. I do notice, however, that in spite of my specifying TLS 1.2, the wire traces show that the server is only responding with TLS 1.0. I pointed the client to another instance of the application on a different machine, but it does respond with TLS 1.2, and works correctly - but with a different cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xC028).

I've also tried the opposite extreme of forcing the app down to TLS 1.0 against the "good" (working) server, and the result is the same - it still works.

I would assume that the failure to send the CIPHER CHANGE SPEC was due to the presumably incorrect determination that it had no common algorithms, but how could the client have offered it if it weren't available? Can something be "corrupted" within one of those cipher specs that wouldn't be realized until it was actually used?

For completeness, I've excerpted the portion of the program that does the SSL connect into a small console app, and it seems trivially simple, but I've reproduced it here in the event someone can see that I'm doing something incorrectly:

static void Main(string[] args)

    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        int portNumber = 9999999;  //edited for obvious reasons
        TcpClient x = new TcpClient("the.server.name", portNumber);
        var foo = new System.Net.Security.SslStream(x.GetStream(), false,
            (a,b,c,d) => {
                Console.WriteLine("connected");
                return true;
            });
        foo.AuthenticateAsClient("the.server.name");
        Console.WriteLine(foo.CipherAlgorithm.ToString());
    }
David W
  • 10,062
  • 34
  • 60
  • Have you tried to turn on tls 1.2 in your IE advance settings? Also see following : https://stackoverflow.com/questions/28286086/default-securityprotocol-in-net-4-5 – jdweng Dec 07 '17 at 22:49
  • Yes.TLS 1.2 has been enabled in IE. – David W Dec 08 '17 at 04:11
  • Which version of Net are you using? The link I provided says 1.2 doesn't work in all version of Net. – jdweng Dec 08 '17 at 04:37
  • I have targeted 4.6 and 4.0, specifying TLS1.2 and 1.0 in that ServicePointManager line. I've tried all the possible permutations - no difference. I've even tried creating 32-bit targets. I am theorizing right now that there's *something* in the process of traversing the trust chain for the server-provided cert that is, without warning or message, failing. I just don't know what. – David W Dec 08 '17 at 13:49
  • The reset is the server closing the TCP connection. So you have to find what is causing the server to send the reset. The reset ack is just the client responding to the server closing the connection. – jdweng Dec 08 '17 at 14:02
  • @jdweng Thanks for the info - let me make sure I'm not misleading - I see no RST coming from the server, only the RST ACK being sent immediately after the SERVER HELLO finishes (presumably successfully). When it works, I normally see the CLIENT KEY EXCHANGE and CHANGE CIPHER SPEC. – David W Dec 08 '17 at 14:08
  • You cannot get a RST ACK without first getting RST? TCP acknowledges every message so RST ACK is the acknowledgement of a RST. RST is closing connection message. – jdweng Dec 08 '17 at 15:14
  • @jdweng There is no RST from the server in the trace. It was my understanding that an RST ACK is not necessarily an acknowledgement of an RST, as described in the answer to https://networkengineering.stackexchange.com/questions/2012/why-do-i-see-a-rst-ack-packet-instead-of-a-rst-packet. It appears that this may be in response to the server abruptly closing the connection. – David W Dec 08 '17 at 15:30
  • Check the sequence numbers carefully and see what sequence is being acknowledged. The link may be correct that the RST ACK is a combination or an ACK and a close. Also check the times of the messages. The client may be closing due to a timeout. The message from the server may be late an you need to increase the timeout. Make sure the sequence number are corresponding between the client and server. Each message will get an ack. Also make sure there are not multiple messages with same sequence number. – jdweng Dec 08 '17 at 15:48

0 Answers0