Loading core/java/android/os/storage/IStorageManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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; } services/core/java/com/android/server/StorageManagerService.java +18 −0 Original line number Diff line number Diff line Loading @@ -2787,6 +2787,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 */ Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +13 −5 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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); } Loading Loading @@ -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); Loading services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
core/java/android/os/storage/IStorageManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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; }
services/core/java/com/android/server/StorageManagerService.java +18 −0 Original line number Diff line number Diff line Loading @@ -2787,6 +2787,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 */ Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +13 −5 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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); } Loading Loading @@ -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); Loading
services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -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); Loading