summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorRubin Xu <rubinxu@google.com>2019-10-08 16:58:54 +0100
committerRubin Xu <rubinxu@google.com>2019-10-09 14:46:06 +0100
commit6232a4cd6a4df0764d77d99c4ae99292cf2281a2 (patch)
tree09a3a97486598aad0d718c4b291a83b77976ead4 /core/java
parenta58125d2a4114b8e40f82ca7c300a75144bdcdb4 (diff)
Unify lockscreen changing logic in LockPatternUtils
Bug: 65239740 Test: atest com.android.internal.widget.LockPatternUtilsTest Test: atest MixedManagedProfileOwnerTest#testResetPasswordWithToken Change-Id: I86fb770fa77c260d93bbe5324391378018b13988
Diffstat (limited to 'core/java')
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java263
-rw-r--r--core/java/com/android/internal/widget/LockscreenCredential.java45
2 files changed, 102 insertions, 206 deletions
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 7874e512d9ee..1daa25af11fc 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -30,7 +30,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.PasswordMetrics;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
import android.content.ComponentName;
@@ -599,44 +598,6 @@ public class LockPatternUtils {
}
/**
- * Clear any lock pattern or password, with the option to ignore incorrect existing credential.
- *
- * <p> This method will fail (returning {@code false}) if the previously
- * saved password provided is incorrect, or if the lockscreen verification
- * is still being throttled.
- *
- * @param savedCredential The previously saved credential
- * @param userHandle the user whose pattern is to be saved.
- * @return whether this was successful or not.
- * @throws RuntimeException if password change encountered an unrecoverable error.
- */
- private boolean clearLock(LockscreenCredential savedCredential, int userHandle,
- boolean allowUntrustedChange) {
- final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
- setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle);
-
- try {
- if (!getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE,
- savedCredential.getCredential(), PASSWORD_QUALITY_UNSPECIFIED, userHandle,
- allowUntrustedChange)) {
- return false;
- }
- } catch (RemoteException | RuntimeException e) {
- setKeyguardStoredPasswordQuality(currentQuality, userHandle);
- throw new RuntimeException("Failed to clear lock", e);
- }
-
- if (userHandle == UserHandle.USER_SYSTEM) {
- // Set the encryption password to default.
- updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
- setCredentialRequiredToDecrypt(false);
- }
-
- onAfterChangingPassword(userHandle);
- return true;
- }
-
- /**
* Disable showing lock screen at all for a given user.
* This is only meaningful if pattern, pin or password are not set.
*
@@ -705,7 +666,7 @@ public class LockPatternUtils {
* being throttled.
* @param newCredential The new credential to save
* @param savedCredential The current credential
- * @param userId the user whose lockscreen credential is to be changed
+ * @param userHandle the user whose lockscreen credential is to be changed
* @param allowUntrustedChange whether we want to allow saving a new pattern if the existing
* credentialt being provided is incorrect.
*
@@ -714,73 +675,43 @@ public class LockPatternUtils {
* @throws RuntimeException if password change encountered an unrecoverable error.
*/
public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
- @NonNull LockscreenCredential savedCredential, int userId,
+ @NonNull LockscreenCredential savedCredential, int userHandle,
boolean allowUntrustedChange) {
- if (newCredential.isNone()) {
- return clearLock(savedCredential, userId, allowUntrustedChange);
- } else if (newCredential.isPattern()) {
- return saveLockPattern(newCredential, savedCredential, userId, allowUntrustedChange);
- } else {
- return saveLockPassword(newCredential, savedCredential, newCredential.getQuality(),
- userId, allowUntrustedChange);
- }
-
- }
-
- /**
- * Save a lock pattern.
- *
- * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
- * is incorrect, or if the lockscreen verification is still being throttled.
- *
- * @param pattern The new pattern to save.
- * @param savedCredential The previously saved credential
- * @param userId the user whose pattern is to be saved.
- * @param allowUntrustedChange whether we want to allow saving a new pattern if the existing
- * credentialt being provided is incorrect.
- *
- * @return whether this was successful or not.
- * @throws RuntimeException if password change encountered an unrecoverable error.
- */
- private boolean saveLockPattern(LockscreenCredential pattern,
- LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange) {
if (!hasSecureLockScreen()) {
throw new UnsupportedOperationException(
"This operation requires the lock screen feature.");
}
- if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
- throw new IllegalArgumentException("pattern must not be null and at least "
- + MIN_LOCK_PATTERN_SIZE + " dots long.");
- }
+ newCredential.checkLength();
+
+ final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
+ setKeyguardStoredPasswordQuality(newCredential.getQuality(), userHandle);
- final int currentQuality = getKeyguardStoredPasswordQuality(userId);
- setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId);
try {
- if (!getLockSettings().setLockCredential(pattern.getCredential(), pattern.getType(),
- savedCredential.getCredential(), PASSWORD_QUALITY_SOMETHING, userId,
- allowUntrustedChange)) {
+ if (!getLockSettings().setLockCredential(
+ newCredential.getCredential(), newCredential.getType(),
+ savedCredential.getCredential(),
+ newCredential.getQuality(), userHandle, allowUntrustedChange)) {
+ setKeyguardStoredPasswordQuality(currentQuality, userHandle);
return false;
}
} catch (RemoteException | RuntimeException e) {
- setKeyguardStoredPasswordQuality(currentQuality, userId);
- throw new RuntimeException("Couldn't save lock pattern", e);
- }
- // Update the device encryption password.
- if (userId == UserHandle.USER_SYSTEM
- && LockPatternUtils.isDeviceEncryptionEnabled()) {
- if (!shouldEncryptWithCredentials(true)) {
- clearEncryptionPassword();
- } else {
- updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN,
- pattern.getCredential());
- }
+ setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+ throw new RuntimeException("Unable to save lock password", e);
}
- reportPatternWasChosen(userId);
- onAfterChangingPassword(userId);
+ onPostPasswordChanged(newCredential, userHandle);
return true;
}
+ private void onPostPasswordChanged(LockscreenCredential newCredential, int userHandle) {
+ updateEncryptionPasswordIfNeeded(newCredential, userHandle);
+ if (newCredential.isPattern()) {
+ reportPatternWasChosen(userHandle);
+ }
+ updatePasswordHistory(newCredential, userHandle);
+ reportEnabledTrustAgentsChanged(userHandle);
+ }
+
private void updateCryptoUserInfo(int userId) {
if (userId != UserHandle.USER_SYSTEM) {
return;
@@ -879,92 +810,23 @@ public class LockPatternUtils {
}
/**
- * Save a lock password.
- *
- * <p> This method will fail (returning {@code false}) if the previously saved password provided
- * is incorrect and allowUntrustedChange is false, or if the lockscreen verification
- * is still being throttled.
- *
- * @param password The password to save
- * @param savedCredential The previously saved lock credential
- * @param requestedQuality {@link DevicePolicyManager#getPasswordQuality(
- * android.content.ComponentName)}
- * @param userHandle The userId of the user to change the password for
- * @param allowUntrustedChange whether we want to allow saving a new password if the existing
- * password being provided is incorrect.
- * @return whether this method saved the new password successfully or not. This flow will fail
- * and return false if the given credential is wrong and allowUntrustedChange is false.
- * @throws RuntimeException if password change encountered an unrecoverable error.
- */
- private boolean saveLockPassword(LockscreenCredential password,
- LockscreenCredential savedCredential, int requestedQuality, int userHandle,
- boolean allowUntrustedChange) {
- if (!hasSecureLockScreen()) {
- throw new UnsupportedOperationException(
- "This operation requires the lock screen feature.");
- }
- if (password.isNone() || password.size() < MIN_LOCK_PASSWORD_SIZE) {
- throw new IllegalArgumentException("password must not be null and at least "
- + "of length " + MIN_LOCK_PASSWORD_SIZE);
- }
-
- if (requestedQuality < PASSWORD_QUALITY_NUMERIC) {
- throw new IllegalArgumentException("quality must be at least NUMERIC, but was "
- + requestedQuality);
- }
-
- final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
- final int passwordQuality =
- PasswordMetrics.computeForPassword(password.getCredential()).quality;
- final int newKeyguardQuality =
- computeKeyguardQuality(CREDENTIAL_TYPE_PASSWORD, requestedQuality, passwordQuality);
- setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle);
- try {
- getLockSettings().setLockCredential(password.getCredential(), password.getType(),
- savedCredential.getCredential(),
- requestedQuality, userHandle, allowUntrustedChange);
- } catch (RemoteException | RuntimeException e) {
- setKeyguardStoredPasswordQuality(currentQuality, userHandle);
- throw new RuntimeException("Unable to save lock password", e);
- }
-
- updateEncryptionPasswordIfNeeded(password.getCredential(), passwordQuality, userHandle);
- updatePasswordHistory(password, userHandle);
- onAfterChangingPassword(userHandle);
- return true;
- }
-
- /**
- * Compute keyguard credential quality to store in PASSWORD_TYPE_KEY by computing max between
- * them so that digit-only password is distinguished from PIN.
- *
- * TODO: remove this method and make CREDENTIAL_TYPE distinguish between PIN and password, so
- * that this quality is no longer needs to be persisted.
- */
- private int computeKeyguardQuality(
- @CredentialType int credentialType, int requestedQuality, int passwordQuality) {
- return credentialType == CREDENTIAL_TYPE_PASSWORD
- ? Math.max(passwordQuality, requestedQuality) : passwordQuality;
- }
-
- /**
* Update device encryption password if calling user is USER_SYSTEM and device supports
* encryption.
*/
- private void updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle) {
+ private void updateEncryptionPasswordIfNeeded(LockscreenCredential credential, int userHandle) {
// Update the device encryption password.
- if (userHandle == UserHandle.USER_SYSTEM
- && LockPatternUtils.isDeviceEncryptionEnabled()) {
- if (!shouldEncryptWithCredentials(true)) {
- clearEncryptionPassword();
- } else {
- boolean numeric = quality == PASSWORD_QUALITY_NUMERIC;
- boolean numericComplex = quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
- int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
- : StorageManager.CRYPT_TYPE_PASSWORD;
- updateEncryptionPassword(type, password);
- }
+ if (userHandle != UserHandle.USER_SYSTEM || !isDeviceEncryptionEnabled()) {
+ return;
}
+ if (!shouldEncryptWithCredentials(true)) {
+ updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
+ return;
+ }
+ if (credential.isNone()) {
+ // Set the encryption password to default.
+ setCredentialRequiredToDecrypt(false);
+ }
+ updateEncryptionPassword(credential.getStorageCryptType(), credential.getCredential());
}
/**
@@ -973,7 +835,10 @@ public class LockPatternUtils {
*/
private void updatePasswordHistory(LockscreenCredential password, int userHandle) {
if (password.isNone()) {
- Log.e(TAG, "checkPasswordHistory: empty password");
+ return;
+ }
+ if (password.isPattern()) {
+ // Do not keep track of historical patterns
return;
}
// Add the password to the password history. We assume all
@@ -1065,7 +930,7 @@ public class LockPatternUtils {
try {
getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
managedUserPassword.getCredential());
- onAfterChangingPassword(userHandle);
+ reportEnabledTrustAgentsChanged(userHandle);
} catch (RemoteException e) {
Log.e(TAG, "Couldn't update work profile challenge enabled");
}
@@ -1506,7 +1371,7 @@ public class LockPatternUtils {
}
}
- private void onAfterChangingPassword(int userHandle) {
+ private void reportEnabledTrustAgentsChanged(int userHandle) {
getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
}
@@ -1674,48 +1539,34 @@ public class LockPatternUtils {
* @param credential The new credential to be set
* @param tokenHandle Handle of the escrow token
* @param token Escrow token
- * @param userId The user who's lock credential to be changed
+ * @param userHandle The user who's lock credential to be changed
* @return {@code true} if the operation is successful.
*/
public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
- byte[] token, int userId) {
+ byte[] token, int userHandle) {
if (!hasSecureLockScreen()) {
throw new UnsupportedOperationException(
"This operation requires the lock screen feature.");
}
+ credential.checkLength();
LockSettingsInternal localService = getLockSettingsInternal();
- if (!credential.isNone()) {
- if (credential.size() < MIN_LOCK_PASSWORD_SIZE) {
- throw new IllegalArgumentException("password must not be null and at least "
- + "of length " + MIN_LOCK_PASSWORD_SIZE);
- }
- final int type = credential.getType();
- final int quality = PasswordMetrics.computeForCredential(credential).quality;
- final int keyguardQuality = computeKeyguardQuality(type, quality,
- credential.getQuality());
- if (!localService.setLockCredentialWithToken(credential.getCredential(), type,
- tokenHandle, token, keyguardQuality, userId)) {
- return false;
- }
- setKeyguardStoredPasswordQuality(quality, userId);
- updateEncryptionPasswordIfNeeded(credential.getCredential(), quality, userId);
- updatePasswordHistory(credential, userId);
- onAfterChangingPassword(userId);
- } else {
- if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE, tokenHandle,
- token, PASSWORD_QUALITY_UNSPECIFIED, userId)) {
- return false;
- }
- setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userId);
+ final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
+ setKeyguardStoredPasswordQuality(credential.getQuality(), userHandle);
- if (userId == UserHandle.USER_SYSTEM) {
- // Set the encryption password to default.
- updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
- setCredentialRequiredToDecrypt(false);
+ try {
+ if (!localService.setLockCredentialWithToken(credential.getCredential(),
+ credential.getType(),
+ tokenHandle, token, credential.getType(), userHandle)) {
+ setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+ return false;
}
+ } catch (RuntimeException e) {
+ setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+ throw new RuntimeException("Unable to save lock credential", e);
}
- onAfterChangingPassword(userId);
+
+ onPostPasswordChanged(credential, userHandle);
return true;
}
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 320e692a71fd..19e6d97eaa06 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -29,6 +29,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.storage.StorageManager;
import android.text.TextUtils;
import com.android.internal.util.Preconditions;
@@ -187,6 +188,25 @@ public class LockscreenCredential implements Parcelable, AutoCloseable {
return mCredential;
}
+ /**
+ * Returns the credential type recognized by {@link StorageManager}. Can be one of
+ * {@link StorageManager#CRYPT_TYPE_DEFAULT}, {@link StorageManager#CRYPT_TYPE_PATTERN},
+ * {@link StorageManager#CRYPT_TYPE_PIN} or {@link StorageManager#CRYPT_TYPE_PASSWORD}.
+ */
+ public int getStorageCryptType() {
+ if (isNone()) {
+ return StorageManager.CRYPT_TYPE_DEFAULT;
+ }
+ if (isPattern()) {
+ return StorageManager.CRYPT_TYPE_PATTERN;
+ }
+ if (isPassword()) {
+ return mQuality == PASSWORD_QUALITY_NUMERIC
+ ? StorageManager.CRYPT_TYPE_PIN : StorageManager.CRYPT_TYPE_PASSWORD;
+ }
+ throw new IllegalStateException("Unhandled credential type");
+ }
+
/** Returns whether this is an empty credential */
public boolean isNone() {
ensureNotZeroized();
@@ -227,6 +247,31 @@ public class LockscreenCredential implements Parcelable, AutoCloseable {
}
}
+ /**
+ * Check if the credential meets minimal length requirement.
+ *
+ * @throws IllegalArgumentException if the credential is too short.
+ */
+ public void checkLength() {
+ if (isNone()) {
+ return;
+ }
+ if (isPattern()) {
+ if (size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
+ throw new IllegalArgumentException("pattern must not be null and at least "
+ + LockPatternUtils.MIN_LOCK_PATTERN_SIZE + " dots long.");
+ }
+ return;
+ }
+ if (isPassword()) {
+ if (size() < LockPatternUtils.MIN_LOCK_PASSWORD_SIZE) {
+ throw new IllegalArgumentException("password must not be null and at least "
+ + "of length " + LockPatternUtils.MIN_LOCK_PASSWORD_SIZE);
+ }
+ return;
+ }
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);