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

Commit 68b474fe authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move signal locking Keystore" into main

parents 9a277a00 ab9f17f8
Loading
Loading
Loading
Loading
+14 −26
Original line number Original line Diff line number Diff line
@@ -113,9 +113,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageManager;
import android.security.KeyStoreAuthorization;
import android.text.TextUtils;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -142,6 +140,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService.UserCompletedEventType;
import com.android.server.SystemService.UserCompletedEventType;
import com.android.server.SystemServiceManager;
import com.android.server.SystemServiceManager;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.locksettings.LockSettingsInternal;
import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserJourneyLogger.UserJourneySession;
import com.android.server.pm.UserJourneyLogger.UserJourneySession;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal;
@@ -1652,7 +1651,6 @@ class UserController implements Handler.Callback {
        }
        }
    }
    }



    private void dispatchUserLocking(@UserIdInt int userId,
    private void dispatchUserLocking(@UserIdInt int userId,
            @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) {
            @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) {
        // Evict user secrets that require strong authentication to unlock. This includes locking
        // Evict user secrets that require strong authentication to unlock. This includes locking
@@ -1660,22 +1658,12 @@ class UserController implements Handler.Callback {
        // Performed on FgThread to make it serialized with call to
        // Performed on FgThread to make it serialized with call to
        // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption.
        // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption.
        FgThread.getHandler().post(() -> {
        FgThread.getHandler().post(() -> {
            synchronized (mLock) {
            if (hasStartedUserState(userId)) {
                if (mStartedUsers.get(userId) != null) {
                Slogf.w(TAG, "User was restarted, skipping key eviction");
                Slogf.w(TAG, "User was restarted, skipping key eviction");
                return;
                return;
            }
            }
            }
            mInjector.getLockSettingsInternal().lockUser(userId);
            try {

                Slogf.i(TAG, "Locking CE storage for user #" + userId);
                mInjector.getStorageManager().lockCeStorage(userId);
            } catch (RemoteException re) {
                throw re.rethrowAsRuntimeException();
            }
            if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) {
                // Send communication to keystore to wipe key cache for the given userId.
                mInjector.getKeyStoreAuthorization().onUserStorageLocked(userId);
            }
            if (keyEvictedCallbacks == null) {
            if (keyEvictedCallbacks == null) {
                return;
                return;
            }
            }
@@ -4245,6 +4233,7 @@ class UserController implements Handler.Callback {
        private final ActivityManagerService mService;
        private final ActivityManagerService mService;
        private UserManagerService mUserManager;
        private UserManagerService mUserManager;
        private UserManagerInternal mUserManagerInternal;
        private UserManagerInternal mUserManagerInternal;
        private LockSettingsInternal mLockSettingsInternal;
        private PowerManagerInternal mPowerManagerInternal;
        private PowerManagerInternal mPowerManagerInternal;
        private Handler mHandler;
        private Handler mHandler;
        private final Object mUserSwitchingDialogLock = new Object();
        private final Object mUserSwitchingDialogLock = new Object();
@@ -4335,6 +4324,13 @@ class UserController implements Handler.Callback {
            return mUserManagerInternal;
            return mUserManagerInternal;
        }
        }


        LockSettingsInternal getLockSettingsInternal() {
            if (mLockSettingsInternal == null) {
                mLockSettingsInternal = LocalServices.getService(LockSettingsInternal.class);
            }
            return mLockSettingsInternal;
        }

        PowerManagerInternal getPowerManagerInternal() {
        PowerManagerInternal getPowerManagerInternal() {
            if (mPowerManagerInternal == null) {
            if (mPowerManagerInternal == null) {
                mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
                mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
@@ -4354,10 +4350,6 @@ class UserController implements Handler.Callback {
            return mService.mContext.getSystemService(KeyguardManager.class);
            return mService.mContext.getSystemService(KeyguardManager.class);
        }
        }


        KeyStoreAuthorization getKeyStoreAuthorization() {
            return KeyStoreAuthorization.getInstance();
        }

        void batteryStatsServiceNoteEvent(int code, String name, int uid) {
        void batteryStatsServiceNoteEvent(int code, String name, int uid) {
            mService.mBatteryStatsService.noteEvent(code, name, uid);
            mService.mBatteryStatsService.noteEvent(code, name, uid);
        }
        }
@@ -4503,10 +4495,6 @@ class UserController implements Handler.Callback {
            return mService.mAtmInternal.isCallerRecents(callingUid);
            return mService.mAtmInternal.isCallerRecents(callingUid);
        }
        }


        protected IStorageManager getStorageManager() {
            return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
        }

        boolean isHeadlessSystemUserMode() {
        boolean isHeadlessSystemUserMode() {
            return UserManager.isHeadlessSystemUserMode();
            return UserManager.isHeadlessSystemUserMode();
        }
        }
+8 −0
Original line number Original line Diff line number Diff line
@@ -130,6 +130,14 @@ public abstract class LockSettingsInternal {
     */
     */
    public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId);
    public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId);



    /**
     * Lock the specified user, i.e. storage, keystore state, and strong auth flags.
     *
     * @param userId the ID of the user being locked.
     */
    public abstract void lockUser(@UserIdInt int userId);

    /**
    /**
     * Returns PasswordMetrics object corresponding to the given user's lockscreen password.
     * Returns PasswordMetrics object corresponding to the given user's lockscreen password.
     * If the user has a password but its metrics isn't known yet (for example if the device
     * If the user has a password but its metrics isn't known yet (for example if the device
+35 −26
Original line number Original line Diff line number Diff line
@@ -97,10 +97,8 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.os.storage.ICeStorageLockEventListener;
import android.os.storage.IStorageManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.provider.Settings;
import android.provider.Settings;
import android.security.AndroidKeyStoreMaintenance;
import android.security.AndroidKeyStoreMaintenance;
import android.security.KeyStoreAuthorization;
import android.security.KeyStoreAuthorization;
@@ -335,8 +333,6 @@ public class LockSettingsService extends ILockSettings.Stub {
    private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners =
    private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners =
            new CopyOnWriteArrayList<>();
            new CopyOnWriteArrayList<>();


    private final StorageManagerInternal mStorageManagerInternal;

    private final Object mGcWorkToken = new Object();
    private final Object mGcWorkToken = new Object();


    // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
    // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
@@ -589,10 +585,6 @@ public class LockSettingsService extends ILockSettings.Stub {
            return null;
            return null;
        }
        }


        public StorageManagerInternal getStorageManagerInternal() {
            return LocalServices.getService(StorageManagerInternal.class);
        }

        public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
        public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
            return new SyntheticPasswordManager(getContext(), storage, getUserManager(),
            return new SyntheticPasswordManager(getContext(), storage, getUserManager(),
                    new PasswordSlotManager());
                    new PasswordSlotManager());
@@ -723,7 +715,6 @@ public class LockSettingsService extends ILockSettings.Stub {
        mNotificationManager = injector.getNotificationManager();
        mNotificationManager = injector.getNotificationManager();
        mUserManager = injector.getUserManager();
        mUserManager = injector.getUserManager();
        mStorageManager = injector.getStorageManager();
        mStorageManager = injector.getStorageManager();
        mStorageManagerInternal = injector.getStorageManagerInternal();
        mStrongAuthTracker = injector.getStrongAuthTracker();
        mStrongAuthTracker = injector.getStrongAuthTracker();
        mStrongAuthTracker.register(mStrongAuth);
        mStrongAuthTracker.register(mStrongAuth);
        mGatekeeperPasswords = new LongSparseArray<>();
        mGatekeeperPasswords = new LongSparseArray<>();
@@ -969,24 +960,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
        mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(),
        mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(),
                mInjector.getFaceManager(), mInjector.getBiometricManager());
                mInjector.getFaceManager(), mInjector.getBiometricManager());
        mStorageManagerInternal.registerStorageLockEventListener(mCeStorageLockEventListener);
    }

    private final ICeStorageLockEventListener mCeStorageLockEventListener =
            new ICeStorageLockEventListener() {
                @Override
                public void onStorageLocked(int userId) {
                    Slog.i(TAG, "Storage lock event received for " + userId);
                    mHandler.post(() -> {
                        UserProperties userProperties = getUserProperties(userId);
                        if (userProperties != null && userProperties
                                .getAllowStoppingUserWithDelayedLocking()) {
                            int strongAuthRequired = LockPatternUtils.StrongAuthTracker
                                    .getDefaultFlags(mContext);
                            requireStrongAuth(strongAuthRequired, userId);
    }
    }
                    });
                }};


    private void loadEscrowData() {
    private void loadEscrowData() {
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler);
        mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler);
@@ -1552,6 +1526,10 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
        }
    }
    }


    private void lockKeystore(int userId) {
        mKeyStoreAuthorization.onUserStorageLocked(userId);
    }

    @VisibleForTesting /** Note: this method is overridden in unit tests */
    @VisibleForTesting /** Note: this method is overridden in unit tests */
    protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId)
    protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId)
            throws KeyStoreException, UnrecoverableKeyException,
            throws KeyStoreException, UnrecoverableKeyException,
@@ -3513,6 +3491,32 @@ public class LockSettingsService extends ILockSettings.Stub {
        return true;
        return true;
    }
    }


    private void lockUser(@UserIdInt int userId) {
        // Lock the user's credential-encrypted storage.
        try {
            Slogf.i(TAG, "Locking CE storage for user #" + userId);
            mInjector.getStorageManager().lockCeStorage(userId);
        } catch (RemoteException re) {
            throw re.rethrowAsRuntimeException();
        }

        // Lock user's Keystore by wiping the user's super key cache.
        if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) {
            lockKeystore(userId);
        }

        // Reset user's strong auth flags
        mHandler.post(() -> {
            UserProperties userProperties = getUserProperties(userId);
            if (userProperties != null && userProperties
                    .getAllowStoppingUserWithDelayedLocking()) {
                int strongAuthRequired = LockPatternUtils.StrongAuthTracker
                        .getDefaultFlags(mContext);
                requireStrongAuth(strongAuthRequired, userId);
            }
        });
    }

    @Override
    @Override
    public boolean tryUnlockWithCachedUnifiedChallenge(int userId) {
    public boolean tryUnlockWithCachedUnifiedChallenge(int userId) {
        checkPasswordReadPermission();
        checkPasswordReadPermission();
@@ -3849,6 +3853,11 @@ public class LockSettingsService extends ILockSettings.Stub {
            return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
            return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
        }
        }


        @Override
        public void lockUser(@UserIdInt int userId) {
            LockSettingsService.this.lockUser(userId);
        }

        @Override
        @Override
        public PasswordMetrics getUserPasswordMetrics(int userHandle) {
        public PasswordMetrics getUserPasswordMetrics(int userHandle) {
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
+9 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.spy;
@@ -29,8 +30,10 @@ import static org.mockito.Mockito.when;


import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Handler;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;


import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal;
@@ -166,5 +169,11 @@ public final class UserControllerMockedTest {


    private void mockSystemUserHeadlessMode(boolean headless) {
    private void mockSystemUserHeadlessMode(boolean headless) {
        when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless);
        when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless);
        UserInfo sysInfo = new UserInfo(UserHandle.USER_SYSTEM,
                "User" + UserHandle.USER_SYSTEM, /* iconPath= */ null,
                headless ? UserInfo.FLAG_SYSTEM : UserInfo.FLAG_FULL | UserInfo.FLAG_SYSTEM,
                headless
                    ? UserManager.USER_TYPE_SYSTEM_HEADLESS : UserManager.USER_TYPE_FULL_SYSTEM);
        when(mUserManagerService.getUserInfo(eq(UserHandle.USER_SYSTEM))).thenReturn(sysInfo);
    }
    }
}
}
+14 −11
Original line number Original line Diff line number Diff line
@@ -116,6 +116,7 @@ import com.android.server.AlarmManagerInternal;
import com.android.server.FgThread;
import com.android.server.FgThread;
import com.android.server.SystemService;
import com.android.server.SystemService;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.locksettings.LockSettingsInternal;
import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.UserManagerService;
@@ -1150,8 +1151,8 @@ public class UserControllerTest {
        // Cannot mock FgThread handler, so confirm that there is no posted message left before
        // Cannot mock FgThread handler, so confirm that there is no posted message left before
        // checking.
        // checking.
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        verify(mInjector.mStorageManagerMock, times(0))
        verify(mInjector.mLockSettingsInternalMock, times(0))
                .lockCeStorage(anyInt());
                .lockUser(anyInt());


        addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
        addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
                numberOfUserSwitches, true, false);
                numberOfUserSwitches, true, false);
@@ -1164,8 +1165,8 @@ public class UserControllerTest {
        ussUser1.setState(UserState.STATE_SHUTDOWN);
        ussUser1.setState(UserState.STATE_SHUTDOWN);
        mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true);
        mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true);
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        verify(mInjector.mStorageManagerMock, times(1))
        verify(mInjector.mLockSettingsInternalMock, times(1))
                .lockCeStorage(TEST_USER_ID);
                .lockUser(TEST_USER_ID);
    }
    }


    /** Tests that we stop excess users when starting a background user. */
    /** Tests that we stop excess users when starting a background user. */
