OSDN Git Service

Add resetKeyStore() in LockSettingsService
authorRicky Wai <rickywai@google.com>
Tue, 24 May 2016 10:11:42 +0000 (11:11 +0100)
committerRicky Wai <rickywai@google.com>
Wed, 25 May 2016 10:39:56 +0000 (11:39 +0100)
Before resetKeyStore(), it will back up child profile keys,
and will be restored after primary profile keystore is cleared.

Bug: 28878708
Change-Id: I0cb4a1f885d468894bc7eb95af694328bf92ce16

core/java/com/android/internal/widget/ILockSettings.aidl
core/java/com/android/internal/widget/LockPatternUtils.java
services/core/java/com/android/server/LockSettingsService.java

index b2fc2bb..353c72f 100644 (file)
@@ -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);
index d9b6329..266eba3 100644 (file)
@@ -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) {
index 596fd44..145aeb2 100644 (file)
@@ -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);
     }