diff options
3 files changed, 66 insertions, 1 deletions
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index b2fc2bb8c89f..353c72fd1a90 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -28,6 +28,7 @@ interface ILockSettings { long getLong(in String key, in long defaultValue, in int userId); String getString(in String key, in String defaultValue, in int userId); void setLockPattern(in String pattern, in String savedPattern, int userId); + void resetKeyStore(int userId); VerifyCredentialResponse checkPattern(in String pattern, int userId); VerifyCredentialResponse verifyPattern(in String pattern, long challenge, int userId); void setLockPassword(in String password, in String savedPassword, int userId); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index d9b63296dea9..266eba34ea43 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -532,6 +532,18 @@ public class LockPatternUtils { } /** + * Use it to reset keystore without wiping work profile + */ + public void resetKeyStore(int userId) { + try { + getLockSettings().resetKeyStore(userId); + } catch (RemoteException e) { + // It should not happen + Log.e(TAG, "Couldn't reset keystore " + e); + } + } + + /** * Clear any lock pattern or password. */ public void clearLock(int userHandle) { diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 596fd441d928..145aeb2125b9 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -46,6 +46,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.IProgressListener; import android.os.Parcel; +import android.os.Process; import android.os.RemoteException; import android.os.storage.IMountService; import android.os.ServiceManager; @@ -127,6 +128,14 @@ public class LockSettingsService extends ILockSettings.Stub { private NotificationManager mNotificationManager; private UserManager mUserManager; + private final KeyStore mKeyStore = KeyStore.getInstance(); + + /** + * The UIDs that are used for system credential storage in keystore. + */ + private static final int[] SYSTEM_CREDENTIAL_UIDS = {Process.WIFI_UID, Process.VPN_UID, + Process.ROOT_UID, Process.SYSTEM_UID}; + static { // Just launch the home screen, which happens anyway ACTION_NULL = new Intent(Intent.ACTION_MAIN); @@ -647,7 +656,7 @@ public class LockSettingsService extends ILockSettings.Stub { NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, CertificateException, IOException { - if (DEBUG) Slog.v(TAG, "Unlock keystore for child profile"); + if (DEBUG) Slog.v(TAG, "Get child profile decrytped key"); byte[] storedData = mStorage.readChildProfileLock(userId); if (storedData == null) { throw new FileNotFoundException("Child profile lock file not found"); @@ -1067,6 +1076,49 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override + public void resetKeyStore(int userId) throws RemoteException { + if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId); + int managedUserId = -1; + String managedUserDecryptedPassword = null; + final List<UserInfo> profiles = mUserManager.getProfiles(userId); + for (UserInfo pi : profiles) { + // Unlock managed profile with unified lock + if (pi.isManagedProfile() + && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id) + && mStorage.hasChildProfileLock(pi.id)) { + try { + if (managedUserId == -1) { + managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id); + managedUserId = pi.id; + } else { + // Should not happen + Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId + + ", uid2:" + pi.id); + } + } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException + | NoSuchAlgorithmException | NoSuchPaddingException + | InvalidAlgorithmParameterException | IllegalBlockSizeException + | BadPaddingException | CertificateException | IOException e) { + Slog.e(TAG, "Failed to decrypt child profile key", e); + } + } + } + try { + // Clear all the users credentials could have been installed in for this user. + for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) { + for (int uid : SYSTEM_CREDENTIAL_UIDS) { + mKeyStore.clearUid(UserHandle.getUid(profileId, uid)); + } + } + } finally { + if (managedUserId != -1 && managedUserDecryptedPassword != null) { + if (DEBUG) Slog.v(TAG, "Restore tied profile lock"); + tieProfileLockToParent(managedUserId, managedUserDecryptedPassword); + } + } + } + + @Override public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException { return doVerifyPattern(pattern, false, 0, userId); } |