Okhttp: OkHttp 3.10.0 breaks TLS handling on Android 4.*

Created on 8 Jun 2018  路  14Comments  路  Source: square/okhttp

Probably related to: https://github.com/square/okhttp/issues/4042
Works as charm on Android 5 and up, but...

Device:

2 devices with Android:
Sony E2003 4.4.4
Samsung GT-I9506 4.4.2

Setup:

okHttpVersion = '3.10.0'
retrofitVersion = '2.4.0'
implementation "com.squareup.okhttp3:okhttp:$okHttpVersion"
implementation "com.squareup.okhttp3:logging-interceptor:$okHttpVersion"
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"
implementation "com.squareup.retrofit2:converter-scalars:$retrofitVersion"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"

This is working for

okHttpVersion = '3.9.1'
retrofitVersion = '2.3.0'

but it looks like the reason is okhttpVersion='3.10.0' (also in retrofit 2.4.0 dependencies)

Stacktrace part:

 Cannot establish TLS with new.services.tv.nu:443 (sni: {OUR_SERVER_ADDRESS}: TlsException("SSL handshake error: Error([('SSL routines', 'SSL23_GET_SERVER_HELLO', 'sslv3 alert handshake failure')],)",)

Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7b7ce0c8: Failure in SSL library, usually a protocol error

I expect failure lies within Cipher Suites scope:
version = 3.10.0
Client supported

TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV

Server Chosen


version = 3.9.1

TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - Server Chosen
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV

Server Chosen


android

Most helpful comment

No further action for us to take on this.

Best fix: change your server鈥檚 TLS configuration to support one of the 5 good Android 4.x cipher suites (above).

Workaround: customize cipher suites to restore legacy behavior:

    // Necessary because our servers don't have the right cipher suites.
    // https://github.com/square/okhttp/issues/4053
    List<CipherSuite> cipherSuites = new ArrayList<>();
    cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
    cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
    cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);

    ConnectionSpec legacyTls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
        .cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
        .build();

    OkHttpClient client = new OkHttpClient.Builder()
        .connectionSpecs(Arrays.asList(legacyTls, ConnectionSpec.CLEARTEXT))
        .build();

All 14 comments

Can confirm, that this issue exists in 10 version. And none of available workarounds didn't help.

Would the GMS provider help you here? The reason for reducing old ciphers and protocols is that they are not secure and shouldn't be used.

https://developer.android.com/training/articles/security-gms-provider

We have the same issue on Android 4. Is there any known workaround?

@florianreinhart only downgrading into 9 version helps me. You can try using GMS provider. It will work on 4.4. But user need have installed Google Play Services and this "hack" may not work on systems that <4.4.

You can manually enable the legacy ciphers suites by creating a custom ConnectionSpec.

// Add legacy cipher suite for Android 4
List<CipherSuite> cipherSuites = ConnectionSpec.MODERN_TLS.cipherSuites();
if (!cipherSuites.contains(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)) {
    cipherSuites = new ArrayList(cipherSuites);
    cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
}
final ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
        .cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
        .build();

OkHttpClient client = new OkHttpClient.Builder()
        .connectionSpecs(Collections.singletonList(spec))
        .build();

If it's easy for anyone here, could you test with a snapshot build? https://oss.jfrog.org/artifactory/libs-snapshot/com/squareup/okhttp3/okhttp/3.11.0-SNAPSHOT/

It theoretically supports TLS1.2 on Android back to 4.1. I'd love confirmation that is really the case.

https://github.com/square/okhttp/pull/4089/files

In order to support OkHttp 3.10 + Android 4.x your server needs to support one of these cipher suites:

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA

More details on the spreadsheet! http://tinyurl.com/okhttp-cipher-suites

No further action for us to take on this.

Best fix: change your server鈥檚 TLS configuration to support one of the 5 good Android 4.x cipher suites (above).

Workaround: customize cipher suites to restore legacy behavior:

    // Necessary because our servers don't have the right cipher suites.
    // https://github.com/square/okhttp/issues/4053
    List<CipherSuite> cipherSuites = new ArrayList<>();
    cipherSuites.addAll(ConnectionSpec.MODERN_TLS.cipherSuites());
    cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
    cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);

    ConnectionSpec legacyTls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
        .cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
        .build();

    OkHttpClient client = new OkHttpClient.Builder()
        .connectionSpecs(Arrays.asList(legacyTls, ConnectionSpec.CLEARTEXT))
        .build();

@swankjesse So OkHttp versioning does not follow semver? I鈥檇 consider this a breaking change.

@florianreinhart specifically with HTTPS, OkHttp tries to stay current with the dynamic TLS ecosystem it interacts with. We retire obsolete cipher suites tracking major browsers. Details on our reasoning are here: https://github.com/square/okhttp/wiki/HTTPS

@Swirastlynn looks like cloudflare cdn not supporting any of this ciphers.

@stalkerg have you tested with 3.11? I'm curious whether the additional TLS 1.2 support helps here.

@yschimke I still need to use hack with custom SSLSocketFactory
Your fix does not work for Android older than 5.0

@PromanSEW Any working solution for Android < 5? i had to downgrade to 3.8.0

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yschimke picture yschimke  路  3Comments

sargunv picture sargunv  路  3Comments

HyakYegoryaln picture HyakYegoryaln  路  3Comments

yschimke picture yschimke  路  3Comments

yschimke picture yschimke  路  3Comments