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

Commit 6e21d416 authored by Billy Huang's avatar Billy Huang Committed by Gerrit Code Review
Browse files

Merge "LockSettingsService: clear strong auth when adding primary credential." into main

parents 129b7d26 1671e74a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -99,3 +99,10 @@ flag {
  description: "Causes TrustManagerService to listen for credential attempts and ignore reports from upstream"
  bug: "323086607"
}

flag {
    name: "clear_strong_auth_on_add_primary_credential"
    namespace: "biometrics"
    description: "Clear StrongAuth on add credential"
    bug: "320817991"
}
+14 −1
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.locksettings;

import static android.security.Flags.reportPrimaryAuthAttempts;
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
@@ -32,6 +31,7 @@ import static android.content.Intent.ACTION_MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTO
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.security.Flags.reportPrimaryAuthAttempts;

import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
@@ -1836,6 +1836,13 @@ public class LockSettingsService extends ILockSettings.Stub {
    }

    /**
     * Set a new LSKF for the given user/profile. Only succeeds if the synthetic password for the
     * user is protected by the given {@param savedCredential}.
     * <p>
     * When {@link android.security.Flags#clearStrongAuthOnAddPrimaryCredential()} is enabled and
     * setting a new credential where there was none, updates the strong auth state for
     * {@param userId} to <tt>STRONG_AUTH_NOT_REQUIRED</tt>.
     *
     * @param savedCredential if the user is a profile with
     * {@link UserManager#isCredentialSharableWithParent()} with unified challenge and
     *   savedCredential is empty, LSS will try to re-derive the profile password internally.
@@ -1884,6 +1891,12 @@ public class LockSettingsService extends ILockSettings.Stub {

            onSyntheticPasswordUnlocked(userId, sp);
            setLockCredentialWithSpLocked(credential, sp, userId);
            if (android.security.Flags.clearStrongAuthOnAddPrimaryCredential()
                    && savedCredential.isNone() && !credential.isNone()) {
                // Clear the strong auth value, since the LSKF has just been entered and set,
                // but only when the previous credential was None.
                mStrongAuth.reportUnlock(userId);
            }
            sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
            return true;
        }
+3 −1
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public abstract class BaseLockSettingsServiceTests {

    MockLockSettingsContext mContext;
    LockSettingsStorageTestable mStorage;
    LockSettingsStrongAuth mStrongAuth;

    Resources mResources;
    FakeGateKeeperService mGateKeeperService;
@@ -135,6 +136,7 @@ public abstract class BaseLockSettingsServiceTests {
        mFingerprintManager = mock(FingerprintManager.class);
        mFaceManager = mock(FaceManager.class);
        mPackageManager = mock(PackageManager.class);
        mStrongAuth = mock(LockSettingsStrongAuth.class);

        LocalServices.removeServiceForTest(LockSettingsInternal.class);
        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -162,7 +164,7 @@ public abstract class BaseLockSettingsServiceTests {
        mInjector =
                new LockSettingsServiceTestable.MockInjector(
                        mContext,
                        mStorage,
                        mStorage, mStrongAuth,
                        mActivityManager,
                        setUpStorageManagerMock(),
                        mSpManager,
+4 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ public class LockSettingsServiceTestable extends LockSettingsService {
    public static class MockInjector extends LockSettingsService.Injector {

        private LockSettingsStorage mLockSettingsStorage;
        private final LockSettingsStrongAuth mStrongAuth;
        private IActivityManager mActivityManager;
        private IStorageManager mStorageManager;
        private SyntheticPasswordManager mSpManager;
@@ -62,12 +63,14 @@ public class LockSettingsServiceTestable extends LockSettingsService {
        public boolean mIsMainUserPermanentAdmin = false;

        public MockInjector(Context context, LockSettingsStorage storage,
                LockSettingsStrongAuth strongAuth,
                IActivityManager activityManager, IStorageManager storageManager,
                SyntheticPasswordManager spManager, FakeGsiService gsiService,
                RecoverableKeyStoreManager recoverableKeyStoreManager,
                UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache) {
            super(context);
            mLockSettingsStorage = storage;
            mStrongAuth = strongAuth;
            mActivityManager = activityManager;
            mStorageManager = storageManager;
            mSpManager = spManager;
@@ -89,7 +92,7 @@ public class LockSettingsServiceTestable extends LockSettingsService {

        @Override
        public LockSettingsStrongAuth getStrongAuth() {
            return mock(LockSettingsStrongAuth.class);
            return mStrongAuth;
        }

        @Override
+130 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.locksettings;

import static android.Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION;
import static android.security.Flags.FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL;
import static android.security.Flags.FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS;

import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
@@ -46,6 +47,10 @@ import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.gatekeeper.GateKeeperResponse;
import android.text.TextUtils;
@@ -71,6 +76,8 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();

    @Before
    public void setUp() {
@@ -257,6 +264,34 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                        PRIMARY_USER_ID);
    }

    @Test
    @RequiresFlagsEnabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_forPrimaryUser_clearsStrongAuthWhenFlagIsOn()
            throws Exception {
        setCredential(PRIMARY_USER_ID, newPassword("password"));

        verify(mStrongAuth).reportUnlock(PRIMARY_USER_ID);
    }

    @Test
    @RequiresFlagsDisabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_forPrimaryUser_leavesStrongAuthWhenFlagIsOff()
            throws Exception {
        setCredential(PRIMARY_USER_ID, newPassword("password"));

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    public void setLockCredential_forPrimaryUserWithCredential_leavesStrongAuth() throws Exception {
        setCredential(PRIMARY_USER_ID, newPassword("password"));
        reset(mStrongAuth);

        setCredential(PRIMARY_USER_ID, newPassword("password2"), newPassword("password"));

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    public void testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()
            throws Exception {
@@ -277,6 +312,28 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                        MANAGED_PROFILE_USER_ID);
    }

    @Test
    @RequiresFlagsEnabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_profileWithNewSeparateChallenge_clearsStrongAuthWhenFlagIsOn()
            throws Exception {
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, true, null);

        setCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));

        verify(mStrongAuth).reportUnlock(MANAGED_PROFILE_USER_ID);
    }

    @Test
    @RequiresFlagsDisabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_profileWithNewSeparateChallenge_leavesStrongAuthWhenFlagIsOff()
            throws Exception {
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, true, null);

        setCredential(MANAGED_PROFILE_USER_ID, newPattern("12345"));

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    public void testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()
            throws Exception {
@@ -305,6 +362,67 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
                        MANAGED_PROFILE_USER_ID);
    }


    @Test
    public void setLockCredential_primaryWithUnifiedProfileAndCredential_leavesStrongAuthForBoth()
            throws Exception {
        final LockscreenCredential oldCredential = newPassword("oldPassword");
        final LockscreenCredential newCredential = newPassword("newPassword");
        setCredential(PRIMARY_USER_ID, oldCredential);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        reset(mStrongAuth);

        setCredential(PRIMARY_USER_ID, newCredential, oldCredential);

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    @RequiresFlagsEnabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_primaryWithUnifiedProfile_clearsStrongAuthForBothWhenFlagIsOn()
            throws Exception {
        final LockscreenCredential credential = newPassword("oldPassword");
        setCredential(PRIMARY_USER_ID, credential);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        clearCredential(PRIMARY_USER_ID, credential);
        reset(mStrongAuth);

        setCredential(PRIMARY_USER_ID, credential);

        verify(mStrongAuth).reportUnlock(PRIMARY_USER_ID);
        verify(mStrongAuth).reportUnlock(MANAGED_PROFILE_USER_ID);
    }

    @Test
    @RequiresFlagsDisabled(FLAG_CLEAR_STRONG_AUTH_ON_ADD_PRIMARY_CREDENTIAL)
    public void setLockCredential_primaryWithUnifiedProfile_leavesStrongAuthForBothWhenFlagIsOff()
            throws Exception {
        final LockscreenCredential credential = newPassword("oldPassword");
        setCredential(PRIMARY_USER_ID, credential);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        clearCredential(PRIMARY_USER_ID, credential);
        reset(mStrongAuth);

        setCredential(PRIMARY_USER_ID, credential);

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }


    @Test
    public void setLockCredential_primaryWithUnifiedProfileWithCredential_leavesStrongAuthForBoth()
            throws Exception {
        final LockscreenCredential oldCredential = newPassword("oldPassword");
        final LockscreenCredential newCredential = newPassword("newPassword");
        setCredential(PRIMARY_USER_ID, oldCredential);
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        reset(mStrongAuth);

        setCredential(PRIMARY_USER_ID, newCredential, oldCredential);

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    public void
            testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()
@@ -342,6 +460,18 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
        checkRecordedFrpNotificationIntent();
    }

    @Test
    public void clearLockCredential_primaryWithUnifiedProfile_leavesStrongAuthForBoth()
            throws Exception {
        setCredential(PRIMARY_USER_ID, newPassword("password"));
        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
        reset(mStrongAuth);

        clearCredential(PRIMARY_USER_ID, newPassword("password"));

        verify(mStrongAuth, never()).reportUnlock(anyInt());
    }

    @Test
    public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()
            throws Exception {