Hi guys!
After migrating from 3.12.0 to 4.7.1
On Android 5.1 I'm getting SSLProtocolException :
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7f2719a89e80: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0x7f2728a53ea0:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318)
The host I'm trying to connect is admin-api-stg.oitchau.com.br
I have tried this:
.connectionSpecs(
listOf(
ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.build()
)
)
But no luck
I can't reproduce on an Android 5.0 (21) device.
You can see the changes we have made to connection specs here https://github.com/square/okhttp/blob/7e4870537e33e2f0c4ea39f97b3a7d41a6ba0711/docs/tls_configuration_history.md
This is the sort of information we'd like with 3.12.0 to work out why it's failing
https://github.com/square/okhttp/issues/6138#issuecomment-647345231
Yep, and you can get that by printing the response鈥檚 handshake.
My guess is you're getting this cipher suite which is gone in even our COMPATIBLE_TLS config:
REMOVED: TLS_AES_128_CCM_SHA256鹿
REMOVED: TLS_AES_128_CCM_8_SHA256鹿
Nope, that's a bad guess because those cipher suites don't really exist on 3.12 either. Please print the handshake from OkHttp 3.12!
One more resource:
http://tinyurl.com/okhttp-cipher-suites
Somehow the intersection of Andoid 5, OkHttp 4.7, and your server is empty.
... and I think the reason is that Android 5 has the wrong version of a cipher suite:
https://security.stackexchange.com/questions/117078/what-does-old-mean-in-old-tls-ecdhe-rsa-with-chacha20-poly1305-sha256#117084
(I'd never heard of this before)
How can I print the handshake information?
It's a field on the Response.
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-handshake/
Guys, thanks for help!
I have fixed this by adding
private fun updateAndroidSecurityProvider() {
try {
ProviderInstaller.installIfNeeded(this)
} catch (e: GooglePlayServicesRepairableException) {
// Thrown when Google Play Services is not installed, up-to-date, or enabled
// Show dialog to allow users to install, update, or otherwise enable Google Play services.
// IGNORE
} catch (e: GooglePlayServicesNotAvailableException) {
Timber.e("SecurityException Google Play Services not available.")
}
}
to my App.onCreate() Important updateAndroidSecurityProvider() invocation must be before OkHttpClient initialization
Successful Handshake on 4.7.1 return:
Handshake{tlsVersion=TLS_1_2 cipherSuite=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 peerCertificates=[CN=sni.cloudflaressl.com, O="Cloudflare, Inc.", L=San Francisco, ST=CA, C=US, CN=CloudFlare Inc ECC CA-2, O="CloudFlare, Inc.", L=San Francisco, ST=CA, C=US, CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE] localCertificates=[]}
To reproduce this Exception I have used this method:
private fun testCall() {
val client = OkHttpClient.Builder()
.connectTimeout(40, TimeUnit.SECONDS)
.writeTimeout(40, TimeUnit.SECONDS)
.readTimeout(40, TimeUnit.SECONDS)
.connectionSpecs(
listOf(
ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.build()
)
)
.addInterceptor { chain ->
val response = chain.proceed(chain.request())
Timber.i(response.handshake.toString())
response
}
.apply {
if (com.oitchau.tablet.BuildConfig.DEBUG)
addNetworkInterceptor(
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
)
}
.build()
val JSON = "application/json; charset=utf-8".toMediaTypeOrNull()
val body = RequestBody.create(JSON, "{ }" )
val request = Request.Builder()
.url("https://admin-api-stg.oitchau.com.br/v1/public/structure/tablets/register")
.post(body)
.build()
GlobalScope.launch {
Timber.i(client.newCall(request).execute().toString())
}
}
I have tested it on this emulator:
Target: google_apis [Google APIs] (API level 22)
CPU/ABI: Google APIs Intel Atom (x86_64)`
Awesome. Since you鈥檙e using the security provider you can remove the line that configures the connectionSpecs. Both the security provider and your server are capable of our default configuration which is a bit more locked down.
Any chance you can print the old handshake from 3.12? I鈥檓 curious if my theory holds that it鈥檚 the old OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 cipher suite.
@swankjesse going to update docs to point to instructions, this is only going to get more painful over time
@swankjesse
Oddly it uses the same cipher suite with User-Agent: okhttp/3.12.0
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_1_2
Most helpful comment
Guys, thanks for help!
I have fixed this by adding
to my App.onCreate() Important
updateAndroidSecurityProvider()invocation must be before OkHttpClient initializationSuccessful Handshake on
4.7.1return:To reproduce this Exception I have used this method:
I have tested it on this emulator: