Skip to content

Certificate injection failure in Android 14 #114

Open
@MHBdev2

Description

@MHBdev2

I'm using Android 14 and want to inject a custom CA certificate
The device is rooted using magisk, so for a smooth operation that will be performed every restart, I put the following code in service.sh

API=`getprop ro.build.version.sdk`
if [ "$API" -ge 33 ]; then
while [ "$(getprop sys.boot_completed)" != 1 ];
do
   sleep 1
done
if [ -d "/apex/com.android.conscrypt/cacerts" ]; then
     cp /apex/com.android.conscrypt/cacerts/* /data/local/tmp/htk-ca-copy/
else
     cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
fi

# Create the in-memory mount on top of the system certs folder
su -mm -c mount -t tmpfs tmpfs /system/etc/security/cacerts

# Copy the existing certs back into the tmpfs mount, so we keep trusting them
mv /data/local/tmp/htk-ca-copy/* /system/etc/security/cacerts/

# Copy our new cert in, so we trust that too
cp /system/etc/cacustom/* /system/etc/security/cacerts/

# Update the perms & selinux context labels, so everything is as readable as before
chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*

echo 'System cacerts setup completed'

           # Create a separate temp directory, to hold the current certificates
             # Without this, when we add the mount we can't read the current certs anymore.

             # Deal with the APEX overrides in Android 14+, which need injecting into each namespace:
             if [ -d "/apex/com.android.conscrypt/cacerts" ]; then
              

                 # When the APEX manages cacerts, we need to mount them at that path too. We can't do
                 # this globally as APEX mounts are name-spaced per process, so we need to inject a
                 # bind mount for this directory into every mount namespace.

                 # First we get the Zygote process(es), which launch each app
                 ZYGOTE_PID=$(pidof zygote || true)
                 ZYGOTE64_PID=$(pidof zygote64 || true)
                 Z_PIDS="$ZYGOTE_PID $ZYGOTE64_PID"
                 # N.b. some devices appear to have both, some have >1 of each (!)

                 # Apps inherit the Zygote's mounts at startup, so we inject here to ensure everything is new
                 # started apps will see these certs straight away:
                 for Z_PID in $Z_PIDS; do
                     if [ -n "$Z_PID" ]; then
                         nsenter --mount=/proc/$Z_PID/ns/mnt -- \
                             /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
                     fi
                 done

              

                 # Then we inject the mount into all already running apps, so they see these certs immediately.

                 # Get the PID of every process whose parent is one of the Zygotes:
                 APP_PIDS=$(
                     echo $Z_PIDS | \
                     xargs -n1 ps -o 'PID' -P | \
                     grep -v PID
                 )

                 # Inject into the mount namespace of each of those apps:
                 for PID in $APP_PIDS; do
                     nsenter --mount=/proc/$PID/ns/mnt -- \
                         /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts &
                 done
                 wait # Launched in parallel - wait for completion here

               
             fi

It really seems that the personalized certificates enter the system but after a few seconds the device crashes (restarts)
This is the log at the moment of the crash

 !@*** FATAL EXCEPTION IN SYSTEM PROCESS: pool-246-thread-1
                                                                                                    java.lang.AssertionError
                                                                                                    	at com.android.okhttp.OkHttpClient.getDefaultSSLSocketFactory(OkHttpClient.java:649)
                                                                                                    	at com.android.okhttp.OkHttpClient.copyWithDefaults(OkHttpClient.java:605)
                                                                                                    	at com.android.okhttp.OkUrlFactory.open(OkUrlFactory.java:63)
                                                                                                    	at com.android.okhttp.OkUrlFactory.open(OkUrlFactory.java:58)
                                                                                                    	at com.android.okhttp.HttpHandler.openConnection(HttpHandler.java:56)
                                                                                                    	at java.net.URL.openConnection(URL.java:1006)
                                                                                                    	at com.android.server.location.gnss.GnssPsdsDownloader.doDownload(GnssPsdsDownloader.java:165)
                                                                                                    	at com.android.server.location.gnss.GnssPsdsDownloader.doDownloadWithTrafficAccounted(GnssPsdsDownloader.java:152)
                                                                                                    	at com.android.server.location.gnss.GnssPsdsDownloader.downloadPsdsData(GnssPsdsDownloader.java:129)
                                                                                                    	at com.android.server.location.gnss.GnssLocationProvider.lambda$handleDownloadPsdsData$6(GnssLocationProvider.java:909)
                                                                                                    	at com.android.server.location.gnss.GnssLocationProvider.$r8$lambda$JL2e1UXaMzOyFO9jVFmVGlpGR4o(GnssLocationProvider.java:0)
                                                                                                    	at com.android.server.location.gnss.GnssLocationProvider$$ExternalSyntheticLambda17.run(R8$$SyntheticClass:0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions