diff options
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 |