Making SSLEngine use TLSv1.2 on Android (4.4.2)?
Asked Answered
J

3

26

Folks, I'm hoping there's something obvious that I'm missing, and I hope someone will be able to shed some light. I'm trying to get TLSv1.2 running in an SSL + NIO context (using the AndroidAsync library), so I'm trying to enable it via an SSLEngine. I can run code like this:

        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, null);
        String[] protocols = sslContext.getSupportedSSLParameters().getProtocols();
        for (String protocol : protocols) {
            Timber.d("Context supported protocol: " + protocol);
        }

        SSLEngine engine = sslContext.createSSLEngine();
        String[] supportedProtocols = engine.getSupportedProtocols();
        for (String protocol : supportedProtocols) {
            Timber.d("Engine supported protocol: " + protocol);
        }

And I end up seeing this on logcat:

06-22 21:56:27.715    1117-1117/? D/XXX﹕ Context supported protocol: SSLv3
06-22 21:56:27.715    1117-1117/? D/XXX﹕ Context supported protocol: TLSv1
06-22 21:56:27.725    1117-1117/? D/XXX﹕ Context supported protocol: TLSv1.1
06-22 21:56:27.725    1117-1117/? D/XXX﹕ Context supported protocol: TLSv1.2
06-22 21:56:27.735    1117-1117/? D/XXX﹕ Engine supported protocol: TLSv1
06-22 21:56:27.745    1117-1117/? D/XXX﹕ Engine supported protocol: SSLv3

Of course if I try to engine.setEnabledProtocols(new String[] { "TLSv1.2" }) I get an IllegalArgumentException "Protocol TLSv1.2 is not supported."

I can see the context claims to support TLSv1.2, but then the engine I make from that context doesn't? What's going on here? None of this changes if I use "TLS" instead of "TLSv1.2" in the first line above, btw.

I gather this might have something to do with this issue, and I've read this (as yet unanswered) question and articles like this, but they don't quite seem to be hitting the spot - solutions I've seen all seem to rely on SSLSocket rather than SSLEngine.

Thanks much for any knowledge you can drop.

UPDATE 6/23/14 10AMEDT

So I found SSLEngine.setSSLParameters, which I was hoping would let me pass in an SSLParameters that I got from SSLContext.getSupportedSSLParameters(), but when I call that I get an exception that claims the cipher suites aren't supported, so it looks like setSSLParameters() is just doing the same thing that setEnabledCipherSuites() does, and the engine is already in a state where it doesn't recognize the TLS 1.2 protocol/suites as supported.

Jarret answered 23/6, 2014 at 2:58 Comment(3)
What happens when you do sslContext.setEnabledProtocols(new String[] { "TLSv1.2" }), and then sslContext.createSSLEngine();?Forage
SSLContext doesn't have a setEnabledProtocols() API. However, I did just discover SSLEngine.setSSLParameters(). About to edit question.Jarret
Hi Glenn i am stuck up with this issue can u help me out ? #49946850Lashundalasker
N
64

The Android API docs correctly state that TLSv1.2 is only supported for SSLEngine in API Level 20 or later (Lollipop) while SSLSocket supports it since level 16.

Using SSLSocket or requiring API 20 was no option for our project and neither was changing the server code to allow TLSv1 or SSLv3. Our solution was to install a newer security provider using Google Play Services:

    ProviderInstaller.installIfNeeded(getApplicationContext());

This effectively gives your app access to a newer version of OpenSSL and Java Security Provider which includes support for TLSv1.2 in SSLEngine. Once the new provider is installed, you can create an SSLEngine which supports SSLv3, TLSv1, TLSv1.1 and TLSv1.2 the usual way:

    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(null, null, null);
    SSLEngine engine = sslContext.createSSLEngine();

Or you can restrict the enabled protocols using engine.setEnabledProtocols.

Nadda answered 27/10, 2014 at 11:13 Comment(6)
Hey thanks for the answer! That is not a thing we've tried yet, will attempt to do so in the next few days and then mark this accepted.Jarret
Hey there! How do we use this with the HttpsUrlConnection on Android?Squall
Man, You are awesome! ProviderInstaller.installIfNeeded(getApplicationContext()); that's why my app wasn't working on android from 4.0Schaub
Do you know if there is any way of testing this on an AVD with, for example, api 18? I've created an AVD with api 18 + Google Apis. In this case I see SSLEngine with TLS v1 and 3 available only. When I add the "ProviderInstaller" and google services dependancy, I get the Dialog to install the upgrade, but as it is an AVD I don't get passed that screen.Viscometer
Hey really You Saved me :) , Thanks A LOT!Germin
what actual package from the google play services did you use for this? There are about 20 packages available.Aluin
I
7

Try this solution if you are using okHttp. Solution for enabling TLSv1.2 on Android 4.4

Had the same issue on Android < 5.0 (16 <= API < 20). Thanks to your posts, I was able to make this work, so for anyone who gets here, this is the out-of-the-box solution. At the time of this writing, I'm using OkHttp 3.4.1.

Tags : Unable to find acceptable protocols, javax.net.ssl.SSLProtocolException: SSL handshake aborted:

Incompletion answered 9/2, 2017 at 8:0 Comment(1)
wow! its great its solve my problem i was tuck since 4 days, Thank you Wolfgang ProferLeilanileininger
R
3

Here is how to do in with AndroidAsync:

ProviderInstaller.installIfNeeded(context);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(KeyManager[] km, TrustManager[] tm, SecureRandom rm);
SSLEngine engine = sslContext.createSSLEngine();
AsyncHttpClient.getDefaultInstance().insertMiddleware((AsyncHttpClientMiddleware) engine); 

Updating SSLEngine and inserting it as middleware into AndroidAsync seems to work.

Reasoned answered 19/9, 2015 at 20:29 Comment(3)
It would be helpful to explain why this solution works, at least a paraphrase of your blog post.Settee
@JordanRéjaud where would context be passed in from?Hoyle
I think it might be better to set the SSLContext in Ion so: Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setSSLContext(sslContext);Prasad

© 2022 - 2024 — McMap. All rights reserved.