summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jim Miller <jaggies@google.com> 2013-09-11 14:58:26 -0700
committer Jim Miller <jaggies@google.com> 2013-09-16 15:34:26 -0700
commitde1af08dd3a073f007ae4b8a114352cae3775028 (patch)
tree3c61a4534410508835e4a102b281cc98aea58e78
parent50e5814c337f67c74d9e249cf6f67ac86dfc832d (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
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl8
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java39
-rw-r--r--services/java/com/android/server/LockSettingsService.java70
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);
}
}