Merge "Provide secret to vold to remove credential"
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 92fecad..bbc936d 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -193,4 +193,5 @@
void startCheckpoint(int numTries) = 85;
boolean needsCheckpoint() = 86;
void abortChanges(in String message, boolean retry) = 87;
+ void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88;
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index bcc3bdb..c95d3e8 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2989,6 +2989,24 @@
}
/*
+ * Clear disk encryption key bound to the associated token / secret pair. Removing the user
+ * binding of the Disk encryption key is done in two phases: first, this call will retrieve
+ * the disk encryption key using the provided token / secret pair and store it by
+ * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
+ * is called to delete all other bindings of the disk encryption key.
+ */
+ @Override
+ public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
+ enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
+
+ try {
+ mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
+ } catch (Exception e) {
+ Slog.wtf(TAG, e);
+ }
+ }
+
+ /*
* Delete all disk encryption token/secret pairs except the most recently added one
*/
@Override
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 7233f34..baae4ea 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1622,7 +1622,7 @@
}
if (credential.isNone()) {
- clearUserKeyProtection(userId);
+ clearUserKeyProtection(userId, null);
gateKeeperClearSecureUserId(userId);
mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
// Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
@@ -1813,9 +1813,17 @@
addUserKeyAuth(userId, token, secretFromCredential(credential));
}
- private void clearUserKeyProtection(int userId) {
+ private void clearUserKeyProtection(int userId, byte[] secret) {
if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
- addUserKeyAuth(userId, null, null);
+ final UserInfo userInfo = mUserManager.getUserInfo(userId);
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ mStorageManager.clearUserKeyAuth(userId, userInfo.serialNumber, null, secret);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("clearUserKeyAuth failed user=" + userId);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
}
private static byte[] secretFromCredential(LockscreenCredential credential) {
@@ -2571,7 +2579,7 @@
setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
setKeystorePassword(auth.deriveKeyStorePassword(), userId);
} else {
- clearUserKeyProtection(userId);
+ clearUserKeyProtection(userId, null);
setKeystorePassword(null, userId);
gateKeeperClearSecureUserId(userId);
}
@@ -2765,7 +2773,7 @@
// during boot. Vold storage needs to be unlocked before manipulation of the keys can
// succeed.
unlockUserKey(userId, null, auth.deriveDiskEncryptionKey());
- clearUserKeyProtection(userId);
+ clearUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
fixateNewestUserKeyAuth(userId);
unlockKeystore(auth.deriveKeyStorePassword(), userId);
setKeystorePassword(null, userId);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index a3d15dd..1b5c56a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -230,6 +230,18 @@
}
}).when(sm).addUserKeyAuth(anyInt(), anyInt(), any(), any());
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ mStorageManager.clearUserKeyAuth((int) args[0] /* userId */,
+ (int) args[1] /* serialNumber */,
+ (byte[]) args[2] /* token */,
+ (byte[]) args[3] /* secret */);
+ return null;
+ }
+ }).when(sm).clearUserKeyAuth(anyInt(), anyInt(), any(), any());
+
doAnswer(
new Answer<Void>() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
index 1ae1fa6..102bac1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
@@ -36,6 +36,15 @@
getUserAuth(userId).add(new Pair<>(token, secret));
}
+ public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
+ ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
+ if (token == null && secret == null) {
+ return;
+ }
+ auths.remove(new Pair<>(token, secret));
+ auths.add(new Pair<>(null, null));
+ }
+
public void fixateNewestUserKeyAuth(int userId) {
ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId);
Pair<byte[], byte[]> latest = auths.get(auths.size() - 1);