diff options
5 files changed, 53 insertions, 5 deletions
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index 92fecaddff22..bbc936d76e1c 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -193,4 +193,5 @@ interface IStorageManager { 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 90b0c11cc8dd..39ad3546e452 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2788,6 +2788,24 @@ class StorageManagerService extends IStorageManager.Stub } /* + * 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 3e039878e9ef..288484fdee01 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -1510,7 +1510,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (credential != null) { Slog.wtf(TAG, "CredentialType is none, but credential is non-null."); } - clearUserKeyProtection(userId); + clearUserKeyProtection(userId, null); getGateKeeperService().clearSecureUserId(userId); mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId); setKeystorePassword(null, userId); @@ -1687,9 +1687,17 @@ public class LockSettingsService extends ILockSettings.Stub { addUserKeyAuth(userId, token, secretFromCredential(credential)); } - private void clearUserKeyProtection(int userId) throws RemoteException { + 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(byte[] credential) throws RemoteException { @@ -2511,7 +2519,7 @@ public class LockSettingsService extends ILockSettings.Stub { setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); setKeystorePassword(auth.deriveKeyStorePassword(), userId); } else { - clearUserKeyProtection(userId); + clearUserKeyProtection(userId, null); setKeystorePassword(null, userId); getGateKeeperService().clearSecureUserId(userId); } @@ -2686,7 +2694,7 @@ public class LockSettingsService extends ILockSettings.Stub { // 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 842cdd5715f9..2aaf7595dce7 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -215,6 +215,18 @@ public abstract class BaseLockSettingsServiceTests { } }).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 1ae1fa65ddf2..102bac111ada 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 @@ public class FakeStorageManager { 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); |