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