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