I am working on an application that is making various requests to a server. When my phone was running android 6, the application was able to make requests to the server, but upon updating to Android 7, it fails to perform the handshake with the server.
On my Nexus 5x, LogCat produces the following stack trace when calling the getInputStream()
method on an HttpURLConnection
:
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
at com.android.okhttp.Connection.connectTls(Connection.java:235)
at com.android.okhttp.Connection.connectSocket(Connection.java:199)
at com.android.okhttp.Connection.connect(Connection.java:172)
at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:130)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:405)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:243)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java)
at api.mynewleafapi.webapi.MNLStatics$override.getBackgroundForTree(MNLStatics.java:229)
at api.mynewleafapi.webapi.MNLStatics$override.access$dispatch(MNLStatics.java)
at api.mynewleafapi.webapi.MNLStatics.getBackgroundForTree(MNLStatics.java:0)
at com.android.mynewleaf.recov.ui.fragment.usermain.UserMainProfileViewFragment$2.run(UserMainProfileViewFragment.java:146)
Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed
... 17 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x786ae841c0: Failure in SSL library, usually a protocol error
error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x786ae12de0:0x00000001)
error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x786880dfce:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 16 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x786ae841c0: Failure in SSL library, usually a protocol error
error:100000af:SSL routines:OPENSSL_internal:NO_CIPHERS_AVAILABLE (external/boringssl/src/ssl/s3_clnt.c:624 0x786880dfce:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 16 more
Which is affirming that the handshake is failing. I know the patricular server with which I'm connecting is using TLS_ECDHE_ECDSA_WITH_AES_128_GCM
, which is in the list of supported cipher suites that I get from asking for String[] array = factory.getDefaultCipherSuites();
. I've been able to reproduce this issue on ther devices running Android 7, but the issue doesn't appear on Android 6 and below. How can this be fixed?
You can refer to the following link to understand: https://developer.android.com/about/versions/nougat/android-7.0-changes.html#other
Android 7.0 makes the following changes to the default TLS/SSL configuration used by apps for HTTPS and other TLS/SSL traffic:
RC4 cipher suites are now disabled. CHACHA20-POLY1305 cipher suites are now enabled. RC4 being disabled by default may lead to breakages in HTTPS or TLS/SSL connectivity when the server does not negotiate modern cipher suites. The preferred fix is to improve the server’s configuration to enable stronger and more modern cipher suites and protocols. Ideally, TLSv1.2 and AES-GCM should be enabled, and Forward Secrecy cipher suites (ECDHE) should be enabled and preferred.
An alternative is to modify the app to use a custom SSLSocketFactory to communicate with the server. The factory should be designed to create SSLSocket instances that have some of the cipher suites required by the server enabled in addition to default cipher suites.