Merge "Remove on-demand initialization of synthetic password"

This commit is contained in:
Eric Biggers
2022-12-14 23:14:20 +00:00
committed by Android (Google) Code Review
6 changed files with 151 additions and 233 deletions

View File

@@ -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;
@@ -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);
}
}
}
@@ -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);
@@ -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
@@ -2322,9 +2315,7 @@ public class LockSettingsService extends ILockSettings.Stub {
return;
}
removeStateForReusedUserIdIfNecessary(userId, userSerialNumber);
synchronized (mSpManager) {
initializeSyntheticPasswordLocked(userId);
}
initializeSyntheticPassword(userId);
}
}
@@ -2650,21 +2641,22 @@ 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) {
Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) ==
SyntheticPasswordManager.NULL_PROTECTOR_ID,
"Cannot reinitialize SP");
SyntheticPassword initializeSyntheticPassword(int userId) {
synchronized (mSpManager) {
Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) ==
SyntheticPasswordManager.NULL_PROTECTOR_ID,
"Cannot reinitialize SP");
final SyntheticPassword sp = mSpManager.newSyntheticPassword(userId);
final long protectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
LockscreenCredential.createNone(), sp, userId);
setCurrentLskfBasedProtectorId(protectorId, userId);
setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
onSyntheticPasswordKnown(userId, sp);
return sp;
final SyntheticPassword sp = mSpManager.newSyntheticPassword(userId);
final long protectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
LockscreenCredential.createNone(), sp, userId);
setCurrentLskfBasedProtectorId(protectorId, userId);
setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
onSyntheticPasswordKnown(userId, sp);
return sp;
}
}
@VisibleForTesting
@@ -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;
@@ -2925,19 +2910,14 @@ 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;
}
sp = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId,
LockscreenCredential.createNone(), userId, null).syntheticPassword;
}
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
if (!mSpManager.hasEscrowData(userId)) {

View File

@@ -59,65 +59,65 @@ import org.junit.runner.RunWith;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
@Before
public void disableProcessCaches() {
public void setUp() {
PropertyInvalidatedCache.disableForTestMode();
mService.initializeSyntheticPassword(PRIMARY_USER_ID);
mService.initializeSyntheticPassword(MANAGED_PROFILE_USER_ID);
}
@Test
public void testCreatePasswordPrimaryUser() throws RemoteException {
testCreateCredential(PRIMARY_USER_ID, newPassword("password"));
public void testSetPasswordPrimaryUser() throws RemoteException {
setAndVerifyCredential(PRIMARY_USER_ID, newPassword("password"));
}
@Test
public void testCreatePasswordFailsWithoutLockScreen() throws RemoteException {
testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPassword("password"));
public void testSetPasswordFailsWithoutLockScreen() throws RemoteException {
testSetCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPassword("password"));
}
@Test
public void testCreatePatternPrimaryUser() throws RemoteException {
testCreateCredential(PRIMARY_USER_ID, newPattern("123456789"));
public void testSetPatternPrimaryUser() throws RemoteException {
setAndVerifyCredential(PRIMARY_USER_ID, newPattern("123456789"));
}
@Test
public void testCreatePatternFailsWithoutLockScreen() throws RemoteException {
testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPattern("123456789"));
public void testSetPatternFailsWithoutLockScreen() throws RemoteException {
testSetCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPattern("123456789"));
}
@Test
public void testChangePasswordPrimaryUser() throws RemoteException {
testChangeCredentials(PRIMARY_USER_ID, newPattern("78963214"), newPassword("asdfghjk"));
testChangeCredential(PRIMARY_USER_ID, newPattern("78963214"), newPassword("asdfghjk"));
}
@Test
public void testChangePatternPrimaryUser() throws RemoteException {
testChangeCredentials(PRIMARY_USER_ID, newPassword("!£$%^&*(())"), newPattern("1596321"));
testChangeCredential(PRIMARY_USER_ID, newPassword("!£$%^&*(())"), newPattern("1596321"));
}
@Test
public void testChangePasswordFailPrimaryUser() throws RemoteException {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"));
setCredential(PRIMARY_USER_ID, newPassword("password"));
assertFalse(mService.setLockCredential(newPassword("newpwd"), newPassword("badpwd"),
PRIMARY_USER_ID));
assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"));
assertVerifyCredential(PRIMARY_USER_ID, newPassword("password"));
}
@Test
public void testClearPasswordPrimaryUser() throws RemoteException {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"));
assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
PRIMARY_USER_ID));
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newPassword("password"));
clearCredential(PRIMARY_USER_ID, newPassword("password"));
}
@Test
public void testManagedProfileUnifiedChallenge() throws RemoteException {
mService.initializeSyntheticPassword(TURNED_OFF_PROFILE_USER_ID);
final LockscreenCredential firstUnifiedPassword = newPassword("pwd-1");
final LockscreenCredential secondUnifiedPassword = newPassword("pwd-2");
assertTrue(mService.setLockCredential(firstUnifiedPassword,
nonePassword(), PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, firstUnifiedPassword);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -146,14 +146,12 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
// Change primary password and verify that profile SID remains
assertTrue(mService.setLockCredential(
secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, secondUnifiedPassword, firstUnifiedPassword);
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
// Clear unified challenge
assertTrue(mService.setLockCredential(nonePassword(),
secondUnifiedPassword, PRIMARY_USER_ID));
clearCredential(PRIMARY_USER_ID, secondUnifiedPassword);
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID));
@@ -163,12 +161,8 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testManagedProfileSeparateChallenge() throws RemoteException {
final LockscreenCredential primaryPassword = newPassword("primary");
final LockscreenCredential profilePassword = newPassword("profile");
assertTrue(mService.setLockCredential(primaryPassword,
nonePassword(),
PRIMARY_USER_ID));
assertTrue(mService.setLockCredential(profilePassword,
nonePassword(),
MANAGED_PROFILE_USER_ID));
setCredential(PRIMARY_USER_ID, primaryPassword);
setCredential(MANAGED_PROFILE_USER_ID, profilePassword);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -191,8 +185,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertTrue(mService.setLockCredential(
newPassword("pwd"), primaryPassword, PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newPassword("pwd"), primaryPassword);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
profilePassword, MANAGED_PROFILE_USER_ID, 0 /* flags */)
.getResponseCode());
@@ -207,8 +200,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(MANAGED_PROFILE_USER_ID));
// Set a separate challenge on the profile
assertTrue(mService.setLockCredential(
newPassword("12345678"), nonePassword(), MANAGED_PROFILE_USER_ID));
setCredential(MANAGED_PROFILE_USER_ID, newPassword("12345678"));
assertNotEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(MANAGED_PROFILE_USER_ID));
@@ -221,11 +213,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
@Test
public void testSetLockCredential_forPrimaryUser_sendsCredentials() throws Exception {
assertTrue(mService.setLockCredential(
newPassword("password"),
nonePassword(),
PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newPassword("password"));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "password".getBytes(),
PRIMARY_USER_ID);
@@ -234,11 +222,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
@Test
public void testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()
throws Exception {
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
MANAGED_PROFILE_USER_ID));
setCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, "12345".getBytes(),
MANAGED_PROFILE_USER_ID);
@@ -248,13 +232,8 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials()
throws Exception {
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, true, null);
initializeStorageWithCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));
assertTrue(mService.setLockCredential(
newPassword("newPassword"),
newPattern("12345"),
MANAGED_PROFILE_USER_ID));
setCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));
setCredential(MANAGED_PROFILE_USER_ID, newPassword("newPassword"), newPattern("12345"));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "newPassword".getBytes(),
MANAGED_PROFILE_USER_ID);
@@ -264,12 +243,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()
throws Exception {
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newPattern("12345"));
verify(mRecoverableKeyStoreManager, never())
.lockScreenSecretChanged(
eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID));
@@ -281,13 +255,9 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
throws Exception {
final LockscreenCredential oldCredential = newPassword("oldPassword");
final LockscreenCredential newCredential = newPassword("newPassword");
initializeStorageWithCredential(PRIMARY_USER_ID, oldCredential);
setCredential(PRIMARY_USER_ID, oldCredential);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertTrue(mService.setLockCredential(
newCredential,
oldCredential,
PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newCredential, oldCredential);
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential.getCredential(),
@@ -301,13 +271,9 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void
testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()
throws Exception {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("oldPassword"));
setCredential(PRIMARY_USER_ID, newPassword("oldPassword"));
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertTrue(mService.setLockCredential(
nonePassword(),
newPassword("oldPassword"),
PRIMARY_USER_ID));
clearCredential(PRIMARY_USER_ID, newPassword("oldPassword"));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, PRIMARY_USER_ID);
@@ -316,11 +282,10 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
}
@Test
public void testSetLockCredential_nullCredential_removeBiometrics() throws RemoteException {
initializeStorageWithCredential(PRIMARY_USER_ID, newPattern("123654"));
public void testClearLockCredential_removesBiometrics() throws RemoteException {
setCredential(PRIMARY_USER_ID, newPattern("123654"));
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID);
clearCredential(PRIMARY_USER_ID, newPattern("123654"));
// Verify fingerprint is removed
verify(mFingerprintManager).removeAll(eq(PRIMARY_USER_ID), any());
@@ -335,14 +300,9 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
throws Exception {
final LockscreenCredential parentPassword = newPassword("parentPassword");
final LockscreenCredential profilePassword = newPassword("profilePassword");
initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword);
setCredential(PRIMARY_USER_ID, parentPassword);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertTrue(mService.setLockCredential(
profilePassword,
nonePassword(),
MANAGED_PROFILE_USER_ID));
setCredential(MANAGED_PROFILE_USER_ID, profilePassword);
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, profilePassword.getCredential(),
MANAGED_PROFILE_USER_ID);
@@ -356,9 +316,8 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final LockscreenCredential profilePassword = newPattern("12345");
mService.setSeparateProfileChallengeEnabled(
MANAGED_PROFILE_USER_ID, true, profilePassword);
initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword);
// Create and verify separate profile credentials.
testCreateCredential(MANAGED_PROFILE_USER_ID, profilePassword);
setCredential(PRIMARY_USER_ID, parentPassword);
setAndVerifyCredential(MANAGED_PROFILE_USER_ID, profilePassword);
mService.setSeparateProfileChallengeEnabled(
MANAGED_PROFILE_USER_ID, false, profilePassword);
@@ -372,7 +331,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
@Test
public void testVerifyCredential_forPrimaryUser_sendsCredentials() throws Exception {
final LockscreenCredential password = newPassword("password");
initializeStorageWithCredential(PRIMARY_USER_ID, password);
setCredential(PRIMARY_USER_ID, password);
reset(mRecoverableKeyStoreManager);
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */);
@@ -386,10 +345,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials()
throws Exception {
final LockscreenCredential pattern = newPattern("12345");
assertTrue(mService.setLockCredential(
pattern,
nonePassword(),
MANAGED_PROFILE_USER_ID));
setCredential(MANAGED_PROFILE_USER_ID, pattern);
reset(mRecoverableKeyStoreManager);
mService.verifyCredential(pattern, MANAGED_PROFILE_USER_ID, 0 /* flags */);
@@ -403,7 +359,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void verifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()
throws Exception {
final LockscreenCredential pattern = newPattern("12345");
initializeStorageWithCredential(PRIMARY_USER_ID, pattern);
setCredential(PRIMARY_USER_ID, pattern);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
reset(mRecoverableKeyStoreManager);
@@ -423,7 +379,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
}
@Test
public void testCredentialChangeNotPossibleInSecureFrpModeDuringSuw() {
public void testSetCredentialNotPossibleInSecureFrpModeDuringSuw() {
setUserSetupComplete(false);
setSecureFrpMode(true);
try {
@@ -433,21 +389,17 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
}
@Test
public void testCredentialChangePossibleInSecureFrpModeAfterSuw() {
public void testSetCredentialPossibleInSecureFrpModeAfterSuw() throws RemoteException {
setUserSetupComplete(true);
setSecureFrpMode(true);
assertTrue(mService.setLockCredential(newPassword("1234"), nonePassword(),
PRIMARY_USER_ID));
setCredential(PRIMARY_USER_ID, newPassword("1234"));
}
@Test
public void testPasswordHistoryDisabledByDefault() throws Exception {
final int userId = PRIMARY_USER_ID;
checkPasswordHistoryLength(userId, 0);
initializeStorageWithCredential(userId, nonePassword());
checkPasswordHistoryLength(userId, 0);
assertTrue(mService.setLockCredential(newPassword("1234"), nonePassword(), userId));
setCredential(userId, newPassword("1234"));
checkPasswordHistoryLength(userId, 0);
}
@@ -456,20 +408,18 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final int userId = PRIMARY_USER_ID;
when(mDevicePolicyManager.getPasswordHistoryLength(any(), eq(userId))).thenReturn(3);
checkPasswordHistoryLength(userId, 0);
initializeStorageWithCredential(userId, nonePassword());
checkPasswordHistoryLength(userId, 0);
assertTrue(mService.setLockCredential(newPassword("pass1"), nonePassword(), userId));
setCredential(userId, newPassword("pass1"));
checkPasswordHistoryLength(userId, 1);
assertTrue(mService.setLockCredential(newPassword("pass2"), newPassword("pass1"), userId));
setCredential(userId, newPassword("pass2"), newPassword("pass1"));
checkPasswordHistoryLength(userId, 2);
assertTrue(mService.setLockCredential(newPassword("pass3"), newPassword("pass2"), userId));
setCredential(userId, newPassword("pass3"), newPassword("pass2"));
checkPasswordHistoryLength(userId, 3);
// maximum length should have been reached
assertTrue(mService.setLockCredential(newPassword("pass4"), newPassword("pass3"), userId));
setCredential(userId, newPassword("pass4"), newPassword("pass3"));
checkPasswordHistoryLength(userId, 3);
}
@@ -479,18 +429,11 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertEquals(expectedLen, hashes.length);
}
private void testCreateCredential(int userId, LockscreenCredential credential)
throws RemoteException {
assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
assertVerifyCredentials(userId, credential);
}
private void testCreateCredentialFailsWithoutLockScreen(
private void testSetCredentialFailsWithoutLockScreen(
int userId, LockscreenCredential credential) throws RemoteException {
mService.mHasSecureLockScreen = false;
try {
mService.setLockCredential(credential, null, userId);
mService.setLockCredential(credential, nonePassword(), userId);
fail("An exception should have been thrown.");
} catch (UnsupportedOperationException e) {
// Success - the exception was expected.
@@ -499,14 +442,14 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(userId));
}
private void testChangeCredentials(int userId, LockscreenCredential newCredential,
private void testChangeCredential(int userId, LockscreenCredential newCredential,
LockscreenCredential oldCredential) throws RemoteException {
initializeStorageWithCredential(userId, oldCredential);
assertTrue(mService.setLockCredential(newCredential, oldCredential, userId));
assertVerifyCredentials(userId, newCredential);
setCredential(userId, oldCredential);
setCredential(userId, newCredential, oldCredential);
assertVerifyCredential(userId, newCredential);
}
private void assertVerifyCredentials(int userId, LockscreenCredential credential)
private void assertVerifyCredential(int userId, LockscreenCredential credential)
throws RemoteException{
VerifyCredentialResponse response = mService.verifyCredential(credential, userId,
0 /* flags */);
@@ -533,16 +476,29 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
badCredential, userId, 0 /* flags */).getResponseCode());
}
private void initializeStorageWithCredential(int userId, LockscreenCredential credential)
private void setAndVerifyCredential(int userId, LockscreenCredential newCredential)
throws RemoteException {
assertEquals(0, mGateKeeperService.getSecureUserId(userId));
synchronized (mService.mSpManager) {
mService.initializeSyntheticPasswordLocked(userId);
}
if (credential.isNone()) {
setCredential(userId, newCredential);
assertVerifyCredential(userId, newCredential);
}
private void setCredential(int userId, LockscreenCredential newCredential)
throws RemoteException {
setCredential(userId, newCredential, nonePassword());
}
private void clearCredential(int userId, LockscreenCredential oldCredential)
throws RemoteException {
setCredential(userId, nonePassword(), oldCredential);
}
private void setCredential(int userId, LockscreenCredential newCredential,
LockscreenCredential oldCredential) throws RemoteException {
assertTrue(mService.setLockCredential(newCredential, oldCredential, userId));
assertEquals(newCredential.getType(), mService.getCredentialType(userId));
if (newCredential.isNone()) {
assertEquals(0, mGateKeeperService.getSecureUserId(userId));
} else {
assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
assertNotEquals(0, mGateKeeperService.getSecureUserId(userId));
}
}

View File

@@ -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

View File

@@ -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;
@@ -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
@@ -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
@@ -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());
}
@@ -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());
}
@@ -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());
@@ -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(
@@ -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());
@@ -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);
@@ -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());
@@ -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());
@@ -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));
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -356,38 +342,20 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
}
@Test
public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
throws RemoteException {
public void testEscrowTokenActivatedImmediatelyIfNoUserPassword() throws RemoteException {
final byte[] token = "some-high-entropy-secure-token".getBytes();
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 testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
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));
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));
@@ -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");
@@ -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);
@@ -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));
@@ -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);
@@ -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);
@@ -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);
@@ -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));
@@ -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);
@@ -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);
}
@@ -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));

View File

@@ -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;
@@ -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 {

View File

@@ -36,7 +36,7 @@ public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests {
assertEquals(Sets.newHashSet(), mPasswordSlotManager.getUsedSlots());
mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, frpWeaverSlot, 0,
new byte[1]);
initializeSyntheticPassword(userId); // This should allocate a Weaver slot.
mService.initializeSyntheticPassword(userId); // This should allocate a Weaver slot.
assertEquals(Sets.newHashSet(1), mPasswordSlotManager.getUsedSlots());
}
@@ -52,7 +52,7 @@ public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests {
assertEquals(Sets.newHashSet(), mPasswordSlotManager.getUsedSlots());
mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, frpWeaverSlot, 0,
new byte[1]);
initializeSyntheticPassword(userId); // This should allocate a Weaver slot.
mService.initializeSyntheticPassword(userId); // This should allocate a Weaver slot.
assertEquals(Sets.newHashSet(0), mPasswordSlotManager.getUsedSlots());
}
}