Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df0db7fe authored by Ben Gruver's avatar Ben Gruver Committed by Android (Google) Code Review
Browse files

Merge "Don't verify signatures in ConfigUpdateInstallReceiver"

parents fcfff284 12964bf5
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -1636,6 +1636,14 @@
        android:protectionLevel="signature" />
    <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>

    <!-- Allows an application to initiate configuration updates
         <p>An application requesting this permission is responsible for
         verifying the source and integrity of any update before passing
         it off to the various individual installer components
         @hide -->
    <permission android:name="android.permission.UPDATE_CONFIG"
        android:protectionLevel="signature|system" />

    <!-- ========================================= -->
    <!-- Permissions for special development tools -->
    <!-- ========================================= -->
@@ -2556,42 +2564,48 @@
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.CertPinInstallReceiver" >
        <receiver android:name="com.android.server.updates.CertPinInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_PINS" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver" >
        <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver" >
        <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver" >
        <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.TzDataInstallReceiver" >
        <receiver android:name="com.android.server.updates.TzDataInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_TZDATA" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver" >
        <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver"
                android:permission="android.permission.UPDATE_CONFIG">
            <intent-filter>
                <action android:name="android.intent.action.UPDATE_SEPOLICY" />
                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+3 −54
Original line number Diff line number Diff line
@@ -16,29 +16,21 @@

package com.android.server.updates;

import com.android.server.EventLogTags;

import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.util.Base64;
import android.util.EventLog;
import android.util.Slog;

import com.android.server.EventLogTags;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;

import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -48,11 +40,8 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
    private static final String TAG = "ConfigUpdateInstallReceiver";

    private static final String EXTRA_REQUIRED_HASH = "REQUIRED_HASH";
    private static final String EXTRA_SIGNATURE = "SIGNATURE";
    private static final String EXTRA_VERSION_NUMBER = "VERSION";

    private static final String UPDATE_CERTIFICATE_KEY = "config_update_certificate";

    protected final File updateDir;
    protected final File updateContent;
    protected final File updateVersion;
@@ -71,16 +60,12 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
            @Override
            public void run() {
                try {
                    // get the certificate from Settings.Secure
                    X509Certificate cert = getCert(context.getContentResolver());
                    // get the content path from the extras
                    byte[] altContent = getAltContent(context, intent);
                    // get the version from the extras
                    int altVersion = getVersionFromIntent(intent);
                    // get the previous value from the extras
                    String altRequiredHash = getRequiredHashFromIntent(intent);
                    // get the signature from the extras
                    String altSig = getSignatureFromIntent(intent);
                    // get the version currently being used
                    int currentVersion = getCurrentVersion();
                    // get the hash of the currently used value
@@ -90,10 +75,6 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
                    } else if (!verifyPreviousHash(currentHash, altRequiredHash)) {
                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
                                            "Current hash did not match required value");
                    } else if (!verifySignature(altContent, altVersion, altRequiredHash, altSig,
                               cert)) {
                        EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
                                            "Signature did not verify");
                    } else {
                        // install the new content
                        Slog.i(TAG, "Found new update, installing...");
@@ -114,20 +95,6 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        }.start();
    }

    private X509Certificate getCert(ContentResolver cr) {
        // get the cert from settings
        String cert = Settings.Secure.getString(cr, UPDATE_CERTIFICATE_KEY);
        // convert it into a real certificate
        try {
            byte[] derCert = Base64.decode(cert.getBytes(), Base64.DEFAULT);
            InputStream istream = new ByteArrayInputStream(derCert);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            return (X509Certificate) cf.generateCertificate(istream);
        } catch (CertificateException e) {
            throw new IllegalStateException("Got malformed certificate from settings, ignoring");
        }
    }

    private Uri getContentFromIntent(Intent i) {
        Uri data = i.getData();
        if (data == null) {
@@ -152,14 +119,6 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        return extraValue.trim();
    }

    private String getSignatureFromIntent(Intent i) {
        String extraValue = i.getStringExtra(EXTRA_SIGNATURE);
        if (extraValue == null) {
            throw new IllegalStateException("Missing required signature, ignoring.");
        }
        return extraValue.trim();
    }

    private int getCurrentVersion() throws NumberFormatException {
        try {
            String strVersion = IoUtils.readFileAsString(updateVersion.getCanonicalPath()).trim();
@@ -215,16 +174,6 @@ public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
        return current.equals(required);
    }

    private boolean verifySignature(byte[] content, int version, String requiredPrevious,
                                   String signature, X509Certificate cert) throws Exception {
        Signature signer = Signature.getInstance("SHA512withRSA");
        signer.initVerify(cert);
        signer.update(content);
        signer.update(Long.toString(version).getBytes());
        signer.update(requiredPrevious.getBytes());
        return signer.verify(Base64.decode(signature.getBytes(), Base64.DEFAULT));
    }

    protected void writeUpdate(File dir, File file, byte[] content) throws IOException {
        FileOutputStream out = null;
        File tmp = null;