1

I know that Mono doesn't support TLS1.1 and TLS1.2 in current version of Xamarin so maybe there is possibility to implement TLS12 on my way?

This part of code doesn't work for Xamarin.Android:

_clientSocket = new TcpClient();
await _clientSocket.ConnectAsync(host, port);
_stream = new SslStream(_clientSocket.GetStream(), false);
_stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, false);
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
XueBao
  • 13
  • 1
  • 4
  • Xamarin brought TLS 1.2 support in Cycle 7 Alpha 1 back in March, https://releases.xamarin.com/alpha-preview-1-cycle-7/ so it should already land on the version (Cycle 8 Update 1) you use if you check carefully. – Lex Li Nov 11 '16 at 22:26
  • You use AuthenticateAsClient. Do you have certs installed on the phone? Are those certs self-signed? – Yuri S Nov 13 '16 at 07:52
  • @LexLi thanks I need to check, I didn't know – XueBao Nov 13 '16 at 18:59
  • @SushiHangover authentication via TLS12 (server always get TLS1 from client even if I set TLS12 like above in example) – XueBao Nov 13 '16 at 18:59
  • @YuriS I don't need it to install cert on the phone because is trusted - not self-signed. When I set to TLS12 (example above) - on the server I get always TLS1 from client because Mono support TLS1 for Mono SslStream. – XueBao Nov 13 '16 at 18:59
  • As @SushiHangover said what doesn't work? What exception you are getting? – Yuri S Nov 13 '16 at 19:09
  • @YuriS or @SushiHangover **Client exception:** The authentication or decryption has failed. **Server output** (see client hello, server thinks that client is TLS1 and it is truth because setting TLS12 on client doesn't work for Xamarin.Android): `878893, READ: TLSv1 Handshake, length = 80 ClientHello, TLSv1 878893, SEND TLSv1.2 ALERT: fatal, description = handshake_failure 878893, handling exception: javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1 not enabled or not supported` – XueBao Nov 13 '16 at 19:31
  • And your server supports ONLY TLS12? Can you use Http or this is not an option? Can you share URI you are connecting for us to try some options? Are you writing or reading first from socket? – Yuri S Nov 13 '16 at 19:38
  • Yes, only support TLS12 because I don't want to use SSL in all versions and TLS1-1.1 be cause of POODLE attack. – XueBao Nov 13 '16 at 19:42
  • Can you answer the rest of my question please – Yuri S Nov 13 '16 at 19:43
  • I can't use HTTP because this is a socket connection via PROTOBUF (real-time application) but TLS12 for HTTP rest api works very well using ModernHttpClient for all platforms in Xamarin (but that's another story). There is no reading from the server, the server immediately breaks the connection just for safe. – XueBao Nov 13 '16 at 19:51
  • If you don't read why you connect at all :-) Can you share your URI? If any SSL client can do it I assume it is not a secret URI? – Yuri S Nov 13 '16 at 19:54
  • @SushiHangover Android 6.0 - API 23 – XueBao Nov 13 '16 at 19:55
  • It seems your cert is self-signed. Is that correct? – Yuri S Nov 13 '16 at 20:02

1 Answers1

1

Make sure you are setting the SSL/TLS Implementation to Native TLS 1.2+ so BoringSsl is used vs. Mono's managed TLS. If the managed implementation is used, your client will only negotiate 1.1.

enter image description here

var _clientSocket = new TcpClient();
using (var _stream = new SslStream(_clientSocket.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidation)))
{
    await _stream.AuthenticateAsClientAsync(host, null, SslProtocols.Tls12, false);
    // do something with your stream

    // FYI: Bug/Issue with Xamarin.Android, the following always return `None`
    Log.Debug(TAG, $"CipherAlgorithm: {_stream.CipherAlgorithm.ToString()}");
    Log.Debug(TAG, $"KeyExchangeAlgorithm: {_stream.KeyExchangeAlgorithm.ToString()}");
    Log.Debug(TAG, $"HashAlgorithm: {_stream.HashAlgorithm.ToString()}");

    // The following are not implemented in Xamarin Mobile, tagged as "Need to Implement"
    // Mobile CipherStrength = NotImplementedException
    // Mobile KeyExchangeStrength = NotImplementedException
    // Mobile HashStrength = NotImplementedException

}
  • Handling RemoteCertificateChainErrors

In order to handle the RemoteCertificateChainErrors on the Self-Signed cert, you can provide a custom RemoteCertificateValidationCallback, while you can just provide a true, you should actually check that the correct server/cert is provided but adding it to the TrustManager would be the preferred/secure way...

static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors certificateErrors)
{
    Console.WriteLine("CertificateValidation");
    Console.WriteLine(certificate.ToString(true));
    Console.WriteLine("Chain");
    Console.WriteLine(chain);
    Console.WriteLine("\tError(s)");
    Console.WriteLine(certificateErrors);
    Console.WriteLine();
    return true;
}

Update:

Manual setting via .csproj (or xbuild/msbuild), within the PropertyGroup for release/debug you can add:

<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<AndroidTlsProvider>btls</AndroidTlsProvider>
SushiHangover
  • 73,120
  • 10
  • 106
  • 165