Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9465960c authored by Eric Biggers's avatar Eric Biggers Committed by Android (Google) Code Review
Browse files

Merge "Remove obsolete support for nonempty credential without SP"

parents fcd84546 9d991c73
Loading
Loading
Loading
Loading
+96 −344

File changed.

Preview size limit exceeded, changes collapsed.

+1 −86
Original line number Diff line number Diff line
@@ -85,8 +85,6 @@ class LockSettingsStorage extends WatchableImpl {
    };

    private static final String SYSTEM_DIRECTORY = "/system/";
    private static final String LOCK_PATTERN_FILE = "gatekeeper.pattern.key";
    private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key";
    private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key";

    private static final String REBOOT_ESCROW_FILE = "reboot.escrow.key";
@@ -248,38 +246,6 @@ class LockSettingsStorage extends WatchableImpl {
            }
            cursor.close();
        }

        // Populate cache by reading the password and pattern files.
        readCredentialHash(userId);
    }

    private CredentialHash readPasswordHashIfExists(int userId) {
        byte[] stored = readFile(getLockPasswordFilename(userId));
        if (!ArrayUtils.isEmpty(stored)) {
            return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN);
        }
        return null;
    }

    private CredentialHash readPatternHashIfExists(int userId) {
        byte[] stored = readFile(getLockPatternFilename(userId));
        if (!ArrayUtils.isEmpty(stored)) {
            return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
        }
        return null;
    }

    public CredentialHash readCredentialHash(int userId) {
        CredentialHash passwordHash = readPasswordHashIfExists(userId);
        if (passwordHash != null) {
            return passwordHash;
        }

        CredentialHash patternHash = readPatternHashIfExists(userId);
        if (patternHash != null) {
            return patternHash;
        }
        return CredentialHash.createEmptyHash();
    }

    public void removeChildProfileLock(int userId) {
@@ -336,14 +302,6 @@ class LockSettingsStorage extends WatchableImpl {
        deleteFile(getRebootEscrowServerBlob());
    }

    public boolean hasPassword(int userId) {
        return hasFile(getLockPasswordFilename(userId));
    }

    public boolean hasPattern(int userId) {
        return hasFile(getLockPatternFilename(userId));
    }

    private boolean hasFile(String name) {
        byte[] contents = readFile(name);
        return contents != null && contents.length > 0;
@@ -429,33 +387,6 @@ class LockSettingsStorage extends WatchableImpl {
        }
    }

    public void writeCredentialHash(CredentialHash hash, int userId) {
        byte[] patternHash = null;
        byte[] passwordHash = null;
        if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN
                || hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
                || hash.type == LockPatternUtils.CREDENTIAL_TYPE_PIN) {
            passwordHash = hash.hash;
        } else if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
            patternHash = hash.hash;
        } else {
            Preconditions.checkArgument(hash.type == LockPatternUtils.CREDENTIAL_TYPE_NONE,
                    "Unknown credential type");
        }
        writeFile(getLockPasswordFilename(userId), passwordHash);
        writeFile(getLockPatternFilename(userId), patternHash);
    }

    @VisibleForTesting
    String getLockPatternFilename(int userId) {
        return getLockCredentialFilePathForUser(userId, LOCK_PATTERN_FILE);
    }

    @VisibleForTesting
    String getLockPasswordFilename(int userId) {
        return getLockCredentialFilePathForUser(userId, LOCK_PASSWORD_FILE);
    }

    @VisibleForTesting
    String getChildProfileLockFile(int userId) {
        return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE);
