Skip to content

Commit

Permalink
RESTRICT AUTOMERGE Delete keystore keys from RecoveryService.rebootRe…
Browse files Browse the repository at this point in the history
…coveryWithCommand()

Adds deleteSecrets() to RecoverySystemService. This method is called
from rebootRecoveryWithCommand () before the --wipe_data command is
passed to recovery and the device is force-rebooted.

deleteSecerts() calls IKeystoreMaintenance.deleteAllKeys() in order to
quickly destroy the keys protecting the synthetic password blobs
used to derive FBE encryption keys.

The intent is to make FBE-encrypted data unrecoverable even if the full
data wipe in recovery is interrupted or skipped.

Bug: 324321147
Test: Manual - System -> Reset options -> Erase all data.
Test: Hold VolDown key to interrupt reboot and stop at bootloader
screen.
Test: fastboot oem bcd wipe command && fastboot oem bcd wipe recovery
Test: fastboot reboot
Test: Device reboots into recovery and prompts to factory reset:
Test: 'Cannot load Android system. Your data may be corrupt. ...'
(cherry picked from https://android-review.googlesource.com/q/commit:0d00031851e9f5d8ef93947205a7e8b5257f0d8d)
Ignore-AOSP-First: Security fix backport
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dfbaa7295390de97ae2e8b154cc9be5512108ac4)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d020a38e4148a642e2f06363e27cce60097efa5d)
Merged-In: I5eb8e97f3ae1a18d5e7e7c2c7eca048ebff3440a
Change-Id: I5eb8e97f3ae1a18d5e7e7c2c7eca048ebff3440a
  • Loading branch information
nelenkov authored and aoleary committed Sep 17, 2024
1 parent 566bbf0 commit 04f7bea
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
22 changes: 22 additions & 0 deletions keystore/java/android/security/AndroidKeyStoreMaintenance.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.StrictMode;
import android.security.maintenance.IKeystoreMaintenance;
import android.system.keystore2.Domain;
import android.system.keystore2.KeyDescriptor;
Expand Down Expand Up @@ -183,4 +185,24 @@ public static int migrateKeyNamespace(KeyDescriptor source, KeyDescriptor destin
return SYSTEM_ERROR;
}
}

/**
* 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.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.sysprop.ApexProperties;
import android.security.AndroidKeyStoreMaintenance;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.FastImmutableArraySet;
Expand All @@ -66,6 +67,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.ApexManager;
import com.android.server.utils.Slogf;

import libcore.io.IoUtils;

Expand Down Expand Up @@ -117,6 +119,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;

Expand Down Expand Up @@ -511,17 +515,32 @@ public boolean setupBcb(String command) {
@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)) {
return;
}

if (isForcedWipe) {
deleteSecrets();
}

// 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);
}
}

private void enforcePermissionForResumeOnReboot() {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
!= PackageManager.PERMISSION_GRANTED
Expand Down

0 comments on commit 04f7bea

Please sign in to comment.