SSL Handshake aborted in Android Emulator

1

I am using Nexus 5X (API level 27) as my emulator for React Native app. I'm trying to have it connect to my java server using SSLSockets, but right after connecting it gives me error: Handshake failed

SSL handshake aborted: ssl=0x9613a1c0: Failure in SSL library, usually a protocol error
error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/tls_record.cc:579 0x9679afc0:0x00000001)
error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/handshake_client.cc:893 0xa43b3dc3:0x00000000)
invoke        JavaMethodWrapper.java:383
invoke        JavaModuleWrapper.java:160
run        NativeRunnable.java
handleCallback        Handler.java:790
dispatchMessage        Handler.java:99
dispatchMessage        MessageQueueThreadHandler.java:29
loop        Looper.java:164
run        MessageQueueThreadImpl.java:192
run        Thread.java:764*

For a while I thought it was using SSLv3, because of the error message, but after examining the connection in Wireshark I noticed it was actually TLSv1.2. Then I tried to enforce specific cipher suites for both server and android client without luck. Writing a custom SocketFactory class didn't help either.

I have found another question which might be related to my problem: SSLHandshakeException: Handshake failed on Android N/7.0. I'm still fairly confident that my issue has something to do with the supported cipher suites and/or elliptic-curve cryptography.

Android client code

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket connection = (SSLSocket) factory.createSocket("127.0.0.1", 4192);

connection.setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
connection.setUseClientMode(true);

DataOutputStream output = new DataOutputStream(connection.getOutputStream());
DataInputStream input = new DataInputStream(connection.getInputStream());

String[] cipher_suites = connection.getSupportedCipherSuites();
connection.setEnabledCipherSuites(cipher_suites);

connection.startHandshake();

Server code

SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(4192, 1);

SSLSocket connection = (SSLSocket) server.accept();

DataInputStream input = new DataInputStream(connection.getInputStream());
DataOutputStream output = new DataOutputStream(connection.getOutputStream());

connection.setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});

String[] cipher_suites = connection.getSupportedCipherSuites();
connection.setEnabledCipherSuites(cipher_suites);

connection.startHandshake();

The server itself works fine and can be connected from a different computer with the exact same code. It runs on openjdk 10.0.1. Same version with android. Interestingly in the release notes it says:

security-libs/javax.net.ssl 3DES Cipher Suites Disabled To improve the strength of SSL/TLS connections, 3DES cipher suites have been disabled in SSL/TLS connections in the JDK via the jdk.tls.disabledAlgorithms Security Property.

The android version is 8.1 in the emulator, I've also tested it with 7.0 on physical device. The error message is all the same. Has anyone else ever encountered this problem before?

Captured Cipher Suites

These are the cipher suites, and the confirmed TLS version, I received with the Client Hello

Version: TLS 1.2 (0x0303)
Cipher Suites (14 suites)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)

Followed by the Handshake Failure alert:

TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
    Content Type: Alert (21)
    Version: TLS 1.2 (0x0303)
    Length: 2
    Alert Message
        Level: Fatal (2)
        Description: Handshake Failure (40)
java
android
ssl
asked on Stack Overflow Aug 7, 2018 by Guy Fawkes • edited Aug 7, 2018 by Guy Fawkes

1 Answer

1

I got it working, at last. The problem was that I had created my keystore file with wrong algorithm. I used keytool to create a new store with -keyalg RSA and now my server is able to use common RSA ciphers with the client.

answered on Stack Overflow Sep 3, 2018 by Guy Fawkes

User contributions licensed under CC BY-SA 3.0