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