Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android 4.4.2 SSL handshake aborted

Tags:

Code works on my Genymotion Android 4.4.4 emulator but not on the device i'm using (4.4.2).

I've tried lots of "trust all certificate" workarounds but to no avail (I don't think this is the issue anyway, as the certificate is AOK).

I think I have identified the cipher (using a wireshark trace from my desktop); TLS 0x00 0x1E which appears to be somewhat rare?

Any idea how to fix?

Here's my code

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); CloseableHttpClient client = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build(); String baseURL = "https://mysite.co.uk/api/"; HttpGetHC4 request = new HttpGetHC4(baseURL + "/authenticate?user=abcd&password=1234"); CloseableHttpResponse response = client.execute(request); 

And error;

 javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6abff398: 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:744 0x684dfce0:0x00000000)      at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:449)      at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:340)      at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:281)      at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:124)      at org.apache.http.impl.conn.BasicHttpClientConnectionManager.connect(BasicHttpClientConnectionManager.java:322)      at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:373)      at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225)      at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)      at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)      at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)      at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:178)      at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)      at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)      at com.example.lee.printticket.Main$OrderAsyncTask.onPostExecute(Main.java:239)      at com.example.lee.printticket.Main$OrderAsyncTask.onPostExecute(Main.java:189)      at android.os.AsyncTask.finish(AsyncTask.java:632)      at android.os.AsyncTask.access$600(AsyncTask.java:177)      at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)      at android.os.Handler.dispatchMessage(Handler.java:102)      at android.os.Looper.loop(Looper.java:136)      at android.app.ActivityThread.main(ActivityThread.java:5017)      at java.lang.reflect.Method.invokeNative(Native Method)      at java.lang.reflect.Method.invoke(Method.java:515)      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)      at dalvik.system.NativeStart.main(Native Method)  Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6abff398: 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:744 0x684dfce0:0x00000000)      at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)      at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406)     ... 25 more 

EDIT

Trying using a different technique/library;

        RequestQueue queue = Volley.newRequestQueue(this);         String url ="https://mysite.co.uk/api/authenticate?user=abcd&password=1234";          // Request a string response from the provided URL.         StringRequest stringRequest = new StringRequest(Request.Method.GET, url,                 new Response.Listener<String>() {                     @Override                     public void onResponse(String response) {                         // Display the first 500 characters of the response string.                         Log.d("response: ", response);                     }                 }, new Response.ErrorListener() {             @Override             public void onErrorResponse(VolleyError error) {                 Log.d("response: ", error.toString());             }         });         // Add the request to the RequestQueue.         queue.add(stringRequest); 

Returns;

D/response:: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6ad51be0: Failure in SSL library, usually a protocol error D/response:: error:140740B5:SSL routines:SSL23_CLIENT_HELLO:no ciphers available (external/openssl/ssl/s23_clnt.c:486 0x684dfce0:0x00000000) 

Or with the NoSSLv3SocketFactory hack from Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: Failure in SSL library, usually a protocol error;

        HttpStack stack = new HurlStack(null, new NoSSLv3SocketFactory());         RequestQueue queue = Volley.newRequestQueue(this, stack); 

Returns;

D/response:: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6ae51d30: Failure in SSL library, usually a protocol error D/response:: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x684dfce0:0x00000000) 
like image 330
Lee Tickett Avatar asked Dec 28 '15 12:12

Lee Tickett


People also ask

Why do we get SSL handshake exception?

SSL Handshake Failed is an error message that occurs when the client or server wasn't able to establish a secure connection. This might occur if: The client is using the wrong date or time. The client is a browser and its specific configuration is causing the error.

What is javax net SSL SSLProtocolException?

javax.net.ssl.SSLProtocolException. Reports an error in the operation of the SSL protocol. Normally this indicates a flaw in one of the protocol implementations.


1 Answers

Android uses different protocols for network operations.

Default configuration for different Android versions.

I found solution for OkHttpClient.

Protocol    Supported (API Levels)  Enabled by default (API Levels)  SSLv3       1–25                    1–22 TLSv1       1+                      1+ TLSv1.1     16+                     20+ TLSv1.2     16+                     20+ 

So we have to change Protocol for connection in Android VERSION >= 16 & VERSION < 22.

Create java file Tls12SocketFactory.java

/**  * Enables TLS v1.2 when creating SSLSockets.  * <p/>  * For some reason, android supports TLS v1.2 from API 16, but enables it by  * default only from API 20.  * @link https://developer.android.com/reference/javax/net/ssl/SSLSocket.html  * @see SSLSocketFactory  */ public class Tls12SocketFactory extends SSLSocketFactory {     private static final String[] TLS_V12_ONLY = {"TLSv1.2"};      final SSLSocketFactory delegate;      public Tls12SocketFactory(SSLSocketFactory base) {         this.delegate = base;     }      @Override     public String[] getDefaultCipherSuites() {         return delegate.getDefaultCipherSuites();     }      @Override     public String[] getSupportedCipherSuites() {         return delegate.getSupportedCipherSuites();     }      @Override     public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {         return patch(delegate.createSocket(s, host, port, autoClose));     }      @Override     public Socket createSocket(String host, int port) throws IOException, UnknownHostException {         return patch(delegate.createSocket(host, port));     }      @Override     public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {         return patch(delegate.createSocket(host, port, localHost, localPort));     }      @Override     public Socket createSocket(InetAddress host, int port) throws IOException {         return patch(delegate.createSocket(host, port));     }      @Override     public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {         return patch(delegate.createSocket(address, port, localAddress, localPort));     }      private Socket patch(Socket s) {         if (s instanceof SSLSocket) {             ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY);         }         return s;     } } 

Put this method some where in your code.

public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) {         if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {             try {                 SSLContext sc = SSLContext.getInstance("TLSv1.2");                 sc.init(null, null, null);                 client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));                  ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)                         .tlsVersions(TlsVersion.TLS_1_2).build();                  List<ConnectionSpec> specs = new ArrayList<>();                 specs.add(cs);                 specs.add(ConnectionSpec.COMPATIBLE_TLS);                 specs.add(ConnectionSpec.CLEARTEXT);                  client.connectionSpecs(specs);             } catch (Exception exc) {                 Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);             }         }          return client;     }      public OkHttpClient getNewHttpClient() {         OkHttpClient.Builder client = new OkHttpClient.Builder().followRedirects(true).followSslRedirects(true)                 .retryOnConnectionFailure(true).cache(null).connectTimeout(5, TimeUnit.SECONDS)                 .writeTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS);          return enableTls12OnPreLollipop(client).build();     } 

Create OkHttp instance like below :

private OkHttpClient getNewHttpClient() {     OkHttpClient.Builder client = new OkHttpClient.Builder()             .followRedirects(true)             .followSslRedirects(true)             .retryOnConnectionFailure(true)             .cache(null)             .connectTimeout(5, TimeUnit.SECONDS)             .writeTimeout(5, TimeUnit.SECONDS)             .readTimeout(5, TimeUnit.SECONDS);      return enableTls12OnPreLollipop(client).build(); } 

Use client object like this:

OkHttpClient client = getNewHttpClient(); Request.Builder requestBuilder = new Request.Builder(); URL url = new URL("YOUR_URL_LINK"); Request request = requestBuilder.url(url).build(); Call call = client.newCall(request); Response response = call.execute(); 

THANKS

like image 149
user9453341 Avatar answered Sep 28 '22 04:09

user9453341