question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SSL Handshake failure in Android 10

See original GitHub issue

Android 10 throws exception in SSL Handshaking both in emulators and Pixel devices. The same code works for Android 9 and before. Steps to reproduce:

  1. Create a Private Public Key Pair. KeyPairGenerator kpg = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_RSA);

         kpg.initialize(new KeyGenParameterSpec.Builder(
                 CLIENT_KEY_ALIAS,
                 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                 .setDigests(KeyProperties.DIGEST_NONE)
                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
                 .build());
    
         KeyPair keyPair = kpg.generateKeyPair();
         return keyPair;
    
  2. Send public key to server and receives client certiricates, and store it in Android Keystore. As well as store Root Server certificate.

         CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    
         X509Certificate[] clientCertArray = new X509Certificate[clientCertArrayFinal.length];
         i = 0;
    
         for (String indCert : clientCertArrayFinal) {
             X509Certificate clientCertFromApi = (X509Certificate) certificateFactory.generateCertificate(new
             ByteArrayInputStream(indCert.getBytes()));
             clientCertArray[i++] = clientCertFromApi;
         }
    
         PrivateKey privateKeyClient = iPrivateKeyClient;
    
         InputStream inServer = iContext.getResources().openRawResource(R.raw.mrca);
         X509Certificate serverCert = (X509Certificate) certificateFactory.generateCertificate(inServer);
    
         KeyStore androidKeyStore = KeyStore.getInstance(CertificateManager.ANDROID_KEYSTORE);
         androidKeyStore.load(null);
    
         androidKeyStore.setCertificateEntry(CertificateManager.SERVER_CERT_ALIAS, serverCert);  //Server cert
         androidKeyStore.setKeyEntry(CertificateManager.CLIENT_KEY_ALIAS, privateKeyClient, null, clientCertArray); //Client cert, can be opened using private key
    
  3. Using Trustmananger to create SSLContext

         KeyStore androidKeyStore = KeyStore.getInstance(CertificateManager.ANDROID_KEYSTORE);
         androidKeyStore.load(null);
    
         TrustManagerFactory trustmanagerfactory =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         trustmanagerfactory.init(androidKeyStore);
         TrustManager[] trustManagers = trustmanagerfactory.getTrustManagers();
         KeyManagerFactory kmf = KeyManagerFactory
                 .getInstance(KeyManagerFactory.getDefaultAlgorithm());
         kmf.init(androidKeyStore, "".toCharArray());
    
         final SSLContext sslContext = SSLContext.getInstance("TLS");
         sslContext.init(kmf.getKeyManagers(), trustManagers, null);
    
  4. Start handshake with server: String server = “185.58.87.115”; SSLSocketFactory ssf = sslContext.getSocketFactory();

                     InetSocketAddress inetSocketAddress = new InetSocketAddress(server, 443);
    
                     SSLSocket socket = (SSLSocket) ssf.createSocket();
                     socket.connect(inetSocketAddress);
                     socket.setKeepAlive(true);
    
                     socket.addHandshakeCompletedListener(new HandshakeCompletedListener() {
                         @Override
                         public void handshakeCompleted(HandshakeCompletedEvent event) {
                             try {
                                 String principal = event.getPeerPrincipal().getName();
                                 Log.i(TAG, principal);
                                 Log.i(TAG, event.getCipherSuite().toString());
    
                             } catch (SSLPeerUnverifiedException e) {
                                 e.printStackTrace();
                             }
    
                         }
                     });
                     Thread.sleep(1000);
                     socket.startHandshake();      
    

The handshake failed with below exception:

`W/CryptoUpcalls: Preferred provider doesn’t support key: java.security.InvalidKeyException: Keystore operation failed at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1362) at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1402) at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54) at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89) at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265) at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109) at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984) at javax.crypto.Cipher.tryCombinations(Cipher.java:2891) at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796) at javax.crypto.Cipher.chooseProvider(Cipher.java:773) at javax.crypto.Cipher.init(Cipher.java:1143) at javax.crypto.Cipher.init(Cipher.java:1084) at com.android.org.conscrypt.CryptoUpcalls.rsaOpWithPrivateKey(CryptoUpcalls.java:173) at com.android.org.conscrypt.CryptoUpcalls.rsaSignDigestWithPrivateKey(CryptoUpcalls.java:132) at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387) at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:226) at asynctls.mimecast.com.asynctlsapp.MainActivity$1.run(MainActivity.java:352) at java.lang.Thread.run(Thread.java:919) Caused by: android.security.KeyStoreException: Incompatible padding mode at android.security.KeyStore.getKeyStoreException(KeyStore.java:1292) at android.security.KeyStore.getInvalidKeyException(KeyStore.java:1402) at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54) at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89) at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265) at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109) at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984) at javax.crypto.Cipher.tryCombinations(Cipher.java:2891) at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796) at javax.crypto.Cipher.chooseProvider(Cipher.java:773) at javax.crypto.Cipher.init(Cipher.java:1143) at javax.crypto.Cipher.init(Cipher.java:1084) at com.android.org.conscrypt.CryptoUpcalls.rsaOpWithPrivateKey(CryptoUpcalls.java:173) at com.android.org.conscrypt.CryptoUpcalls.rsaSignDigestWithPrivateKey(CryptoUpcalls.java:132) at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387) at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:226) at asynctls.mimecast.com.asynctlsapp.MainActivity$1.run(MainActivity.java:352) at java.lang.Thread.run(Thread.java:919)

W/CryptoUpcalls: Could not find provider for algorithm: RSA/ECB/NoPadding W/System.err: javax.net.ssl.SSLHandshakeException: Handshake failed W/System.err: at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:288) W/System.err: at asynctls.mimecast.com.asynctlsapp.MainActivity$1.run(MainActivity.java:351) W/System.err: at java.lang.Thread.run(Thread.java:919) W/System.err: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7dbcec0850c8: Failure in SSL library, usually a protocol error W/System.err: error:04000044:RSA routines:OPENSSL_internal:internal error (external/conscrypt/common/src/jni/main/cpp/conscrypt/native_crypto.cc:740 0x7dbce6155e73:0x00000000) W/System.err: at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) W/System.err: at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387) W/System.err: at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:226) W/System.err: … 2 more`

The app works fine with Pre Android 10 phone. Could you please look, this will block our app’s functionality completely.

Thanks,

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
nildekacommented, Sep 26, 2019

We are able to solve the problem. Adding setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) during RSA Key-pair generation solved the problem.

