1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.widget; 18 19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; 23 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 24 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 25 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 26 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 27 28 import android.annotation.IntDef; 29 import android.annotation.Nullable; 30 import android.app.admin.DevicePolicyManager; 31 import android.app.admin.PasswordMetrics; 32 import android.app.trust.IStrongAuthTracker; 33 import android.app.trust.TrustManager; 34 import android.compat.annotation.UnsupportedAppUsage; 35 import android.content.ComponentName; 36 import android.content.ContentResolver; 37 import android.content.Context; 38 import android.content.pm.PackageManager; 39 import android.content.pm.UserInfo; 40 import android.os.AsyncTask; 41 import android.os.Handler; 42 import android.os.IBinder; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.RemoteException; 46 import android.os.ServiceManager; 47 import android.os.SystemClock; 48 import android.os.UserHandle; 49 import android.os.UserManager; 50 import android.os.storage.IStorageManager; 51 import android.os.storage.StorageManager; 52 import android.provider.Settings; 53 import android.text.TextUtils; 54 import android.util.Log; 55 import android.util.SparseIntArray; 56 import android.util.SparseLongArray; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.server.LocalServices; 60 61 import libcore.util.HexEncoding; 62 63 import com.google.android.collect.Lists; 64 65 import java.lang.annotation.Retention; 66 import java.lang.annotation.RetentionPolicy; 67 import java.security.MessageDigest; 68 import java.security.NoSuchAlgorithmException; 69 import java.security.SecureRandom; 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.Collection; 73 import java.util.List; 74 import java.util.StringJoiner; 75 76 /** 77 * Utilities for the lock pattern and its settings. 78 */ 79 public class LockPatternUtils { 80 81 private static final String TAG = "LockPatternUtils"; 82 private static final boolean FRP_CREDENTIAL_ENABLED = true; 83 84 /** 85 * The key to identify when the lock pattern enabled flag is being accessed for legacy reasons. 86 */ 87 public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled"; 88 89 /** 90 * The interval of the countdown for showing progress of the lockout. 91 */ 92 public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; 93 94 95 /** 96 * This dictates when we start telling the user that continued failed attempts will wipe 97 * their device. 98 */ 99 public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5; 100 101 /** 102 * The minimum number of dots in a valid pattern. 103 */ 104 public static final int MIN_LOCK_PATTERN_SIZE = 4; 105 106 /** 107 * The minimum size of a valid password. 108 */ 109 public static final int MIN_LOCK_PASSWORD_SIZE = 4; 110 111 /** 112 * The minimum number of dots the user must include in a wrong pattern attempt for it to be 113 * counted. 114 */ 115 public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; 116 117 public static final int CREDENTIAL_TYPE_NONE = -1; 118 public static final int CREDENTIAL_TYPE_PATTERN = 1; 119 public static final int CREDENTIAL_TYPE_PASSWORD = 2; 120 121 @Retention(RetentionPolicy.SOURCE) 122 @IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = { 123 CREDENTIAL_TYPE_NONE, 124 CREDENTIAL_TYPE_PATTERN, 125 CREDENTIAL_TYPE_PASSWORD, // Either pin or password. 126 }) 127 public @interface CredentialType {} 128 129 /** 130 * Special user id for triggering the FRP verification flow. 131 */ 132 public static final int USER_FRP = UserHandle.USER_NULL + 1; 133 134 @Deprecated 135 public final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; 136 public final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; 137 public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; 138 @Deprecated 139 public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate"; 140 public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt"; 141 public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled"; 142 public final static String LOCKSCREEN_OPTIONS = "lockscreen.options"; 143 @Deprecated 144 public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK 145 = "lockscreen.biometric_weak_fallback"; 146 @Deprecated 147 public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY 148 = "lockscreen.biometricweakeverchosen"; 149 public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS 150 = "lockscreen.power_button_instantly_locks"; 151 @Deprecated 152 public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled"; 153 154 public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory"; 155 156 private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO; 157 private static final String LOCK_SCREEN_OWNER_INFO_ENABLED = 158 Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 159 160 private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info"; 161 162 private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents"; 163 private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged"; 164 165 public static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_"; 166 public static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_"; 167 public static final String SYNTHETIC_PASSWORD_KEY_PREFIX = "synthetic_password_"; 168 169 public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle"; 170 public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp"; 171 private static final String HISTORY_DELIMITER = ","; 172 173 @UnsupportedAppUsage 174 private final Context mContext; 175 @UnsupportedAppUsage 176 private final ContentResolver mContentResolver; 177 private DevicePolicyManager mDevicePolicyManager; 178 private ILockSettings mLockSettingsService; 179 private UserManager mUserManager; 180 private final Handler mHandler; 181 private final SparseLongArray mLockoutDeadlines = new SparseLongArray(); 182 private Boolean mHasSecureLockScreen; 183 184 /** 185 * Use {@link TrustManager#isTrustUsuallyManaged(int)}. 186 * 187 * This returns the lazily-peristed value and should only be used by TrustManagerService. 188 */ isTrustUsuallyManaged(int userId)189 public boolean isTrustUsuallyManaged(int userId) { 190 if (!(mLockSettingsService instanceof ILockSettings.Stub)) { 191 throw new IllegalStateException("May only be called by TrustManagerService. " 192 + "Use TrustManager.isTrustUsuallyManaged()"); 193 } 194 try { 195 return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId); 196 } catch (RemoteException e) { 197 return false; 198 } 199 } 200 setTrustUsuallyManaged(boolean managed, int userId)201 public void setTrustUsuallyManaged(boolean managed, int userId) { 202 try { 203 getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId); 204 } catch (RemoteException e) { 205 // System dead. 206 } 207 } 208 userPresent(int userId)209 public void userPresent(int userId) { 210 try { 211 getLockSettings().userPresent(userId); 212 } catch (RemoteException e) { 213 throw e.rethrowFromSystemServer(); 214 } 215 } 216 217 public static final class RequestThrottledException extends Exception { 218 private int mTimeoutMs; 219 @UnsupportedAppUsage RequestThrottledException(int timeoutMs)220 public RequestThrottledException(int timeoutMs) { 221 mTimeoutMs = timeoutMs; 222 } 223 224 /** 225 * @return The amount of time in ms before another request may 226 * be executed 227 */ 228 @UnsupportedAppUsage getTimeoutMs()229 public int getTimeoutMs() { 230 return mTimeoutMs; 231 } 232 233 } 234 235 @UnsupportedAppUsage getDevicePolicyManager()236 public DevicePolicyManager getDevicePolicyManager() { 237 if (mDevicePolicyManager == null) { 238 mDevicePolicyManager = 239 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 240 if (mDevicePolicyManager == null) { 241 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?", 242 new IllegalStateException("Stack trace:")); 243 } 244 } 245 return mDevicePolicyManager; 246 } 247 getUserManager()248 private UserManager getUserManager() { 249 if (mUserManager == null) { 250 mUserManager = UserManager.get(mContext); 251 } 252 return mUserManager; 253 } 254 getTrustManager()255 private TrustManager getTrustManager() { 256 TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); 257 if (trust == null) { 258 Log.e(TAG, "Can't get TrustManagerService: is it running?", 259 new IllegalStateException("Stack trace:")); 260 } 261 return trust; 262 } 263 264 @UnsupportedAppUsage LockPatternUtils(Context context)265 public LockPatternUtils(Context context) { 266 mContext = context; 267 mContentResolver = context.getContentResolver(); 268 269 Looper looper = Looper.myLooper(); 270 mHandler = looper != null ? new Handler(looper) : null; 271 } 272 273 @UnsupportedAppUsage 274 @VisibleForTesting getLockSettings()275 public ILockSettings getLockSettings() { 276 if (mLockSettingsService == null) { 277 ILockSettings service = ILockSettings.Stub.asInterface( 278 ServiceManager.getService("lock_settings")); 279 mLockSettingsService = service; 280 } 281 return mLockSettingsService; 282 } 283 getRequestedMinimumPasswordLength(int userId)284 public int getRequestedMinimumPasswordLength(int userId) { 285 return getDevicePolicyManager().getPasswordMinimumLength(null, userId); 286 } 287 getMaximumPasswordLength(int quality)288 public int getMaximumPasswordLength(int quality) { 289 return getDevicePolicyManager().getPasswordMaximumLength(quality); 290 } 291 292 /** 293 * Gets the device policy password mode. If the mode is non-specific, returns 294 * MODE_PATTERN which allows the user to choose anything. 295 */ getRequestedPasswordQuality(int userId)296 public int getRequestedPasswordQuality(int userId) { 297 return getDevicePolicyManager().getPasswordQuality(null, userId); 298 } 299 getRequestedPasswordHistoryLength(int userId)300 private int getRequestedPasswordHistoryLength(int userId) { 301 return getDevicePolicyManager().getPasswordHistoryLength(null, userId); 302 } 303 getRequestedPasswordMinimumLetters(int userId)304 public int getRequestedPasswordMinimumLetters(int userId) { 305 return getDevicePolicyManager().getPasswordMinimumLetters(null, userId); 306 } 307 getRequestedPasswordMinimumUpperCase(int userId)308 public int getRequestedPasswordMinimumUpperCase(int userId) { 309 return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId); 310 } 311 getRequestedPasswordMinimumLowerCase(int userId)312 public int getRequestedPasswordMinimumLowerCase(int userId) { 313 return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId); 314 } 315 getRequestedPasswordMinimumNumeric(int userId)316 public int getRequestedPasswordMinimumNumeric(int userId) { 317 return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId); 318 } 319 getRequestedPasswordMinimumSymbols(int userId)320 public int getRequestedPasswordMinimumSymbols(int userId) { 321 return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId); 322 } 323 getRequestedPasswordMinimumNonLetter(int userId)324 public int getRequestedPasswordMinimumNonLetter(int userId) { 325 return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId); 326 } 327 328 @UnsupportedAppUsage reportFailedPasswordAttempt(int userId)329 public void reportFailedPasswordAttempt(int userId) { 330 if (userId == USER_FRP && frpCredentialEnabled(mContext)) { 331 return; 332 } 333 getDevicePolicyManager().reportFailedPasswordAttempt(userId); 334 getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); 335 } 336 337 @UnsupportedAppUsage reportSuccessfulPasswordAttempt(int userId)338 public void reportSuccessfulPasswordAttempt(int userId) { 339 if (userId == USER_FRP && frpCredentialEnabled(mContext)) { 340 return; 341 } 342 getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); 343 getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); 344 } 345 reportPasswordLockout(int timeoutMs, int userId)346 public void reportPasswordLockout(int timeoutMs, int userId) { 347 if (userId == USER_FRP && frpCredentialEnabled(mContext)) { 348 return; 349 } 350 getTrustManager().reportUnlockLockout(timeoutMs, userId); 351 } 352 getCurrentFailedPasswordAttempts(int userId)353 public int getCurrentFailedPasswordAttempts(int userId) { 354 if (userId == USER_FRP && frpCredentialEnabled(mContext)) { 355 return 0; 356 } 357 return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); 358 } 359 getMaximumFailedPasswordsForWipe(int userId)360 public int getMaximumFailedPasswordsForWipe(int userId) { 361 if (userId == USER_FRP && frpCredentialEnabled(mContext)) { 362 return 0; 363 } 364 return getDevicePolicyManager().getMaximumFailedPasswordsForWipe( 365 null /* componentName */, userId); 366 } 367 verifyCredential(byte[] credential, int type, long challenge, int userId)368 private byte[] verifyCredential(byte[] credential, int type, long challenge, int userId) 369 throws RequestThrottledException { 370 try { 371 VerifyCredentialResponse response = getLockSettings().verifyCredential(credential, 372 type, challenge, userId); 373 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 374 return response.getPayload(); 375 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 376 throw new RequestThrottledException(response.getTimeout()); 377 } else { 378 return null; 379 } 380 } catch (RemoteException re) { 381 return null; 382 } 383 } 384 checkCredential(byte[] credential, int type, int userId, @Nullable CheckCredentialProgressCallback progressCallback)385 private boolean checkCredential(byte[] credential, int type, int userId, 386 @Nullable CheckCredentialProgressCallback progressCallback) 387 throws RequestThrottledException { 388 try { 389 VerifyCredentialResponse response = getLockSettings().checkCredential(credential, type, 390 userId, wrapCallback(progressCallback)); 391 392 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 393 return true; 394 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 395 throw new RequestThrottledException(response.getTimeout()); 396 } else { 397 return false; 398 } 399 } catch (RemoteException re) { 400 return false; 401 } 402 } 403 404 /** 405 * Check to see if a pattern matches the saved pattern. 406 * If pattern matches, return an opaque attestation that the challenge 407 * was verified. 408 * 409 * @param pattern The pattern to check. 410 * @param challenge The challenge to verify against the pattern 411 * @return the attestation that the challenge was verified, or null. 412 */ verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)413 public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId) 414 throws RequestThrottledException { 415 throwIfCalledOnMainThread(); 416 return verifyCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, challenge, 417 userId); 418 } 419 420 /** 421 * Check to see if a pattern matches the saved pattern. If no pattern exists, 422 * always returns true. 423 * @param pattern The pattern to check. 424 * @return Whether the pattern matches the stored one. 425 */ checkPattern(List<LockPatternView.Cell> pattern, int userId)426 public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId) 427 throws RequestThrottledException { 428 return checkPattern(pattern, userId, null /* progressCallback */); 429 } 430 431 /** 432 * Check to see if a pattern matches the saved pattern. If no pattern exists, 433 * always returns true. 434 * @param pattern The pattern to check. 435 * @return Whether the pattern matches the stored one. 436 */ checkPattern(List<LockPatternView.Cell> pattern, int userId, @Nullable CheckCredentialProgressCallback progressCallback)437 public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId, 438 @Nullable CheckCredentialProgressCallback progressCallback) 439 throws RequestThrottledException { 440 throwIfCalledOnMainThread(); 441 return checkCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, userId, 442 progressCallback); 443 } 444 445 /** 446 * Check to see if a password matches the saved password. 447 * If password matches, return an opaque attestation that the challenge 448 * was verified. 449 * 450 * @param password The password to check. 451 * @param challenge The challenge to verify against the password 452 * @return the attestation that the challenge was verified, or null. 453 */ verifyPassword(byte[] password, long challenge, int userId)454 public byte[] verifyPassword(byte[] password, long challenge, int userId) 455 throws RequestThrottledException { 456 throwIfCalledOnMainThread(); 457 return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId); 458 } 459 460 461 /** 462 * Check to see if a password matches the saved password. 463 * If password matches, return an opaque attestation that the challenge 464 * was verified. 465 * 466 * @param password The password to check. 467 * @param challenge The challenge to verify against the password 468 * @return the attestation that the challenge was verified, or null. 469 */ verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge, int userId)470 public byte[] verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge, 471 int userId) throws RequestThrottledException { 472 throwIfCalledOnMainThread(); 473 try { 474 VerifyCredentialResponse response = 475 getLockSettings().verifyTiedProfileChallenge(password, 476 isPattern ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_PASSWORD, challenge, 477 userId); 478 479 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 480 return response.getPayload(); 481 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 482 throw new RequestThrottledException(response.getTimeout()); 483 } else { 484 return null; 485 } 486 } catch (RemoteException re) { 487 return null; 488 } 489 } 490 491 /** 492 * 493 * Check to see if a password matches the saved password. If no password exists, 494 * always returns true. 495 * @param password The password to check. 496 * @return Whether the password matches the stored one. 497 */ 498 @UnsupportedAppUsage checkPassword(String password, int userId)499 public boolean checkPassword(String password, int userId) throws RequestThrottledException { 500 byte[] passwordBytes = password != null ? password.getBytes() : null; 501 return checkPassword(passwordBytes, userId, null /* progressCallback */); 502 } 503 504 505 /** 506 * 507 * Check to see if a password matches the saved password. If no password exists, 508 * always returns true. 509 * @param password The password to check. 510 * @return Whether the password matches the stored one. 511 */ checkPassword(byte[] password, int userId)512 public boolean checkPassword(byte[] password, int userId) throws RequestThrottledException { 513 return checkPassword(password, userId, null /* progressCallback */); 514 } 515 516 // TODO(b/120484642): This method is necessary for vendor/qcom code and is a hidden api 517 /* * 518 * Check to see if a password matches the saved password. If no password exists, 519 * always returns true. 520 * @param password The password to check. 521 * @return Whether the password matches the stored one. 522 */ checkPassword(String password, int userId, @Nullable CheckCredentialProgressCallback progressCallback)523 public boolean checkPassword(String password, int userId, 524 @Nullable CheckCredentialProgressCallback progressCallback) 525 throws RequestThrottledException { 526 byte[] passwordBytes = password != null ? password.getBytes() : null; 527 throwIfCalledOnMainThread(); 528 return checkCredential(passwordBytes, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback); 529 530 } 531 532 /** 533 * Check to see if a password matches the saved password. If no password exists, 534 * always returns true. 535 * @param password The password to check. 536 * @return Whether the password matches the stored one. 537 */ 538 checkPassword(byte[] password, int userId, @Nullable CheckCredentialProgressCallback progressCallback)539 public boolean checkPassword(byte[] password, int userId, 540 @Nullable CheckCredentialProgressCallback progressCallback) 541 throws RequestThrottledException { 542 throwIfCalledOnMainThread(); 543 return checkCredential(password, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback); 544 } 545 546 /** 547 * Check to see if vold already has the password. 548 * Note that this also clears vold's copy of the password. 549 * @return Whether the vold password matches or not. 550 */ checkVoldPassword(int userId)551 public boolean checkVoldPassword(int userId) { 552 try { 553 return getLockSettings().checkVoldPassword(userId); 554 } catch (RemoteException re) { 555 return false; 556 } 557 } 558 559 /** 560 * Returns the password history hash factor, needed to check new password against password 561 * history with {@link #checkPasswordHistory(String, byte[], int)} 562 */ getPasswordHistoryHashFactor(byte[] currentPassword, int userId)563 public byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) { 564 try { 565 return getLockSettings().getHashFactor(currentPassword, userId); 566 } catch (RemoteException e) { 567 Log.e(TAG, "failed to get hash factor", e); 568 return null; 569 } 570 } 571 572 /** 573 * Check to see if a password matches any of the passwords stored in the 574 * password history. 575 * 576 * @param passwordToCheck The password to check. 577 * @param hashFactor Hash factor of the current user returned from 578 * {@link ILockSettings#getHashFactor} 579 * @return Whether the password matches any in the history. 580 */ checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId)581 public boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) { 582 if (passwordToCheck == null || passwordToCheck.length == 0) { 583 Log.e(TAG, "checkPasswordHistory: empty password"); 584 return false; 585 } 586 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId); 587 if (TextUtils.isEmpty(passwordHistory)) { 588 return false; 589 } 590 int passwordHistoryLength = getRequestedPasswordHistoryLength(userId); 591 if(passwordHistoryLength == 0) { 592 return false; 593 } 594 String legacyHash = legacyPasswordToHash(passwordToCheck, userId); 595 String passwordHash = passwordToHistoryHash(passwordToCheck, hashFactor, userId); 596 String[] history = passwordHistory.split(HISTORY_DELIMITER); 597 // Password History may be too long... 598 for (int i = 0; i < Math.min(passwordHistoryLength, history.length); i++) { 599 if (history[i].equals(legacyHash) || history[i].equals(passwordHash)) { 600 return true; 601 } 602 } 603 return false; 604 } 605 606 /** 607 * Check to see if the user has stored a lock pattern. 608 * @return Whether a saved pattern exists. 609 */ savedPatternExists(int userId)610 private boolean savedPatternExists(int userId) { 611 try { 612 return getLockSettings().havePattern(userId); 613 } catch (RemoteException re) { 614 return false; 615 } 616 } 617 618 /** 619 * Check to see if the user has stored a lock pattern. 620 * @return Whether a saved pattern exists. 621 */ savedPasswordExists(int userId)622 private boolean savedPasswordExists(int userId) { 623 try { 624 return getLockSettings().havePassword(userId); 625 } catch (RemoteException re) { 626 return false; 627 } 628 } 629 630 /** 631 * Return true if the user has ever chosen a pattern. This is true even if the pattern is 632 * currently cleared. 633 * 634 * @return True if the user has ever chosen a pattern. 635 */ isPatternEverChosen(int userId)636 public boolean isPatternEverChosen(int userId) { 637 return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId); 638 } 639 640 /** 641 * Records that the user has chosen a pattern at some time, even if the pattern is 642 * currently cleared. 643 */ reportPatternWasChosen(int userId)644 public void reportPatternWasChosen(int userId) { 645 setBoolean(PATTERN_EVER_CHOSEN_KEY, true, userId); 646 } 647 648 /** 649 * Used by device policy manager to validate the current password 650 * information it has. 651 */ 652 @UnsupportedAppUsage getActivePasswordQuality(int userId)653 public int getActivePasswordQuality(int userId) { 654 int quality = getKeyguardStoredPasswordQuality(userId); 655 656 if (isLockPasswordEnabled(quality, userId)) { 657 // Quality is a password and a password exists. Return the quality. 658 return quality; 659 } 660 661 if (isLockPatternEnabled(quality, userId)) { 662 // Quality is a pattern and a pattern exists. Return the quality. 663 return quality; 664 } 665 666 return PASSWORD_QUALITY_UNSPECIFIED; 667 } 668 669 /** 670 * Use it to reset keystore without wiping work profile 671 */ resetKeyStore(int userId)672 public void resetKeyStore(int userId) { 673 try { 674 getLockSettings().resetKeyStore(userId); 675 } catch (RemoteException e) { 676 // It should not happen 677 Log.e(TAG, "Couldn't reset keystore " + e); 678 } 679 } 680 681 /** 682 * Clear any lock pattern or password. 683 */ clearLock(byte[] savedCredential, int userHandle)684 public boolean clearLock(byte[] savedCredential, int userHandle) { 685 return clearLock(savedCredential, userHandle, false); 686 } 687 688 /** 689 * Clear any lock pattern or password, with the option to ignore incorrect existing credential. 690 */ clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange)691 public boolean clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange) { 692 final int currentQuality = getKeyguardStoredPasswordQuality(userHandle); 693 setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle); 694 695 try{ 696 getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, 697 savedCredential, PASSWORD_QUALITY_UNSPECIFIED, userHandle, 698 allowUntrustedChange); 699 } catch (Exception e) { 700 Log.e(TAG, "Failed to clear lock", e); 701 setKeyguardStoredPasswordQuality(currentQuality, userHandle); 702 return false; 703 } 704 705 if (userHandle == UserHandle.USER_SYSTEM) { 706 // Set the encryption password to default. 707 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); 708 setCredentialRequiredToDecrypt(false); 709 } 710 711 onAfterChangingPassword(userHandle); 712 return true; 713 } 714 715 /** 716 * Disable showing lock screen at all for a given user. 717 * This is only meaningful if pattern, pin or password are not set. 718 * 719 * @param disable Disables lock screen when true 720 * @param userId User ID of the user this has effect on 721 */ setLockScreenDisabled(boolean disable, int userId)722 public void setLockScreenDisabled(boolean disable, int userId) { 723 setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId); 724 } 725 726 /** 727 * Determine if LockScreen is disabled for the current user. This is used to decide whether 728 * LockScreen is shown after reboot or after screen timeout / short press on power. 729 * 730 * @return true if lock screen is disabled 731 */ 732 @UnsupportedAppUsage isLockScreenDisabled(int userId)733 public boolean isLockScreenDisabled(int userId) { 734 if (isSecure(userId)) { 735 return false; 736 } 737 boolean disabledByDefault = mContext.getResources().getBoolean( 738 com.android.internal.R.bool.config_disableLockscreenByDefault); 739 boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM; 740 UserInfo userInfo = getUserManager().getUserInfo(userId); 741 boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null 742 && userInfo.isDemo(); 743 return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId) 744 || (disabledByDefault && !isSystemUser) 745 || isDemoUser; 746 } 747 748 /** 749 * Save a lock pattern. 750 * @param pattern The new pattern to save. 751 * @param savedPattern The previously saved pattern, converted to byte[] format 752 * @param userId the user whose pattern is to be saved. 753 * 754 * @return whether this was successful or not. 755 */ saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, int userId)756 public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, 757 int userId) { 758 return saveLockPattern(pattern, savedPattern, userId, false); 759 } 760 761 /** 762 * Save a lock pattern. 763 * @param pattern The new pattern to save. 764 * @param savedPattern The previously saved pattern, converted to byte[] format 765 * @param userId the user whose pattern is to be saved. 766 * @param allowUntrustedChange whether we want to allow saving a new password if the existing 767 * password being provided is incorrect. 768 * 769 * @return whether this was successful or not. 770 */ saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, int userId, boolean allowUntrustedChange)771 public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern, 772 int userId, boolean allowUntrustedChange) { 773 if (!hasSecureLockScreen()) { 774 throw new UnsupportedOperationException( 775 "This operation requires the lock screen feature."); 776 } 777 if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) { 778 throw new IllegalArgumentException("pattern must not be null and at least " 779 + MIN_LOCK_PATTERN_SIZE + " dots long."); 780 } 781 782 final byte[] bytePattern = patternToByteArray(pattern); 783 final int currentQuality = getKeyguardStoredPasswordQuality(userId); 784 setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId); 785 try { 786 getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN, savedPattern, 787 PASSWORD_QUALITY_SOMETHING, userId, allowUntrustedChange); 788 } catch (Exception e) { 789 Log.e(TAG, "Couldn't save lock pattern", e); 790 setKeyguardStoredPasswordQuality(currentQuality, userId); 791 return false; 792 } 793 // Update the device encryption password. 794 if (userId == UserHandle.USER_SYSTEM 795 && LockPatternUtils.isDeviceEncryptionEnabled()) { 796 if (!shouldEncryptWithCredentials(true)) { 797 clearEncryptionPassword(); 798 } else { 799 updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, bytePattern); 800 } 801 } 802 803 reportPatternWasChosen(userId); 804 onAfterChangingPassword(userId); 805 return true; 806 } 807 updateCryptoUserInfo(int userId)808 private void updateCryptoUserInfo(int userId) { 809 if (userId != UserHandle.USER_SYSTEM) { 810 return; 811 } 812 813 final String ownerInfo = isOwnerInfoEnabled(userId) ? getOwnerInfo(userId) : ""; 814 815 IBinder service = ServiceManager.getService("mount"); 816 if (service == null) { 817 Log.e(TAG, "Could not find the mount service to update the user info"); 818 return; 819 } 820 821 IStorageManager storageManager = IStorageManager.Stub.asInterface(service); 822 try { 823 Log.d(TAG, "Setting owner info"); 824 storageManager.setField(StorageManager.OWNER_INFO_KEY, ownerInfo); 825 } catch (RemoteException e) { 826 Log.e(TAG, "Error changing user info", e); 827 } 828 } 829 830 @UnsupportedAppUsage setOwnerInfo(String info, int userId)831 public void setOwnerInfo(String info, int userId) { 832 setString(LOCK_SCREEN_OWNER_INFO, info, userId); 833 updateCryptoUserInfo(userId); 834 } 835 836 @UnsupportedAppUsage setOwnerInfoEnabled(boolean enabled, int userId)837 public void setOwnerInfoEnabled(boolean enabled, int userId) { 838 setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId); 839 updateCryptoUserInfo(userId); 840 } 841 842 @UnsupportedAppUsage getOwnerInfo(int userId)843 public String getOwnerInfo(int userId) { 844 return getString(LOCK_SCREEN_OWNER_INFO, userId); 845 } 846 isOwnerInfoEnabled(int userId)847 public boolean isOwnerInfoEnabled(int userId) { 848 return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId); 849 } 850 851 /** 852 * Sets the device owner information. If the information is {@code null} or empty then the 853 * device owner info is cleared. 854 * 855 * @param info Device owner information which will be displayed instead of the user 856 * owner info. 857 */ setDeviceOwnerInfo(String info)858 public void setDeviceOwnerInfo(String info) { 859 if (info != null && info.isEmpty()) { 860 info = null; 861 } 862 863 setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM); 864 } 865 getDeviceOwnerInfo()866 public String getDeviceOwnerInfo() { 867 return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM); 868 } 869 isDeviceOwnerInfoEnabled()870 public boolean isDeviceOwnerInfoEnabled() { 871 return getDeviceOwnerInfo() != null; 872 } 873 874 /** Update the encryption password if it is enabled **/ updateEncryptionPassword(final int type, final byte[] password)875 private void updateEncryptionPassword(final int type, final byte[] password) { 876 if (!hasSecureLockScreen()) { 877 throw new UnsupportedOperationException( 878 "This operation requires the lock screen feature."); 879 } 880 if (!isDeviceEncryptionEnabled()) { 881 return; 882 } 883 final IBinder service = ServiceManager.getService("mount"); 884 if (service == null) { 885 Log.e(TAG, "Could not find the mount service to update the encryption password"); 886 return; 887 } 888 889 // TODO(b/120484642): This is a location where we still use a String for vold 890 String passwordString = password != null ? new String(password) : null; 891 new AsyncTask<Void, Void, Void>() { 892 @Override 893 protected Void doInBackground(Void... dummy) { 894 IStorageManager storageManager = IStorageManager.Stub.asInterface(service); 895 try { 896 storageManager.changeEncryptionPassword(type, passwordString); 897 } catch (RemoteException e) { 898 Log.e(TAG, "Error changing encryption password", e); 899 } 900 return null; 901 } 902 }.execute(); 903 } 904 905 /** 906 * Save a lock password. Does not ensure that the password is as good 907 * as the requested mode, but will adjust the mode to be as good as the 908 * password. 909 * @param password The password to save 910 * @param savedPassword The previously saved lock password, or null if none 911 * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( 912 * android.content.ComponentName)} 913 * @param userHandle The userId of the user to change the password for 914 * 915 * @return whether this was successful or not. 916 * 917 * @deprecated Pass password as a byte array 918 */ 919 @Deprecated saveLockPassword(String password, String savedPassword, int requestedQuality, int userHandle)920 public boolean saveLockPassword(String password, String savedPassword, int requestedQuality, 921 int userHandle) { 922 byte[] passwordBytes = password != null ? password.getBytes() : null; 923 byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null; 924 return saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle); 925 } 926 927 /** 928 * Save a lock password. Does not ensure that the password is as good 929 * as the requested mode, but will adjust the mode to be as good as the 930 * password. 931 * @param password The password to save 932 * @param savedPassword The previously saved lock password, or null if none 933 * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( 934 * android.content.ComponentName)} 935 * @param userHandle The userId of the user to change the password for 936 * 937 * @return whether this was successful or not. 938 */ saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle)939 public boolean saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, 940 int userHandle) { 941 return saveLockPassword(password, savedPassword, requestedQuality, 942 userHandle, false); 943 } 944 945 /** 946 * Save a lock password. Does not ensure that the password is as good 947 * as the requested mode, but will adjust the mode to be as good as the 948 * password. 949 * @param password The password to save 950 * @param savedPassword The previously saved lock password, or null if none 951 * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality( 952 * android.content.ComponentName)} 953 * @param userHandle The userId of the user to change the password for 954 * @param allowUntrustedChange whether we want to allow saving a new password if the existing 955 * password being provided is incorrect. 956 * 957 * @return whether this method saved the new password successfully or not. This flow will fail 958 * and return false if the given credential is wrong and allowUntrustedChange is false. 959 */ saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality, int userHandle, boolean allowUntrustedChange)960 public boolean saveLockPassword(byte[] password, byte[] savedPassword, 961 int requestedQuality, int userHandle, boolean allowUntrustedChange) { 962 if (!hasSecureLockScreen()) { 963 throw new UnsupportedOperationException( 964 "This operation requires the lock screen feature."); 965 } 966 if (password == null || password.length < MIN_LOCK_PASSWORD_SIZE) { 967 throw new IllegalArgumentException("password must not be null and at least " 968 + "of length " + MIN_LOCK_PASSWORD_SIZE); 969 } 970 971 if (requestedQuality < PASSWORD_QUALITY_NUMERIC) { 972 throw new IllegalArgumentException("quality must be at least NUMERIC, but was " 973 + requestedQuality); 974 } 975 976 final int currentQuality = getKeyguardStoredPasswordQuality(userHandle); 977 final int passwordQuality = PasswordMetrics.computeForPassword(password).quality; 978 final int newKeyguardQuality = 979 computeKeyguardQuality(CREDENTIAL_TYPE_PASSWORD, requestedQuality, passwordQuality); 980 setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle); 981 try { 982 getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword, 983 requestedQuality, userHandle, allowUntrustedChange); 984 } catch (Exception e) { 985 Log.e(TAG, "Unable to save lock password", e); 986 setKeyguardStoredPasswordQuality(currentQuality, userHandle); 987 return false; 988 } 989 990 updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle); 991 updatePasswordHistory(password, userHandle); 992 onAfterChangingPassword(userHandle); 993 return true; 994 } 995 996 /** 997 * Compute keyguard credential quality to store in PASSWORD_TYPE_KEY by computing max between 998 * them so that digit-only password is distinguished from PIN. 999 * 1000 * TODO: remove this method and make CREDENTIAL_TYPE distinguish between PIN and password, so 1001 * that this quality is no longer needs to be persisted. 1002 */ computeKeyguardQuality( @redentialType int credentialType, int requestedQuality, int passwordQuality)1003 private int computeKeyguardQuality( 1004 @CredentialType int credentialType, int requestedQuality, int passwordQuality) { 1005 return credentialType == CREDENTIAL_TYPE_PASSWORD 1006 ? Math.max(passwordQuality, requestedQuality) : passwordQuality; 1007 } 1008 1009 /** 1010 * Update device encryption password if calling user is USER_SYSTEM and device supports 1011 * encryption. 1012 */ updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle)1013 private void updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle) { 1014 // Update the device encryption password. 1015 if (userHandle == UserHandle.USER_SYSTEM 1016 && LockPatternUtils.isDeviceEncryptionEnabled()) { 1017 if (!shouldEncryptWithCredentials(true)) { 1018 clearEncryptionPassword(); 1019 } else { 1020 boolean numeric = quality == PASSWORD_QUALITY_NUMERIC; 1021 boolean numericComplex = quality == PASSWORD_QUALITY_NUMERIC_COMPLEX; 1022 int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN 1023 : StorageManager.CRYPT_TYPE_PASSWORD; 1024 updateEncryptionPassword(type, password); 1025 } 1026 } 1027 } 1028 1029 /** 1030 * Store the hash of the *current* password in the password history list, if device policy 1031 * enforces password history requirement. 1032 */ updatePasswordHistory(byte[] password, int userHandle)1033 private void updatePasswordHistory(byte[] password, int userHandle) { 1034 if (password == null || password.length == 0) { 1035 Log.e(TAG, "checkPasswordHistory: empty password"); 1036 return; 1037 } 1038 // Add the password to the password history. We assume all 1039 // password hashes have the same length for simplicity of implementation. 1040 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle); 1041 if (passwordHistory == null) { 1042 passwordHistory = ""; 1043 } 1044 int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle); 1045 if (passwordHistoryLength == 0) { 1046 passwordHistory = ""; 1047 } else { 1048 final byte[] hashFactor = getPasswordHistoryHashFactor(password, userHandle); 1049 String hash = passwordToHistoryHash(password, hashFactor, userHandle); 1050 if (hash == null) { 1051 Log.e(TAG, "Compute new style password hash failed, fallback to legacy style"); 1052 hash = legacyPasswordToHash(password, userHandle); 1053 } 1054 if (TextUtils.isEmpty(passwordHistory)) { 1055 passwordHistory = hash; 1056 } else { 1057 String[] history = passwordHistory.split(HISTORY_DELIMITER); 1058 StringJoiner joiner = new StringJoiner(HISTORY_DELIMITER); 1059 joiner.add(hash); 1060 for (int i = 0; i < passwordHistoryLength - 1 && i < history.length; i++) { 1061 joiner.add(history[i]); 1062 } 1063 passwordHistory = joiner.toString(); 1064 } 1065 } 1066 setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); 1067 } 1068 1069 /** 1070 * Determine if the device supports encryption, even if it's set to default. This 1071 * differs from isDeviceEncrypted() in that it returns true even if the device is 1072 * encrypted with the default password. 1073 * @return true if device encryption is enabled 1074 */ 1075 @UnsupportedAppUsage isDeviceEncryptionEnabled()1076 public static boolean isDeviceEncryptionEnabled() { 1077 return StorageManager.isEncrypted(); 1078 } 1079 1080 /** 1081 * Determine if the device is file encrypted 1082 * @return true if device is file encrypted 1083 */ isFileEncryptionEnabled()1084 public static boolean isFileEncryptionEnabled() { 1085 return StorageManager.isFileEncryptedNativeOrEmulated(); 1086 } 1087 1088 /** 1089 * Clears the encryption password. 1090 */ clearEncryptionPassword()1091 public void clearEncryptionPassword() { 1092 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); 1093 } 1094 1095 /** 1096 * Retrieves the quality mode for {@param userHandle}. 1097 * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 1098 * 1099 * @return stored password quality 1100 */ 1101 @UnsupportedAppUsage getKeyguardStoredPasswordQuality(int userHandle)1102 public int getKeyguardStoredPasswordQuality(int userHandle) { 1103 return (int) getLong(PASSWORD_TYPE_KEY, PASSWORD_QUALITY_UNSPECIFIED, userHandle); 1104 } 1105 setKeyguardStoredPasswordQuality(int quality, int userHandle)1106 private void setKeyguardStoredPasswordQuality(int quality, int userHandle) { 1107 setLong(PASSWORD_TYPE_KEY, quality, userHandle); 1108 } 1109 1110 /** 1111 * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op 1112 * for user handles that do not belong to a managed profile. 1113 * 1114 * @param userHandle Managed profile user id 1115 * @param enabled True if separate challenge is enabled 1116 * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is 1117 * true 1118 */ setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, byte[] managedUserPassword)1119 public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, 1120 byte[] managedUserPassword) { 1121 if (!isManagedProfile(userHandle)) { 1122 return; 1123 } 1124 try { 1125 getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled, 1126 managedUserPassword); 1127 onAfterChangingPassword(userHandle); 1128 } catch (RemoteException e) { 1129 Log.e(TAG, "Couldn't update work profile challenge enabled"); 1130 } 1131 } 1132 1133 /** 1134 * Returns true if {@param userHandle} is a managed profile with separate challenge. 1135 */ isSeparateProfileChallengeEnabled(int userHandle)1136 public boolean isSeparateProfileChallengeEnabled(int userHandle) { 1137 return isManagedProfile(userHandle) && hasSeparateChallenge(userHandle); 1138 } 1139 1140 /** 1141 * Returns true if {@param userHandle} is a managed profile with unified challenge. 1142 */ isManagedProfileWithUnifiedChallenge(int userHandle)1143 public boolean isManagedProfileWithUnifiedChallenge(int userHandle) { 1144 return isManagedProfile(userHandle) && !hasSeparateChallenge(userHandle); 1145 } 1146 1147 /** 1148 * Retrieves whether the current DPM allows use of the Profile Challenge. 1149 */ isSeparateProfileChallengeAllowed(int userHandle)1150 public boolean isSeparateProfileChallengeAllowed(int userHandle) { 1151 return isManagedProfile(userHandle) 1152 && getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle); 1153 } 1154 1155 /** 1156 * Retrieves whether the current profile and device locks can be unified. 1157 * @param userHandle profile user handle. 1158 */ isSeparateProfileChallengeAllowedToUnify(int userHandle)1159 public boolean isSeparateProfileChallengeAllowedToUnify(int userHandle) { 1160 return getDevicePolicyManager().isProfileActivePasswordSufficientForParent(userHandle) 1161 && !getUserManager().hasUserRestriction( 1162 UserManager.DISALLOW_UNIFIED_PASSWORD, UserHandle.of(userHandle)); 1163 } 1164 hasSeparateChallenge(int userHandle)1165 private boolean hasSeparateChallenge(int userHandle) { 1166 try { 1167 return getLockSettings().getSeparateProfileChallengeEnabled(userHandle); 1168 } catch (RemoteException e) { 1169 Log.e(TAG, "Couldn't get separate profile challenge enabled"); 1170 // Default value is false 1171 return false; 1172 } 1173 } 1174 isManagedProfile(int userHandle)1175 private boolean isManagedProfile(int userHandle) { 1176 final UserInfo info = getUserManager().getUserInfo(userHandle); 1177 return info != null && info.isManagedProfile(); 1178 } 1179 1180 /** 1181 * Deserialize a pattern. 1182 * @param string The pattern serialized with {@link #patternToString} 1183 * @return The pattern. 1184 * @deprecated Pass patterns as byte[] and use byteArrayToPattern 1185 */ 1186 @Deprecated stringToPattern(String string)1187 public static List<LockPatternView.Cell> stringToPattern(String string) { 1188 if (string == null) { 1189 return null; 1190 } 1191 return byteArrayToPattern(string.getBytes()); 1192 } 1193 1194 /** 1195 * Deserialize a pattern. 1196 * @param bytes The pattern serialized with {@link #patternToByteArray} 1197 * @return The pattern. 1198 */ byteArrayToPattern(byte[] bytes)1199 public static List<LockPatternView.Cell> byteArrayToPattern(byte[] bytes) { 1200 if (bytes == null) { 1201 return null; 1202 } 1203 1204 List<LockPatternView.Cell> result = Lists.newArrayList(); 1205 1206 for (int i = 0; i < bytes.length; i++) { 1207 byte b = (byte) (bytes[i] - '1'); 1208 result.add(LockPatternView.Cell.of(b / 3, b % 3)); 1209 } 1210 return result; 1211 } 1212 1213 /** 1214 * Serialize a pattern. 1215 * @param pattern The pattern. 1216 * @return The pattern in string form. 1217 * @deprecated Use patternToByteArray instead. 1218 */ 1219 @UnsupportedAppUsage 1220 @Deprecated patternToString(List<LockPatternView.Cell> pattern)1221 public static String patternToString(List<LockPatternView.Cell> pattern) { 1222 return new String(patternToByteArray(pattern)); 1223 } 1224 1225 1226 /** 1227 * Serialize a pattern. 1228 * @param pattern The pattern. 1229 * @return The pattern in byte array form. 1230 */ patternToByteArray(List<LockPatternView.Cell> pattern)1231 public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) { 1232 if (pattern == null) { 1233 return new byte[0]; 1234 } 1235 final int patternSize = pattern.size(); 1236 1237 byte[] res = new byte[patternSize]; 1238 for (int i = 0; i < patternSize; i++) { 1239 LockPatternView.Cell cell = pattern.get(i); 1240 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1'); 1241 } 1242 return res; 1243 } 1244 1245 /** 1246 * Transform a pattern byte array to base zero form. 1247 * @param bytes pattern byte array. 1248 * @return The pattern in base zero form. 1249 */ patternByteArrayToBaseZero(byte[] bytes)1250 public static byte[] patternByteArrayToBaseZero(byte[] bytes) { 1251 if (bytes == null) { 1252 return new byte[0]; 1253 } 1254 final int patternSize = bytes.length; 1255 byte[] res = new byte[patternSize]; 1256 for (int i = 0; i < patternSize; i++) { 1257 res[i] = (byte) (bytes[i] - '1'); 1258 } 1259 return res; 1260 } 1261 1262 /* 1263 * Generate an SHA-1 hash for the pattern. Not the most secure, but it is 1264 * at least a second level of protection. First level is that the file 1265 * is in a location only readable by the system process. 1266 * @param pattern the gesture pattern. 1267 * @return the hash of the pattern in a byte array. 1268 */ 1269 @UnsupportedAppUsage patternToHash(List<LockPatternView.Cell> pattern)1270 public static byte[] patternToHash(List<LockPatternView.Cell> pattern) { 1271 if (pattern == null) { 1272 return null; 1273 } 1274 1275 final int patternSize = pattern.size(); 1276 byte[] res = new byte[patternSize]; 1277 for (int i = 0; i < patternSize; i++) { 1278 LockPatternView.Cell cell = pattern.get(i); 1279 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn()); 1280 } 1281 try { 1282 MessageDigest md = MessageDigest.getInstance("SHA-1"); 1283 byte[] hash = md.digest(res); 1284 return hash; 1285 } catch (NoSuchAlgorithmException nsa) { 1286 return res; 1287 } 1288 } 1289 getSalt(int userId)1290 private String getSalt(int userId) { 1291 long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId); 1292 if (salt == 0) { 1293 try { 1294 salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 1295 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId); 1296 Log.v(TAG, "Initialized lock password salt for user: " + userId); 1297 } catch (NoSuchAlgorithmException e) { 1298 // Throw an exception rather than storing a password we'll never be able to recover 1299 throw new IllegalStateException("Couldn't get SecureRandom number", e); 1300 } 1301 } 1302 return Long.toHexString(salt); 1303 } 1304 1305 /** 1306 * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. 1307 * Not the most secure, but it is at least a second level of protection. First level is that 1308 * the file is in a location only readable by the system process. 1309 * 1310 * @param password the gesture pattern. 1311 * 1312 * @return the hash of the pattern in a byte array. 1313 */ legacyPasswordToHash(byte[] password, int userId)1314 public String legacyPasswordToHash(byte[] password, int userId) { 1315 if (password == null || password.length == 0) { 1316 return null; 1317 } 1318 1319 try { 1320 // Previously the password was passed as a String with the following code: 1321 // byte[] saltedPassword = (password + getSalt(userId)).getBytes(); 1322 // The code below creates the identical digest preimage using byte arrays: 1323 byte[] salt = getSalt(userId).getBytes(); 1324 byte[] saltedPassword = Arrays.copyOf(password, password.length + salt.length); 1325 System.arraycopy(salt, 0, saltedPassword, password.length, salt.length); 1326 byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword); 1327 byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword); 1328 1329 byte[] combined = new byte[sha1.length + md5.length]; 1330 System.arraycopy(sha1, 0, combined, 0, sha1.length); 1331 System.arraycopy(md5, 0, combined, sha1.length, md5.length); 1332 1333 final char[] hexEncoded = HexEncoding.encode(combined); 1334 Arrays.fill(saltedPassword, (byte) 0); 1335 return new String(hexEncoded); 1336 } catch (NoSuchAlgorithmException e) { 1337 throw new AssertionError("Missing digest algorithm: ", e); 1338 } 1339 } 1340 1341 /** 1342 * Hash the password for password history check purpose. 1343 */ passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId)1344 private String passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId) { 1345 if (passwordToHash == null || passwordToHash.length == 0 || hashFactor == null) { 1346 return null; 1347 } 1348 try { 1349 MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); 1350 sha256.update(hashFactor); 1351 byte[] salt = getSalt(userId).getBytes(); 1352 byte[] saltedPassword = Arrays.copyOf(passwordToHash, passwordToHash.length 1353 + salt.length); 1354 System.arraycopy(salt, 0, saltedPassword, passwordToHash.length, salt.length); 1355 sha256.update(saltedPassword); 1356 Arrays.fill(saltedPassword, (byte) 0); 1357 return new String(HexEncoding.encode(sha256.digest())); 1358 } catch (NoSuchAlgorithmException e) { 1359 throw new AssertionError("Missing digest algorithm: ", e); 1360 } 1361 } 1362 1363 /** 1364 * @param userId the user for which to report the value 1365 * @return Whether the lock screen is secured. 1366 */ 1367 @UnsupportedAppUsage isSecure(int userId)1368 public boolean isSecure(int userId) { 1369 int mode = getKeyguardStoredPasswordQuality(userId); 1370 return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId); 1371 } 1372 1373 @UnsupportedAppUsage isLockPasswordEnabled(int userId)1374 public boolean isLockPasswordEnabled(int userId) { 1375 return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId); 1376 } 1377 isLockPasswordEnabled(int mode, int userId)1378 private boolean isLockPasswordEnabled(int mode, int userId) { 1379 final boolean passwordEnabled = mode == PASSWORD_QUALITY_ALPHABETIC 1380 || mode == PASSWORD_QUALITY_NUMERIC 1381 || mode == PASSWORD_QUALITY_NUMERIC_COMPLEX 1382 || mode == PASSWORD_QUALITY_ALPHANUMERIC 1383 || mode == PASSWORD_QUALITY_COMPLEX 1384 || mode == PASSWORD_QUALITY_MANAGED; 1385 return passwordEnabled && savedPasswordExists(userId); 1386 } 1387 1388 /** 1389 * @return Whether the lock pattern is enabled 1390 */ 1391 @UnsupportedAppUsage isLockPatternEnabled(int userId)1392 public boolean isLockPatternEnabled(int userId) { 1393 return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId); 1394 } 1395 1396 @Deprecated isLegacyLockPatternEnabled(int userId)1397 public boolean isLegacyLockPatternEnabled(int userId) { 1398 // Note: this value should default to {@code true} to avoid any reset that might result. 1399 // We must use a special key to read this value, since it will by default return the value 1400 // based on the new logic. 1401 return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId); 1402 } 1403 1404 @Deprecated setLegacyLockPatternEnabled(int userId)1405 public void setLegacyLockPatternEnabled(int userId) { 1406 setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId); 1407 } 1408 isLockPatternEnabled(int mode, int userId)1409 private boolean isLockPatternEnabled(int mode, int userId) { 1410 return mode == PASSWORD_QUALITY_SOMETHING && savedPatternExists(userId); 1411 } 1412 1413 /** 1414 * @return Whether the visible pattern is enabled. 1415 */ 1416 @UnsupportedAppUsage isVisiblePatternEnabled(int userId)1417 public boolean isVisiblePatternEnabled(int userId) { 1418 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId); 1419 } 1420 1421 /** 1422 * Set whether the visible pattern is enabled. 1423 */ setVisiblePatternEnabled(boolean enabled, int userId)1424 public void setVisiblePatternEnabled(boolean enabled, int userId) { 1425 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId); 1426 1427 // Update for crypto if owner 1428 if (userId != UserHandle.USER_SYSTEM) { 1429 return; 1430 } 1431 1432 IBinder service = ServiceManager.getService("mount"); 1433 if (service == null) { 1434 Log.e(TAG, "Could not find the mount service to update the user info"); 1435 return; 1436 } 1437 1438 IStorageManager storageManager = IStorageManager.Stub.asInterface(service); 1439 try { 1440 storageManager.setField(StorageManager.PATTERN_VISIBLE_KEY, enabled ? "1" : "0"); 1441 } catch (RemoteException e) { 1442 Log.e(TAG, "Error changing pattern visible state", e); 1443 } 1444 } 1445 isVisiblePatternEverChosen(int userId)1446 public boolean isVisiblePatternEverChosen(int userId) { 1447 return getString(Settings.Secure.LOCK_PATTERN_VISIBLE, userId) != null; 1448 } 1449 1450 /** 1451 * Set whether the visible password is enabled for cryptkeeper screen. 1452 */ setVisiblePasswordEnabled(boolean enabled, int userId)1453 public void setVisiblePasswordEnabled(boolean enabled, int userId) { 1454 // Update for crypto if owner 1455 if (userId != UserHandle.USER_SYSTEM) { 1456 return; 1457 } 1458 1459 IBinder service = ServiceManager.getService("mount"); 1460 if (service == null) { 1461 Log.e(TAG, "Could not find the mount service to update the user info"); 1462 return; 1463 } 1464 1465 IStorageManager storageManager = IStorageManager.Stub.asInterface(service); 1466 try { 1467 storageManager.setField(StorageManager.PASSWORD_VISIBLE_KEY, enabled ? "1" : "0"); 1468 } catch (RemoteException e) { 1469 Log.e(TAG, "Error changing password visible state", e); 1470 } 1471 } 1472 1473 /** 1474 * @return Whether tactile feedback for the pattern is enabled. 1475 */ 1476 @UnsupportedAppUsage isTactileFeedbackEnabled()1477 public boolean isTactileFeedbackEnabled() { 1478 return Settings.System.getIntForUser(mContentResolver, 1479 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0; 1480 } 1481 1482 /** 1483 * Set and store the lockout deadline, meaning the user can't attempt his/her unlock 1484 * pattern until the deadline has passed. 1485 * @return the chosen deadline. 1486 */ 1487 @UnsupportedAppUsage setLockoutAttemptDeadline(int userId, int timeoutMs)1488 public long setLockoutAttemptDeadline(int userId, int timeoutMs) { 1489 final long deadline = SystemClock.elapsedRealtime() + timeoutMs; 1490 if (userId == USER_FRP) { 1491 // For secure password storage (that is required for FRP), the underlying storage also 1492 // enforces the deadline. Since we cannot store settings for the FRP user, don't. 1493 return deadline; 1494 } 1495 mLockoutDeadlines.put(userId, deadline); 1496 return deadline; 1497 } 1498 1499 /** 1500 * @return The elapsed time in millis in the future when the user is allowed to 1501 * attempt to enter his/her lock pattern, or 0 if the user is welcome to 1502 * enter a pattern. 1503 */ getLockoutAttemptDeadline(int userId)1504 public long getLockoutAttemptDeadline(int userId) { 1505 final long deadline = mLockoutDeadlines.get(userId, 0L); 1506 final long now = SystemClock.elapsedRealtime(); 1507 if (deadline < now && deadline != 0) { 1508 // timeout expired 1509 mLockoutDeadlines.put(userId, 0); 1510 return 0L; 1511 } 1512 return deadline; 1513 } 1514 getBoolean(String secureSettingKey, boolean defaultValue, int userId)1515 private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) { 1516 try { 1517 return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId); 1518 } catch (RemoteException re) { 1519 return defaultValue; 1520 } 1521 } 1522 setBoolean(String secureSettingKey, boolean enabled, int userId)1523 private void setBoolean(String secureSettingKey, boolean enabled, int userId) { 1524 try { 1525 getLockSettings().setBoolean(secureSettingKey, enabled, userId); 1526 } catch (RemoteException re) { 1527 // What can we do? 1528 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re); 1529 } 1530 } 1531 getLong(String secureSettingKey, long defaultValue, int userHandle)1532 private long getLong(String secureSettingKey, long defaultValue, int userHandle) { 1533 try { 1534 return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle); 1535 } catch (RemoteException re) { 1536 return defaultValue; 1537 } 1538 } 1539 1540 @UnsupportedAppUsage setLong(String secureSettingKey, long value, int userHandle)1541 private void setLong(String secureSettingKey, long value, int userHandle) { 1542 try { 1543 getLockSettings().setLong(secureSettingKey, value, userHandle); 1544 } catch (RemoteException re) { 1545 // What can we do? 1546 Log.e(TAG, "Couldn't write long " + secureSettingKey + re); 1547 } 1548 } 1549 1550 @UnsupportedAppUsage getString(String secureSettingKey, int userHandle)1551 private String getString(String secureSettingKey, int userHandle) { 1552 try { 1553 return getLockSettings().getString(secureSettingKey, null, userHandle); 1554 } catch (RemoteException re) { 1555 return null; 1556 } 1557 } 1558 1559 @UnsupportedAppUsage setString(String secureSettingKey, String value, int userHandle)1560 private void setString(String secureSettingKey, String value, int userHandle) { 1561 try { 1562 getLockSettings().setString(secureSettingKey, value, userHandle); 1563 } catch (RemoteException re) { 1564 // What can we do? 1565 Log.e(TAG, "Couldn't write string " + secureSettingKey + re); 1566 } 1567 } 1568 setPowerButtonInstantlyLocks(boolean enabled, int userId)1569 public void setPowerButtonInstantlyLocks(boolean enabled, int userId) { 1570 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId); 1571 } 1572 1573 @UnsupportedAppUsage getPowerButtonInstantlyLocks(int userId)1574 public boolean getPowerButtonInstantlyLocks(int userId) { 1575 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId); 1576 } 1577 isPowerButtonInstantlyLocksEverChosen(int userId)1578 public boolean isPowerButtonInstantlyLocksEverChosen(int userId) { 1579 return getString(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, userId) != null; 1580 } 1581 setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1582 public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) { 1583 StringBuilder sb = new StringBuilder(); 1584 for (ComponentName cn : activeTrustAgents) { 1585 if (sb.length() > 0) { 1586 sb.append(','); 1587 } 1588 sb.append(cn.flattenToShortString()); 1589 } 1590 setString(ENABLED_TRUST_AGENTS, sb.toString(), userId); 1591 getTrustManager().reportEnabledTrustAgentsChanged(userId); 1592 } 1593 getEnabledTrustAgents(int userId)1594 public List<ComponentName> getEnabledTrustAgents(int userId) { 1595 String serialized = getString(ENABLED_TRUST_AGENTS, userId); 1596 if (TextUtils.isEmpty(serialized)) { 1597 return null; 1598 } 1599 String[] split = serialized.split(","); 1600 ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length); 1601 for (String s : split) { 1602 if (!TextUtils.isEmpty(s)) { 1603 activeTrustAgents.add(ComponentName.unflattenFromString(s)); 1604 } 1605 } 1606 return activeTrustAgents; 1607 } 1608 1609 /** 1610 * Disable trust until credentials have been entered for user {@param userId}. 1611 * 1612 * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. 1613 * 1614 * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL} 1615 */ requireCredentialEntry(int userId)1616 public void requireCredentialEntry(int userId) { 1617 requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId); 1618 } 1619 1620 /** 1621 * Requests strong authentication for user {@param userId}. 1622 * 1623 * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. 1624 * 1625 * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating 1626 * the reason for and the strength of the requested authentication. 1627 * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL} 1628 */ requireStrongAuth(@trongAuthTracker.StrongAuthFlags int strongAuthReason, int userId)1629 public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason, 1630 int userId) { 1631 try { 1632 getLockSettings().requireStrongAuth(strongAuthReason, userId); 1633 } catch (RemoteException e) { 1634 Log.e(TAG, "Error while requesting strong auth: " + e); 1635 } 1636 } 1637 onAfterChangingPassword(int userHandle)1638 private void onAfterChangingPassword(int userHandle) { 1639 getTrustManager().reportEnabledTrustAgentsChanged(userHandle); 1640 } 1641 isCredentialRequiredToDecrypt(boolean defaultValue)1642 public boolean isCredentialRequiredToDecrypt(boolean defaultValue) { 1643 final int value = Settings.Global.getInt(mContentResolver, 1644 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1); 1645 return value == -1 ? defaultValue : (value != 0); 1646 } 1647 setCredentialRequiredToDecrypt(boolean required)1648 public void setCredentialRequiredToDecrypt(boolean required) { 1649 if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) { 1650 throw new IllegalStateException( 1651 "Only the system or primary user may call setCredentialRequiredForDecrypt()"); 1652 } 1653 1654 if (isDeviceEncryptionEnabled()){ 1655 Settings.Global.putInt(mContext.getContentResolver(), 1656 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0); 1657 } 1658 } 1659 isDoNotAskCredentialsOnBootSet()1660 private boolean isDoNotAskCredentialsOnBootSet() { 1661 return getDevicePolicyManager().getDoNotAskCredentialsOnBoot(); 1662 } 1663 shouldEncryptWithCredentials(boolean defaultValue)1664 private boolean shouldEncryptWithCredentials(boolean defaultValue) { 1665 return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet(); 1666 } 1667 throwIfCalledOnMainThread()1668 private void throwIfCalledOnMainThread() { 1669 if (Looper.getMainLooper().isCurrentThread()) { 1670 throw new IllegalStateException("should not be called from the main thread."); 1671 } 1672 } 1673 registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1674 public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) { 1675 try { 1676 getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub); 1677 } catch (RemoteException e) { 1678 throw new RuntimeException("Could not register StrongAuthTracker"); 1679 } 1680 } 1681 unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1682 public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) { 1683 try { 1684 getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub); 1685 } catch (RemoteException e) { 1686 Log.e(TAG, "Could not unregister StrongAuthTracker", e); 1687 } 1688 } 1689 1690 /** 1691 * @see StrongAuthTracker#getStrongAuthForUser 1692 */ getStrongAuthForUser(int userId)1693 public int getStrongAuthForUser(int userId) { 1694 try { 1695 return getLockSettings().getStrongAuthForUser(userId); 1696 } catch (RemoteException e) { 1697 Log.e(TAG, "Could not get StrongAuth", e); 1698 return StrongAuthTracker.getDefaultFlags(mContext); 1699 } 1700 } 1701 1702 /** 1703 * @see StrongAuthTracker#isTrustAllowedForUser 1704 */ isTrustAllowedForUser(int userId)1705 public boolean isTrustAllowedForUser(int userId) { 1706 return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; 1707 } 1708 1709 /** 1710 * @see StrongAuthTracker#isBiometricAllowedForUser(int) 1711 */ isBiometricAllowedForUser(int userId)1712 public boolean isBiometricAllowedForUser(int userId) { 1713 return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_BIOMETRIC) == 0; 1714 } 1715 isUserInLockdown(int userId)1716 public boolean isUserInLockdown(int userId) { 1717 return getStrongAuthForUser(userId) 1718 == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; 1719 } 1720 wrapCallback( final CheckCredentialProgressCallback callback)1721 private ICheckCredentialProgressCallback wrapCallback( 1722 final CheckCredentialProgressCallback callback) { 1723 if (callback == null) { 1724 return null; 1725 } else { 1726 if (mHandler == null) { 1727 throw new IllegalStateException("Must construct LockPatternUtils on a looper thread" 1728 + " to use progress callbacks."); 1729 } 1730 return new ICheckCredentialProgressCallback.Stub() { 1731 1732 @Override 1733 public void onCredentialVerified() throws RemoteException { 1734 mHandler.post(callback::onEarlyMatched); 1735 } 1736 }; 1737 } 1738 } 1739 1740 private LockSettingsInternal getLockSettingsInternal() { 1741 LockSettingsInternal service = LocalServices.getService(LockSettingsInternal.class); 1742 if (service == null) { 1743 throw new SecurityException("Only available to system server itself"); 1744 } 1745 return service; 1746 } 1747 /** 1748 * Create an escrow token for the current user, which can later be used to unlock FBE 1749 * or change user password. 1750 * 1751 * After adding, if the user currently has lockscreen password, he will need to perform a 1752 * confirm credential operation in order to activate the token for future use. If the user 1753 * has no secure lockscreen, then the token is activated immediately. 1754 * 1755 * <p>This method is only available to code running in the system server process itself. 1756 * 1757 * @return a unique 64-bit token handle which is needed to refer to this token later. 1758 */ 1759 public long addEscrowToken(byte[] token, int userId, 1760 @Nullable EscrowTokenStateChangeCallback callback) { 1761 return getLockSettingsInternal().addEscrowToken(token, userId, callback); 1762 } 1763 1764 /** 1765 * Callback interface to notify when an added escrow token has been activated. 1766 */ 1767 public interface EscrowTokenStateChangeCallback { 1768 /** 1769 * The method to be called when the token is activated. 1770 * @param handle 64 bit handle corresponding to the escrow token 1771 * @param userid user for whom the escrow token has been added 1772 */ 1773 void onEscrowTokenActivated(long handle, int userid); 1774 } 1775 1776 /** 1777 * Remove an escrow token. 1778 * 1779 * <p>This method is only available to code running in the system server process itself. 1780 * 1781 * @return true if the given handle refers to a valid token previously returned from 1782 * {@link #addEscrowToken}, whether it's active or not. return false otherwise. 1783 */ 1784 public boolean removeEscrowToken(long handle, int userId) { 1785 return getLockSettingsInternal().removeEscrowToken(handle, userId); 1786 } 1787 1788 /** 1789 * Check if the given escrow token is active or not. Only active token can be used to call 1790 * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken} 1791 * 1792 * <p>This method is only available to code running in the system server process itself. 1793 */ 1794 public boolean isEscrowTokenActive(long handle, int userId) { 1795 return getLockSettingsInternal().isEscrowTokenActive(handle, userId); 1796 } 1797 1798 /** 1799 * Change a user's lock credential with a pre-configured escrow token. 1800 * 1801 * <p>This method is only available to code running in the system server process itself. 1802 * 1803 * @param credential The new credential to be set 1804 * @param type Credential type: password / pattern / none. 1805 * @param requestedQuality the requested password quality by DevicePolicyManager. 1806 * See {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} 1807 * @param tokenHandle Handle of the escrow token 1808 * @param token Escrow token 1809 * @param userId The user who's lock credential to be changed 1810 * @return {@code true} if the operation is successful. 1811 */ 1812 public boolean setLockCredentialWithToken(byte[] credential, int type, int requestedQuality, 1813 long tokenHandle, byte[] token, int userId) { 1814 if (!hasSecureLockScreen()) { 1815 throw new UnsupportedOperationException( 1816 "This operation requires the lock screen feature."); 1817 } 1818 LockSettingsInternal localService = getLockSettingsInternal(); 1819 if (type != CREDENTIAL_TYPE_NONE) { 1820 if (credential == null || credential.length < MIN_LOCK_PASSWORD_SIZE) { 1821 throw new IllegalArgumentException("password must not be null and at least " 1822 + "of length " + MIN_LOCK_PASSWORD_SIZE); 1823 } 1824 final int quality = PasswordMetrics.computeForCredential(type, credential).quality; 1825 final int keyguardQuality = computeKeyguardQuality(type, quality, requestedQuality); 1826 if (!localService.setLockCredentialWithToken(credential, type, tokenHandle, token, 1827 keyguardQuality, userId)) { 1828 return false; 1829 } 1830 setKeyguardStoredPasswordQuality(quality, userId); 1831 1832 updateEncryptionPasswordIfNeeded(credential, quality, userId); 1833 updatePasswordHistory(credential, userId); 1834 onAfterChangingPassword(userId); 1835 } else { 1836 if (!(credential == null || credential.length == 0)) { 1837 throw new IllegalArgumentException("password must be emtpy for NONE type"); 1838 } 1839 if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE, tokenHandle, 1840 token, PASSWORD_QUALITY_UNSPECIFIED, userId)) { 1841 return false; 1842 } 1843 setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userId); 1844 1845 if (userId == UserHandle.USER_SYSTEM) { 1846 // Set the encryption password to default. 1847 updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); 1848 setCredentialRequiredToDecrypt(false); 1849 } 1850 } 1851 onAfterChangingPassword(userId); 1852 return true; 1853 } 1854 1855 /** 1856 * Unlock the specified user by an pre-activated escrow token. This should have the same effect 1857 * on device encryption as the user entering his lockscreen credentials for the first time after 1858 * boot, this includes unlocking the user's credential-encrypted storage as well as the keystore 1859 * 1860 * <p>This method is only available to code running in the system server process itself. 1861 * 1862 * @return {@code true} if the supplied token is valid and unlock succeeds, 1863 * {@code false} otherwise. 1864 */ 1865 public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) { 1866 return getLockSettingsInternal().unlockUserWithToken(tokenHandle, token, userId); 1867 } 1868 1869 1870 /** 1871 * Callback to be notified about progress when checking credentials. 1872 */ 1873 public interface CheckCredentialProgressCallback { 1874 1875 /** 1876 * Called as soon as possible when we know that the credentials match but the user hasn't 1877 * been fully unlocked. 1878 */ 1879 void onEarlyMatched(); 1880 } 1881 1882 /** 1883 * Tracks the global strong authentication state. 1884 */ 1885 public static class StrongAuthTracker { 1886 1887 @IntDef(flag = true, 1888 value = { STRONG_AUTH_NOT_REQUIRED, 1889 STRONG_AUTH_REQUIRED_AFTER_BOOT, 1890 STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, 1891 SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, 1892 STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, 1893 STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, 1894 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN}) 1895 @Retention(RetentionPolicy.SOURCE) 1896 public @interface StrongAuthFlags {} 1897 1898 /** 1899 * Strong authentication is not required. 1900 */ 1901 public static final int STRONG_AUTH_NOT_REQUIRED = 0x0; 1902 1903 /** 1904 * Strong authentication is required because the user has not authenticated since boot. 1905 */ 1906 public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1; 1907 1908 /** 1909 * Strong authentication is required because a device admin has requested it. 1910 */ 1911 public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2; 1912 1913 /** 1914 * Some authentication is required because the user has temporarily disabled trust. 1915 */ 1916 public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4; 1917 1918 /** 1919 * Strong authentication is required because the user has been locked out after too many 1920 * attempts. 1921 */ 1922 public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8; 1923 1924 /** 1925 * Strong authentication is required because it hasn't been used for a time required by 1926 * a device admin. 1927 */ 1928 public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10; 1929 1930 /** 1931 * Strong authentication is required because the user has triggered lockdown. 1932 */ 1933 public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20; 1934 1935 /** 1936 * Strong auth flags that do not prevent biometric methods from being accepted as auth. 1937 * If any other flags are set, biometric authentication is disabled. 1938 */ 1939 private static final int ALLOWING_BIOMETRIC = STRONG_AUTH_NOT_REQUIRED 1940 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; 1941 1942 private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray(); 1943 private final H mHandler; 1944 private final int mDefaultStrongAuthFlags; 1945 1946 public StrongAuthTracker(Context context) { 1947 this(context, Looper.myLooper()); 1948 } 1949 1950 /** 1951 * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged} 1952 * will be scheduled. 1953 * @param context the current {@link Context} 1954 */ 1955 public StrongAuthTracker(Context context, Looper looper) { 1956 mHandler = new H(looper); 1957 mDefaultStrongAuthFlags = getDefaultFlags(context); 1958 } 1959 1960 public static @StrongAuthFlags int getDefaultFlags(Context context) { 1961 boolean strongAuthRequired = context.getResources().getBoolean( 1962 com.android.internal.R.bool.config_strongAuthRequiredOnBoot); 1963 return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED; 1964 } 1965 1966 /** 1967 * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required, 1968 * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong 1969 * authentication is required. 1970 * 1971 * @param userId the user for whom the state is queried. 1972 */ 1973 public @StrongAuthFlags int getStrongAuthForUser(int userId) { 1974 return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags); 1975 } 1976 1977 /** 1978 * @return true if unlocking with trust alone is allowed for {@param userId} by the current 1979 * strong authentication requirements. 1980 */ 1981 public boolean isTrustAllowedForUser(int userId) { 1982 return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED; 1983 } 1984 1985 /** 1986 * @return true if unlocking with a biometric method alone is allowed for {@param userId} 1987 * by the current strong authentication requirements. 1988 */ 1989 public boolean isBiometricAllowedForUser(int userId) { 1990 return (getStrongAuthForUser(userId) & ~ALLOWING_BIOMETRIC) == 0; 1991 } 1992 1993 /** 1994 * Called when the strong authentication requirements for {@param userId} changed. 1995 */ 1996 public void onStrongAuthRequiredChanged(int userId) { 1997 } 1998 1999 protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags, 2000 int userId) { 2001 int oldValue = getStrongAuthForUser(userId); 2002 if (strongAuthFlags != oldValue) { 2003 if (strongAuthFlags == mDefaultStrongAuthFlags) { 2004 mStrongAuthRequiredForUser.delete(userId); 2005 } else { 2006 mStrongAuthRequiredForUser.put(userId, strongAuthFlags); 2007 } 2008 onStrongAuthRequiredChanged(userId); 2009 } 2010 } 2011 2012 2013 protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() { 2014 @Override 2015 public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags, 2016 int userId) { 2017 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED, 2018 strongAuthFlags, userId).sendToTarget(); 2019 } 2020 }; 2021 2022 private class H extends Handler { 2023 static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1; 2024 2025 public H(Looper looper) { 2026 super(looper); 2027 } 2028 2029 @Override 2030 public void handleMessage(Message msg) { 2031 switch (msg.what) { 2032 case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED: 2033 handleStrongAuthRequiredChanged(msg.arg1, msg.arg2); 2034 break; 2035 } 2036 } 2037 } 2038 } 2039 2040 public void enableSyntheticPassword() { 2041 setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1L, UserHandle.USER_SYSTEM); 2042 } 2043 2044 public void disableSyntheticPassword() { 2045 setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0L, UserHandle.USER_SYSTEM); 2046 } 2047 2048 public boolean isSyntheticPasswordEnabled() { 2049 return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0; 2050 } 2051 2052 /** 2053 * Returns whether the given user has pending escrow tokens 2054 */ 2055 public boolean hasPendingEscrowToken(int userId) { 2056 try { 2057 return getLockSettings().hasPendingEscrowToken(userId); 2058 } catch (RemoteException e) { 2059 e.rethrowFromSystemServer(); 2060 } 2061 return false; 2062 } 2063 2064 /** 2065 * Return true if the device supports the lock screen feature, false otherwise. 2066 */ 2067 public boolean hasSecureLockScreen() { 2068 if (mHasSecureLockScreen == null) { 2069 mHasSecureLockScreen = Boolean.valueOf(mContext.getPackageManager() 2070 .hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)); 2071 } 2072 return mHasSecureLockScreen.booleanValue(); 2073 } 2074 2075 public static boolean userOwnsFrpCredential(Context context, UserInfo info) { 2076 return info != null && info.isPrimary() && info.isAdmin() && frpCredentialEnabled(context); 2077 } 2078 2079 public static boolean frpCredentialEnabled(Context context) { 2080 return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean( 2081 com.android.internal.R.bool.config_enableCredentialFactoryResetProtection); 2082 } 2083 2084 /** 2085 * Converts a CharSequence to a byte array without requiring a toString(), which creates an 2086 * additional copy. 2087 * 2088 * @param chars The CharSequence to convert 2089 * @return A byte array representing the input 2090 */ 2091 public static byte[] charSequenceToByteArray(CharSequence chars) { 2092 if (chars == null) { 2093 return null; 2094 } 2095 byte[] bytes = new byte[chars.length()]; 2096 for (int i = 0; i < chars.length(); i++) { 2097 bytes[i] = (byte) chars.charAt(i); 2098 } 2099 return bytes; 2100 } 2101 } 2102