@@ -567,12 +498,7 @@ class LockSettingsStorage extends WatchableImpl {

        if (parentInfo == null) {
            // This user owns its lock settings files - safe to delete them
            synchronized (mFileWriteLock) {
                deleteFilesAndRemoveCache(
                        getLockPasswordFilename(userId),
                        getLockPatternFilename(userId),
                        getRebootEscrowFile(userId));
            }
            deleteFile(getRebootEscrowFile(userId));
        } else {
            // Managed profile
            removeChildProfileLock(userId);
@@ -594,17 +520,6 @@ class LockSettingsStorage extends WatchableImpl {
        dispatchChange(this);
    }

    private void deleteFilesAndRemoveCache(String... names) {
        for (String name : names) {
            File file = new File(name);
            if (file.exists()) {
                file.delete();
                mCache.putFile(name, null);
                dispatchChange(this);
            }
        }
    }

    public void setBoolean(String key, boolean value, int userId) {
        setString(key, value ? "1" : "0", userId);
    }
+5 −33
Original line number Diff line number Diff line
@@ -599,47 +599,19 @@ public class SyntheticPasswordManager {
    }

    /**
     * Initializing a new Authentication token, possibly from an existing credential and hash.
     * Initializes a new Authentication token for the given user.
     *
     * The authentication token would bear a randomly-generated synthetic password.
     * The authentication token will bear a randomly-generated synthetic password.
     *
     * This method has the side effect of rebinding the SID of the given user to the
     * newly-generated SP.
     *
     * If the existing credential hash is non-null, the existing SID mill be migrated so
     * the synthetic password in the authentication token will produce the same SID
     * (the corresponding synthetic password handle is persisted by SyntheticPasswordManager
     * in a per-user data storage.)
     *
     * If the existing credential hash is null, it means the given user should have no SID so
     * SyntheticPasswordManager will nuke any SP handle previously persisted. In this case,
     * the supplied credential parameter is also ignored.
     * Any existing SID for the user is cleared.
     *
     * Also saves the escrow information necessary to re-generate the synthetic password under
     * an escrow scheme. This information can be removed with {@link #destroyEscrowData} if
     * password escrow should be disabled completely on the given user.
     *
     */
    public AuthenticationToken newSyntheticPasswordAndSid(IGateKeeperService gatekeeper,
            byte[] hash, LockscreenCredential credential, int userId) {
        AuthenticationToken result = AuthenticationToken.create();
        GateKeeperResponse response;
        if (hash != null) {
            try {
                response = gatekeeper.enroll(userId, hash, credential.getCredential(),
                        result.deriveGkPassword());
            } catch (RemoteException e) {
                throw new IllegalStateException("Failed to enroll credential duing SP init", e);
            }
            if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
                Slog.w(TAG, "Fail to migrate SID, assuming no SID, user " + userId);
                clearSidForUser(userId);
            } else {
                saveSyntheticPasswordHandle(response.getPayload(), userId);
            }
        } else {
    AuthenticationToken newSyntheticPassword(int userId) {
        clearSidForUser(userId);
        }
        AuthenticationToken result = AuthenticationToken.create();
        saveEscrowData(result, userId);
        return result;
    }
+0 −5
Original line number Diff line number Diff line
@@ -135,11 +135,6 @@ public class LockSettingsServiceTestable extends LockSettingsService {
            return mUserManagerInternal;
        }

        @Override
        public boolean hasEnrolledBiometrics(int userId) {
            return false;
        }

        @Override
        public int binderGetCallingUid() {
            return Process.SYSTEM_UID;
+21 −42
Original line number Diff line number Diff line
@@ -42,11 +42,8 @@ import android.service.gatekeeper.GateKeeperResponse;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle;
import com.android.server.locksettings.LockSettingsStorage.CredentialHash;

import org.junit.Before;
import org.junit.Test;
@@ -96,17 +93,16 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {

    @Test
    public void testChangePasswordFailPrimaryUser() throws RemoteException {
        final long sid = 1234;
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), sid);
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"));

        assertFalse(mService.setLockCredential(newPassword("newpwd"), newPassword("badpwd"),
                    PRIMARY_USER_ID));
        assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"), sid);
        assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"));
    }

    @Test
    public void testClearPasswordPrimaryUser() throws RemoteException {
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"));
        assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
                PRIMARY_USER_ID));
        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
@@ -264,10 +260,7 @@ 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"),
                1234);
        initializeStorageWithCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));

        assertTrue(mService.setLockCredential(
                newPassword("newPassword"),
@@ -300,8 +293,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                    throws Exception {
        final LockscreenCredential oldCredential = newPassword("oldPassword");
        final LockscreenCredential newCredential = newPassword("newPassword");
        initializeStorageWithCredential(
                PRIMARY_USER_ID, oldCredential, 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, oldCredential);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);

        assertTrue(mService.setLockCredential(
@@ -321,7 +313,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    public void
            testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()
                    throws Exception {
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("oldPassword"), 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("oldPassword"));
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);

        assertTrue(mService.setLockCredential(
@@ -337,10 +329,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {

    @Test
    public void testSetLockCredential_nullCredential_removeBiometrics() throws RemoteException {
        initializeStorageWithCredential(
                PRIMARY_USER_ID,
                newPattern("123654"),
                1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, newPattern("123654"));
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);

        mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID);
@@ -358,7 +347,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
            throws Exception {
        final LockscreenCredential parentPassword = newPassword("parentPassword");
        final LockscreenCredential profilePassword = newPassword("profilePassword");
        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword, 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);

        assertTrue(mService.setLockCredential(
@@ -377,7 +366,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                    throws Exception {
        final LockscreenCredential parentPassword = newPassword("parentPassword");
        final LockscreenCredential profilePassword = newPattern("12345");
        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword, 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword);
        // Create and verify separate profile credentials.
        testCreateCredential(MANAGED_PROFILE_USER_ID, profilePassword);

@@ -393,7 +382,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    @Test
    public void testVerifyCredential_forPrimaryUser_sendsCredentials() throws Exception {
        final LockscreenCredential password = newPassword("password");
        initializeStorageWithCredential(PRIMARY_USER_ID, password, 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, password);
        reset(mRecoverableKeyStoreManager);

        mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */);
@@ -424,7 +413,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    public void verifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()
                    throws Exception {
        final LockscreenCredential pattern = newPattern("12345");
        initializeStorageWithCredential(PRIMARY_USER_ID, pattern, 1234);
        initializeStorageWithCredential(PRIMARY_USER_ID, pattern);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        reset(mRecoverableKeyStoreManager);

@@ -464,7 +453,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    private void testCreateCredential(int userId, LockscreenCredential credential)
            throws RemoteException {
        assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
        assertVerifyCredentials(userId, credential, -1);
        assertVerifyCredentials(userId, credential);
    }

    private void testCreateCredentialFailsWithoutLockScreen(
@@ -483,19 +472,17 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {

    private void testChangeCredentials(int userId, LockscreenCredential newCredential,
            LockscreenCredential oldCredential) throws RemoteException {
        final long sid = 1234;
        initializeStorageWithCredential(userId, oldCredential, sid);
        initializeStorageWithCredential(userId, oldCredential);
        assertTrue(mService.setLockCredential(newCredential, oldCredential, userId));
        assertVerifyCredentials(userId, newCredential, sid);
        assertVerifyCredentials(userId, newCredential);
    }

    private void assertVerifyCredentials(int userId, LockscreenCredential credential, long sid)
    private void assertVerifyCredentials(int userId, LockscreenCredential credential)
            throws RemoteException{
        VerifyCredentialResponse response = mService.verifyCredential(credential, userId,
                0 /* flags */);

        assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
        if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
        if (credential.isPassword()) {
            assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
        } else if (credential.isPin()) {
@@ -517,19 +504,11 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                badCredential, userId, 0 /* flags */).getResponseCode());
    }

    private void initializeStorageWithCredential(int userId, LockscreenCredential credential,
            long sid) throws RemoteException {
        byte[] oldHash = new VerifyHandle(credential.getCredential(), sid).toBytes();
        if (mService.shouldMigrateToSyntheticPasswordLocked(userId)) {
            mService.initializeSyntheticPasswordLocked(oldHash, credential, userId);
        } else {
            if (credential.isPassword() || credential.isPin()) {
                mStorage.writeCredentialHash(CredentialHash.create(oldHash,
                        LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), userId);
            } else {
                mStorage.writeCredentialHash(CredentialHash.create(oldHash,
                        LockPatternUtils.CREDENTIAL_TYPE_PATTERN), userId);
            }
        }
    @SuppressWarnings("GuardedBy") // for initializeSyntheticPasswordLocked
    private void initializeStorageWithCredential(int userId, LockscreenCredential credential)
            throws RemoteException {
        assertEquals(0, mGateKeeperService.getSecureUserId(userId));
        mService.initializeSyntheticPasswordLocked(credential, userId);
        assertNotEquals(0, mGateKeeperService.getSecureUserId(userId));
    }
}
Loading