@@ -2119,8 +2120,8 @@ public class UserControllerTest {
        // no easy way to get that information passed through lambda.
        // no easy way to get that information passed through lambda.
        mUserController.finishUserStopped(ussUser, allowDelayedLocking);
        mUserController.finishUserStopped(ussUser, allowDelayedLocking);
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
        verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0))
        verify(mInjector.mLockSettingsInternalMock, times(expectLocking ? 1 : 0))
                .lockCeStorage(userId);
                .lockUser(eq(userId));
    }
    }


    private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
    private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
@@ -2288,6 +2289,7 @@ public class UserControllerTest {


        private final IStorageManager mStorageManagerMock;
        private final IStorageManager mStorageManagerMock;
        private final UserManagerInternal mUserManagerInternalMock;
        private final UserManagerInternal mUserManagerInternalMock;
        private final LockSettingsInternal mLockSettingsInternalMock;
        private final WindowManagerService mWindowManagerMock;
        private final WindowManagerService mWindowManagerMock;
        private final PowerManagerInternal mPowerManagerInternal;
        private final PowerManagerInternal mPowerManagerInternal;
        private final AlarmManagerInternal mAlarmManagerInternal;
        private final AlarmManagerInternal mAlarmManagerInternal;
@@ -2310,6 +2312,7 @@ public class UserControllerTest {
            mUiHandler = new TestHandler(mHandlerThread.getLooper());
            mUiHandler = new TestHandler(mHandlerThread.getLooper());
            mUserManagerMock = mock(UserManagerService.class);
            mUserManagerMock = mock(UserManagerService.class);
            mUserManagerInternalMock = mock(UserManagerInternal.class);
            mUserManagerInternalMock = mock(UserManagerInternal.class);
            mLockSettingsInternalMock = mock(LockSettingsInternal.class);
            mWindowManagerMock = mock(WindowManagerService.class);
            mWindowManagerMock = mock(WindowManagerService.class);
            mStorageManagerMock = mock(IStorageManager.class);
            mStorageManagerMock = mock(IStorageManager.class);
            mPowerManagerInternal = mock(PowerManagerInternal.class);
            mPowerManagerInternal = mock(PowerManagerInternal.class);
@@ -2341,6 +2344,11 @@ public class UserControllerTest {
            return mUserManagerInternalMock;
            return mUserManagerInternalMock;
        }
        }


        @Override
        LockSettingsInternal getLockSettingsInternal() {
            return mLockSettingsInternalMock;
        }

        @Override
        @Override
        protected Context getContext() {
        protected Context getContext() {
            return mCtx;
            return mCtx;
@@ -2426,11 +2434,6 @@ public class UserControllerTest {
            return true;
            return true;
        }
        }


        @Override
        protected IStorageManager getStorageManager() {
            return mStorageManagerMock;
        }

        @Override
        @Override
        void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
        void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
                String switchingFromSystemUserMessage, String switchingToSystemUserMessage,
                String switchingFromSystemUserMessage, String switchingToSystemUserMessage,
Loading