I have an application that I want to use on the emulator for testing purposes. I'm using the emulator/platform/system image in API level 19 with x86 ABI and Google APIs.
The app needs to POST some data to an HTTPS enabled server. The certificate is provided by Let's Encrypt and is signed by the X3 CA.
I have the following error when trying to make the request:
Couldn't execute API call retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall@b0fdfbd8 (Request{method=POST, url=https://hostname.net/api/session, tag=null})
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb80589b0: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0xa90ed990:0x00000000)
at: com.android.org.conscrypt.OpenSSLSocketImpl startHandshake (OpenSSLSocketImpl.java:448)
at: okhttp3.internal.connection.RealConnection connectTls (RealConnection.java:299)
at: okhttp3.internal.connection.RealConnection establishProtocol (RealConnection.java:268)
at: okhttp3.internal.connection.RealConnection connect (RealConnection.java:160)
at: okhttp3.internal.connection.StreamAllocation findConnection (StreamAllocation.java:256)
at: okhttp3.internal.connection.StreamAllocation findHealthyConnection (StreamAllocation.java:134)
at: okhttp3.internal.connection.StreamAllocation newStream (StreamAllocation.java:113)
at: okhttp3.internal.connection.ConnectInterceptor intercept (ConnectInterceptor.java:42)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:147)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:121)
at: okhttp3.internal.cache.CacheInterceptor intercept (CacheInterceptor.java:93)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:147)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:121)
at: okhttp3.internal.http.BridgeInterceptor intercept (BridgeInterceptor.java:93)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:147)
at: okhttp3.internal.http.RetryAndFollowUpInterceptor intercept (RetryAndFollowUpInterceptor.java:125)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:147)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:121)
at: com.redacted.backend.SessionInterceptor intercept (SessionInterceptor.java:61)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:147)
at: okhttp3.internal.http.RealInterceptorChain proceed (RealInterceptorChain.java:121)
at: okhttp3.RealCall getResponseWithInterceptorChain (RealCall.java:200)
at: okhttp3.RealCall execute (RealCall.java:77)
at: retrofit2.OkHttpCall execute (OkHttpCall.java:180)
at: retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall execute (ExecutorCallAdapterFactory.java:91)
at: com.redacted.backend.Backend executeApiCall (Backend.java:139)
at: com.redacted.backend.Backend createSession (Backend.java:62)
at: com.redacted.viewmodel.LoginActivityViewModel$1 run (LoginActivityViewModel.java:50)
at: java.util.concurrent.ThreadPoolExecutor runWorker (ThreadPoolExecutor.java:1112)
at: java.util.concurrent.ThreadPoolExecutor$Worker run (ThreadPoolExecutor.java:587)
at: java.lang.Thread run (Thread.java:841)
So I figured that the emulator had an outdated CA bundle, so I uploaded a new one generated following these instructions:
This is a custom script but it should be straightforward. $device
contains the emulator name, such as emulator-5554
.
echo "Download lets encrypt X3 CA cert"
[ -f X3.pem ] && rm X3.pem
wget -O X3.pem https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt || fail "Unable to download LE X3 CA cert"
echo "Encode CA cert to emulator format"
filename="$(openssl x509 -in X3.pem -hash -noout).0"
openssl x509 -in X3.pem >$filename
openssl x509 -in X3.pem -text -fingerprint -noout >>$filename
echo "Push encoded CA cert to $device"
$adb -s $device root || fail "Unable to access emulator '$device' as root"
$adb -s $device remount || fail "Unable to remount RW the emulator '$device'"
$adb -s $device push $filename /system/etc/security/cacerts/ || fail "Unable to push encoded CA cert to '$device'"
The file was indeed pushed, but I still have the same error message in the logs.
Is there a way to update the CA certs on the emulator?
More information:
- server uses TLS v1.2
- I even added the server certificate (not its CA) in the
cacerts
folder of the emulator, same result