diff options
| author | 2013-09-11 14:58:26 -0700 | |
|---|---|---|
| committer | 2013-09-16 15:34:26 -0700 | |
| commit | de1af08dd3a073f007ae4b8a114352cae3775028 (patch) | |
| tree | 3c61a4534410508835e4a102b281cc98aea58e78 | |
| parent | 50e5814c337f67c74d9e249cf6f67ac86dfc832d (diff) | |
Fix keyguard/Keystore storage issue
Keystore stored keys broke when keyguard was moved out of the system process
due to Keystore enforcing the calling app to be in the system process.
The fix moves the critical code into LockSettingsService, which continues
to live in the system process.
Fixes bug 10201270
Change-Id: I16e2de018e85b01265634dcfbefd7f06740dafa8
3 files changed, 61 insertions, 56 deletions
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index c72c77097412..91056f160910 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -24,10 +24,10 @@ interface ILockSettings { boolean getBoolean(in String key, in boolean defaultValue, in int userId); 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 byte[] hash, int userId); - boolean checkPattern(in byte[] hash, int userId); - void setLockPassword(in byte[] hash, int userId); - boolean checkPassword(in byte[] hash, int userId); + void setLockPattern(in String pattern, int userId); + boolean checkPattern(in String pattern, int userId); + void setLockPassword(in String password, int userId); + boolean checkPassword(in String password, int userId); boolean havePattern(int userId); boolean havePassword(int userId); void removeUser(int userId); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 1f2ab9373ba8..8adc7b629a3e 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -32,7 +32,6 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.storage.IMountService; import android.provider.Settings; -import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -292,11 +291,7 @@ public class LockPatternUtils { public boolean checkPattern(List<LockPatternView.Cell> pattern) { final int userId = getCurrentOrCallingUserId(); try { - final boolean matched = getLockSettings().checkPattern(patternToHash(pattern), userId); - if (matched && (userId == UserHandle.USER_OWNER)) { - KeyStore.getInstance().password(patternToString(pattern)); - } - return matched; + return getLockSettings().checkPattern(patternToString(pattern), userId); } catch (RemoteException re) { return true; } @@ -311,12 +306,7 @@ public class LockPatternUtils { public boolean checkPassword(String password) { final int userId = getCurrentOrCallingUserId(); try { - final boolean matched = getLockSettings().checkPassword(passwordToHash(password), - userId); - if (matched && (userId == UserHandle.USER_OWNER)) { - KeyStore.getInstance().password(password); - } - return matched; + return getLockSettings().checkPassword(password, userId); } catch (RemoteException re) { return true; } @@ -505,14 +495,10 @@ public class LockPatternUtils { * @param isFallback Specifies if this is a fallback to biometric weak */ public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) { - // Compute the hash - final byte[] hash = LockPatternUtils.patternToHash(pattern); try { - getLockSettings().setLockPattern(hash, getCurrentOrCallingUserId()); + getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId()); DevicePolicyManager dpm = getDevicePolicyManager(); - KeyStore keyStore = KeyStore.getInstance(); if (pattern != null) { - keyStore.password(patternToString(pattern)); setBoolean(PATTERN_EVER_CHOSEN_KEY, true); if (!isFallback) { deleteGallery(); @@ -528,9 +514,6 @@ public class LockPatternUtils { 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); } } else { - if (keyStore.isEmpty()) { - keyStore.reset(); - } dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); } @@ -637,19 +620,13 @@ public class LockPatternUtils { * @param userHandle The userId of the user to change the password for */ public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { - // Compute the hash - final byte[] hash = passwordToHash(password); try { - getLockSettings().setLockPassword(hash, userHandle); + getLockSettings().setLockPassword(password, userHandle); DevicePolicyManager dpm = getDevicePolicyManager(); - KeyStore keyStore = KeyStore.getInstance(); if (password != null) { if (userHandle == UserHandle.USER_OWNER) { // Update the encryption password. updateEncryptionPassword(password); - - // Update the keystore password - keyStore.password(password); } int computedQuality = computePasswordQuality(password); @@ -709,6 +686,7 @@ public class LockPatternUtils { if (passwordHistoryLength == 0) { passwordHistory = ""; } else { + byte[] hash = passwordToHash(password); passwordHistory = new String(hash) + "," + passwordHistory; // Cut it to contain passwordHistoryLength hashes // and passwordHistoryLength -1 commas. @@ -718,11 +696,6 @@ public class LockPatternUtils { } setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); } else { - // Conditionally reset the keystore if empty. If - // non-empty, we are just switching key guard type - if (keyStore.isEmpty()) { - keyStore.reset(); - } dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle); @@ -803,7 +776,7 @@ public class LockPatternUtils { * @param pattern the gesture pattern. * @return the hash of the pattern in a byte array. */ - private static byte[] patternToHash(List<LockPatternView.Cell> pattern) { + public static byte[] patternToHash(List<LockPatternView.Cell> pattern) { if (pattern == null) { return null; } diff --git a/services/java/com/android/server/LockSettingsService.java b/services/java/com/android/server/LockSettingsService.java index c5555c871680..cd746cf44823 100644 --- a/services/java/com/android/server/LockSettingsService.java +++ b/services/java/com/android/server/LockSettingsService.java @@ -40,6 +40,7 @@ import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; +import android.security.KeyStore; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -80,11 +81,14 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String LOCK_PASSWORD_FILE = "password.key"; private final Context mContext; + private LockPatternUtils mLockPatternUtils; public LockSettingsService(Context context) { mContext = context; // Open the database mOpenHelper = new DatabaseHelper(mContext); + + mLockPatternUtils = new LockPatternUtils(context); } public void systemReady() { @@ -255,15 +259,42 @@ public class LockSettingsService extends ILockSettings.Stub { return new File(getLockPatternFilename(userId)).length() > 0; } + private void maybeUpdateKeystore(String password, int userId) { + if (userId == UserHandle.USER_OWNER) { + final KeyStore keyStore = KeyStore.getInstance(); + // Conditionally reset the keystore if empty. If non-empty, we are just + // switching key guard type + if (TextUtils.isEmpty(password) && keyStore.isEmpty()) { + keyStore.reset(); + } else { + // Update the keystore password + keyStore.password(password); + } + } + } + @Override - public void setLockPattern(byte[] hash, int userId) throws RemoteException { + public void setLockPattern(String pattern, int userId) throws RemoteException { checkWritePermission(userId); + maybeUpdateKeystore(pattern, userId); + + final byte[] hash = LockPatternUtils.patternToHash( + LockPatternUtils.stringToPattern(pattern)); writeFile(getLockPatternFilename(userId), hash); } @Override - public boolean checkPattern(byte[] hash, int userId) throws RemoteException { + public void setLockPassword(String password, int userId) throws RemoteException { + checkWritePermission(userId); + + maybeUpdateKeystore(password, userId); + + writeFile(getLockPasswordFilename(userId), mLockPatternUtils.passwordToHash(password)); + } + + @Override + public boolean checkPattern(String pattern, int userId) throws RemoteException { checkPasswordReadPermission(userId); try { // Read all the bytes from the file @@ -275,25 +306,23 @@ public class LockSettingsService extends ILockSettings.Stub { return true; } // Compare the hash from the file with the entered pattern's hash - return Arrays.equals(stored, hash); + final byte[] hash = LockPatternUtils.patternToHash( + LockPatternUtils.stringToPattern(pattern)); + final boolean matched = Arrays.equals(stored, hash); + if (matched && !TextUtils.isEmpty(pattern)) { + maybeUpdateKeystore(pattern, userId); + } + return matched; } catch (FileNotFoundException fnfe) { Slog.e(TAG, "Cannot read file " + fnfe); - return true; } catch (IOException ioe) { Slog.e(TAG, "Cannot read file " + ioe); - return true; } + return true; } @Override - public void setLockPassword(byte[] hash, int userId) throws RemoteException { - checkWritePermission(userId); - - writeFile(getLockPasswordFilename(userId), hash); - } - - @Override - public boolean checkPassword(byte[] hash, int userId) throws RemoteException { + public boolean checkPassword(String password, int userId) throws RemoteException { checkPasswordReadPermission(userId); try { @@ -306,14 +335,18 @@ public class LockSettingsService extends ILockSettings.Stub { return true; } // Compare the hash from the file with the entered password's hash - return Arrays.equals(stored, hash); + final byte[] hash = mLockPatternUtils.passwordToHash(password); + final boolean matched = Arrays.equals(stored, hash); + if (matched && !TextUtils.isEmpty(password)) { + maybeUpdateKeystore(password, userId); + } + return matched; } catch (FileNotFoundException fnfe) { Slog.e(TAG, "Cannot read file " + fnfe); - return true; } catch (IOException ioe) { Slog.e(TAG, "Cannot read file " + ioe); - return true; } + return true; } @Override @@ -445,13 +478,12 @@ public class LockSettingsService extends ILockSettings.Stub { private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) { final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); final ContentResolver cr = mContext.getContentResolver(); - final LockPatternUtils utils = new LockPatternUtils(mContext); final List<UserInfo> users = um.getUsers(); for (int i = 0; i < users.size(); i++) { final int userId = users.get(i).id; - final boolean enabled = utils.hasWidgetsEnabledInKeyguard(userId); + final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId); Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled=" - + enabled + ", w[]=" + utils.getAppWidgets()); + + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets()); loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled); } } |