Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +25 −45 Original line number Diff line number Diff line Loading @@ -240,8 +240,7 @@ public class LockSettingsService extends ILockSettings.Stub { protected final UserManager mUserManager; private final IStorageManager mStorageManager; private final IActivityManager mActivityManager; @VisibleForTesting protected final SyntheticPasswordManager mSpManager; private final SyntheticPasswordManager mSpManager; private final java.security.KeyStore mJavaKeyStore; private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; Loading Loading @@ -946,7 +945,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (!isSyntheticPasswordBasedCredentialLocked(userId)) { Slogf.i(TAG, "Creating locksettings state for user %d now that boot " + "is complete", userId); initializeSyntheticPasswordLocked(userId); initializeSyntheticPassword(userId); } } } Loading Loading @@ -985,7 +984,7 @@ public class LockSettingsService extends ILockSettings.Stub { long protectorId = getCurrentLskfBasedProtectorId(userId); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId); initializeSyntheticPasswordLocked(userId); initializeSyntheticPassword(userId); } else { Slogf.i(TAG, "Existing unsecured user %d has a synthetic password; re-encrypting CE " + "key with it", userId); Loading Loading @@ -1652,13 +1651,7 @@ public class LockSettingsService extends ILockSettings.Stub { Objects.requireNonNull(savedCredential); if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId); synchronized (mSpManager) { if (!isSyntheticPasswordBasedCredentialLocked(userId)) { if (!savedCredential.isNone()) { throw new IllegalStateException("Saved credential given, but user has no SP"); } // TODO(b/232452368): this case is only needed by unit tests now; remove it. initializeSyntheticPasswordLocked(userId); } else if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { // get credential from keystore when profile has unified lock try { //TODO: remove as part of b/80170828 Loading Loading @@ -2322,9 +2315,7 @@ public class LockSettingsService extends ILockSettings.Stub { return; } removeStateForReusedUserIdIfNecessary(userId, userSerialNumber); synchronized (mSpManager) { initializeSyntheticPasswordLocked(userId); } initializeSyntheticPassword(userId); } } Loading Loading @@ -2650,9 +2641,9 @@ public class LockSettingsService extends ILockSettings.Stub { * until the time when Weaver is guaranteed to be available), or when upgrading from Android 13 * or earlier where users with no LSKF didn't necessarily have an SP. */ @GuardedBy("mSpManager") @VisibleForTesting SyntheticPassword initializeSyntheticPasswordLocked(int userId) { SyntheticPassword initializeSyntheticPassword(int userId) { synchronized (mSpManager) { Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId); Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) == SyntheticPasswordManager.NULL_PROTECTOR_ID, Loading @@ -2666,6 +2657,7 @@ public class LockSettingsService extends ILockSettings.Stub { onSyntheticPasswordKnown(userId, sp); return sp; } } @VisibleForTesting long getCurrentLskfBasedProtectorId(int userId) { Loading @@ -2680,13 +2672,6 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(LSKF_LAST_CHANGED_TIME_KEY, System.currentTimeMillis(), userId); } @VisibleForTesting boolean isSyntheticPasswordBasedCredential(int userId) { synchronized (mSpManager) { return isSyntheticPasswordBasedCredentialLocked(userId); } } private boolean isSyntheticPasswordBasedCredentialLocked(int userId) { if (userId == USER_FRP) { final int type = mStorage.readPersistentDataBlock().type; Loading Loading @@ -2925,20 +2910,15 @@ public class LockSettingsService extends ILockSettings.Stub { @NonNull EscrowTokenStateChangeCallback callback) { if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type); synchronized (mSpManager) { // If the user has no LSKF, then the token can be activated immediately, after creating // the user's SP if it doesn't already exist. Otherwise, the token can't be activated // until the SP is unlocked by another protector (normally the LSKF-based one). // If the user has no LSKF, then the token can be activated immediately. Otherwise, the // token can't be activated until the SP is unlocked by another protector (normally the // LSKF-based one). SyntheticPassword sp = null; if (!isUserSecure(userId)) { long protectorId = getCurrentLskfBasedProtectorId(userId); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { // TODO(b/232452368): this case is only needed by unit tests now; remove it. sp = initializeSyntheticPasswordLocked(userId); } else { sp = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, null).syntheticPassword; } } disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); if (!mSpManager.hasEscrowData(userId)) { throw new SecurityException("Escrow token is disabled on the current user"); Loading services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +81 −125 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -42,14 +42,13 @@ import org.junit.runner.RunWith; public class LockscreenFrpTest extends BaseLockSettingsServiceTests { @Before public void setDeviceNotProvisioned() throws Exception { public void setUp() throws Exception { PropertyInvalidatedCache.disableForTestMode(); // FRP credential can only be verified prior to provisioning setDeviceProvisioned(false); } @Before public void disableProcessCaches() { PropertyInvalidatedCache.disableForTestMode(); mService.initializeSyntheticPassword(PRIMARY_USER_ID); } @Test Loading services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +34 −57 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package com.android.server.locksettings; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -59,9 +58,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import java.io.File; import java.util.ArrayList; import java.util.Arrays; /** * atest FrameworksServicesTests:SyntheticPasswordTests Loading Loading @@ -127,21 +123,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { return mGateKeeperService.getSecureUserId(SyntheticPasswordManager.fakeUserId(userId)) != 0; } private boolean hasSyntheticPassword(int userId) throws RemoteException { return mService.getLong(CURRENT_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId) != 0; } private void initializeCredential(LockscreenCredential password, int userId) private void initSpAndSetCredential(int userId, LockscreenCredential credential) throws RemoteException { assertTrue(mService.setLockCredential(password, nonePassword(), userId)); assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId)); assertTrue(mService.isSyntheticPasswordBasedCredential(userId)); } protected void initializeSyntheticPassword(int userId) { synchronized (mService.mSpManager) { mService.initializeSyntheticPasswordLocked(userId); } mService.initializeSyntheticPassword(userId); assertTrue(mService.setLockCredential(credential, nonePassword(), userId)); assertEquals(credential.getType(), mService.getCredentialType(userId)); } // Tests that the FRP credential is updated when an LSKF-based protector is created for the user Loading @@ -149,7 +135,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testFrpCredentialSyncedIfDeviceProvisioned() throws RemoteException { setDeviceProvisioned(true); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any()); } Loading @@ -159,7 +145,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testEmptyFrpCredentialNotSyncedIfDeviceNotProvisioned() throws RemoteException { setDeviceProvisioned(false); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any()); } Loading @@ -169,7 +155,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testNonEmptyFrpCredentialSyncedIfDeviceNotProvisioned() throws RemoteException { setDeviceProvisioned(false); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any()); mService.setLockCredential(newPassword("password"), nonePassword(), PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any()); Loading @@ -180,7 +166,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final LockscreenCredential password = newPassword("password"); final LockscreenCredential newPassword = newPassword("newpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); mService.setLockCredential(newPassword, password, PRIMARY_USER_ID); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( Loading @@ -193,7 +179,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("badpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mActivityManager).unlockUser2(eq(PRIMARY_USER_ID), any()); Loading @@ -207,7 +193,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("newpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID); Loading @@ -225,7 +211,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("new"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); mService.setLockCredential(badPassword, password, PRIMARY_USER_ID); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); Loading @@ -242,7 +228,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testVerifyPassesPrimaryUserAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); reset(mAuthSecretService); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); Loading @@ -253,7 +239,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, SECONDARY_USER_ID); initSpAndSetCredential(SECONDARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, SECONDARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class)); Loading @@ -262,7 +248,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID); reset(mAuthSecretService); Loading @@ -275,7 +261,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); // Disregard any reportPasswordChanged() invocations as part of credential setup. flushHandlerTasks(); reset(mDevicePolicyManager); Loading Loading @@ -310,7 +296,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); Loading @@ -336,7 +322,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential pattern = newPattern("123654"); LockscreenCredential newPassword = newPassword("password"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); Loading @@ -356,38 +342,20 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { } @Test public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration() throws RemoteException { final byte[] token = "some-high-entropy-secure-token".getBytes(); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); } @Test public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration() throws RemoteException { public void testEscrowTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException { final byte[] token = "some-high-entropy-secure-token".getBytes(); // By first setting a password and then clearing it, we enter the state where SP is // initialized but the user currently has no password initializeCredential(newPassword("password"), PRIMARY_USER_ID); assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), PRIMARY_USER_ID)); assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID)); mService.initializeSyntheticPassword(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); } @Test public void testEscrowTokenActivatedLaterWithUserPassword() throws RemoteException { byte[] token = "some-high-entropy-secure-token".getBytes(); LockscreenCredential password = newPassword("password"); mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); // Token not activated immediately since user password exists assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading @@ -407,6 +375,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { when(mUserManagerInternal.isUserManaged(PRIMARY_USER_ID)).thenReturn(false); when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true); mService.initializeSyntheticPassword(PRIMARY_USER_ID); try { mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); fail("Escrow token should not be possible on unmanaged device"); Loading @@ -421,7 +390,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long handle0 = mLocalService.addEscrowToken(token0, PRIMARY_USER_ID, null); long handle1 = mLocalService.addEscrowToken(token1, PRIMARY_USER_ID, null); Loading Loading @@ -450,6 +419,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { byte[] token = "some-high-entropy-secure-token".getBytes(); mService.mHasSecureLockScreen = false; mService.initializeSyntheticPassword(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading @@ -473,7 +443,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorPrimaryUser() throws RemoteException { LockscreenCredential password = newPassword("password"); mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID); assertNotNull(hashFactor); Loading @@ -486,6 +456,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException { mService.initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID); LockscreenCredential pattern = newPattern("1236"); mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); Loading @@ -494,6 +467,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException { mService.initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID); LockscreenCredential primaryPassword = newPassword("primary"); LockscreenCredential profilePassword = newPassword("profile"); mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID); Loading Loading @@ -594,7 +570,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("testGsiDisablesAuthSecret-password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class)); Loading @@ -604,7 +580,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testUnlockUserWithToken() throws Exception { LockscreenCredential password = newPassword("password"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); // Disregard any reportPasswordChanged() invocations as part of credential setup. flushHandlerTasks(); reset(mDevicePolicyManager); Loading @@ -625,7 +601,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testPasswordChange_NoOrphanedFilesLeft() throws Exception { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID)); assertNoOrphanedFilesLeft(PRIMARY_USER_ID); } Loading @@ -633,6 +609,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testAddingEscrowToken_NoOrphanedFilesLeft() throws Exception { final byte[] token = "some-high-entropy-secure-token".getBytes(); mService.initializeSyntheticPassword(PRIMARY_USER_ID); for (int i = 0; i < 16; i++) { long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.internal.widget.IWeakEscrowTokenRemovedListener; import com.android.internal.widget.LockscreenCredential; import com.android.internal.widget.VerifyCredentialResponse; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -49,6 +50,11 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class WeakEscrowTokenTests extends BaseLockSettingsServiceTests{ @Before public void setUp() { mService.initializeSyntheticPassword(PRIMARY_USER_ID); } @Test public void testWeakTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException { Loading Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +25 −45 Original line number Diff line number Diff line Loading @@ -240,8 +240,7 @@ public class LockSettingsService extends ILockSettings.Stub { protected final UserManager mUserManager; private final IStorageManager mStorageManager; private final IActivityManager mActivityManager; @VisibleForTesting protected final SyntheticPasswordManager mSpManager; private final SyntheticPasswordManager mSpManager; private final java.security.KeyStore mJavaKeyStore; private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; Loading Loading @@ -946,7 +945,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (!isSyntheticPasswordBasedCredentialLocked(userId)) { Slogf.i(TAG, "Creating locksettings state for user %d now that boot " + "is complete", userId); initializeSyntheticPasswordLocked(userId); initializeSyntheticPassword(userId); } } } Loading Loading @@ -985,7 +984,7 @@ public class LockSettingsService extends ILockSettings.Stub { long protectorId = getCurrentLskfBasedProtectorId(userId); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId); initializeSyntheticPasswordLocked(userId); initializeSyntheticPassword(userId); } else { Slogf.i(TAG, "Existing unsecured user %d has a synthetic password; re-encrypting CE " + "key with it", userId); Loading Loading @@ -1652,13 +1651,7 @@ public class LockSettingsService extends ILockSettings.Stub { Objects.requireNonNull(savedCredential); if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId); synchronized (mSpManager) { if (!isSyntheticPasswordBasedCredentialLocked(userId)) { if (!savedCredential.isNone()) { throw new IllegalStateException("Saved credential given, but user has no SP"); } // TODO(b/232452368): this case is only needed by unit tests now; remove it. initializeSyntheticPasswordLocked(userId); } else if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { // get credential from keystore when profile has unified lock try { //TODO: remove as part of b/80170828 Loading Loading @@ -2322,9 +2315,7 @@ public class LockSettingsService extends ILockSettings.Stub { return; } removeStateForReusedUserIdIfNecessary(userId, userSerialNumber); synchronized (mSpManager) { initializeSyntheticPasswordLocked(userId); } initializeSyntheticPassword(userId); } } Loading Loading @@ -2650,9 +2641,9 @@ public class LockSettingsService extends ILockSettings.Stub { * until the time when Weaver is guaranteed to be available), or when upgrading from Android 13 * or earlier where users with no LSKF didn't necessarily have an SP. */ @GuardedBy("mSpManager") @VisibleForTesting SyntheticPassword initializeSyntheticPasswordLocked(int userId) { SyntheticPassword initializeSyntheticPassword(int userId) { synchronized (mSpManager) { Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId); Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) == SyntheticPasswordManager.NULL_PROTECTOR_ID, Loading @@ -2666,6 +2657,7 @@ public class LockSettingsService extends ILockSettings.Stub { onSyntheticPasswordKnown(userId, sp); return sp; } } @VisibleForTesting long getCurrentLskfBasedProtectorId(int userId) { Loading @@ -2680,13 +2672,6 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(LSKF_LAST_CHANGED_TIME_KEY, System.currentTimeMillis(), userId); } @VisibleForTesting boolean isSyntheticPasswordBasedCredential(int userId) { synchronized (mSpManager) { return isSyntheticPasswordBasedCredentialLocked(userId); } } private boolean isSyntheticPasswordBasedCredentialLocked(int userId) { if (userId == USER_FRP) { final int type = mStorage.readPersistentDataBlock().type; Loading Loading @@ -2925,20 +2910,15 @@ public class LockSettingsService extends ILockSettings.Stub { @NonNull EscrowTokenStateChangeCallback callback) { if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type); synchronized (mSpManager) { // If the user has no LSKF, then the token can be activated immediately, after creating // the user's SP if it doesn't already exist. Otherwise, the token can't be activated // until the SP is unlocked by another protector (normally the LSKF-based one). // If the user has no LSKF, then the token can be activated immediately. Otherwise, the // token can't be activated until the SP is unlocked by another protector (normally the // LSKF-based one). SyntheticPassword sp = null; if (!isUserSecure(userId)) { long protectorId = getCurrentLskfBasedProtectorId(userId); if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { // TODO(b/232452368): this case is only needed by unit tests now; remove it. sp = initializeSyntheticPasswordLocked(userId); } else { sp = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, null).syntheticPassword; } } disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); if (!mSpManager.hasEscrowData(userId)) { throw new SecurityException("Escrow token is disabled on the current user"); Loading
services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java +81 −125 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java +4 −5 Original line number Diff line number Diff line Loading @@ -42,14 +42,13 @@ import org.junit.runner.RunWith; public class LockscreenFrpTest extends BaseLockSettingsServiceTests { @Before public void setDeviceNotProvisioned() throws Exception { public void setUp() throws Exception { PropertyInvalidatedCache.disableForTestMode(); // FRP credential can only be verified prior to provisioning setDeviceProvisioned(false); } @Before public void disableProcessCaches() { PropertyInvalidatedCache.disableForTestMode(); mService.initializeSyntheticPassword(PRIMARY_USER_ID); } @Test Loading
services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +34 −57 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package com.android.server.locksettings; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -59,9 +58,6 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import java.io.File; import java.util.ArrayList; import java.util.Arrays; /** * atest FrameworksServicesTests:SyntheticPasswordTests Loading Loading @@ -127,21 +123,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { return mGateKeeperService.getSecureUserId(SyntheticPasswordManager.fakeUserId(userId)) != 0; } private boolean hasSyntheticPassword(int userId) throws RemoteException { return mService.getLong(CURRENT_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId) != 0; } private void initializeCredential(LockscreenCredential password, int userId) private void initSpAndSetCredential(int userId, LockscreenCredential credential) throws RemoteException { assertTrue(mService.setLockCredential(password, nonePassword(), userId)); assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId)); assertTrue(mService.isSyntheticPasswordBasedCredential(userId)); } protected void initializeSyntheticPassword(int userId) { synchronized (mService.mSpManager) { mService.initializeSyntheticPasswordLocked(userId); } mService.initializeSyntheticPassword(userId); assertTrue(mService.setLockCredential(credential, nonePassword(), userId)); assertEquals(credential.getType(), mService.getCredentialType(userId)); } // Tests that the FRP credential is updated when an LSKF-based protector is created for the user Loading @@ -149,7 +135,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testFrpCredentialSyncedIfDeviceProvisioned() throws RemoteException { setDeviceProvisioned(true); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any()); } Loading @@ -159,7 +145,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testEmptyFrpCredentialNotSyncedIfDeviceNotProvisioned() throws RemoteException { setDeviceProvisioned(false); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any()); } Loading @@ -169,7 +155,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testNonEmptyFrpCredentialSyncedIfDeviceNotProvisioned() throws RemoteException { setDeviceProvisioned(false); initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager, never()).setFrpCredentialHandle(any()); mService.setLockCredential(newPassword("password"), nonePassword(), PRIMARY_USER_ID); verify(mStorage.mPersistentDataBlockManager).setFrpCredentialHandle(any()); Loading @@ -180,7 +166,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final LockscreenCredential password = newPassword("password"); final LockscreenCredential newPassword = newPassword("newpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); mService.setLockCredential(newPassword, password, PRIMARY_USER_ID); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( Loading @@ -193,7 +179,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("badpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mActivityManager).unlockUser2(eq(PRIMARY_USER_ID), any()); Loading @@ -207,7 +193,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("newpassword"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); // clear password mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID); Loading @@ -225,7 +211,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential badPassword = newPassword("new"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); mService.setLockCredential(badPassword, password, PRIMARY_USER_ID); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); Loading @@ -242,7 +228,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testVerifyPassesPrimaryUserAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); reset(mAuthSecretService); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); Loading @@ -253,7 +239,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, SECONDARY_USER_ID); initSpAndSetCredential(SECONDARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, SECONDARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class)); Loading @@ -262,7 +248,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecret() throws RemoteException { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID); reset(mAuthSecretService); Loading @@ -275,7 +261,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); // Disregard any reportPasswordChanged() invocations as part of credential setup. flushHandlerTasks(); reset(mDevicePolicyManager); Loading Loading @@ -310,7 +296,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); Loading @@ -336,7 +322,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential pattern = newPattern("123654"); LockscreenCredential newPassword = newPassword("password"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); Loading @@ -356,38 +342,20 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { } @Test public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration() throws RemoteException { final byte[] token = "some-high-entropy-secure-token".getBytes(); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); } @Test public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration() throws RemoteException { public void testEscrowTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException { final byte[] token = "some-high-entropy-secure-token".getBytes(); // By first setting a password and then clearing it, we enter the state where SP is // initialized but the user currently has no password initializeCredential(newPassword("password"), PRIMARY_USER_ID); assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), PRIMARY_USER_ID)); assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID)); mService.initializeSyntheticPassword(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); } @Test public void testEscrowTokenActivatedLaterWithUserPassword() throws RemoteException { byte[] token = "some-high-entropy-secure-token".getBytes(); LockscreenCredential password = newPassword("password"); mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); // Token not activated immediately since user password exists assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading @@ -407,6 +375,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { when(mUserManagerInternal.isUserManaged(PRIMARY_USER_ID)).thenReturn(false); when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true); mService.initializeSyntheticPassword(PRIMARY_USER_ID); try { mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); fail("Escrow token should not be possible on unmanaged device"); Loading @@ -421,7 +390,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("password"); LockscreenCredential pattern = newPattern("123654"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); long handle0 = mLocalService.addEscrowToken(token0, PRIMARY_USER_ID, null); long handle1 = mLocalService.addEscrowToken(token1, PRIMARY_USER_ID, null); Loading Loading @@ -450,6 +419,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { byte[] token = "some-high-entropy-secure-token".getBytes(); mService.mHasSecureLockScreen = false; mService.initializeSyntheticPassword(PRIMARY_USER_ID); long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading @@ -473,7 +443,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorPrimaryUser() throws RemoteException { LockscreenCredential password = newPassword("password"); mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID); assertNotNull(hashFactor); Loading @@ -486,6 +456,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException { mService.initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID); LockscreenCredential pattern = newPattern("1236"); mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID); mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); Loading @@ -494,6 +467,9 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException { mService.initializeSyntheticPassword(PRIMARY_USER_ID); mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID); LockscreenCredential primaryPassword = newPassword("primary"); LockscreenCredential profilePassword = newPassword("profile"); mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID); Loading Loading @@ -594,7 +570,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { LockscreenCredential password = newPassword("testGsiDisablesAuthSecret-password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode()); verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class)); Loading @@ -604,7 +580,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { public void testUnlockUserWithToken() throws Exception { LockscreenCredential password = newPassword("password"); byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); // Disregard any reportPasswordChanged() invocations as part of credential setup. flushHandlerTasks(); reset(mDevicePolicyManager); Loading @@ -625,7 +601,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testPasswordChange_NoOrphanedFilesLeft() throws Exception { LockscreenCredential password = newPassword("password"); initializeCredential(password, PRIMARY_USER_ID); initSpAndSetCredential(PRIMARY_USER_ID, password); assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID)); assertNoOrphanedFilesLeft(PRIMARY_USER_ID); } Loading @@ -633,6 +609,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { @Test public void testAddingEscrowToken_NoOrphanedFilesLeft() throws Exception { final byte[] token = "some-high-entropy-secure-token".getBytes(); mService.initializeSyntheticPassword(PRIMARY_USER_ID); for (int i = 0; i < 16; i++) { long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null); assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); Loading
services/tests/servicestests/src/com/android/server/locksettings/WeakEscrowTokenTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.internal.widget.IWeakEscrowTokenRemovedListener; import com.android.internal.widget.LockscreenCredential; import com.android.internal.widget.VerifyCredentialResponse; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -49,6 +50,11 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class WeakEscrowTokenTests extends BaseLockSettingsServiceTests{ @Before public void setUp() { mService.initializeSyntheticPassword(PRIMARY_USER_ID); } @Test public void testWeakTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException { Loading