summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java88
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java17
2 files changed, 97 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a105c8414afe..2ce7e60067ac 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -192,6 +192,14 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
+ public void onBootPhase(int phase) {
+ super.onBootPhase(phase);
+ if (phase == PHASE_ACTIVITY_MANAGER_READY) {
+ mLockSettingsService.migrateOldDataAfterSystemReady();
+ }
+ }
+
+ @Override
public void onStartUser(int userHandle) {
mLockSettingsService.onStartUser(userHandle);
}
@@ -720,6 +728,73 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
+ private void migrateOldDataAfterSystemReady() {
+ try {
+ // Migrate the FRP credential to the persistent data block
+ if (LockPatternUtils.frpCredentialEnabled() && !getBoolean("migrated_frp", false, 0)) {
+ migrateFrpCredential();
+ setBoolean("migrated_frp", true, 0);
+ Slog.i(TAG, "Migrated migrated_frp.");
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to migrateOldDataAfterSystemReady", e);
+ }
+ }
+
+ /**
+ * Migrate the credential for the FRP credential owner user if the following are satisfied:
+ * - the user has a secure credential
+ * - the FRP credential is not set up
+ * - the credential is based on a synthetic password.
+ */
+ private void migrateFrpCredential() throws RemoteException {
+ if (mStorage.readPersistentDataBlock() != PersistentData.NONE) {
+ return;
+ }
+ for (UserInfo userInfo : mUserManager.getUsers()) {
+ if (userOwnsFrpCredential(userInfo) && isUserSecure(userInfo.id)) {
+ synchronized (mSpManager) {
+ if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) {
+ int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
+
+ mSpManager.migrateFrpPasswordLocked(
+ getSyntheticPasswordHandleLocked(userInfo.id),
+ userInfo,
+ redactActualQualityToMostLenientEquivalentQuality(actualQuality));
+ }
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Returns the lowest password quality that still presents the same UI for entering it.
+ *
+ * For the FRP credential, we do not want to leak the actual quality of the password, only what
+ * kind of UI it requires. However, when migrating, we only know the actual quality, not the
+ * originally requested quality; since this is only used to determine what input variant to
+ * present to the user, we just assume the lowest possible quality was requested.
+ */
+ private int redactActualQualityToMostLenientEquivalentQuality(int quality) {
+ switch (quality) {
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+ case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
+ default:
+ return quality;
+ }
+ }
+
private final void checkWritePermission(int userId) {
mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
}
@@ -803,7 +878,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
+ public boolean getBoolean(String key, boolean defaultValue, int userId) {
checkReadPermission(key, userId);
String value = getStringUnchecked(key, null, userId);
return TextUtils.isEmpty(value) ?
@@ -811,14 +886,14 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public long getLong(String key, long defaultValue, int userId) throws RemoteException {
+ public long getLong(String key, long defaultValue, int userId) {
checkReadPermission(key, userId);
String value = getStringUnchecked(key, null, userId);
return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
}
@Override
- public String getString(String key, String defaultValue, int userId) throws RemoteException {
+ public String getString(String key, String defaultValue, int userId) {
checkReadPermission(key, userId);
return getStringUnchecked(key, defaultValue, userId);
}
@@ -1923,11 +1998,8 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private long getSyntheticPasswordHandleLocked(int userId) {
- try {
- return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId);
- } catch (RemoteException e) {
- return SyntheticPasswordManager.DEFAULT_HANDLE;
- }
+ return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY,
+ SyntheticPasswordManager.DEFAULT_HANDLE, userId);
}
private boolean isSyntheticPasswordBasedCredentialLocked(int userId) throws RemoteException {
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 603e46a49e19..ded42c020b45 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -19,6 +19,7 @@ package com.android.server.locksettings;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
+import android.content.pm.UserInfo;
import android.hardware.weaver.V1_0.IWeaver;
import android.hardware.weaver.V1_0.WeaverConfig;
import android.hardware.weaver.V1_0.WeaverReadResponse;
@@ -642,6 +643,22 @@ public class SyntheticPasswordManager {
}
+ public void migrateFrpPasswordLocked(long handle, UserInfo userInfo, int requestedQuality) {
+ if (mStorage.getPersistentDataBlock() != null
+ && LockPatternUtils.userOwnsFrpCredential(userInfo)) {
+ PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, handle,
+ userInfo.id));
+ if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ int weaverSlot = loadWeaverSlot(handle, userInfo.id);
+ if (weaverSlot != INVALID_WEAVER_SLOT) {
+ synchronizeWeaverFrpPassword(pwd, requestedQuality, userInfo.id, weaverSlot);
+ } else {
+ synchronizeFrpPassword(pwd, requestedQuality, userInfo.id);
+ }
+ }
+ }
+ }
+
private void synchronizeFrpPassword(PasswordData pwd,
int requestedQuality, int userId) {
if (mStorage.getPersistentDataBlock() != null