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

Commit 060b87b0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Unlock managed profile keystore when user is unlocked." into oc-mr1-dev

parents 5285e053 0acc4bf5
Loading
Loading
Loading
Loading
+36 −6
Original line number Original line Diff line number Diff line
@@ -74,6 +74,7 @@ import android.security.KeyStore;
import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.security.keystore.KeyProtection;
import android.security.keystore.UserNotAuthenticatedException;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
import android.text.TextUtils;
@@ -503,12 +504,34 @@ public class LockSettingsService extends ILockSettings.Stub {
        maybeShowEncryptionNotificationForUser(userId);
        maybeShowEncryptionNotificationForUser(userId);
    }
    }


    /**
     * Check if profile got unlocked but the keystore is still locked. This happens on full disk
     * encryption devices since the profile may not yet be running when we consider unlocking it
     * during the normal flow. In this case unlock the keystore for the profile.
     */
    private void ensureProfileKeystoreUnlocked(int userId) {
        final KeyStore ks = KeyStore.getInstance();
        if (ks.state(userId) == KeyStore.State.LOCKED
                && tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) {
            Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore");
            try {
                // If boot took too long and the password in vold got expired, parent keystore will
                // be still locked, we ignore this case since the user will be prompted to unlock
                // the device after boot.
                unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to unlock child profile");
            }
        }
    }

    public void onUnlockUser(final int userId) {
    public void onUnlockUser(final int userId) {
        // Perform tasks which require locks in LSS on a handler, as we are callbacks from
        // Perform tasks which require locks in LSS on a handler, as we are callbacks from
        // ActivityManager.unlockUser()
        // ActivityManager.unlockUser()
        mHandler.post(new Runnable() {
        mHandler.post(new Runnable() {
            @Override
            @Override
            public void run() {
            public void run() {
                ensureProfileKeystoreUnlocked(userId);
                // Hide notification first, as tie managed profile lock takes time
                // Hide notification first, as tie managed profile lock takes time
                hideEncryptionNotification(new UserHandle(userId));
                hideEncryptionNotification(new UserHandle(userId));


@@ -1027,7 +1050,8 @@ public class LockSettingsService extends ILockSettings.Stub {
        return new String(decryptionResult, StandardCharsets.UTF_8);
        return new String(decryptionResult, StandardCharsets.UTF_8);
    }
    }


    private void unlockChildProfile(int profileHandle) throws RemoteException {
    private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated)
            throws RemoteException {
        try {
        try {
            doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
            doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
@@ -1038,6 +1062,8 @@ public class LockSettingsService extends ILockSettings.Stub {
                | BadPaddingException | CertificateException | IOException e) {
                | BadPaddingException | CertificateException | IOException e) {
            if (e instanceof FileNotFoundException) {
            if (e instanceof FileNotFoundException) {
                Slog.i(TAG, "Child profile key not found");
                Slog.i(TAG, "Child profile key not found");
            } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) {
                Slog.i(TAG, "Parent keystore seems locked, ignoring");
            } else {
            } else {
                Slog.e(TAG, "Failed to decrypt child profile key", e);
                Slog.e(TAG, "Failed to decrypt child profile key", e);
            }
            }
@@ -1081,11 +1107,8 @@ public class LockSettingsService extends ILockSettings.Stub {
                final List<UserInfo> profiles = mUserManager.getProfiles(userId);
                final List<UserInfo> profiles = mUserManager.getProfiles(userId);
                for (UserInfo pi : profiles) {
                for (UserInfo pi : profiles) {
                    // Unlock managed profile with unified lock
                    // Unlock managed profile with unified lock
                    if (pi.isManagedProfile()
                    if (tiedManagedProfileReadyToUnlock(pi)) {
                            && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
                        unlockChildProfile(pi.id, false /* ignoreUserNotAuthenticated */);
                            && mStorage.hasChildProfileLock(pi.id)
                            && mUserManager.isUserRunning(pi.id)) {
                        unlockChildProfile(pi.id);
                    }
                    }
                }
                }
            }
            }
@@ -1094,6 +1117,13 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
        }
    }
    }


    private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) {
        return userInfo.isManagedProfile()
                && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id)
                && mStorage.hasChildProfileLock(userInfo.id)
                && mUserManager.isUserRunning(userInfo.id);
    }

    private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
    private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
            return null;
            return null;