Matthew Leibowitz: Enabling TLS v1.2 on Android 4.2
While I was busy making self-signed certificates work on Android, I had to add support for TLS version 1.2 on Android 4.2. Although it is supported, it is disabled by default.
The SSL Socket Factory
Enabling TLS support is relatively easy in that we just wrap the DefaultSSLSocketFactory
in a new SSLSocketFactory
, and when a socket is created, we enable all the supported protocols:
private class CompleteSSLSocketFactory : SSLSocketFactory
{
private readonly SSLSocketFactory innerFactory;
public CompleteSSLSocketFactory()
{
this.innerFactory = HttpsURLConnection.DefaultSSLSocketFactory;
}
public override string[] GetDefaultCipherSuites()
{
return innerFactory.GetDefaultCipherSuites();
}
public override string[] GetSupportedCipherSuites()
{
return innerFactory.GetSupportedCipherSuites();
}
public override Socket CreateSocket()
{
return MakeSocketSafe(innerFactory.CreateSocket());
}
public override Socket CreateSocket(Socket s, string host, int port, bool autoClose)
{
return MakeSocketSafe(innerFactory.CreateSocket(s, host, port, autoClose));
}
public override Socket CreateSocket(string host, int port)
{
return MakeSocketSafe(innerFactory.CreateSocket(host, port));
}
public override Socket CreateSocket(string host, int port, InetAddress localHost, int localPort)
{
return MakeSocketSafe(innerFactory.CreateSocket(host, port, localHost, localPort));
}
public override Socket CreateSocket(InetAddress host, int port)
{
return MakeSocketSafe(innerFactory.CreateSocket(host, port));
}
public override Socket CreateSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
{
return MakeSocketSafe(innerFactory.CreateSocket(address, port, localAddress, localPort));
}
private Socket MakeSocketSafe(Socket socket)
{
var sslSocket = socket as SSLSocket;
if (sslSocket != null) {
// enable all supported protocols for this socket
sslSocket.SetEnabledProtocols(sslSocket.GetSupportedProtocols());
sslSocket.SetEnabledCipherSuites(sslSocket.GetSupportedCipherSuites());
}
return socket;
}
}
The HTTP Client
Now, we just pass an instance of the factory to the client using SetSslSocketFactory
. Although, we caould probably create a singleton for the factory:
// create a new OkHttpClinet
var client = new OkHttpClient();
// only for the older Androids do we do this
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) {
client.SetSslSocketFactory(new CompleteSSLSocketFactory());
}