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