Nathan H Nathan H - 4 months ago 55
Android Question

Has Android changed SSL configuration in API 24?

When my Android 23 project attempts to connect to my server via HTTPS, all is fine.

If I switch the target SDK to 24, I get the following error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
at android.net.SSLCertificateSocketFactory.verifyHostname(SSLCertificateSocketFactory.java:198)
at android.net.SSLCertificateSocketFactory.createSocket(SSLCertificateSocketFactory.java:443)
at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:394)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:170)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:366)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
at com.worklight.wlclient.WLRequestSender.run(WLRequestSender.java:47)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:563)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:444)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:508)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:508)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:401)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:375)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:304)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:178)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:596)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 13 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.


Switching back to 23 and it works again.

Has something changed in 24 regarding the minimum requirements for certificates?

Answer

User-installed certificates, via the Settings app, are not incorporated by default on Android 7.0 if your targetSdkVersion is 24+:

By default secure (e.g. TLS, HTTPS) connections from all apps trust the pre-installed system CAs, and apps targeting API level 23 (Android M) and below also trust the user-added CA store by default.

(from the network security configuration docs)

To work around that, you will need to define a network security configuration XML resource:

<?xml version="1.0" encoding="utf-8"?>

<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>

Then, point to that XML resource from your android:networkSecurityConfig attribute in your <application> element in your manifest.


In general, Android 7.0 routes HTTPS through the network security configuration subsystem (android.security.net.config.RootTrustManager and kin from your stack trace). It's possible that there are other compatibility issues introduced here that are tied to targetSdkVersion. So, if the lack of user certificates is not your issue, and you can create a sample project that reproduces the problem, file an issue. Since I maintain a backport of that stuff, I would be interested in knowing about any bugs. :-)