kpg.initialize(new KeyGenParameterSpec.Builder( CLIENT_KEY_ALIAS, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) .build());

Looks like conscrypt has changed internal implementation of Signing handshake data. It worked in Pre-Android 10, because it only does Signing with private key. But from Android 10, it encrypts data with private key. In our case it encrypts with RSA/ECB/NoPadding. After adding encryption padding during key pair genration solved the problem.

Thanks

0reactions
satur9ninecommented, Aug 19, 2020

@farble1670 This appears to be the commit that broke us: https://github.com/google/conscrypt/commit/80469b4a9eae1f51d1c7af42963c452eb2d35fcd

Our custom keystore only allowed Signature and not Cipher so after this change conscrypt cannot use our keystore to perform mutual TLS. Ouch.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Resolve an SSL Connection Error on Android Devices
7 Ways to Solve Your Android SSL Connection Error · 1. Correct the Date & Time on Your Device · 2. Clear Browsing...
Read more >
How to Fix SSL Connection Error On Android Devices?
How to Fix SSL Connection Error On Android? · Step #1. The correct date and time should be set · Step #2. The...
Read more >
SSLHandshakeException: Handshake failed on Android N/7.0
This is a known regression in Android 7.0, acknowledged by Google and fixed sometime before the release of Android 7.1.1. Here is the...
Read more >
How to Fix issue of SSL Handshake Exception on Android
How to Fix issue of SSL Handshake Exception on Android · The Certificate Authority (CA) that issued the server certificate was unknown. ·...
Read more >
How to Fix SSL Connection Error on Android Phone - SSL2BUY
This is the most common reason behind SSL certificate errors. If there's a mismatch between the clock on your device and the clock...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found