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