summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystore/java/android/security/AndroidKeyStoreMaintenance.java20
-rw-r--r--services/core/Android.bp2
-rw-r--r--services/core/java/com/android/server/recoverysystem/RecoverySystemService.java45
3 files changed, 67 insertions, 0 deletions
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 2430e8d8e662..7821102b8459 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -243,4 +243,24 @@ public class AndroidKeyStoreMaintenance {
"Keystore error while trying to get apps affected by SID.");
}
}
+
+ /**
+ * Deletes all keys in all KeyMint devices.
+ * Called by RecoverySystem before rebooting to recovery in order to delete all KeyMint keys,
+ * including synthetic password protector keys (used by LockSettingsService), as well as keys
+ * protecting DE and metadata encryption keys (used by vold). This ensures that FBE-encrypted
+ * data is unrecoverable even if the data wipe in recovery is interrupted or skipped.
+ */
+ public static void deleteAllKeys() throws KeyStoreException {
+ StrictMode.noteDiskWrite();
+ try {
+ getService().deleteAllKeys();
+ } catch (RemoteException | NullPointerException e) {
+ throw new KeyStoreException(SYSTEM_ERROR,
+ "Failure to connect to Keystore while trying to delete all keys.");
+ } catch (ServiceSpecificException e) {
+ throw new KeyStoreException(e.errorCode,
+ "Keystore error while trying to delete all keys.");
+ }
+ }
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index d1d7ee7ba0e4..5fe4be72c036 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -213,7 +213,9 @@ java_library_static {
"android.hardware.health-V3-java", // AIDL
"android.hardware.health-translate-java",
"android.hardware.light-V1-java",
+ "android.hardware.security.authgraph-V1-java",
"android.hardware.security.rkp-V3-java",
+ "android.hardware.security.secretkeeper-V1-java",
"android.hardware.tv.cec-V1.1-java",
"android.hardware.tv.hdmi.cec-V1-java",
"android.hardware.tv.hdmi.connection-V1-java",
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 3c0547edbd92..c24240b92289 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -30,6 +30,7 @@ import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_
import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.apex.CompressedApexInfo;
import android.apex.CompressedApexInfoList;
import android.content.Context;
@@ -37,6 +38,7 @@ import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.boot.IBootControl;
+import android.hardware.security.secretkeeper.ISecretkeeper;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Binder;
@@ -52,6 +54,7 @@ import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
+import android.security.AndroidKeyStoreMaintenance;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.FastImmutableArraySet;
@@ -68,6 +71,7 @@ import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
import com.android.server.recoverysystem.hal.BootControlHIDL;
+import com.android.server.utils.Slogf;
import libcore.io.IoUtils;
@@ -122,6 +126,8 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp";
static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count";
+ static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data";
+
private final Injector mInjector;
private final Context mContext;
@@ -525,18 +531,57 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
@Override // Binder call
public void rebootRecoveryWithCommand(String command) {
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+
+ boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND);
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
Slog.e(TAG, "rebootRecoveryWithCommand failed to setup BCB");
return;
}
+ if (isForcedWipe) {
+ deleteSecrets();
+ // TODO: consider adding a dedicated forced-wipe-reboot method to PowerManager and
+ // calling here.
+ }
+
// Having set up the BCB, go ahead and reboot.
PowerManager pm = mInjector.getPowerManager();
pm.reboot(PowerManager.REBOOT_RECOVERY);
}
}
+ private static void deleteSecrets() {
+ Slogf.w(TAG, "deleteSecrets");
+ try {
+ AndroidKeyStoreMaintenance.deleteAllKeys();
+ } catch (android.security.KeyStoreException e) {
+ Log.wtf(TAG, "Failed to delete all keys from keystore.", e);
+ }
+
+ try {
+ ISecretkeeper secretKeeper = getSecretKeeper();
+ if (secretKeeper != null) {
+ Slogf.i(TAG, "ISecretkeeper.deleteAll();");
+ secretKeeper.deleteAll();
+ }
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Failed to delete all secrets from secretkeeper.", e);
+ }
+ }
+
+ private static @Nullable ISecretkeeper getSecretKeeper() {
+ ISecretkeeper result = null;
+ try {
+ result = ISecretkeeper.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(ISecretkeeper.DESCRIPTOR + "/default"));
+ } catch (SecurityException e) {
+ Slog.w(TAG, "Does not have permissions to get AIDL secretkeeper service");
+ }
+
+ return result;
+ }
+
private void enforcePermissionForResumeOnReboot() {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
!= PackageManager.PERMISSION_GRANTED