Loading core/res/AndroidManifest.xml +20 −6 Original line number Diff line number Diff line Loading @@ -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 --> <!-- ========================================= --> Loading Loading @@ -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="*/*" /> Loading services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java +3 −54 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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..."); Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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; Loading Loading
core/res/AndroidManifest.xml +20 −6 Original line number Diff line number Diff line Loading @@ -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 --> <!-- ========================================= --> Loading Loading @@ -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="*/*" /> Loading
services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java +3 −54 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading @@ -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..."); Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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; Loading