Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +36 −6 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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, Loading @@ -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); } } Loading Loading @@ -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); } } } } } } Loading @@ -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; Loading Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +36 −6 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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, Loading @@ -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); } } Loading Loading @@ -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); } } } } } } Loading @@ -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; Loading