Loading keystore/java/android/security/AndroidKeyStoreMaintenance.java +20 −0 Original line number Diff line number Diff line Loading @@ -229,4 +229,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."); } } } services/core/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -169,7 +169,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", Loading services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +45 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -67,6 +70,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ApexManager; import com.android.server.recoverysystem.hal.BootControlHIDL; import com.android.server.utils.Slogf; import libcore.io.IoUtils; Loading Loading @@ -118,6 +122,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; Loading Loading @@ -521,18 +527,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 Loading Loading
keystore/java/android/security/AndroidKeyStoreMaintenance.java +20 −0 Original line number Diff line number Diff line Loading @@ -229,4 +229,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."); } } }
services/core/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -169,7 +169,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", Loading
services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +45 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -67,6 +70,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ApexManager; import com.android.server.recoverysystem.hal.BootControlHIDL; import com.android.server.utils.Slogf; import libcore.io.IoUtils; Loading Loading @@ -118,6 +122,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; Loading Loading @@ -521,18 +527,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 Loading