1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.widget; 18 19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; 21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 23 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 24 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 25 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.UserIdInt; 30 import android.app.PropertyInvalidatedCache; 31 import android.app.RemoteLockscreenValidationResult; 32 import android.app.RemoteLockscreenValidationSession; 33 import android.app.admin.DevicePolicyManager; 34 import android.app.admin.PasswordMetrics; 35 import android.app.trust.IStrongAuthTracker; 36 import android.app.trust.TrustManager; 37 import android.compat.annotation.UnsupportedAppUsage; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.pm.PackageManager; 42 import android.content.pm.UserInfo; 43 import android.os.Build; 44 import android.os.Handler; 45 import android.os.Looper; 46 import android.os.Message; 47 import android.os.RemoteException; 48 import android.os.ServiceManager; 49 import android.os.SystemClock; 50 import android.os.SystemProperties; 51 import android.os.UserHandle; 52 import android.os.UserManager; 53 import android.os.storage.StorageManager; 54 import android.provider.Settings; 55 import android.text.TextUtils; 56 import android.util.Log; 57 import android.util.SparseBooleanArray; 58 import android.util.SparseIntArray; 59 import android.util.SparseLongArray; 60 61 import com.android.internal.annotations.VisibleForTesting; 62 import com.android.server.LocalServices; 63 64 import com.google.android.collect.Lists; 65 66 import java.lang.annotation.Retention; 67 import java.lang.annotation.RetentionPolicy; 68 import java.nio.charset.StandardCharsets; 69 import java.security.NoSuchAlgorithmException; 70 import java.security.SecureRandom; 71 import java.util.ArrayList; 72 import java.util.Collection; 73 import java.util.HashMap; 74 import java.util.List; 75 76 /** 77 * Utilities for the lock pattern and its settings. 78 */ 79 public class LockPatternUtils { 80 private static final String TAG = "LockPatternUtils"; 81 private static final boolean FRP_CREDENTIAL_ENABLED = true; 82 83 /** 84 * The interval of the countdown for showing progress of the lockout. 85 */ 86 public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; 87 88 /** 89 * This dictates when we start telling the user that continued failed attempts will wipe 90 * their device. 91 */ 92 public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5; 93 94 /** 95 * The minimum number of dots in a valid pattern. 96 */ 97 public static final int MIN_LOCK_PATTERN_SIZE = 4; 98 99 /** 100 * The minimum size of a valid password or PIN. 101 */ 102 public static final int MIN_LOCK_PASSWORD_SIZE = 4; 103 104 /** 105 * The minimum number of dots the user must include in a wrong pattern attempt for it to be 106 * counted. 107 */ 108 public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; 109 110 // NOTE: When modifying this, make sure credential sufficiency validation logic is intact. 111 public static final int CREDENTIAL_TYPE_NONE = -1; 112 public static final int CREDENTIAL_TYPE_PATTERN = 1; 113 // This is the legacy value persisted on disk. Never return it to clients, but internally 114 // we still need it to handle upgrade cases. 115 public static final int CREDENTIAL_TYPE_PASSWORD_OR_PIN = 2; 116 public static final int CREDENTIAL_TYPE_PIN = 3; 117 public static final int CREDENTIAL_TYPE_PASSWORD = 4; 118 119 // This is the value of pin length whenever pin length is not available 120 public static final int PIN_LENGTH_UNAVAILABLE = -1; 121 122 // This is the minimum pin length at which auto confirmation is supported 123 public static final int MIN_AUTO_PIN_REQUIREMENT_LENGTH = 6; 124 125 /** 126 * Header used for the encryption and decryption of the device credential for 127 * remote device lockscreen validation. 128 */ 129 public static final byte[] ENCRYPTED_REMOTE_CREDENTIALS_HEADER = 130 "encrypted_remote_credentials".getBytes(StandardCharsets.UTF_8); 131 132 @Retention(RetentionPolicy.SOURCE) 133 @IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = { 134 CREDENTIAL_TYPE_NONE, 135 CREDENTIAL_TYPE_PATTERN, 136 CREDENTIAL_TYPE_PASSWORD, 137 CREDENTIAL_TYPE_PIN, 138 // CREDENTIAL_TYPE_PASSWORD_OR_PIN is missing on purpose. 139 }) 140 public @interface CredentialType {} 141 credentialTypeToString(int credentialType)142 public static String credentialTypeToString(int credentialType) { 143 switch (credentialType) { 144 case CREDENTIAL_TYPE_NONE: 145 return "NONE"; 146 case CREDENTIAL_TYPE_PATTERN: 147 return "PATTERN"; 148 case CREDENTIAL_TYPE_PIN: 149 return "PIN"; 150 case CREDENTIAL_TYPE_PASSWORD: 151 return "PASSWORD"; 152 default: 153 return "UNKNOWN_" + credentialType; 154 } 155 } 156 157 /** 158 * Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the 159 * method will return a handle to the Gatekeeper Password in the 160 * {@link VerifyCredentialResponse}. 161 */ 162 public static final int VERIFY_FLAG_REQUEST_GK_PW_HANDLE = 1 << 0; 163 164 /** 165 * Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the 166 * method writes the password data to the repair mode file after the credential is verified 167 * successfully. 168 */ 169 public static final int VERIFY_FLAG_WRITE_REPAIR_MODE_PW = 1 << 1; 170 171 @Retention(RetentionPolicy.SOURCE) 172 @IntDef(flag = true, value = { 173 VERIFY_FLAG_REQUEST_GK_PW_HANDLE, 174 VERIFY_FLAG_WRITE_REPAIR_MODE_PW 175 }) 176 public @interface VerifyFlag {} 177 178 /** 179 * Special user id for triggering the FRP verification flow. 180 */ 181 public static final int USER_FRP = UserHandle.USER_NULL + 1; 182 183 /** 184 * Special user id for triggering the exiting repair mode verification flow. 185 */ 186 public static final int USER_REPAIR_MODE = UserHandle.USER_NULL + 2; 187 188 public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; 189 @Deprecated 190 public final static String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate"; 191 public final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt"; 192 public final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled"; 193 public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS 194 = "lockscreen.power_button_instantly_locks"; 195 @Deprecated 196 public final static String LOCKSCREEN_WIDGETS_ENABLED = "lockscreen.widgets_enabled"; 197 198 public final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory"; 199 200 private static final String LOCK_SCREEN_OWNER_INFO = Settings.Secure.LOCK_SCREEN_OWNER_INFO; 201 private static final String LOCK_SCREEN_OWNER_INFO_ENABLED = 202 Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 203 204 private static final String LOCK_PIN_ENHANCED_PRIVACY = "pin_enhanced_privacy"; 205 206 private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info"; 207 208 private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents"; 209 private static final String KNOWN_TRUST_AGENTS = "lockscreen.knowntrustagents"; 210 private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged"; 211 212 public static final String AUTO_PIN_CONFIRM = "lockscreen.auto_pin_confirm"; 213 214 public static final String CURRENT_LSKF_BASED_PROTECTOR_ID_KEY = "sp-handle"; 215 public static final String PASSWORD_HISTORY_DELIMITER = ","; 216 217 private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; 218 219 /** 220 * drives the pin auto confirmation feature availability in code logic. 221 */ 222 public static final String FLAG_ENABLE_AUTO_PIN_CONFIRMATION = 223 "AutoPinConfirmation__enable_auto_pin_confirmation"; 224 225 @UnsupportedAppUsage 226 private final Context mContext; 227 @UnsupportedAppUsage 228 private final ContentResolver mContentResolver; 229 private DevicePolicyManager mDevicePolicyManager; 230 private ILockSettings mLockSettingsService; 231 private UserManager mUserManager; 232 private final Handler mHandler; 233 private final SparseLongArray mLockoutDeadlines = new SparseLongArray(); 234 private Boolean mHasSecureLockScreen; 235 236 private HashMap<UserHandle, UserManager> mUserManagerCache = new HashMap<>(); 237 238 /** 239 * Use {@link TrustManager#isTrustUsuallyManaged(int)}. 240 * 241 * This returns the lazily-peristed value and should only be used by TrustManagerService. 242 */ isTrustUsuallyManaged(int userId)243 public boolean isTrustUsuallyManaged(int userId) { 244 if (!(mLockSettingsService instanceof ILockSettings.Stub)) { 245 throw new IllegalStateException("May only be called by TrustManagerService. " 246 + "Use TrustManager.isTrustUsuallyManaged()"); 247 } 248 try { 249 return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId); 250 } catch (RemoteException e) { 251 return false; 252 } 253 } 254 setTrustUsuallyManaged(boolean managed, int userId)255 public void setTrustUsuallyManaged(boolean managed, int userId) { 256 try { 257 getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId); 258 } catch (RemoteException e) { 259 // System dead. 260 } 261 } 262 userPresent(int userId)263 public void userPresent(int userId) { 264 try { 265 getLockSettings().userPresent(userId); 266 } catch (RemoteException e) { 267 throw e.rethrowFromSystemServer(); 268 } 269 } 270 271 public static final class RequestThrottledException extends Exception { 272 private int mTimeoutMs; 273 @UnsupportedAppUsage RequestThrottledException(int timeoutMs)274 public RequestThrottledException(int timeoutMs) { 275 mTimeoutMs = timeoutMs; 276 } 277 278 /** 279 * @return The amount of time in ms before another request may 280 * be executed 281 */ 282 @UnsupportedAppUsage getTimeoutMs()283 public int getTimeoutMs() { 284 return mTimeoutMs; 285 } 286 287 } 288 289 @UnsupportedAppUsage getDevicePolicyManager()290 public DevicePolicyManager getDevicePolicyManager() { 291 if (mDevicePolicyManager == null) { 292 mDevicePolicyManager = 293 (DevicePolicyManager)mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 294 if (mDevicePolicyManager == null) { 295 Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?", 296 new IllegalStateException("Stack trace:")); 297 } 298 } 299 return mDevicePolicyManager; 300 } 301 getUserManager()302 private UserManager getUserManager() { 303 if (mUserManager == null) { 304 mUserManager = UserManager.get(mContext); 305 } 306 return mUserManager; 307 } 308 getUserManager(int userId)309 private UserManager getUserManager(int userId) { 310 UserHandle userHandle = UserHandle.of(userId); 311 if (mUserManagerCache.containsKey(userHandle)) { 312 return mUserManagerCache.get(userHandle); 313 } 314 315 try { 316 Context userContext = mContext.createPackageContextAsUser("system", 0, userHandle); 317 UserManager userManager = userContext.getSystemService(UserManager.class); 318 mUserManagerCache.put(userHandle, userManager); 319 return userManager; 320 } catch (PackageManager.NameNotFoundException e) { 321 throw new RuntimeException("Failed to create context for user " + userHandle, e); 322 } 323 } 324 getTrustManager()325 private TrustManager getTrustManager() { 326 TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); 327 if (trust == null) { 328 Log.e(TAG, "Can't get TrustManagerService: is it running?", 329 new IllegalStateException("Stack trace:")); 330 } 331 return trust; 332 } 333 334 @UnsupportedAppUsage LockPatternUtils(Context context)335 public LockPatternUtils(Context context) { 336 this(context, null); 337 } 338 339 @VisibleForTesting LockPatternUtils(Context context, ILockSettings lockSettings)340 public LockPatternUtils(Context context, ILockSettings lockSettings) { 341 mContext = context; 342 mContentResolver = context.getContentResolver(); 343 344 Looper looper = Looper.myLooper(); 345 mHandler = looper != null ? new Handler(looper) : null; 346 mLockSettingsService = lockSettings; 347 } 348 349 @UnsupportedAppUsage 350 @VisibleForTesting getLockSettings()351 public ILockSettings getLockSettings() { 352 if (mLockSettingsService == null) { 353 ILockSettings service = ILockSettings.Stub.asInterface( 354 ServiceManager.getService("lock_settings")); 355 mLockSettingsService = service; 356 } 357 return mLockSettingsService; 358 } 359 getRequestedMinimumPasswordLength(int userId)360 public int getRequestedMinimumPasswordLength(int userId) { 361 return getDevicePolicyManager().getPasswordMinimumLength(null, userId); 362 } 363 getMaximumPasswordLength(int quality)364 public int getMaximumPasswordLength(int quality) { 365 return getDevicePolicyManager().getPasswordMaximumLength(quality); 366 } 367 368 /** 369 * Returns aggregated (legacy) password quality requirement on the target user from all admins. 370 */ getRequestedPasswordMetrics(int userId)371 public PasswordMetrics getRequestedPasswordMetrics(int userId) { 372 return getRequestedPasswordMetrics(userId, false); 373 } 374 375 /** 376 * Returns aggregated (legacy) password quality requirement on the target user from all admins, 377 * optioanlly disregarding policies set on the managed profile as if the profile had separate 378 * work challenge. 379 */ getRequestedPasswordMetrics(int userId, boolean deviceWideOnly)380 public PasswordMetrics getRequestedPasswordMetrics(int userId, boolean deviceWideOnly) { 381 return getDevicePolicyManager().getPasswordMinimumMetrics(userId, deviceWideOnly); 382 } 383 getRequestedPasswordHistoryLength(int userId)384 private int getRequestedPasswordHistoryLength(int userId) { 385 return getDevicePolicyManager().getPasswordHistoryLength(null, userId); 386 } 387 388 /** 389 * Returns the effective complexity for the user. 390 * @param userId The user to return the complexity for. 391 * @return complexity level for the user. 392 */ getRequestedPasswordComplexity(int userId)393 public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId) { 394 return getRequestedPasswordComplexity(userId, false); 395 } 396 397 /** 398 * Returns the effective complexity for the user, optioanlly disregarding complexity set on the 399 * managed profile as if the profile had separate work challenge. 400 401 * @param userId The user to return the complexity for. 402 * @param deviceWideOnly whether to ignore complexity set on the managed profile. 403 * @return complexity level for the user. 404 */ getRequestedPasswordComplexity(int userId, boolean deviceWideOnly)405 public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId, 406 boolean deviceWideOnly) { 407 return getDevicePolicyManager().getAggregatedPasswordComplexityForUser(userId, 408 deviceWideOnly); 409 } 410 411 @UnsupportedAppUsage reportFailedPasswordAttempt(int userId)412 public void reportFailedPasswordAttempt(int userId) { 413 if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { 414 return; 415 } 416 getDevicePolicyManager().reportFailedPasswordAttempt(userId); 417 getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); 418 } 419 420 @UnsupportedAppUsage reportSuccessfulPasswordAttempt(int userId)421 public void reportSuccessfulPasswordAttempt(int userId) { 422 if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { 423 return; 424 } 425 getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); 426 getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); 427 } 428 reportPasswordLockout(int timeoutMs, int userId)429 public void reportPasswordLockout(int timeoutMs, int userId) { 430 if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { 431 return; 432 } 433 getTrustManager().reportUnlockLockout(timeoutMs, userId); 434 } 435 getCurrentFailedPasswordAttempts(int userId)436 public int getCurrentFailedPasswordAttempts(int userId) { 437 if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { 438 return 0; 439 } 440 return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); 441 } 442 getMaximumFailedPasswordsForWipe(int userId)443 public int getMaximumFailedPasswordsForWipe(int userId) { 444 if (isSpecialUserId(mContext, userId, /* checkDeviceSupported= */ true)) { 445 return 0; 446 } 447 return getDevicePolicyManager().getMaximumFailedPasswordsForWipe( 448 null /* componentName */, userId); 449 } 450 451 /** 452 * Check to see if a credential matches the saved one. 453 * If credential matches, return an opaque attestation that the challenge was verified. 454 * 455 * @param credential The credential to check. 456 * @param userId The user whose credential is being verified 457 * @param flags See {@link VerifyFlag} 458 * @throws IllegalStateException if called on the main thread. 459 */ 460 @NonNull verifyCredential(@onNull LockscreenCredential credential, int userId, @VerifyFlag int flags)461 public VerifyCredentialResponse verifyCredential(@NonNull LockscreenCredential credential, 462 int userId, @VerifyFlag int flags) { 463 throwIfCalledOnMainThread(); 464 try { 465 final VerifyCredentialResponse response = getLockSettings().verifyCredential( 466 credential, userId, flags); 467 if (response == null) { 468 return VerifyCredentialResponse.ERROR; 469 } else { 470 return response; 471 } 472 } catch (RemoteException re) { 473 Log.e(TAG, "failed to verify credential", re); 474 return VerifyCredentialResponse.ERROR; 475 } 476 } 477 478 /** 479 * With the Gatekeeper Password Handle returned via {@link #verifyCredential( 480 * LockscreenCredential, int, int)}, request Gatekeeper to create a HardwareAuthToken wrapping 481 * the given challenge. 482 */ 483 @NonNull verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId)484 public VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, 485 long challenge, int userId) { 486 try { 487 final VerifyCredentialResponse response = getLockSettings() 488 .verifyGatekeeperPasswordHandle(gatekeeperPasswordHandle, challenge, userId); 489 if (response == null) { 490 return VerifyCredentialResponse.ERROR; 491 } 492 return response; 493 } catch (RemoteException e) { 494 Log.e(TAG, "failed to verify gatekeeper password", e); 495 return VerifyCredentialResponse.ERROR; 496 } 497 } 498 removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle)499 public void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle) { 500 try { 501 getLockSettings().removeGatekeeperPasswordHandle(gatekeeperPasswordHandle); 502 } catch (RemoteException e) { 503 Log.e(TAG, "failed to remove gatekeeper password handle", e); 504 } 505 } 506 507 /** 508 * Check to see if a credential matches the saved one. 509 * 510 * @param credential The credential to check. 511 * @param userId The user whose credential is being checked 512 * @param progressCallback callback to deliver early signal that the credential matches 513 * @return {@code true} if credential matches, {@code false} otherwise 514 * @throws RequestThrottledException if credential verification is being throttled due to 515 * to many incorrect attempts. 516 * @throws IllegalStateException if called on the main thread. 517 */ checkCredential(@onNull LockscreenCredential credential, int userId, @Nullable CheckCredentialProgressCallback progressCallback)518 public boolean checkCredential(@NonNull LockscreenCredential credential, int userId, 519 @Nullable CheckCredentialProgressCallback progressCallback) 520 throws RequestThrottledException { 521 throwIfCalledOnMainThread(); 522 try { 523 VerifyCredentialResponse response = getLockSettings().checkCredential( 524 credential, userId, wrapCallback(progressCallback)); 525 if (response == null) { 526 return false; 527 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 528 return true; 529 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 530 throw new RequestThrottledException(response.getTimeout()); 531 } else { 532 return false; 533 } 534 } catch (RemoteException re) { 535 Log.e(TAG, "failed to check credential", re); 536 return false; 537 } 538 } 539 540 /** 541 * Check if the credential of a managed profile with unified challenge matches. In this context, 542 * The credential should be the parent user's lockscreen password. If credential matches, 543 * return an opaque attestation associated with the managed profile that the challenge was 544 * verified. 545 * 546 * @param credential The parent user's credential to check. 547 * @return the attestation that the challenge was verified, or null 548 * @param userId The managed profile user id 549 * @param flags See {@link VerifyFlag} 550 * @throws IllegalStateException if called on the main thread. 551 */ 552 @NonNull verifyTiedProfileChallenge( @onNull LockscreenCredential credential, int userId, @VerifyFlag int flags)553 public VerifyCredentialResponse verifyTiedProfileChallenge( 554 @NonNull LockscreenCredential credential, int userId, @VerifyFlag int flags) { 555 throwIfCalledOnMainThread(); 556 try { 557 final VerifyCredentialResponse response = getLockSettings() 558 .verifyTiedProfileChallenge(credential, userId, flags); 559 if (response == null) { 560 return VerifyCredentialResponse.ERROR; 561 } else { 562 return response; 563 } 564 } catch (RemoteException re) { 565 Log.e(TAG, "failed to verify tied profile credential", re); 566 return VerifyCredentialResponse.ERROR; 567 } 568 } 569 570 /** 571 * Returns the password history hash factor, needed to check new password against password 572 * history with {@link #checkPasswordHistory(byte[], byte[], int)} 573 */ getPasswordHistoryHashFactor(@onNull LockscreenCredential currentPassword, int userId)574 public byte[] getPasswordHistoryHashFactor(@NonNull LockscreenCredential currentPassword, 575 int userId) { 576 try { 577 return getLockSettings().getHashFactor(currentPassword, userId); 578 } catch (RemoteException e) { 579 Log.e(TAG, "failed to get hash factor", e); 580 return null; 581 } 582 } 583 584 /** 585 * Check to see if a password matches any of the passwords stored in the 586 * password history. 587 * 588 * @param passwordToCheck The password to check. 589 * @param hashFactor Hash factor of the current user returned from 590 * {@link ILockSettings#getHashFactor} 591 * @return Whether the password matches any in the history. 592 */ checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId)593 public boolean checkPasswordHistory(byte[] passwordToCheck, byte[] hashFactor, int userId) { 594 if (passwordToCheck == null || passwordToCheck.length == 0) { 595 Log.e(TAG, "checkPasswordHistory: empty password"); 596 return false; 597 } 598 String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId); 599 if (TextUtils.isEmpty(passwordHistory)) { 600 return false; 601 } 602 int passwordHistoryLength = getRequestedPasswordHistoryLength(userId); 603 if(passwordHistoryLength == 0) { 604 return false; 605 } 606 byte[] salt = getSalt(userId).getBytes(); 607 String legacyHash = LockscreenCredential.legacyPasswordToHash(passwordToCheck, salt); 608 String passwordHash = LockscreenCredential.passwordToHistoryHash( 609 passwordToCheck, salt, hashFactor); 610 String[] history = passwordHistory.split(PASSWORD_HISTORY_DELIMITER); 611 // Password History may be too long... 612 for (int i = 0; i < Math.min(passwordHistoryLength, history.length); i++) { 613 if (history[i].equals(legacyHash) || history[i].equals(passwordHash)) { 614 return true; 615 } 616 } 617 return false; 618 } 619 620 /** 621 * Returns the length of the PIN set by a particular user. 622 * @param userId user id of the user whose pin length we have to return 623 * @return 624 * A. the length of the pin set by user if it is currently available 625 * B. PIN_LENGTH_UNAVAILABLE if it is not available or if an exception occurs 626 */ getPinLength(int userId)627 public int getPinLength(int userId) { 628 try { 629 return getLockSettings().getPinLength(userId); 630 } catch (RemoteException e) { 631 Log.e(TAG, "Could not fetch PIN length " + e); 632 return PIN_LENGTH_UNAVAILABLE; 633 } 634 } 635 636 /** 637 * This method saves the pin length value to disk based on the user's auto pin 638 * confirmation flag setting. If the auto pin confirmation flag is disabled, or if the 639 * user does not have a PIN setup, or if length of PIN is less than minimum storable PIN length 640 * value, the pin length value is set to PIN_LENGTH_UNAVAILABLE. Otherwise, if the 641 * flag is enabled, the pin length value is set to the actual length of the user's PIN. 642 * @param userId user id of the user whose pin length we want to save 643 * @return true/false depending on whether PIN length has been saved or not 644 */ refreshStoredPinLength(int userId)645 public boolean refreshStoredPinLength(int userId) { 646 try { 647 return getLockSettings().refreshStoredPinLength(userId); 648 } catch (RemoteException e) { 649 Log.e(TAG, "Could not store PIN length on disk " + e); 650 return false; 651 } 652 } 653 654 /** 655 * Used by device policy manager to validate the current password 656 * information it has. 657 * @Deprecated use {@link #getKeyguardStoredPasswordQuality} 658 */ 659 @UnsupportedAppUsage getActivePasswordQuality(int userId)660 public int getActivePasswordQuality(int userId) { 661 return getKeyguardStoredPasswordQuality(userId); 662 } 663 664 /** 665 * Use it to reset keystore without wiping work profile 666 */ resetKeyStore(int userId)667 public void resetKeyStore(int userId) { 668 try { 669 getLockSettings().resetKeyStore(userId); 670 } catch (RemoteException e) { 671 // It should not happen 672 Log.e(TAG, "Couldn't reset keystore " + e); 673 } 674 } 675 676 /** 677 * Disable showing lock screen at all for a given user. 678 * This is only meaningful if pattern, pin or password are not set. 679 * 680 * @param disable Disables lock screen when true 681 * @param userId User ID of the user this has effect on 682 */ setLockScreenDisabled(boolean disable, int userId)683 public void setLockScreenDisabled(boolean disable, int userId) { 684 setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId); 685 } 686 687 /** 688 * Determine if LockScreen is disabled for the current user. This is used to decide whether 689 * LockScreen is shown after reboot or after screen timeout / short press on power. 690 * 691 * @return true if lock screen is disabled 692 */ 693 @UnsupportedAppUsage isLockScreenDisabled(int userId)694 public boolean isLockScreenDisabled(int userId) { 695 if (isSecure(userId)) { 696 return false; 697 } 698 boolean disabledByDefault = mContext.getResources().getBoolean( 699 com.android.internal.R.bool.config_disableLockscreenByDefault); 700 UserInfo userInfo = getUserManager().getUserInfo(userId); 701 boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null 702 && userInfo.isDemo(); 703 return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId) 704 || disabledByDefault 705 || isDemoUser; 706 } 707 708 /** 709 * Sets the pin auto confirm capability to enabled or disabled 710 * @param enabled enables pin auto confirm capability when true 711 * @param userId user ID of the user this has effect on 712 */ setAutoPinConfirm(boolean enabled, int userId)713 public void setAutoPinConfirm(boolean enabled, int userId) { 714 setBoolean(AUTO_PIN_CONFIRM, enabled, userId); 715 } 716 717 /** 718 * Determines if the auto pin confirmation feature is enabled or not for current user 719 * If setting is not available, the default behaviour is disabled 720 * @param userId user ID of the user this has effect on 721 * 722 * @return true, if the entered pin should be auto confirmed 723 */ isAutoPinConfirmEnabled(int userId)724 public boolean isAutoPinConfirmEnabled(int userId) { 725 return getBoolean(AUTO_PIN_CONFIRM, /* defaultValue= */ false, userId); 726 } 727 728 /** 729 * Whether the auto pin feature is available or not. 730 * @return true. This method is always returning true due to feature flags not working 731 * properly (b/282246482). Ideally, this should check if deviceConfig flag is set to true 732 * and then return the appropriate value. 733 */ isAutoPinConfirmFeatureAvailable()734 public static boolean isAutoPinConfirmFeatureAvailable() { 735 return true; 736 } 737 738 /** Returns if the given quality maps to an alphabetic password */ isQualityAlphabeticPassword(int quality)739 public static boolean isQualityAlphabeticPassword(int quality) { 740 return quality >= PASSWORD_QUALITY_ALPHABETIC; 741 } 742 743 /** Returns if the given quality maps to an numeric pin */ isQualityNumericPin(int quality)744 public static boolean isQualityNumericPin(int quality) { 745 return quality == PASSWORD_QUALITY_NUMERIC || quality == PASSWORD_QUALITY_NUMERIC_COMPLEX; 746 } 747 748 /** Returns the canonical password quality corresponding to the given credential type. */ credentialTypeToPasswordQuality(int credentialType)749 public static int credentialTypeToPasswordQuality(int credentialType) { 750 switch (credentialType) { 751 case CREDENTIAL_TYPE_NONE: 752 return PASSWORD_QUALITY_UNSPECIFIED; 753 case CREDENTIAL_TYPE_PATTERN: 754 return PASSWORD_QUALITY_SOMETHING; 755 case CREDENTIAL_TYPE_PIN: 756 return PASSWORD_QUALITY_NUMERIC; 757 case CREDENTIAL_TYPE_PASSWORD: 758 return PASSWORD_QUALITY_ALPHABETIC; 759 default: 760 throw new IllegalStateException("Unknown type: " + credentialType); 761 } 762 } 763 764 /** Returns the credential type corresponding to the given PIN or password quality. */ pinOrPasswordQualityToCredentialType(int quality)765 public static int pinOrPasswordQualityToCredentialType(int quality) { 766 if (isQualityAlphabeticPassword(quality)) { 767 return CREDENTIAL_TYPE_PASSWORD; 768 } 769 if (isQualityNumericPin(quality)) { 770 return CREDENTIAL_TYPE_PIN; 771 } 772 throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality); 773 } 774 775 /** 776 * Save a new lockscreen credential. 777 * 778 * <p> This method will fail (returning {@code false}) if the previously saved credential 779 * provided is incorrect, or if the lockscreen verification is still being throttled. 780 * 781 * @param newCredential The new credential to save 782 * @param savedCredential The current credential 783 * @param userHandle the user whose lockscreen credential is to be changed 784 * 785 * @return whether this method saved the new password successfully or not. This flow will fail 786 * and return false if the given credential is wrong. 787 * @throws RuntimeException if password change encountered an unrecoverable error. 788 * @throws UnsupportedOperationException secure lockscreen is not supported on this device. 789 */ setLockCredential(@onNull LockscreenCredential newCredential, @NonNull LockscreenCredential savedCredential, int userHandle)790 public boolean setLockCredential(@NonNull LockscreenCredential newCredential, 791 @NonNull LockscreenCredential savedCredential, int userHandle) { 792 if (!hasSecureLockScreen() && newCredential.getType() != CREDENTIAL_TYPE_NONE) { 793 throw new UnsupportedOperationException( 794 "This operation requires the lock screen feature."); 795 } 796 797 try { 798 if (!getLockSettings().setLockCredential(newCredential, savedCredential, userHandle)) { 799 return false; 800 } 801 } catch (RemoteException e) { 802 throw new RuntimeException("Unable to save lock password", e); 803 } 804 return true; 805 } 806 807 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setOwnerInfo(String info, int userId)808 public void setOwnerInfo(String info, int userId) { 809 setString(LOCK_SCREEN_OWNER_INFO, info, userId); 810 } 811 812 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setOwnerInfoEnabled(boolean enabled, int userId)813 public void setOwnerInfoEnabled(boolean enabled, int userId) { 814 setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId); 815 } 816 817 @UnsupportedAppUsage getOwnerInfo(int userId)818 public String getOwnerInfo(int userId) { 819 return getString(LOCK_SCREEN_OWNER_INFO, userId); 820 } 821 isOwnerInfoEnabled(int userId)822 public boolean isOwnerInfoEnabled(int userId) { 823 return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId); 824 } 825 826 /** 827 * Sets the device owner information. If the information is {@code null} or empty then the 828 * device owner info is cleared. 829 * 830 * @param info Device owner information which will be displayed instead of the user 831 * owner info. 832 */ setDeviceOwnerInfo(String info)833 public void setDeviceOwnerInfo(String info) { 834 if (info != null && info.isEmpty()) { 835 info = null; 836 } 837 838 setString(LOCK_SCREEN_DEVICE_OWNER_INFO, info, UserHandle.USER_SYSTEM); 839 } 840 getDeviceOwnerInfo()841 public String getDeviceOwnerInfo() { 842 return getString(LOCK_SCREEN_DEVICE_OWNER_INFO, UserHandle.USER_SYSTEM); 843 } 844 isDeviceOwnerInfoEnabled()845 public boolean isDeviceOwnerInfoEnabled() { 846 return getDeviceOwnerInfo() != null; 847 } 848 849 /** 850 * Determine if the device supports encryption, even if it's set to default. This 851 * differs from isDeviceEncrypted() in that it returns true even if the device is 852 * encrypted with the default password. 853 * @return true if device encryption is enabled 854 */ 855 @UnsupportedAppUsage isDeviceEncryptionEnabled()856 public static boolean isDeviceEncryptionEnabled() { 857 return StorageManager.isEncrypted(); 858 } 859 860 /** 861 * Determine if the device is file encrypted 862 * @return true if device is file encrypted 863 */ isFileEncryptionEnabled()864 public static boolean isFileEncryptionEnabled() { 865 return StorageManager.isFileEncrypted(); 866 } 867 868 /** 869 * Retrieves the quality mode for {@code userHandle}. 870 * @see DevicePolicyManager#getPasswordQuality(android.content.ComponentName) 871 * 872 * @return stored password quality 873 * @deprecated use {@link #getCredentialTypeForUser(int)} instead 874 */ 875 @UnsupportedAppUsage 876 @Deprecated getKeyguardStoredPasswordQuality(int userHandle)877 public int getKeyguardStoredPasswordQuality(int userHandle) { 878 return credentialTypeToPasswordQuality(getCredentialTypeForUser(userHandle)); 879 } 880 881 /** 882 * Enables/disables the Separate Profile Challenge for this {@code userHandle}. This is a no-op 883 * for user handles that do not belong to a profile that shares credential with parent. 884 * (managed profile and clone profile share lock credential with parent). 885 * 886 * @param userHandle Managed profile user id 887 * @param enabled True if separate challenge is enabled 888 * @param profilePassword Managed/Clone profile previous password. Null when {@code enabled} is 889 * true 890 */ setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, LockscreenCredential profilePassword)891 public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled, 892 LockscreenCredential profilePassword) { 893 if (!isCredentialSharableWithParent(userHandle)) { 894 return; 895 } 896 try { 897 getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled, 898 profilePassword); 899 reportEnabledTrustAgentsChanged(userHandle); 900 } catch (RemoteException e) { 901 Log.e(TAG, "Couldn't update work profile challenge enabled"); 902 } 903 } 904 905 /** 906 * Returns true if {@code userHandle} is a profile with separate challenge. 907 * <p> 908 * Returns false if {@code userHandle} is a profile with unified challenge, a profile whose 909 * credential is not shareable with its parent, or a non-profile user. 910 */ isSeparateProfileChallengeEnabled(int userHandle)911 public boolean isSeparateProfileChallengeEnabled(int userHandle) { 912 return isCredentialSharableWithParent(userHandle) && hasSeparateChallenge(userHandle); 913 } 914 915 /** 916 * Returns true if {@code userHandle} is a profile with unified challenge. 917 * <p> 918 * Returns false if {@code userHandle} is a profile with separate challenge, a profile whose 919 * credential is not shareable with its parent, or a non-profile user. 920 */ isProfileWithUnifiedChallenge(int userHandle)921 public boolean isProfileWithUnifiedChallenge(int userHandle) { 922 return isCredentialSharableWithParent(userHandle) && !hasSeparateChallenge(userHandle); 923 } 924 925 /** 926 * Returns true if {@code userHandle} is a managed profile with unified challenge. 927 */ isManagedProfileWithUnifiedChallenge(int userHandle)928 public boolean isManagedProfileWithUnifiedChallenge(int userHandle) { 929 return isManagedProfile(userHandle) && !hasSeparateChallenge(userHandle); 930 } 931 hasSeparateChallenge(int userHandle)932 private boolean hasSeparateChallenge(int userHandle) { 933 try { 934 return getLockSettings().getSeparateProfileChallengeEnabled(userHandle); 935 } catch (RemoteException e) { 936 Log.e(TAG, "Couldn't get separate profile challenge enabled"); 937 // Default value is false 938 return false; 939 } 940 } 941 isManagedProfile(int userHandle)942 private boolean isManagedProfile(int userHandle) { 943 final UserInfo info = getUserManager().getUserInfo(userHandle); 944 return info != null && info.isManagedProfile(); 945 } 946 isCredentialSharableWithParent(int userHandle)947 private boolean isCredentialSharableWithParent(int userHandle) { 948 return getUserManager(userHandle).isCredentialSharableWithParent(); 949 } 950 951 /** 952 * Deserialize a pattern. 953 * @param bytes The pattern serialized with {@link #patternToByteArray} 954 * @return The pattern. 955 */ byteArrayToPattern(byte[] bytes)956 public static List<LockPatternView.Cell> byteArrayToPattern(byte[] bytes) { 957 if (bytes == null) { 958 return null; 959 } 960 961 List<LockPatternView.Cell> result = Lists.newArrayList(); 962 963 for (int i = 0; i < bytes.length; i++) { 964 byte b = (byte) (bytes[i] - '1'); 965 result.add(LockPatternView.Cell.of(b / 3, b % 3)); 966 } 967 return result; 968 } 969 970 /** 971 * Serialize a pattern. 972 * @param pattern The pattern. 973 * @return The pattern in byte array form. 974 */ patternToByteArray(List<LockPatternView.Cell> pattern)975 public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) { 976 if (pattern == null) { 977 return new byte[0]; 978 } 979 final int patternSize = pattern.size(); 980 981 byte[] res = new byte[patternSize]; 982 for (int i = 0; i < patternSize; i++) { 983 LockPatternView.Cell cell = pattern.get(i); 984 res[i] = (byte) (cell.getRow() * 3 + cell.getColumn() + '1'); 985 } 986 return res; 987 } 988 getSalt(int userId)989 private String getSalt(int userId) { 990 long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId); 991 if (salt == 0) { 992 try { 993 salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 994 setLong(LOCK_PASSWORD_SALT_KEY, salt, userId); 995 Log.v(TAG, "Initialized lock password salt for user: " + userId); 996 } catch (NoSuchAlgorithmException e) { 997 // Throw an exception rather than storing a password we'll never be able to recover 998 throw new IllegalStateException("Couldn't get SecureRandom number", e); 999 } 1000 } 1001 return Long.toHexString(salt); 1002 } 1003 1004 /** 1005 * Retrieve the credential type of a user. 1006 */ 1007 private final PropertyInvalidatedCache.QueryHandler<Integer, Integer> mCredentialTypeQuery = 1008 new PropertyInvalidatedCache.QueryHandler<>() { 1009 @Override 1010 public Integer apply(Integer userHandle) { 1011 try { 1012 return getLockSettings().getCredentialType(userHandle); 1013 } catch (RemoteException re) { 1014 Log.e(TAG, "failed to get credential type", re); 1015 return CREDENTIAL_TYPE_NONE; 1016 } 1017 } 1018 @Override 1019 public boolean shouldBypassCache(Integer userHandle) { 1020 return isSpecialUserId(userHandle); 1021 } 1022 }; 1023 1024 /** 1025 * The API that is cached. 1026 */ 1027 private final static String CREDENTIAL_TYPE_API = "getCredentialType"; 1028 1029 /** 1030 * Cache the credential type of a user. 1031 */ 1032 private final PropertyInvalidatedCache<Integer, Integer> mCredentialTypeCache = 1033 new PropertyInvalidatedCache<>(4, PropertyInvalidatedCache.MODULE_SYSTEM, 1034 CREDENTIAL_TYPE_API, CREDENTIAL_TYPE_API, mCredentialTypeQuery); 1035 1036 /** 1037 * Invalidate the credential type cache 1038 * @hide 1039 */ invalidateCredentialTypeCache()1040 public final static void invalidateCredentialTypeCache() { 1041 PropertyInvalidatedCache.invalidateCache(PropertyInvalidatedCache.MODULE_SYSTEM, 1042 CREDENTIAL_TYPE_API); 1043 } 1044 1045 /** 1046 * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE}, 1047 * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and 1048 * {@link #CREDENTIAL_TYPE_PASSWORD} 1049 */ getCredentialTypeForUser(int userHandle)1050 public @CredentialType int getCredentialTypeForUser(int userHandle) { 1051 return mCredentialTypeCache.query(userHandle); 1052 } 1053 1054 /** 1055 * @param userId the user for which to report the value 1056 * @return Whether the lock screen is secured. 1057 */ 1058 @UnsupportedAppUsage isSecure(int userId)1059 public boolean isSecure(int userId) { 1060 int type = getCredentialTypeForUser(userId); 1061 return type != CREDENTIAL_TYPE_NONE; 1062 } 1063 1064 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isLockPasswordEnabled(int userId)1065 public boolean isLockPasswordEnabled(int userId) { 1066 int type = getCredentialTypeForUser(userId); 1067 return type == CREDENTIAL_TYPE_PASSWORD || type == CREDENTIAL_TYPE_PIN; 1068 } 1069 1070 /** 1071 * @return Whether the lock pattern is enabled 1072 */ 1073 @UnsupportedAppUsage isLockPatternEnabled(int userId)1074 public boolean isLockPatternEnabled(int userId) { 1075 int type = getCredentialTypeForUser(userId); 1076 return type == CREDENTIAL_TYPE_PATTERN; 1077 } 1078 1079 /** 1080 * @return Whether the visible pattern is enabled. 1081 */ 1082 @UnsupportedAppUsage isVisiblePatternEnabled(int userId)1083 public boolean isVisiblePatternEnabled(int userId) { 1084 return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, true, userId); 1085 } 1086 1087 /** 1088 * Set whether the visible pattern is enabled. 1089 */ setVisiblePatternEnabled(boolean enabled, int userId)1090 public void setVisiblePatternEnabled(boolean enabled, int userId) { 1091 setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId); 1092 } 1093 isVisiblePatternEverChosen(int userId)1094 public boolean isVisiblePatternEverChosen(int userId) { 1095 return getString(Settings.Secure.LOCK_PATTERN_VISIBLE, userId) != null; 1096 } 1097 1098 /** 1099 * @return Whether enhanced pin privacy is enabled. 1100 */ isPinEnhancedPrivacyEnabled(int userId)1101 public boolean isPinEnhancedPrivacyEnabled(int userId) { 1102 return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, false, userId); 1103 } 1104 1105 /** 1106 * Set whether enhanced pin privacy is enabled. 1107 */ setPinEnhancedPrivacyEnabled(boolean enabled, int userId)1108 public void setPinEnhancedPrivacyEnabled(boolean enabled, int userId) { 1109 setBoolean(LOCK_PIN_ENHANCED_PRIVACY, enabled, userId); 1110 } 1111 1112 /** 1113 * @return Whether enhanced pin privacy was ever chosen. 1114 */ isPinEnhancedPrivacyEverChosen(int userId)1115 public boolean isPinEnhancedPrivacyEverChosen(int userId) { 1116 return getString(LOCK_PIN_ENHANCED_PRIVACY, userId) != null; 1117 } 1118 1119 /** 1120 * Set and store the lockout deadline, meaning the user can't attempt their unlock 1121 * pattern until the deadline has passed. 1122 * @return the chosen deadline. 1123 */ 1124 @UnsupportedAppUsage setLockoutAttemptDeadline(int userId, int timeoutMs)1125 public long setLockoutAttemptDeadline(int userId, int timeoutMs) { 1126 final long deadline = SystemClock.elapsedRealtime() + timeoutMs; 1127 if (userId == USER_FRP) { 1128 // For secure password storage (that is required for FRP), the underlying storage also 1129 // enforces the deadline. Since we cannot store settings for the FRP user, don't. 1130 return deadline; 1131 } 1132 mLockoutDeadlines.put(userId, deadline); 1133 return deadline; 1134 } 1135 1136 /** 1137 * @return The elapsed time in millis in the future when the user is allowed to 1138 * attempt to enter their lock pattern, or 0 if the user is welcome to 1139 * enter a pattern. 1140 */ getLockoutAttemptDeadline(int userId)1141 public long getLockoutAttemptDeadline(int userId) { 1142 final long deadline = mLockoutDeadlines.get(userId, 0L); 1143 final long now = SystemClock.elapsedRealtime(); 1144 if (deadline < now && deadline != 0) { 1145 // timeout expired 1146 mLockoutDeadlines.put(userId, 0); 1147 return 0L; 1148 } 1149 return deadline; 1150 } 1151 getBoolean(String secureSettingKey, boolean defaultValue, int userId)1152 private boolean getBoolean(String secureSettingKey, boolean defaultValue, int userId) { 1153 try { 1154 return getLockSettings().getBoolean(secureSettingKey, defaultValue, userId); 1155 } catch (RemoteException re) { 1156 return defaultValue; 1157 } 1158 } 1159 setBoolean(String secureSettingKey, boolean enabled, int userId)1160 private void setBoolean(String secureSettingKey, boolean enabled, int userId) { 1161 try { 1162 getLockSettings().setBoolean(secureSettingKey, enabled, userId); 1163 } catch (RemoteException re) { 1164 // What can we do? 1165 Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re); 1166 } 1167 } 1168 getLong(String secureSettingKey, long defaultValue, int userHandle)1169 private long getLong(String secureSettingKey, long defaultValue, int userHandle) { 1170 try { 1171 return getLockSettings().getLong(secureSettingKey, defaultValue, userHandle); 1172 } catch (RemoteException re) { 1173 return defaultValue; 1174 } 1175 } 1176 1177 @UnsupportedAppUsage setLong(String secureSettingKey, long value, int userHandle)1178 private void setLong(String secureSettingKey, long value, int userHandle) { 1179 try { 1180 getLockSettings().setLong(secureSettingKey, value, userHandle); 1181 } catch (RemoteException re) { 1182 // What can we do? 1183 Log.e(TAG, "Couldn't write long " + secureSettingKey + re); 1184 } 1185 } 1186 1187 @UnsupportedAppUsage getString(String secureSettingKey, int userHandle)1188 private String getString(String secureSettingKey, int userHandle) { 1189 try { 1190 return getLockSettings().getString(secureSettingKey, null, userHandle); 1191 } catch (RemoteException re) { 1192 return null; 1193 } 1194 } 1195 1196 @UnsupportedAppUsage setString(String secureSettingKey, String value, int userHandle)1197 private void setString(String secureSettingKey, String value, int userHandle) { 1198 try { 1199 getLockSettings().setString(secureSettingKey, value, userHandle); 1200 } catch (RemoteException re) { 1201 // What can we do? 1202 Log.e(TAG, "Couldn't write string " + secureSettingKey + re); 1203 } 1204 } 1205 setPowerButtonInstantlyLocks(boolean enabled, int userId)1206 public void setPowerButtonInstantlyLocks(boolean enabled, int userId) { 1207 setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId); 1208 } 1209 1210 @UnsupportedAppUsage getPowerButtonInstantlyLocks(int userId)1211 public boolean getPowerButtonInstantlyLocks(int userId) { 1212 return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId); 1213 } 1214 isPowerButtonInstantlyLocksEverChosen(int userId)1215 public boolean isPowerButtonInstantlyLocksEverChosen(int userId) { 1216 return getString(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, userId) != null; 1217 } 1218 1219 /** Updates the list of enabled trust agent in LockSettings storage for the given user. */ setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId)1220 public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) { 1221 setString(ENABLED_TRUST_AGENTS, serializeTrustAgents(activeTrustAgents), userId); 1222 getTrustManager().reportEnabledTrustAgentsChanged(userId); 1223 } 1224 1225 /** Returns the list of enabled trust agent in LockSettings storage for the given user. */ getEnabledTrustAgents(int userId)1226 public List<ComponentName> getEnabledTrustAgents(int userId) { 1227 return deserializeTrustAgents(getString(ENABLED_TRUST_AGENTS, userId)); 1228 } 1229 1230 /** Updates the list of known trust agent in LockSettings storage for the given user. */ setKnownTrustAgents(Collection<ComponentName> knownTrustAgents, int userId)1231 public void setKnownTrustAgents(Collection<ComponentName> knownTrustAgents, int userId) { 1232 setString(KNOWN_TRUST_AGENTS, serializeTrustAgents(knownTrustAgents), userId); 1233 } 1234 1235 /** Returns the list of known trust agent in LockSettings storage for the given user. */ getKnownTrustAgents(int userId)1236 public List<ComponentName> getKnownTrustAgents(int userId) { 1237 return deserializeTrustAgents(getString(KNOWN_TRUST_AGENTS, userId)); 1238 } 1239 serializeTrustAgents(Collection<ComponentName> trustAgents)1240 private String serializeTrustAgents(Collection<ComponentName> trustAgents) { 1241 StringBuilder sb = new StringBuilder(); 1242 for (ComponentName cn : trustAgents) { 1243 if (sb.length() > 0) { 1244 sb.append(','); 1245 } 1246 sb.append(cn.flattenToShortString()); 1247 } 1248 return sb.toString(); 1249 } 1250 deserializeTrustAgents(String serializedTrustAgents)1251 private List<ComponentName> deserializeTrustAgents(String serializedTrustAgents) { 1252 if (TextUtils.isEmpty(serializedTrustAgents)) { 1253 return new ArrayList<>(); 1254 } 1255 String[] split = serializedTrustAgents.split(","); 1256 ArrayList<ComponentName> trustAgents = new ArrayList<>(split.length); 1257 for (String s : split) { 1258 if (!TextUtils.isEmpty(s)) { 1259 trustAgents.add(ComponentName.unflattenFromString(s)); 1260 } 1261 } 1262 return trustAgents; 1263 } 1264 1265 /** 1266 * Disable trust until credentials have been entered for user {@code userId}. 1267 * 1268 * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. 1269 * 1270 * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL} 1271 */ requireCredentialEntry(int userId)1272 public void requireCredentialEntry(int userId) { 1273 requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId); 1274 } 1275 1276 /** 1277 * Requests strong authentication for user {@code userId}. 1278 * 1279 * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. 1280 * 1281 * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating 1282 * the reason for and the strength of the requested authentication. 1283 * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL} 1284 */ requireStrongAuth(@trongAuthTracker.StrongAuthFlags int strongAuthReason, int userId)1285 public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason, 1286 int userId) { 1287 try { 1288 getLockSettings().requireStrongAuth(strongAuthReason, userId); 1289 } catch (RemoteException e) { 1290 Log.e(TAG, "Error while requesting strong auth: " + e); 1291 } 1292 } 1293 reportEnabledTrustAgentsChanged(int userHandle)1294 private void reportEnabledTrustAgentsChanged(int userHandle) { 1295 getTrustManager().reportEnabledTrustAgentsChanged(userHandle); 1296 } 1297 throwIfCalledOnMainThread()1298 private void throwIfCalledOnMainThread() { 1299 if (Looper.getMainLooper().isCurrentThread()) { 1300 throw new IllegalStateException("should not be called from the main thread."); 1301 } 1302 } 1303 registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1304 public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) { 1305 try { 1306 getLockSettings().registerStrongAuthTracker(strongAuthTracker.getStub()); 1307 } catch (RemoteException e) { 1308 throw new RuntimeException("Could not register StrongAuthTracker"); 1309 } 1310 } 1311 unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker)1312 public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) { 1313 try { 1314 getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.getStub()); 1315 } catch (RemoteException e) { 1316 Log.e(TAG, "Could not unregister StrongAuthTracker", e); 1317 } 1318 } 1319 1320 /** Register the given WeakEscrowTokenRemovedListener. */ registerWeakEscrowTokenRemovedListener( @onNull final IWeakEscrowTokenRemovedListener listener)1321 public boolean registerWeakEscrowTokenRemovedListener( 1322 @NonNull final IWeakEscrowTokenRemovedListener listener) { 1323 try { 1324 return getLockSettings().registerWeakEscrowTokenRemovedListener(listener); 1325 } catch (RemoteException e) { 1326 Log.e(TAG, "Could not register WeakEscrowTokenRemovedListener."); 1327 throw e.rethrowFromSystemServer(); 1328 } 1329 } 1330 1331 /** Unregister the given WeakEscrowTokenRemovedListener. */ unregisterWeakEscrowTokenRemovedListener( @onNull final IWeakEscrowTokenRemovedListener listener)1332 public boolean unregisterWeakEscrowTokenRemovedListener( 1333 @NonNull final IWeakEscrowTokenRemovedListener listener) { 1334 try { 1335 return getLockSettings().unregisterWeakEscrowTokenRemovedListener(listener); 1336 } catch (RemoteException e) { 1337 Log.e(TAG, "Could not register WeakEscrowTokenRemovedListener."); 1338 throw e.rethrowFromSystemServer(); 1339 } 1340 } 1341 reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId)1342 public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) { 1343 try { 1344 getLockSettings().reportSuccessfulBiometricUnlock(isStrongBiometric, userId); 1345 } catch (RemoteException e) { 1346 Log.e(TAG, "Could not report successful biometric unlock", e); 1347 } 1348 } 1349 scheduleNonStrongBiometricIdleTimeout(int userId)1350 public void scheduleNonStrongBiometricIdleTimeout(int userId) { 1351 try { 1352 getLockSettings().scheduleNonStrongBiometricIdleTimeout(userId); 1353 } catch (RemoteException e) { 1354 Log.e(TAG, "Could not schedule non-strong biometric idle timeout", e); 1355 } 1356 } 1357 1358 /** 1359 * @see StrongAuthTracker#getStrongAuthForUser 1360 */ getStrongAuthForUser(int userId)1361 public int getStrongAuthForUser(int userId) { 1362 try { 1363 return getLockSettings().getStrongAuthForUser(userId); 1364 } catch (RemoteException e) { 1365 Log.e(TAG, "Could not get StrongAuth", e); 1366 return StrongAuthTracker.getDefaultFlags(mContext); 1367 } 1368 } 1369 1370 /** 1371 * Whether the user is not allowed to set any credentials via PASSWORD_QUALITY_MANAGED. 1372 */ isCredentialsDisabledForUser(int userId)1373 public boolean isCredentialsDisabledForUser(int userId) { 1374 return getDevicePolicyManager().getPasswordQuality(/* admin= */ null, userId) 1375 == PASSWORD_QUALITY_MANAGED; 1376 } 1377 1378 /** 1379 * @see StrongAuthTracker#isTrustAllowedForUser 1380 */ isTrustAllowedForUser(int userId)1381 public boolean isTrustAllowedForUser(int userId) { 1382 return getStrongAuthForUser(userId) == StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; 1383 } 1384 1385 /** 1386 * @see StrongAuthTracker#isBiometricAllowedForUser(int) 1387 */ isBiometricAllowedForUser(int userId)1388 public boolean isBiometricAllowedForUser(int userId) { 1389 return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_BIOMETRIC) == 0; 1390 } 1391 isUserInLockdown(int userId)1392 public boolean isUserInLockdown(int userId) { 1393 return (getStrongAuthForUser(userId) 1394 & StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) != 0; 1395 } 1396 1397 private static class WrappedCallback extends ICheckCredentialProgressCallback.Stub { 1398 1399 private Handler mHandler; 1400 private CheckCredentialProgressCallback mCallback; 1401 WrappedCallback(Handler handler, CheckCredentialProgressCallback callback)1402 WrappedCallback(Handler handler, CheckCredentialProgressCallback callback) { 1403 mHandler = handler; 1404 mCallback = callback; 1405 } 1406 1407 @Override onCredentialVerified()1408 public void onCredentialVerified() throws RemoteException { 1409 if (mHandler == null) { 1410 Log.e(TAG, "Handler is null during callback"); 1411 } 1412 // Kill reference immediately to allow early GC at client side independent of 1413 // when system_server decides to lose its reference to the 1414 // ICheckCredentialProgressCallback binder object. 1415 mHandler.post(() -> { 1416 mCallback.onEarlyMatched(); 1417 mCallback = null; 1418 }); 1419 mHandler = null; 1420 } 1421 } 1422 wrapCallback( final CheckCredentialProgressCallback callback)1423 private ICheckCredentialProgressCallback wrapCallback( 1424 final CheckCredentialProgressCallback callback) { 1425 if (callback == null) { 1426 return null; 1427 } else { 1428 if (mHandler == null) { 1429 throw new IllegalStateException("Must construct LockPatternUtils on a looper thread" 1430 + " to use progress callbacks."); 1431 } 1432 return new WrappedCallback(mHandler, callback); 1433 } 1434 } 1435 getLockSettingsInternal()1436 private LockSettingsInternal getLockSettingsInternal() { 1437 LockSettingsInternal service = LocalServices.getService(LockSettingsInternal.class); 1438 if (service == null) { 1439 throw new SecurityException("Only available to system server itself"); 1440 } 1441 return service; 1442 } 1443 /** 1444 * Create an escrow token for the current user, which can later be used to unlock FBE 1445 * or change user password. 1446 * 1447 * After adding, if the user currently has lockscreen password, they will need to perform a 1448 * confirm credential operation in order to activate the token for future use. If the user 1449 * has no secure lockscreen, then the token is activated immediately. 1450 * 1451 * <p>This method is only available to code running in the system server process itself. 1452 * 1453 * @return a unique 64-bit token handle which is needed to refer to this token later. 1454 */ addEscrowToken(byte[] token, int userId, @Nullable EscrowTokenStateChangeCallback callback)1455 public long addEscrowToken(byte[] token, int userId, 1456 @Nullable EscrowTokenStateChangeCallback callback) { 1457 return getLockSettingsInternal().addEscrowToken(token, userId, callback); 1458 } 1459 1460 /** 1461 * Create a weak escrow token for the current user, which can later be used to unlock FBE 1462 * or change user password. 1463 * 1464 * After adding, if the user currently has lockscreen password, they will need to perform a 1465 * confirm credential operation in order to activate the token for future use. If the user 1466 * has no secure lockscreen, then the token is activated immediately. 1467 * 1468 * If the user changes or removes lockscreen password, activated weak escrow tokens will be 1469 * removed. 1470 * 1471 * @return a unique 64-bit token handle which is needed to refer to this token later. 1472 */ addWeakEscrowToken(byte[] token, int userId, @NonNull IWeakEscrowTokenActivatedListener callback)1473 public long addWeakEscrowToken(byte[] token, int userId, 1474 @NonNull IWeakEscrowTokenActivatedListener callback) { 1475 try { 1476 return getLockSettings().addWeakEscrowToken(token, userId, callback); 1477 } catch (RemoteException e) { 1478 Log.e(TAG, "Could not add weak token."); 1479 throw e.rethrowFromSystemServer(); 1480 } 1481 } 1482 1483 /** 1484 * Callback interface to notify when an added escrow token has been activated. 1485 */ 1486 public interface EscrowTokenStateChangeCallback { 1487 /** 1488 * The method to be called when the token is activated. 1489 * @param handle 64 bit handle corresponding to the escrow token 1490 * @param userId user for whom the escrow token has been added 1491 */ onEscrowTokenActivated(long handle, int userId)1492 void onEscrowTokenActivated(long handle, int userId); 1493 } 1494 1495 /** 1496 * Remove an escrow token. 1497 * 1498 * <p>This method is only available to code running in the system server process itself. 1499 * 1500 * @return true if the given handle refers to a valid token previously returned from 1501 * {@link #addEscrowToken}, whether it's active or not. return false otherwise. 1502 */ removeEscrowToken(long handle, int userId)1503 public boolean removeEscrowToken(long handle, int userId) { 1504 return getLockSettingsInternal().removeEscrowToken(handle, userId); 1505 } 1506 1507 /** 1508 * Remove a weak escrow token. 1509 * 1510 * @return true if the given handle refers to a valid weak token previously returned from 1511 * {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise. 1512 */ removeWeakEscrowToken(long handle, int userId)1513 public boolean removeWeakEscrowToken(long handle, int userId) { 1514 try { 1515 return getLockSettings().removeWeakEscrowToken(handle, userId); 1516 } catch (RemoteException e) { 1517 Log.e(TAG, "Could not remove the weak token."); 1518 throw e.rethrowFromSystemServer(); 1519 } 1520 } 1521 1522 /** 1523 * Check if the given escrow token is active or not. Only active token can be used to call 1524 * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken} 1525 * 1526 * <p>This method is only available to code running in the system server process itself. 1527 */ isEscrowTokenActive(long handle, int userId)1528 public boolean isEscrowTokenActive(long handle, int userId) { 1529 return getLockSettingsInternal().isEscrowTokenActive(handle, userId); 1530 } 1531 1532 /** 1533 * Check if the given weak escrow token is active or not. Only active token can be used to call 1534 * {@link #setLockCredentialWithToken} and {@link #unlockUserWithToken} 1535 */ isWeakEscrowTokenActive(long handle, int userId)1536 public boolean isWeakEscrowTokenActive(long handle, int userId) { 1537 try { 1538 return getLockSettings().isWeakEscrowTokenActive(handle, userId); 1539 } catch (RemoteException e) { 1540 Log.e(TAG, "Could not check the weak token."); 1541 throw e.rethrowFromSystemServer(); 1542 } 1543 } 1544 1545 /** Check if the given weak escrow token is valid. */ isWeakEscrowTokenValid(long handle, byte[] token, int userId)1546 public boolean isWeakEscrowTokenValid(long handle, byte[] token, int userId) { 1547 try { 1548 return getLockSettings().isWeakEscrowTokenValid(handle, token, userId); 1549 } catch (RemoteException e) { 1550 Log.e(TAG, "Could not validate the weak token."); 1551 throw e.rethrowFromSystemServer(); 1552 } 1553 } 1554 1555 /** 1556 * Change a user's lock credential with a pre-configured escrow token. 1557 * 1558 * <p>This method is only available to code running in the system server process itself. 1559 * 1560 * @param credential The new credential to be set 1561 * @param tokenHandle Handle of the escrow token 1562 * @param token Escrow token 1563 * @param userHandle The user who's lock credential to be changed 1564 * @return {@code true} if the operation is successful. 1565 */ setLockCredentialWithToken(@onNull LockscreenCredential credential, long tokenHandle, byte[] token, int userHandle)1566 public boolean setLockCredentialWithToken(@NonNull LockscreenCredential credential, 1567 long tokenHandle, byte[] token, int userHandle) { 1568 if (!hasSecureLockScreen() && credential.getType() != CREDENTIAL_TYPE_NONE) { 1569 throw new UnsupportedOperationException( 1570 "This operation requires the lock screen feature."); 1571 } 1572 LockSettingsInternal localService = getLockSettingsInternal(); 1573 1574 return localService.setLockCredentialWithToken(credential, tokenHandle, token, userHandle); 1575 } 1576 1577 /** 1578 * Unlock the specified user by an pre-activated escrow token. This should have the same effect 1579 * on device encryption as the user entering their lockscreen credentials for the first time after 1580 * boot, this includes unlocking the user's credential-encrypted storage as well as the keystore 1581 * 1582 * <p>This method is only available to code running in the system server process itself. 1583 * 1584 * @return {@code true} if the supplied token is valid and unlock succeeds, 1585 * {@code false} otherwise. 1586 */ unlockUserWithToken(long tokenHandle, byte[] token, int userId)1587 public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) { 1588 return getLockSettingsInternal().unlockUserWithToken(tokenHandle, token, userId); 1589 } 1590 1591 1592 /** 1593 * Callback to be notified about progress when checking credentials. 1594 */ 1595 public interface CheckCredentialProgressCallback { 1596 1597 /** 1598 * Called as soon as possible when we know that the credentials match but the user hasn't 1599 * been fully unlocked. 1600 */ onEarlyMatched()1601 void onEarlyMatched(); 1602 } 1603 1604 /** 1605 * Tracks the global strong authentication state. 1606 */ 1607 public static class StrongAuthTracker { 1608 1609 @IntDef(flag = true, 1610 value = { STRONG_AUTH_NOT_REQUIRED, 1611 STRONG_AUTH_REQUIRED_AFTER_BOOT, 1612 STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, 1613 SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, 1614 STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, 1615 STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, 1616 STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, 1617 STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT, 1618 SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, 1619 SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST}) 1620 @Retention(RetentionPolicy.SOURCE) 1621 public @interface StrongAuthFlags {} 1622 1623 /** 1624 * Strong authentication is not required. 1625 */ 1626 public static final int STRONG_AUTH_NOT_REQUIRED = 0x0; 1627 1628 /** 1629 * Strong authentication is required because the user has not authenticated since boot. 1630 */ 1631 public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1; 1632 1633 /** 1634 * Strong authentication is required because a device admin has requested it. 1635 */ 1636 public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2; 1637 1638 /** 1639 * Some authentication is required because the user has temporarily disabled trust. 1640 */ 1641 public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4; 1642 1643 /** 1644 * Strong authentication is required because the user has been locked out after too many 1645 * attempts using primary auth methods (i.e. PIN/pattern/password) from the lock screen, 1646 * Android Settings, and BiometricPrompt where user authentication is required. 1647 */ 1648 public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8; 1649 1650 /** 1651 * Strong authentication is required because it hasn't been used for a time required by 1652 * a device admin. 1653 */ 1654 public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10; 1655 1656 /** 1657 * Strong authentication is required because the user has triggered lockdown. 1658 */ 1659 public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20; 1660 1661 /** 1662 * Strong authentication is required to prepare for unattended upgrade. 1663 */ 1664 public static final int STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE = 0x40; 1665 1666 /** 1667 * Strong authentication is required because it hasn't been used for a time after a 1668 * non-strong biometric (i.e. weak or convenience biometric) is used to unlock device. 1669 */ 1670 public static final int STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT = 0x80; 1671 1672 /** 1673 * Some authentication is required because the trustagent either timed out or was disabled 1674 * manually. 1675 */ 1676 public static final int SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED = 0x100; 1677 1678 /** 1679 * Some authentication is required because adaptive auth has requested to lock device due to 1680 * repeated failed primary auth (i.e. PIN/pattern/password) or biometric auth attempts which 1681 * can come from Android Settings or BiometricPrompt where user authentication is required, 1682 * in addition to from the lock screen. When a risk is determined, adaptive auth will 1683 * proactively prompt the lock screen and will require users to re-enter the device with 1684 * either primary auth or biometric auth (if not prohibited by other flags). 1685 */ 1686 public static final int SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST = 0x200; 1687 1688 /** 1689 * Strong auth flags that do not prevent biometric methods from being accepted as auth. 1690 * If any other flags are set, biometric authentication is disabled. 1691 */ 1692 private static final int ALLOWING_BIOMETRIC = STRONG_AUTH_NOT_REQUIRED 1693 | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST 1694 | SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED 1695 | SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST; 1696 1697 private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray(); 1698 private final H mHandler; 1699 private final int mDefaultStrongAuthFlags; 1700 1701 private final SparseBooleanArray mIsNonStrongBiometricAllowedForUser = 1702 new SparseBooleanArray(); 1703 private final boolean mDefaultIsNonStrongBiometricAllowed = true; 1704 StrongAuthTracker(Context context)1705 public StrongAuthTracker(Context context) { 1706 this(context, Looper.myLooper()); 1707 } 1708 1709 /** 1710 * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged} 1711 * will be scheduled. 1712 * @param context the current {@link Context} 1713 */ StrongAuthTracker(Context context, Looper looper)1714 public StrongAuthTracker(Context context, Looper looper) { 1715 mHandler = new H(looper); 1716 mDefaultStrongAuthFlags = getDefaultFlags(context); 1717 } 1718 getDefaultFlags(Context context)1719 public static @StrongAuthFlags int getDefaultFlags(Context context) { 1720 boolean strongAuthRequired = context.getResources().getBoolean( 1721 com.android.internal.R.bool.config_strongAuthRequiredOnBoot); 1722 return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED; 1723 } 1724 1725 /** 1726 * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required, 1727 * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong 1728 * authentication is required. 1729 * 1730 * @param userId the user for whom the state is queried. 1731 */ getStrongAuthForUser(int userId)1732 public @StrongAuthFlags int getStrongAuthForUser(int userId) { 1733 return mStrongAuthRequiredForUser.get(userId, mDefaultStrongAuthFlags); 1734 } 1735 1736 /** 1737 * @return true if unlocking with trust alone is allowed for {@code userId} by the current 1738 * strong authentication requirements. 1739 */ isTrustAllowedForUser(int userId)1740 public boolean isTrustAllowedForUser(int userId) { 1741 return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED; 1742 } 1743 1744 /** 1745 * @return true if unlocking with a biometric method alone is allowed for {@code userId} 1746 * by the current strong authentication requirements. 1747 */ isBiometricAllowedForUser(boolean isStrongBiometric, int userId)1748 public boolean isBiometricAllowedForUser(boolean isStrongBiometric, int userId) { 1749 boolean allowed = ((getStrongAuthForUser(userId) & ~ALLOWING_BIOMETRIC) == 0); 1750 if (!isStrongBiometric) { 1751 allowed &= isNonStrongBiometricAllowedAfterIdleTimeout(userId); 1752 } 1753 return allowed; 1754 } 1755 1756 /** 1757 * @return true if unlocking with a non-strong (i.e. weak or convenience) biometric method 1758 * alone is allowed for {@code userId}, otherwise returns false. 1759 */ isNonStrongBiometricAllowedAfterIdleTimeout(int userId)1760 public boolean isNonStrongBiometricAllowedAfterIdleTimeout(int userId) { 1761 return mIsNonStrongBiometricAllowedForUser.get(userId, 1762 mDefaultIsNonStrongBiometricAllowed); 1763 } 1764 1765 /** 1766 * Called when the strong authentication requirements for {@code userId} changed. 1767 */ onStrongAuthRequiredChanged(int userId)1768 public void onStrongAuthRequiredChanged(int userId) { 1769 } 1770 1771 /** 1772 * Called when whether non-strong biometric is allowed for {@code userId} changed. 1773 */ onIsNonStrongBiometricAllowedChanged(int userId)1774 public void onIsNonStrongBiometricAllowedChanged(int userId) { 1775 } 1776 handleStrongAuthRequiredChanged(@trongAuthFlags int strongAuthFlags, int userId)1777 protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags, 1778 int userId) { 1779 int oldValue = getStrongAuthForUser(userId); 1780 if (strongAuthFlags != oldValue) { 1781 if (strongAuthFlags == mDefaultStrongAuthFlags) { 1782 mStrongAuthRequiredForUser.delete(userId); 1783 } else { 1784 mStrongAuthRequiredForUser.put(userId, strongAuthFlags); 1785 } 1786 onStrongAuthRequiredChanged(userId); 1787 } 1788 } 1789 handleIsNonStrongBiometricAllowedChanged(boolean allowed, int userId)1790 protected void handleIsNonStrongBiometricAllowedChanged(boolean allowed, 1791 int userId) { 1792 boolean oldValue = isNonStrongBiometricAllowedAfterIdleTimeout(userId); 1793 if (allowed != oldValue) { 1794 if (allowed == mDefaultIsNonStrongBiometricAllowed) { 1795 mIsNonStrongBiometricAllowedForUser.delete(userId); 1796 } else { 1797 mIsNonStrongBiometricAllowedForUser.put(userId, allowed); 1798 } 1799 onIsNonStrongBiometricAllowedChanged(userId); 1800 } 1801 } 1802 1803 private final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() { 1804 @Override 1805 public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags, 1806 int userId) { 1807 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED, 1808 strongAuthFlags, userId).sendToTarget(); 1809 } 1810 1811 @Override 1812 public void onIsNonStrongBiometricAllowedChanged(boolean allowed, int userId) { 1813 mHandler.obtainMessage(H.MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED, 1814 allowed ? 1 : 0, userId).sendToTarget(); 1815 } 1816 }; 1817 getStub()1818 public IStrongAuthTracker.Stub getStub() { 1819 return mStub; 1820 } 1821 1822 private class H extends Handler { 1823 static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1; 1824 static final int MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED = 2; 1825 H(Looper looper)1826 public H(Looper looper) { 1827 super(looper); 1828 } 1829 1830 @Override handleMessage(Message msg)1831 public void handleMessage(Message msg) { 1832 switch (msg.what) { 1833 case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED: 1834 handleStrongAuthRequiredChanged(msg.arg1, msg.arg2); 1835 break; 1836 case MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED: 1837 handleIsNonStrongBiometricAllowedChanged(msg.arg1 == 1 /* allowed */, 1838 msg.arg2); 1839 break; 1840 } 1841 } 1842 } 1843 } 1844 1845 /** 1846 * Returns whether the given user has pending escrow tokens 1847 */ hasPendingEscrowToken(int userId)1848 public boolean hasPendingEscrowToken(int userId) { 1849 try { 1850 return getLockSettings().hasPendingEscrowToken(userId); 1851 } catch (RemoteException e) { 1852 e.rethrowFromSystemServer(); 1853 } 1854 return false; 1855 } 1856 1857 /** 1858 * Return true if the device supports the lock screen feature, false otherwise. 1859 */ hasSecureLockScreen()1860 public boolean hasSecureLockScreen() { 1861 if (mHasSecureLockScreen == null) { 1862 try { 1863 mHasSecureLockScreen = Boolean.valueOf(getLockSettings().hasSecureLockScreen()); 1864 } catch (RemoteException e) { 1865 e.rethrowFromSystemServer(); 1866 } 1867 } 1868 return mHasSecureLockScreen.booleanValue(); 1869 } 1870 userOwnsFrpCredential(Context context, UserInfo info)1871 public static boolean userOwnsFrpCredential(Context context, UserInfo info) { 1872 return info != null && info.isMain() && info.isAdmin() && frpCredentialEnabled(context); 1873 } 1874 frpCredentialEnabled(Context context)1875 public static boolean frpCredentialEnabled(Context context) { 1876 return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean( 1877 com.android.internal.R.bool.config_enableCredentialFactoryResetProtection); 1878 } 1879 1880 /** 1881 * Return {@code true} if repair mode is supported by the device. 1882 */ isRepairModeSupported(Context context)1883 public static boolean isRepairModeSupported(Context context) { 1884 return context.getResources().getBoolean( 1885 com.android.internal.R.bool.config_repairModeSupported); 1886 } 1887 1888 /** 1889 * Return {@code true} if repair mode is active on the device. 1890 */ isRepairModeActive(Context context)1891 public static boolean isRepairModeActive(Context context) { 1892 return Settings.Global.getInt(context.getContentResolver(), 1893 Settings.Global.REPAIR_MODE_ACTIVE, /* def= */ 0) > 0; 1894 } 1895 1896 /** 1897 * Return {@code true} if repair mode is supported by the device and the user has been granted 1898 * admin privileges. 1899 */ canUserEnterRepairMode(Context context, UserInfo info)1900 public static boolean canUserEnterRepairMode(Context context, UserInfo info) { 1901 return info != null && info.isAdmin() && isRepairModeSupported(context); 1902 } 1903 1904 /** 1905 * Return {@code true} if GSI is running on the device. 1906 */ isGsiRunning()1907 public static boolean isGsiRunning() { 1908 return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; 1909 } 1910 1911 /** 1912 * Return {@code true} if the given user id is a special user such as {@link #USER_FRP}. 1913 */ isSpecialUserId(int userId)1914 public static boolean isSpecialUserId(int userId) { 1915 return isSpecialUserId(/* context= */ null, userId, /* checkDeviceSupported= */ false); 1916 } 1917 1918 /** 1919 * Return {@code true} if the given user id is a special user for the verification flow. 1920 * 1921 * @param checkDeviceSupported {@code true} to check the specified user is supported 1922 * by the device. 1923 */ isSpecialUserId(@ullable Context context, int userId, boolean checkDeviceSupported)1924 private static boolean isSpecialUserId(@Nullable Context context, int userId, 1925 boolean checkDeviceSupported) { 1926 switch (userId) { 1927 case USER_FRP: 1928 if (checkDeviceSupported) return frpCredentialEnabled(context); 1929 return true; 1930 1931 case USER_REPAIR_MODE: 1932 if (checkDeviceSupported) return isRepairModeSupported(context); 1933 return true; 1934 } 1935 return false; 1936 } 1937 1938 /** 1939 * Attempt to rederive the unified work challenge for the specified profile user and unlock the 1940 * user. If successful, this would allow the user to leave quiet mode automatically without 1941 * additional user authentication. 1942 * 1943 * This is made possible by the framework storing an encrypted copy of the unified challenge 1944 * auth-bound to the primary user's lockscreen. As long as the primery user has unlocked 1945 * recently (7 days), the framework will be able to decrypt it and plug the secret into the 1946 * unlock flow. 1947 * 1948 * @return {@code true} if automatic unlocking is successful, {@code false} otherwise. 1949 */ tryUnlockWithCachedUnifiedChallenge(int userId)1950 public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { 1951 try { 1952 return getLockSettings().tryUnlockWithCachedUnifiedChallenge(userId); 1953 } catch (RemoteException re) { 1954 return false; 1955 } 1956 } 1957 1958 /** Remove cached unified profile challenge, for testing and CTS usage. */ removeCachedUnifiedChallenge(int userId)1959 public void removeCachedUnifiedChallenge(int userId) { 1960 try { 1961 getLockSettings().removeCachedUnifiedChallenge(userId); 1962 } catch (RemoteException re) { 1963 re.rethrowFromSystemServer(); 1964 } 1965 } 1966 1967 /** 1968 * If the user is not secured, ie doesn't have an LSKF, then decrypt the user's synthetic 1969 * password and use it to unlock various cryptographic keys associated with the user. This 1970 * primarily includes unlocking the user's credential-encrypted (CE) storage. It also includes 1971 * unlocking the user's Keystore super keys, and deriving or decrypting the vendor auth secret 1972 * and sending it to the AuthSecret HAL in order to unlock Secure Element firmware updates. 1973 * <p> 1974 * These tasks would normally be done when the LSKF is verified. This method is where these 1975 * tasks are done when the user doesn't have an LSKF. It's called when the user is started. 1976 * <p> 1977 * Except on permission denied, this method doesn't throw an exception on failure. However, the 1978 * last thing that it does is unlock CE storage, and whether CE storage has been successfully 1979 * unlocked can be determined by {@link StorageManager#isCeStorageUnlocked()}. 1980 * <p> 1981 * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. 1982 * 1983 * @param userId the ID of the user whose keys to unlock 1984 */ unlockUserKeyIfUnsecured(@serIdInt int userId)1985 public void unlockUserKeyIfUnsecured(@UserIdInt int userId) { 1986 try { 1987 getLockSettings().unlockUserKeyIfUnsecured(userId); 1988 } catch (RemoteException re) { 1989 re.rethrowFromSystemServer(); 1990 } 1991 } 1992 createNewUser(@serIdInt int userId, int userSerialNumber)1993 public void createNewUser(@UserIdInt int userId, int userSerialNumber) { 1994 getLockSettingsInternal().createNewUser(userId, userSerialNumber); 1995 } 1996 removeUser(@serIdInt int userId)1997 public void removeUser(@UserIdInt int userId) { 1998 getLockSettingsInternal().removeUser(userId); 1999 } 2000 2001 /** 2002 * Starts a session to verify lockscreen credentials provided by a remote device. 2003 */ 2004 @NonNull startRemoteLockscreenValidation()2005 public RemoteLockscreenValidationSession startRemoteLockscreenValidation() { 2006 try { 2007 return getLockSettings().startRemoteLockscreenValidation(); 2008 } catch (RemoteException e) { 2009 throw e.rethrowFromSystemServer(); 2010 } 2011 } 2012 2013 /** 2014 * Verifies credentials guess from a remote device. 2015 */ 2016 @NonNull validateRemoteLockscreen( @onNull byte[] encryptedCredential)2017 public RemoteLockscreenValidationResult validateRemoteLockscreen( 2018 @NonNull byte[] encryptedCredential) { 2019 try { 2020 return getLockSettings().validateRemoteLockscreen(encryptedCredential); 2021 } catch (RemoteException e) { 2022 throw e.rethrowFromSystemServer(); 2023 } 2024 } 2025 } 2026