1 /* 2 * Copyright (C) 2012 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.server.locksettings; 18 19 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; 20 import static android.Manifest.permission.MANAGE_BIOMETRIC; 21 import static android.Manifest.permission.READ_CONTACTS; 22 import static android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS; 23 import static android.Manifest.permission.SET_INITIAL_LOCK; 24 import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_DETAIL; 25 import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_MESSAGE; 26 import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_TITLE; 27 import static android.content.Context.KEYGUARD_SERVICE; 28 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 29 import static android.os.UserHandle.USER_ALL; 30 31 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; 32 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 33 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN; 34 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; 35 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN; 36 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; 37 import static com.android.internal.widget.LockPatternUtils.PROFILE_KEY_NAME_DECRYPT; 38 import static com.android.internal.widget.LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT; 39 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; 40 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; 41 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE; 42 import static com.android.internal.widget.LockPatternUtils.USER_FRP; 43 import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE; 44 import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; 45 import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; 46 import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_STRONG; 47 import static com.android.server.locksettings.SyntheticPasswordManager.TOKEN_TYPE_WEAK; 48 49 import android.Manifest; 50 import android.annotation.NonNull; 51 import android.annotation.Nullable; 52 import android.annotation.UserIdInt; 53 import android.app.ActivityManager; 54 import android.app.IActivityManager; 55 import android.app.KeyguardManager; 56 import android.app.Notification; 57 import android.app.NotificationManager; 58 import android.app.PendingIntent; 59 import android.app.admin.DevicePolicyManager; 60 import android.app.admin.DevicePolicyManagerInternal; 61 import android.app.admin.DeviceStateCache; 62 import android.app.admin.PasswordMetrics; 63 import android.app.trust.IStrongAuthTracker; 64 import android.app.trust.TrustManager; 65 import android.content.BroadcastReceiver; 66 import android.content.ContentResolver; 67 import android.content.Context; 68 import android.content.Intent; 69 import android.content.IntentFilter; 70 import android.content.pm.PackageManager; 71 import android.content.pm.UserInfo; 72 import android.content.res.Resources; 73 import android.database.ContentObserver; 74 import android.database.sqlite.SQLiteDatabase; 75 import android.hardware.authsecret.V1_0.IAuthSecret; 76 import android.hardware.biometrics.BiometricManager; 77 import android.hardware.face.Face; 78 import android.hardware.face.FaceManager; 79 import android.hardware.fingerprint.Fingerprint; 80 import android.hardware.fingerprint.FingerprintManager; 81 import android.net.Uri; 82 import android.os.Binder; 83 import android.os.Build; 84 import android.os.Bundle; 85 import android.os.Handler; 86 import android.os.IBinder; 87 import android.os.IProgressListener; 88 import android.os.Process; 89 import android.os.RemoteException; 90 import android.os.ResultReceiver; 91 import android.os.ServiceManager; 92 import android.os.ShellCallback; 93 import android.os.StrictMode; 94 import android.os.SystemProperties; 95 import android.os.UserHandle; 96 import android.os.UserManager; 97 import android.os.storage.IStorageManager; 98 import android.os.storage.StorageManager; 99 import android.provider.Settings; 100 import android.provider.Settings.Secure; 101 import android.provider.Settings.SettingNotFoundException; 102 import android.security.AndroidKeyStoreMaintenance; 103 import android.security.Authorization; 104 import android.security.KeyStore; 105 import android.security.keystore.KeyProperties; 106 import android.security.keystore.KeyProtection; 107 import android.security.keystore.UserNotAuthenticatedException; 108 import android.security.keystore.recovery.KeyChainProtectionParams; 109 import android.security.keystore.recovery.KeyChainSnapshot; 110 import android.security.keystore.recovery.RecoveryCertPath; 111 import android.security.keystore.recovery.WrappedApplicationKey; 112 import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; 113 import android.security.keystore2.AndroidKeyStoreProvider; 114 import android.service.gatekeeper.GateKeeperResponse; 115 import android.service.gatekeeper.IGateKeeperService; 116 import android.system.keystore2.Domain; 117 import android.text.TextUtils; 118 import android.util.ArrayMap; 119 import android.util.ArraySet; 120 import android.util.EventLog; 121 import android.util.Log; 122 import android.util.LongSparseArray; 123 import android.util.Slog; 124 import android.util.SparseArray; 125 126 import com.android.internal.R; 127 import com.android.internal.annotations.GuardedBy; 128 import com.android.internal.annotations.VisibleForTesting; 129 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 130 import com.android.internal.notification.SystemNotificationChannels; 131 import com.android.internal.util.DumpUtils; 132 import com.android.internal.util.IndentingPrintWriter; 133 import com.android.internal.util.Preconditions; 134 import com.android.internal.widget.ICheckCredentialProgressCallback; 135 import com.android.internal.widget.ILockSettings; 136 import com.android.internal.widget.IWeakEscrowTokenActivatedListener; 137 import com.android.internal.widget.IWeakEscrowTokenRemovedListener; 138 import com.android.internal.widget.LockPatternUtils; 139 import com.android.internal.widget.LockSettingsInternal; 140 import com.android.internal.widget.LockscreenCredential; 141 import com.android.internal.widget.RebootEscrowListener; 142 import com.android.internal.widget.VerifyCredentialResponse; 143 import com.android.server.LocalServices; 144 import com.android.server.ServiceThread; 145 import com.android.server.SystemService; 146 import com.android.server.locksettings.LockSettingsStorage.CredentialHash; 147 import com.android.server.locksettings.LockSettingsStorage.PersistentData; 148 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult; 149 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; 150 import com.android.server.locksettings.SyntheticPasswordManager.TokenType; 151 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; 152 import com.android.server.pm.UserManagerInternal; 153 import com.android.server.utils.Watchable; 154 import com.android.server.utils.Watcher; 155 import com.android.server.wm.WindowManagerInternal; 156 157 import libcore.util.HexEncoding; 158 159 import java.io.ByteArrayOutputStream; 160 import java.io.FileDescriptor; 161 import java.io.FileNotFoundException; 162 import java.io.IOException; 163 import java.io.PrintWriter; 164 import java.security.GeneralSecurityException; 165 import java.security.InvalidAlgorithmParameterException; 166 import java.security.InvalidKeyException; 167 import java.security.KeyStoreException; 168 import java.security.MessageDigest; 169 import java.security.NoSuchAlgorithmException; 170 import java.security.SecureRandom; 171 import java.security.UnrecoverableKeyException; 172 import java.security.cert.CertificateException; 173 import java.text.SimpleDateFormat; 174 import java.util.ArrayList; 175 import java.util.Arrays; 176 import java.util.Date; 177 import java.util.Enumeration; 178 import java.util.HashMap; 179 import java.util.List; 180 import java.util.Map; 181 import java.util.NoSuchElementException; 182 import java.util.Objects; 183 import java.util.Random; 184 import java.util.Set; 185 import java.util.StringJoiner; 186 import java.util.concurrent.CountDownLatch; 187 import java.util.concurrent.TimeUnit; 188 189 import javax.crypto.BadPaddingException; 190 import javax.crypto.Cipher; 191 import javax.crypto.IllegalBlockSizeException; 192 import javax.crypto.KeyGenerator; 193 import javax.crypto.NoSuchPaddingException; 194 import javax.crypto.SecretKey; 195 import javax.crypto.spec.GCMParameterSpec; 196 197 /** 198 * Keeps the lock pattern/password data and related settings for each user. Used by 199 * LockPatternUtils. Needs to be a service because Settings app also needs to be able to save 200 * lockscreen information for secondary users. 201 * 202 * @hide 203 */ 204 public class LockSettingsService extends ILockSettings.Stub { 205 private static final String TAG = "LockSettingsService"; 206 private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE; 207 private static final String BIOMETRIC_PERMISSION = MANAGE_BIOMETRIC; 208 private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG); 209 210 private static final int PROFILE_KEY_IV_SIZE = 12; 211 private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge"; 212 private static final String PREV_SYNTHETIC_PASSWORD_HANDLE_KEY = "prev-sp-handle"; 213 private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts"; 214 private static final String USER_SERIAL_NUMBER_KEY = "serial-number"; 215 216 // Duration that LockSettingsService will store the gatekeeper password for. This allows 217 // multiple biometric enrollments without prompting the user to enter their password via 218 // ConfirmLockPassword/ConfirmLockPattern multiple times. This needs to be at least the duration 219 // from the start of the first biometric sensor's enrollment to the start of the last biometric 220 // sensor's enrollment. If biometric enrollment requests a password handle that has expired, the 221 // user's credential must be presented again, e.g. via ConfirmLockPattern/ConfirmLockPassword. 222 private static final int GK_PW_HANDLE_STORE_DURATION_MS = 10 * 60 * 1000; // 10 minutes 223 224 // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this 225 // Do not call into ActivityManager while holding mSpManager lock. 226 private final Object mSeparateChallengeLock = new Object(); 227 228 private final DeviceProvisionedObserver mDeviceProvisionedObserver = 229 new DeviceProvisionedObserver(); 230 231 private final Injector mInjector; 232 private final Context mContext; 233 @VisibleForTesting 234 protected final Handler mHandler; 235 @VisibleForTesting 236 protected final LockSettingsStorage mStorage; 237 private final Watcher mStorageWatcher; 238 private final LockSettingsStrongAuth mStrongAuth; 239 private final SynchronizedStrongAuthTracker mStrongAuthTracker; 240 private final BiometricDeferredQueue mBiometricDeferredQueue; 241 private final LongSparseArray<byte[]> mGatekeeperPasswords; 242 private final Random mRandom; 243 244 private final NotificationManager mNotificationManager; 245 protected final UserManager mUserManager; 246 private final IStorageManager mStorageManager; 247 private final IActivityManager mActivityManager; 248 private final SyntheticPasswordManager mSpManager; 249 250 private final KeyStore mKeyStore; 251 private final java.security.KeyStore mJavaKeyStore; 252 private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; 253 private ManagedProfilePasswordCache mManagedProfilePasswordCache; 254 255 private final RebootEscrowManager mRebootEscrowManager; 256 257 // Current password metric for all users on the device. Updated when user unlocks 258 // the device or changes password. Removed when user is stopped. 259 @GuardedBy("this") 260 final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>(); 261 @VisibleForTesting 262 protected boolean mHasSecureLockScreen; 263 264 protected IGateKeeperService mGateKeeperService; 265 protected IAuthSecret mAuthSecretService; 266 267 private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; 268 269 /** 270 * The UIDs that are used for system credential storage in keystore. 271 */ 272 private static final int[] SYSTEM_CREDENTIAL_UIDS = { 273 Process.VPN_UID, Process.ROOT_UID, Process.SYSTEM_UID}; 274 275 private HashMap<UserHandle, UserManager> mUserManagerCache = new HashMap<>(); 276 277 // This class manages life cycle events for encrypted users on File Based Encryption (FBE) 278 // devices. The most basic of these is to show/hide notifications about missing features until 279 // the user unlocks the account and credential-encrypted storage is available. 280 public static final class Lifecycle extends SystemService { 281 private LockSettingsService mLockSettingsService; 282 Lifecycle(Context context)283 public Lifecycle(Context context) { 284 super(context); 285 } 286 287 @Override onStart()288 public void onStart() { 289 AndroidKeyStoreProvider.install(); 290 mLockSettingsService = new LockSettingsService(getContext()); 291 publishBinderService("lock_settings", mLockSettingsService); 292 } 293 294 @Override onBootPhase(int phase)295 public void onBootPhase(int phase) { 296 super.onBootPhase(phase); 297 if (phase == PHASE_ACTIVITY_MANAGER_READY) { 298 mLockSettingsService.migrateOldDataAfterSystemReady(); 299 mLockSettingsService.loadEscrowData(); 300 } 301 } 302 303 @Override onUserStarting(@onNull TargetUser user)304 public void onUserStarting(@NonNull TargetUser user) { 305 mLockSettingsService.onStartUser(user.getUserIdentifier()); 306 } 307 308 @Override onUserUnlocking(@onNull TargetUser user)309 public void onUserUnlocking(@NonNull TargetUser user) { 310 mLockSettingsService.onUnlockUser(user.getUserIdentifier()); 311 } 312 313 @Override onUserStopped(@onNull TargetUser user)314 public void onUserStopped(@NonNull TargetUser user) { 315 mLockSettingsService.onCleanupUser(user.getUserIdentifier()); 316 } 317 } 318 319 @VisibleForTesting 320 protected static class SynchronizedStrongAuthTracker 321 extends LockPatternUtils.StrongAuthTracker { SynchronizedStrongAuthTracker(Context context)322 public SynchronizedStrongAuthTracker(Context context) { 323 super(context); 324 } 325 326 @Override handleStrongAuthRequiredChanged(int strongAuthFlags, int userId)327 protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) { 328 synchronized (this) { 329 super.handleStrongAuthRequiredChanged(strongAuthFlags, userId); 330 } 331 } 332 333 @Override getStrongAuthForUser(int userId)334 public int getStrongAuthForUser(int userId) { 335 synchronized (this) { 336 return super.getStrongAuthForUser(userId); 337 } 338 } 339 register(LockSettingsStrongAuth strongAuth)340 void register(LockSettingsStrongAuth strongAuth) { 341 strongAuth.registerStrongAuthTracker(getStub()); 342 } 343 } 344 generateRandomProfilePassword()345 private LockscreenCredential generateRandomProfilePassword() { 346 byte[] randomLockSeed = new byte[] {}; 347 try { 348 randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40); 349 char[] newPasswordChars = HexEncoding.encode(randomLockSeed); 350 byte[] newPassword = new byte[newPasswordChars.length]; 351 for (int i = 0; i < newPasswordChars.length; i++) { 352 newPassword[i] = (byte) newPasswordChars[i]; 353 } 354 LockscreenCredential credential = 355 LockscreenCredential.createManagedPassword(newPassword); 356 Arrays.fill(newPasswordChars, '\u0000'); 357 Arrays.fill(newPassword, (byte) 0); 358 Arrays.fill(randomLockSeed, (byte) 0); 359 return credential; 360 } catch (NoSuchAlgorithmException e) { 361 throw new IllegalStateException("Fail to generate profile password", e); 362 } 363 } 364 365 /** 366 * Tie profile to primary profile if it is in unified mode and not tied before. 367 * Only for profiles which share credential with parent. (e.g. managed and clone profiles) 368 * 369 * @param profileUserId profile user Id 370 * @param profileUserPassword profile original password (when it has separated lock). 371 */ tieProfileLockIfNecessary(int profileUserId, LockscreenCredential profileUserPassword)372 public void tieProfileLockIfNecessary(int profileUserId, 373 LockscreenCredential profileUserPassword) { 374 if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + profileUserId); 375 // Only for profiles that shares credential with parent 376 if (!isCredentialSharableWithParent(profileUserId)) { 377 return; 378 } 379 // Do not tie profile when work challenge is enabled 380 if (getSeparateProfileChallengeEnabledInternal(profileUserId)) { 381 return; 382 } 383 // Do not tie profile to parent when it's done already 384 if (mStorage.hasChildProfileLock(profileUserId)) { 385 return; 386 } 387 // If parent does not have a screen lock, simply clear credential from the profile, 388 // to maintain the invariant that unified profile should always have the same secure state 389 // as its parent. 390 final int parentId = mUserManager.getProfileParent(profileUserId).id; 391 if (!isUserSecure(parentId) && !profileUserPassword.isNone()) { 392 if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock but profile has one"); 393 394 setLockCredentialInternal(LockscreenCredential.createNone(), profileUserPassword, 395 profileUserId, /* isLockTiedToParent= */ true); 396 return; 397 } 398 // Do not tie when the parent has no SID (but does have a screen lock). 399 // This can only happen during an upgrade path where SID is yet to be 400 // generated when the user unlocks for the first time. 401 try { 402 if (getGateKeeperService().getSecureUserId(parentId) == 0) { 403 return; 404 } 405 } catch (RemoteException e) { 406 Slog.e(TAG, "Failed to talk to GateKeeper service", e); 407 return; 408 } 409 if (DEBUG) Slog.v(TAG, "Tie profile to parent now!"); 410 try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) { 411 setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId, 412 /* isLockTiedToParent= */ true); 413 tieProfileLockToParent(profileUserId, unifiedProfilePassword); 414 mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword); 415 } 416 } 417 418 static class Injector { 419 420 protected Context mContext; 421 Injector(Context context)422 public Injector(Context context) { 423 mContext = context; 424 } 425 getContext()426 public Context getContext() { 427 return mContext; 428 } 429 getServiceThread()430 public ServiceThread getServiceThread() { 431 ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, 432 true /*allowIo*/); 433 handlerThread.start(); 434 return handlerThread; 435 } 436 getHandler(ServiceThread handlerThread)437 public Handler getHandler(ServiceThread handlerThread) { 438 return new Handler(handlerThread.getLooper()); 439 } 440 getStorage()441 public LockSettingsStorage getStorage() { 442 final LockSettingsStorage storage = new LockSettingsStorage(mContext); 443 storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() { 444 @Override 445 public void initialize(SQLiteDatabase db) { 446 // Get the lockscreen default from a system property, if available 447 boolean lockScreenDisable = SystemProperties.getBoolean( 448 "ro.lockscreen.disable.default", false); 449 if (lockScreenDisable) { 450 storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); 451 } 452 } 453 }); 454 return storage; 455 } 456 getStrongAuth()457 public LockSettingsStrongAuth getStrongAuth() { 458 return new LockSettingsStrongAuth(mContext); 459 } 460 getStrongAuthTracker()461 public SynchronizedStrongAuthTracker getStrongAuthTracker() { 462 return new SynchronizedStrongAuthTracker(mContext); 463 } 464 getActivityManager()465 public IActivityManager getActivityManager() { 466 return ActivityManager.getService(); 467 } 468 getNotificationManager()469 public NotificationManager getNotificationManager() { 470 return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 471 } 472 getUserManager()473 public UserManager getUserManager() { 474 return (UserManager) mContext.getSystemService(Context.USER_SERVICE); 475 } 476 getUserManagerInternal()477 public UserManagerInternal getUserManagerInternal() { 478 return LocalServices.getService(UserManagerInternal.class); 479 } 480 481 /** 482 * Return the {@link DevicePolicyManager} object. 483 * 484 * Since LockSettingsService is considered a lower-level component than DevicePolicyManager, 485 * do NOT hold any lock in this class while calling into DevicePolicyManager to prevent 486 * the risk of deadlock. 487 */ getDevicePolicyManager()488 public DevicePolicyManager getDevicePolicyManager() { 489 return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 490 } 491 getDeviceStateCache()492 public DeviceStateCache getDeviceStateCache() { 493 return DeviceStateCache.getInstance(); 494 } 495 getKeyStore()496 public KeyStore getKeyStore() { 497 return KeyStore.getInstance(); 498 } 499 getRecoverableKeyStoreManager()500 public RecoverableKeyStoreManager getRecoverableKeyStoreManager() { 501 return RecoverableKeyStoreManager.getInstance(mContext); 502 } 503 getStorageManager()504 public IStorageManager getStorageManager() { 505 final IBinder service = ServiceManager.getService("mount"); 506 if (service != null) { 507 return IStorageManager.Stub.asInterface(service); 508 } 509 return null; 510 } 511 getSyntheticPasswordManager(LockSettingsStorage storage)512 public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { 513 return new SyntheticPasswordManager(getContext(), storage, getUserManager(), 514 new PasswordSlotManager()); 515 } 516 getRebootEscrowManager(RebootEscrowManager.Callbacks callbacks, LockSettingsStorage storage)517 public RebootEscrowManager getRebootEscrowManager(RebootEscrowManager.Callbacks callbacks, 518 LockSettingsStorage storage) { 519 return new RebootEscrowManager(mContext, callbacks, storage); 520 } 521 hasEnrolledBiometrics(int userId)522 public boolean hasEnrolledBiometrics(int userId) { 523 BiometricManager bm = mContext.getSystemService(BiometricManager.class); 524 return bm.hasEnrolledBiometrics(userId); 525 } 526 binderGetCallingUid()527 public int binderGetCallingUid() { 528 return Binder.getCallingUid(); 529 } 530 isGsiRunning()531 public boolean isGsiRunning() { 532 return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0; 533 } 534 getFingerprintManager()535 public FingerprintManager getFingerprintManager() { 536 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 537 return (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE); 538 } else { 539 return null; 540 } 541 } 542 getFaceManager()543 public FaceManager getFaceManager() { 544 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) { 545 return (FaceManager) mContext.getSystemService(Context.FACE_SERVICE); 546 } else { 547 return null; 548 } 549 } 550 settingsGlobalGetInt(ContentResolver contentResolver, String keyName, int defaultValue)551 public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName, 552 int defaultValue) { 553 return Settings.Global.getInt(contentResolver, keyName, defaultValue); 554 } 555 settingsSecureGetInt(ContentResolver contentResolver, String keyName, int defaultValue, int userId)556 public int settingsSecureGetInt(ContentResolver contentResolver, String keyName, 557 int defaultValue, int userId) { 558 return Settings.Secure.getIntForUser(contentResolver, keyName, defaultValue, userId); 559 } 560 getJavaKeyStore()561 public java.security.KeyStore getJavaKeyStore() { 562 try { 563 java.security.KeyStore ks = java.security.KeyStore.getInstance( 564 SyntheticPasswordCrypto.androidKeystoreProviderName()); 565 ks.load(new AndroidKeyStoreLoadStoreParameter( 566 SyntheticPasswordCrypto.keyNamespace())); 567 return ks; 568 } catch (Exception e) { 569 throw new IllegalStateException("Cannot load keystore", e); 570 } 571 } 572 getManagedProfilePasswordCache( java.security.KeyStore ks)573 public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache( 574 java.security.KeyStore ks) { 575 return new ManagedProfilePasswordCache(ks, getUserManager()); 576 } 577 } 578 579 private class StorageWatcher extends Watcher { onChange(Watchable what)580 public void onChange(Watchable what) { 581 LockSettingsService.this.onChange(); 582 } 583 } 584 LockSettingsService(Context context)585 public LockSettingsService(Context context) { 586 this(new Injector(context)); 587 } 588 589 @VisibleForTesting LockSettingsService(Injector injector)590 protected LockSettingsService(Injector injector) { 591 mInjector = injector; 592 mContext = injector.getContext(); 593 mKeyStore = injector.getKeyStore(); 594 mJavaKeyStore = injector.getJavaKeyStore(); 595 mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(); 596 mHandler = injector.getHandler(injector.getServiceThread()); 597 mStrongAuth = injector.getStrongAuth(); 598 mActivityManager = injector.getActivityManager(); 599 600 IntentFilter filter = new IntentFilter(); 601 filter.addAction(Intent.ACTION_USER_ADDED); 602 filter.addAction(Intent.ACTION_USER_STARTING); 603 filter.addAction(Intent.ACTION_USER_REMOVED); 604 injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, 605 null, null); 606 607 mStorage = injector.getStorage(); 608 mNotificationManager = injector.getNotificationManager(); 609 mUserManager = injector.getUserManager(); 610 mStorageManager = injector.getStorageManager(); 611 mStrongAuthTracker = injector.getStrongAuthTracker(); 612 mStrongAuthTracker.register(mStrongAuth); 613 mGatekeeperPasswords = new LongSparseArray<>(); 614 mRandom = new SecureRandom(); 615 616 mSpManager = injector.getSyntheticPasswordManager(mStorage); 617 mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache(mJavaKeyStore); 618 mBiometricDeferredQueue = new BiometricDeferredQueue(mContext, mSpManager, mHandler); 619 620 mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(), 621 mStorage); 622 623 LocalServices.addService(LockSettingsInternal.class, new LocalService()); 624 625 mStorageWatcher = new StorageWatcher(); 626 mStorage.registerObserver(mStorageWatcher); 627 } 628 629 /** 630 * Invalidate caches if the storage has changed. 631 */ onChange()632 private void onChange() { 633 LockPatternUtils.invalidateCredentialTypeCache(); 634 } 635 636 /** 637 * If the account is credential-encrypted, show notification requesting the user to unlock the 638 * device. 639 */ maybeShowEncryptionNotificationForUser(@serIdInt int userId, String reason)640 private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId, String reason) { 641 final UserInfo user = mUserManager.getUserInfo(userId); 642 if (!user.isManagedProfile()) { 643 // When the user is locked, we communicate it loud-and-clear 644 // on the lockscreen; we only show a notification below for 645 // locked managed profiles. 646 return; 647 } 648 649 if (isUserKeyUnlocked(userId)) { 650 // If storage is not locked, the user will be automatically unlocked so there is 651 // no need to show the notification. 652 return; 653 } 654 655 final UserHandle userHandle = user.getUserHandle(); 656 final boolean isSecure = isUserSecure(userId); 657 if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) { 658 UserInfo parent = mUserManager.getProfileParent(userId); 659 if (parent != null && 660 mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) && 661 !mUserManager.isQuietModeEnabled(userHandle)) { 662 // Only show notifications for managed profiles once their parent 663 // user is unlocked. 664 showEncryptionNotificationForProfile(userHandle, reason); 665 } 666 } 667 } 668 showEncryptionNotificationForProfile(UserHandle user, String reason)669 private void showEncryptionNotificationForProfile(UserHandle user, String reason) { 670 Resources r = mContext.getResources(); 671 CharSequence title = getEncryptionNotificationTitle(); 672 CharSequence message = getEncryptionNotificationMessage(); 673 CharSequence detail = getEncryptionNotificationDetail(); 674 675 final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE); 676 final Intent unlockIntent = 677 km.createConfirmDeviceCredentialIntent(null, null, user.getIdentifier()); 678 if (unlockIntent == null) { 679 return; 680 } 681 682 // Suppress all notifications on non-FBE devices for now 683 if (!StorageManager.isFileEncryptedNativeOrEmulated()) return; 684 685 unlockIntent.setFlags( 686 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 687 PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent, 688 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED); 689 690 Slog.d(TAG, String.format("showing encryption notification, user: %d; reason: %s", 691 user.getIdentifier(), reason)); 692 693 showEncryptionNotification(user, title, message, detail, intent); 694 } 695 getEncryptionNotificationTitle()696 private String getEncryptionNotificationTitle() { 697 return mInjector.getDevicePolicyManager().getResources().getString( 698 PROFILE_ENCRYPTED_TITLE, 699 () -> mContext.getString(R.string.profile_encrypted_title)); 700 } 701 getEncryptionNotificationDetail()702 private String getEncryptionNotificationDetail() { 703 return mInjector.getDevicePolicyManager().getResources().getString( 704 PROFILE_ENCRYPTED_DETAIL, 705 () -> mContext.getString(R.string.profile_encrypted_detail)); 706 } 707 getEncryptionNotificationMessage()708 private String getEncryptionNotificationMessage() { 709 return mInjector.getDevicePolicyManager().getResources().getString( 710 PROFILE_ENCRYPTED_MESSAGE, 711 () -> mContext.getString(R.string.profile_encrypted_message)); 712 } 713 showEncryptionNotification(UserHandle user, CharSequence title, CharSequence message, CharSequence detail, PendingIntent intent)714 private void showEncryptionNotification(UserHandle user, CharSequence title, 715 CharSequence message, CharSequence detail, PendingIntent intent) { 716 Notification notification = 717 new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN) 718 .setSmallIcon(com.android.internal.R.drawable.ic_user_secure) 719 .setWhen(0) 720 .setOngoing(true) 721 .setTicker(title) 722 .setColor(mContext.getColor( 723 com.android.internal.R.color.system_notification_accent_color)) 724 .setContentTitle(title) 725 .setContentText(message) 726 .setSubText(detail) 727 .setVisibility(Notification.VISIBILITY_PUBLIC) 728 .setContentIntent(intent) 729 .build(); 730 mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION, 731 notification, user); 732 } 733 hideEncryptionNotification(UserHandle userHandle)734 private void hideEncryptionNotification(UserHandle userHandle) { 735 Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier()); 736 mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION, 737 userHandle); 738 } 739 onCleanupUser(int userId)740 public void onCleanupUser(int userId) { 741 hideEncryptionNotification(new UserHandle(userId)); 742 // User is stopped with its CE key evicted. Restore strong auth requirement to the default 743 // flags after boot since stopping and restarting a user later is equivalent to rebooting 744 // the device. 745 int strongAuthRequired = LockPatternUtils.StrongAuthTracker.getDefaultFlags(mContext); 746 requireStrongAuth(strongAuthRequired, userId); 747 synchronized (this) { 748 mUserPasswordMetrics.remove(userId); 749 } 750 } 751 onStartUser(final int userId)752 public void onStartUser(final int userId) { 753 maybeShowEncryptionNotificationForUser(userId, "user started"); 754 } 755 756 /** 757 * Clean up states associated with the given user, in case the userId is reused but LSS didn't 758 * get a chance to do cleanup previously during ACTION_USER_REMOVED. 759 * 760 * Internally, LSS stores serial number for each user and check it against the current user's 761 * serial number to determine if the userId is reused and invoke cleanup code. 762 */ cleanupDataForReusedUserIdIfNecessary(int userId)763 private void cleanupDataForReusedUserIdIfNecessary(int userId) { 764 if (userId == UserHandle.USER_SYSTEM) { 765 // Short circuit as we never clean up user 0. 766 return; 767 } 768 // Serial number is never reusued, so we can use it as a distinguisher for user Id reuse. 769 int serialNumber = mUserManager.getUserSerialNumber(userId); 770 771 int storedSerialNumber = mStorage.getInt(USER_SERIAL_NUMBER_KEY, -1, userId); 772 if (storedSerialNumber != serialNumber) { 773 // If LockSettingsStorage does not have a copy of the serial number, it could be either 774 // this is a user created before the serial number recording logic is introduced, or 775 // the user does not exist or was removed and cleaned up properly. In either case, don't 776 // invoke removeUser(). 777 if (storedSerialNumber != -1) { 778 removeUser(userId, /* unknownUser */ true); 779 } 780 mStorage.setInt(USER_SERIAL_NUMBER_KEY, serialNumber, userId); 781 } 782 } 783 784 /** 785 * Check if profile got unlocked but the keystore is still locked. This happens on full disk 786 * encryption devices since the profile may not yet be running when we consider unlocking it 787 * during the normal flow. In this case unlock the keystore for the profile. 788 */ ensureProfileKeystoreUnlocked(int userId)789 private void ensureProfileKeystoreUnlocked(int userId) { 790 final KeyStore ks = KeyStore.getInstance(); 791 if (ks.state(userId) == KeyStore.State.LOCKED 792 && isCredentialSharableWithParent(userId) 793 && hasUnifiedChallenge(userId)) { 794 Slog.i(TAG, "Profile got unlocked, will unlock its keystore"); 795 // If boot took too long and the password in vold got expired, parent keystore will 796 // be still locked, we ignore this case since the user will be prompted to unlock 797 // the device after boot. 798 unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */); 799 } 800 } 801 onUnlockUser(final int userId)802 public void onUnlockUser(final int userId) { 803 // Perform tasks which require locks in LSS on a handler, as we are callbacks from 804 // ActivityManager.unlockUser() 805 mHandler.post(new Runnable() { 806 @Override 807 public void run() { 808 cleanupDataForReusedUserIdIfNecessary(userId); 809 ensureProfileKeystoreUnlocked(userId); 810 // Hide notification first, as tie managed profile lock takes time 811 hideEncryptionNotification(new UserHandle(userId)); 812 813 if (isCredentialSharableWithParent(userId)) { 814 tieProfileLockIfNecessary(userId, LockscreenCredential.createNone()); 815 } 816 817 // If the user doesn't have a credential, try and derive their secret for the 818 // AuthSecret HAL. The secret will have been enrolled if the user previously set a 819 // credential and still needs to be passed to the HAL once that credential is 820 // removed. 821 if (mUserManager.getUserInfo(userId).isPrimary() && !isUserSecure(userId)) { 822 tryDeriveAuthTokenForUnsecuredPrimaryUser(userId); 823 } 824 } 825 }); 826 } 827 tryDeriveAuthTokenForUnsecuredPrimaryUser(@serIdInt int userId)828 private void tryDeriveAuthTokenForUnsecuredPrimaryUser(@UserIdInt int userId) { 829 synchronized (mSpManager) { 830 // Make sure the user has a synthetic password to derive 831 if (!isSyntheticPasswordBasedCredentialLocked(userId)) { 832 return; 833 } 834 835 final long handle = getSyntheticPasswordHandleLocked(userId); 836 AuthenticationResult result = 837 mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(), 838 handle, LockscreenCredential.createNone(), userId, null); 839 if (result.authToken != null) { 840 Slog.i(TAG, "Retrieved auth token for user " + userId); 841 onAuthTokenKnownForUser(userId, result.authToken); 842 } else { 843 Slog.e(TAG, "Auth token not available for user " + userId); 844 } 845 } 846 } 847 848 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 849 @Override 850 public void onReceive(Context context, Intent intent) { 851 if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { 852 // Notify keystore that a new user was added. 853 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 854 AndroidKeyStoreMaintenance.onUserAdded(userHandle); 855 } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { 856 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 857 mStorage.prefetchUser(userHandle); 858 } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { 859 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 860 if (userHandle > 0) { 861 removeUser(userHandle, /* unknownUser= */ false); 862 } 863 } 864 } 865 }; 866 867 @Override // binder interface systemReady()868 public void systemReady() { 869 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { 870 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet 871 } 872 checkWritePermission(UserHandle.USER_SYSTEM); 873 874 mHasSecureLockScreen = mContext.getPackageManager() 875 .hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN); 876 migrateOldData(); 877 getGateKeeperService(); 878 mSpManager.initWeaverService(); 879 getAuthSecretHal(); 880 mDeviceProvisionedObserver.onSystemReady(); 881 882 // TODO: maybe skip this for split system user mode. 883 mStorage.prefetchUser(UserHandle.USER_SYSTEM); 884 mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), 885 mInjector.getFaceManager()); 886 } 887 loadEscrowData()888 private void loadEscrowData() { 889 mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); 890 } 891 getAuthSecretHal()892 private void getAuthSecretHal() { 893 try { 894 mAuthSecretService = IAuthSecret.getService(/* retry */ true); 895 } catch (NoSuchElementException e) { 896 Slog.i(TAG, "Device doesn't implement AuthSecret HAL"); 897 } catch (RemoteException e) { 898 Slog.w(TAG, "Failed to get AuthSecret HAL", e); 899 } 900 } 901 migrateOldData()902 private void migrateOldData() { 903 // These Settings moved before multi-user was enabled, so we only have to do it for the 904 // root user. 905 if (getString("migrated", null, 0) == null) { 906 final ContentResolver cr = mContext.getContentResolver(); 907 for (String validSetting : VALID_SETTINGS) { 908 String value = Settings.Secure.getStringForUser(cr, validSetting, cr.getUserId()); 909 if (value != null) { 910 setString(validSetting, value, 0); 911 } 912 } 913 // No need to move the password / pattern files. They're already in the right place. 914 setString("migrated", "true", 0); 915 Slog.i(TAG, "Migrated lock settings to new location"); 916 } 917 918 // These Settings changed after multi-user was enabled, hence need to be moved per user. 919 if (getString("migrated_user_specific", null, 0) == null) { 920 final ContentResolver cr = mContext.getContentResolver(); 921 List<UserInfo> users = mUserManager.getUsers(); 922 for (int user = 0; user < users.size(); user++) { 923 // Migrate owner info 924 final int userId = users.get(user).id; 925 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO; 926 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId); 927 if (!TextUtils.isEmpty(ownerInfo)) { 928 setString(OWNER_INFO, ownerInfo, userId); 929 Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId); 930 } 931 932 // Migrate owner info enabled. Note there was a bug where older platforms only 933 // stored this value if the checkbox was toggled at least once. The code detects 934 // this case by handling the exception. 935 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 936 boolean enabled; 937 try { 938 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId); 939 enabled = ivalue != 0; 940 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId); 941 } catch (SettingNotFoundException e) { 942 // Setting was never stored. Store it if the string is not empty. 943 if (!TextUtils.isEmpty(ownerInfo)) { 944 setLong(OWNER_INFO_ENABLED, 1, userId); 945 } 946 } 947 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId); 948 } 949 // No need to move the password / pattern files. They're already in the right place. 950 setString("migrated_user_specific", "true", 0); 951 Slog.i(TAG, "Migrated per-user lock settings to new location"); 952 } 953 954 // Migrates biometric weak such that the fallback mechanism becomes the primary. 955 if (getString("migrated_biometric_weak", null, 0) == null) { 956 List<UserInfo> users = mUserManager.getUsers(); 957 for (int i = 0; i < users.size(); i++) { 958 int userId = users.get(i).id; 959 long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 960 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 961 userId); 962 long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 963 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 964 userId); 965 if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { 966 setLong(LockPatternUtils.PASSWORD_TYPE_KEY, 967 alternateType, 968 userId); 969 } 970 setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 971 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 972 userId); 973 } 974 setString("migrated_biometric_weak", "true", 0); 975 Slog.i(TAG, "Migrated biometric weak to use the fallback instead"); 976 } 977 978 // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one 979 // user was present on the system, so if we're upgrading to M and there is more than one 980 // user we disable the flag to remain consistent. 981 if (getString("migrated_lockscreen_disabled", null, 0) == null) { 982 final List<UserInfo> users = mUserManager.getUsers(); 983 final int userCount = users.size(); 984 int switchableUsers = 0; 985 for (int i = 0; i < userCount; i++) { 986 if (users.get(i).supportsSwitchTo()) { 987 switchableUsers++; 988 } 989 } 990 991 if (switchableUsers > 1) { 992 for (int i = 0; i < userCount; i++) { 993 int id = users.get(i).id; 994 995 if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) { 996 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id); 997 } 998 } 999 } 1000 1001 setString("migrated_lockscreen_disabled", "true", 0); 1002 Slog.i(TAG, "Migrated lockscreen disabled flag"); 1003 } 1004 1005 boolean isWatch = mContext.getPackageManager().hasSystemFeature( 1006 PackageManager.FEATURE_WATCH); 1007 // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts 1008 // and device management the lockscreen must be re-enabled now for users that upgrade. 1009 if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) { 1010 final List<UserInfo> users = mUserManager.getUsers(); 1011 final int userCount = users.size(); 1012 for (int i = 0; i < userCount; i++) { 1013 int id = users.get(i).id; 1014 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id); 1015 } 1016 setString("migrated_wear_lockscreen_disabled", "true", 0); 1017 Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices"); 1018 } 1019 1020 if (getString("migrated_keystore_namespace", null, 0) == null) { 1021 boolean success = true; 1022 synchronized (mSpManager) { 1023 success &= mSpManager.migrateKeyNamespace(); 1024 } 1025 success &= migrateProfileLockKeys(); 1026 if (success) { 1027 setString("migrated_keystore_namespace", "true", 0); 1028 Slog.i(TAG, "Migrated keys to LSS namespace"); 1029 } else { 1030 Slog.w(TAG, "Failed to migrate keys to LSS namespace"); 1031 } 1032 } 1033 1034 } 1035 migrateOldDataAfterSystemReady()1036 private void migrateOldDataAfterSystemReady() { 1037 // Migrate the FRP credential to the persistent data block 1038 if (LockPatternUtils.frpCredentialEnabled(mContext) 1039 && !getBoolean("migrated_frp", false, 0)) { 1040 migrateFrpCredential(); 1041 setBoolean("migrated_frp", true, 0); 1042 Slog.i(TAG, "Migrated migrated_frp."); 1043 } 1044 } 1045 1046 /** 1047 * Migrate the credential for the FRP credential owner user if the following are satisfied: 1048 * - the user has a secure credential 1049 * - the FRP credential is not set up 1050 * - the credential is based on a synthetic password. 1051 */ migrateFrpCredential()1052 private void migrateFrpCredential() { 1053 if (mStorage.readPersistentDataBlock() != PersistentData.NONE) { 1054 return; 1055 } 1056 for (UserInfo userInfo : mUserManager.getUsers()) { 1057 if (userOwnsFrpCredential(mContext, userInfo) && isUserSecure(userInfo.id)) { 1058 synchronized (mSpManager) { 1059 if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) { 1060 int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 1061 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id); 1062 1063 mSpManager.migrateFrpPasswordLocked( 1064 getSyntheticPasswordHandleLocked(userInfo.id), 1065 userInfo, 1066 redactActualQualityToMostLenientEquivalentQuality(actualQuality)); 1067 } 1068 } 1069 return; 1070 } 1071 } 1072 } 1073 migrateProfileLockKeys()1074 private boolean migrateProfileLockKeys() { 1075 boolean success = true; 1076 final List<UserInfo> users = mUserManager.getUsers(); 1077 final int userCount = users.size(); 1078 for (int i = 0; i < userCount; i++) { 1079 UserInfo user = users.get(i); 1080 if (isCredentialSharableWithParent(user.id) 1081 && !getSeparateProfileChallengeEnabledInternal(user.id)) { 1082 success &= SyntheticPasswordCrypto.migrateLockSettingsKey( 1083 PROFILE_KEY_NAME_ENCRYPT + user.id); 1084 success &= SyntheticPasswordCrypto.migrateLockSettingsKey( 1085 PROFILE_KEY_NAME_DECRYPT + user.id); 1086 } 1087 } 1088 return success; 1089 } 1090 1091 /** 1092 * Returns the lowest password quality that still presents the same UI for entering it. 1093 * 1094 * For the FRP credential, we do not want to leak the actual quality of the password, only what 1095 * kind of UI it requires. However, when migrating, we only know the actual quality, not the 1096 * originally requested quality; since this is only used to determine what input variant to 1097 * present to the user, we just assume the lowest possible quality was requested. 1098 */ redactActualQualityToMostLenientEquivalentQuality(int quality)1099 private int redactActualQualityToMostLenientEquivalentQuality(int quality) { 1100 switch (quality) { 1101 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 1102 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 1103 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 1104 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 1105 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 1106 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 1107 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 1108 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 1109 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 1110 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 1111 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK: 1112 default: 1113 return quality; 1114 } 1115 } 1116 enforceFrpResolved()1117 private void enforceFrpResolved() { 1118 final ContentResolver cr = mContext.getContentResolver(); 1119 final boolean inSetupWizard = mInjector.settingsSecureGetInt(cr, 1120 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_SYSTEM) == 0; 1121 final boolean secureFrp = mInjector.settingsSecureGetInt(cr, 1122 Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1; 1123 if (inSetupWizard && secureFrp) { 1124 throw new SecurityException("Cannot change credential in SUW while factory reset" 1125 + " protection is not resolved yet"); 1126 } 1127 } 1128 checkWritePermission(int userId)1129 private final void checkWritePermission(int userId) { 1130 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite"); 1131 } 1132 checkPasswordReadPermission()1133 private final void checkPasswordReadPermission() { 1134 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead"); 1135 } 1136 checkPasswordHavePermission(int userId)1137 private final void checkPasswordHavePermission(int userId) { 1138 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { 1139 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet 1140 } 1141 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave"); 1142 } 1143 checkReadPermission(String requestedKey, int userId)1144 private final void checkReadPermission(String requestedKey, int userId) { 1145 final int callingUid = Binder.getCallingUid(); 1146 1147 for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) { 1148 String key = READ_CONTACTS_PROTECTED_SETTINGS[i]; 1149 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS) 1150 != PackageManager.PERMISSION_GRANTED) { 1151 throw new SecurityException("uid=" + callingUid 1152 + " needs permission " + READ_CONTACTS + " to read " 1153 + requestedKey + " for user " + userId); 1154 } 1155 } 1156 1157 for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) { 1158 String key = READ_PASSWORD_PROTECTED_SETTINGS[i]; 1159 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION) 1160 != PackageManager.PERMISSION_GRANTED) { 1161 throw new SecurityException("uid=" + callingUid 1162 + " needs permission " + PERMISSION + " to read " 1163 + requestedKey + " for user " + userId); 1164 } 1165 } 1166 } 1167 checkBiometricPermission()1168 private final void checkBiometricPermission() { 1169 mContext.enforceCallingOrSelfPermission(BIOMETRIC_PERMISSION, "LockSettingsBiometric"); 1170 } 1171 hasPermission(String permission)1172 private boolean hasPermission(String permission) { 1173 return mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; 1174 } 1175 checkManageWeakEscrowTokenMethodUsage()1176 private void checkManageWeakEscrowTokenMethodUsage() { 1177 mContext.enforceCallingOrSelfPermission( 1178 Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN, 1179 "Requires MANAGE_WEAK_ESCROW_TOKEN permission."); 1180 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 1181 throw new IllegalArgumentException( 1182 "Weak escrow token are only for automotive devices."); 1183 } 1184 } 1185 1186 @Override hasSecureLockScreen()1187 public boolean hasSecureLockScreen() { 1188 return mHasSecureLockScreen; 1189 } 1190 1191 @Override getSeparateProfileChallengeEnabled(int userId)1192 public boolean getSeparateProfileChallengeEnabled(int userId) { 1193 checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId); 1194 return getSeparateProfileChallengeEnabledInternal(userId); 1195 } 1196 getSeparateProfileChallengeEnabledInternal(int userId)1197 private boolean getSeparateProfileChallengeEnabledInternal(int userId) { 1198 synchronized (mSeparateChallengeLock) { 1199 return mStorage.getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId); 1200 } 1201 } 1202 1203 @Override setSeparateProfileChallengeEnabled(int userId, boolean enabled, LockscreenCredential profileUserPassword)1204 public void setSeparateProfileChallengeEnabled(int userId, boolean enabled, 1205 LockscreenCredential profileUserPassword) { 1206 checkWritePermission(userId); 1207 if (!mHasSecureLockScreen 1208 && profileUserPassword != null 1209 && profileUserPassword.getType() != CREDENTIAL_TYPE_NONE) { 1210 throw new UnsupportedOperationException( 1211 "This operation requires secure lock screen feature."); 1212 } 1213 synchronized (mSeparateChallengeLock) { 1214 setSeparateProfileChallengeEnabledLocked(userId, enabled, profileUserPassword != null 1215 ? profileUserPassword : LockscreenCredential.createNone()); 1216 } 1217 notifySeparateProfileChallengeChanged(userId); 1218 } 1219 1220 @GuardedBy("mSeparateChallengeLock") setSeparateProfileChallengeEnabledLocked(@serIdInt int userId, boolean enabled, LockscreenCredential profileUserPassword)1221 private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId, 1222 boolean enabled, LockscreenCredential profileUserPassword) { 1223 final boolean old = getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId); 1224 setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId); 1225 try { 1226 if (enabled) { 1227 mStorage.removeChildProfileLock(userId); 1228 removeKeystoreProfileKey(userId); 1229 } else { 1230 tieProfileLockIfNecessary(userId, profileUserPassword); 1231 } 1232 } catch (IllegalStateException e) { 1233 setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, old, userId); 1234 throw e; 1235 } 1236 } 1237 notifySeparateProfileChallengeChanged(int userId)1238 private void notifySeparateProfileChallengeChanged(int userId) { 1239 // LSS cannot call into DPM directly, otherwise it will cause deadlock. 1240 // In this case, calling DPM on a handler thread is OK since DPM doesn't 1241 // expect reportSeparateProfileChallengeChanged() to happen synchronously. 1242 mHandler.post(() -> { 1243 final DevicePolicyManagerInternal dpmi = LocalServices.getService( 1244 DevicePolicyManagerInternal.class); 1245 if (dpmi != null) { 1246 dpmi.reportSeparateProfileChallengeChanged(userId); 1247 } 1248 }); 1249 } 1250 1251 @Override setBoolean(String key, boolean value, int userId)1252 public void setBoolean(String key, boolean value, int userId) { 1253 checkWritePermission(userId); 1254 mStorage.setBoolean(key, value, userId); 1255 } 1256 1257 @Override setLong(String key, long value, int userId)1258 public void setLong(String key, long value, int userId) { 1259 checkWritePermission(userId); 1260 mStorage.setLong(key, value, userId); 1261 } 1262 1263 @Override setString(String key, String value, int userId)1264 public void setString(String key, String value, int userId) { 1265 checkWritePermission(userId); 1266 mStorage.setString(key, value, userId); 1267 } 1268 1269 @Override getBoolean(String key, boolean defaultValue, int userId)1270 public boolean getBoolean(String key, boolean defaultValue, int userId) { 1271 checkReadPermission(key, userId); 1272 if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) { 1273 return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN; 1274 } 1275 return mStorage.getBoolean(key, defaultValue, userId); 1276 } 1277 1278 @Override getLong(String key, long defaultValue, int userId)1279 public long getLong(String key, long defaultValue, int userId) { 1280 checkReadPermission(key, userId); 1281 return mStorage.getLong(key, defaultValue, userId); 1282 } 1283 1284 @Override getString(String key, String defaultValue, int userId)1285 public String getString(String key, String defaultValue, int userId) { 1286 checkReadPermission(key, userId); 1287 return mStorage.getString(key, defaultValue, userId); 1288 } 1289 setKeyguardStoredQuality(int quality, int userId)1290 private void setKeyguardStoredQuality(int quality, int userId) { 1291 if (DEBUG) Slog.d(TAG, "setKeyguardStoredQuality: user=" + userId + " quality=" + quality); 1292 mStorage.setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, userId); 1293 } 1294 getKeyguardStoredQuality(int userId)1295 private int getKeyguardStoredQuality(int userId) { 1296 return (int) mStorage.getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 1297 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId); 1298 } 1299 1300 /** 1301 * This API is cached; whenever the result would change, 1302 * {@link com.android.internal.widget.LockPatternUtils#invalidateCredentialTypeCache} 1303 * must be called. 1304 */ 1305 @Override getCredentialType(int userId)1306 public int getCredentialType(int userId) { 1307 checkPasswordHavePermission(userId); 1308 return getCredentialTypeInternal(userId); 1309 } 1310 1311 // TODO: this is a hot path, can we optimize it? 1312 /** 1313 * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE}, 1314 * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and 1315 * {@link #CREDENTIAL_TYPE_PASSWORD} 1316 */ getCredentialTypeInternal(int userId)1317 public int getCredentialTypeInternal(int userId) { 1318 if (userId == USER_FRP) { 1319 return getFrpCredentialType(); 1320 } 1321 synchronized (mSpManager) { 1322 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1323 final long handle = getSyntheticPasswordHandleLocked(userId); 1324 int rawType = mSpManager.getCredentialType(handle, userId); 1325 if (rawType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) { 1326 return rawType; 1327 } 1328 return pinOrPasswordQualityToCredentialType(getKeyguardStoredQuality(userId)); 1329 } 1330 } 1331 // Intentional duplication of the getKeyguardStoredQuality() call above since this is a 1332 // unlikely code path (device with pre-synthetic password credential). We want to skip 1333 // calling getKeyguardStoredQuality whenever possible. 1334 final int savedQuality = getKeyguardStoredQuality(userId); 1335 if (savedQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING 1336 && mStorage.hasPattern(userId)) { 1337 return CREDENTIAL_TYPE_PATTERN; 1338 } 1339 if (savedQuality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC 1340 && mStorage.hasPassword(userId)) { 1341 return pinOrPasswordQualityToCredentialType(savedQuality); 1342 } 1343 return CREDENTIAL_TYPE_NONE; 1344 } 1345 getFrpCredentialType()1346 private int getFrpCredentialType() { 1347 PersistentData data = mStorage.readPersistentDataBlock(); 1348 if (data.type != PersistentData.TYPE_SP && data.type != PersistentData.TYPE_SP_WEAVER) { 1349 return CREDENTIAL_TYPE_NONE; 1350 } 1351 int credentialType = SyntheticPasswordManager.getFrpCredentialType(data.payload); 1352 if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) { 1353 return credentialType; 1354 } 1355 return pinOrPasswordQualityToCredentialType(data.qualityForUi); 1356 } 1357 pinOrPasswordQualityToCredentialType(int quality)1358 private static int pinOrPasswordQualityToCredentialType(int quality) { 1359 if (LockPatternUtils.isQualityAlphabeticPassword(quality)) { 1360 return CREDENTIAL_TYPE_PASSWORD; 1361 } 1362 if (LockPatternUtils.isQualityNumericPin(quality)) { 1363 return CREDENTIAL_TYPE_PIN; 1364 } 1365 throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality); 1366 } 1367 isUserSecure(int userId)1368 private boolean isUserSecure(int userId) { 1369 return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE; 1370 } 1371 1372 @VisibleForTesting /** Note: this method is overridden in unit tests */ setKeystorePassword(byte[] password, int userHandle)1373 void setKeystorePassword(byte[] password, int userHandle) { 1374 AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password); 1375 } 1376 unlockKeystore(byte[] password, int userHandle)1377 private void unlockKeystore(byte[] password, int userHandle) { 1378 if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle); 1379 Authorization.onLockScreenEvent(false, userHandle, password, null); 1380 } 1381 1382 @VisibleForTesting /** Note: this method is overridden in unit tests */ getDecryptedPasswordForTiedProfile(int userId)1383 protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId) 1384 throws KeyStoreException, UnrecoverableKeyException, 1385 NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, 1386 InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, 1387 CertificateException, IOException { 1388 if (DEBUG) Slog.v(TAG, "Get child profile decrypted key"); 1389 byte[] storedData = mStorage.readChildProfileLock(userId); 1390 if (storedData == null) { 1391 throw new FileNotFoundException("Child profile lock file not found"); 1392 } 1393 byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE); 1394 byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE, 1395 storedData.length); 1396 byte[] decryptionResult; 1397 SecretKey decryptionKey = (SecretKey) mJavaKeyStore.getKey( 1398 PROFILE_KEY_NAME_DECRYPT + userId, null); 1399 1400 Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 1401 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); 1402 1403 cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv)); 1404 decryptionResult = cipher.doFinal(encryptedPassword); 1405 LockscreenCredential credential = LockscreenCredential.createManagedPassword( 1406 decryptionResult); 1407 Arrays.fill(decryptionResult, (byte) 0); 1408 mManagedProfilePasswordCache.storePassword(userId, credential); 1409 return credential; 1410 } 1411 unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated)1412 private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated) { 1413 try { 1414 doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle), 1415 profileHandle, null /* progressCallback */, 0 /* flags */); 1416 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1417 | NoSuchAlgorithmException | NoSuchPaddingException 1418 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1419 | BadPaddingException | CertificateException | IOException e) { 1420 if (e instanceof FileNotFoundException) { 1421 Slog.i(TAG, "Child profile key not found"); 1422 } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) { 1423 Slog.i(TAG, "Parent keystore seems locked, ignoring"); 1424 } else { 1425 Slog.e(TAG, "Failed to decrypt child profile key", e); 1426 } 1427 } 1428 } 1429 1430 /** 1431 * Unlock the user (both storage and user state) and its associated profiles 1432 * that share lock credential (e.g. managed and clone profiles) synchronously. 1433 * 1434 * <em>Be very careful about the risk of deadlock here: ActivityManager.unlockUser() 1435 * can end up calling into other system services to process user unlock request (via 1436 * {@link com.android.server.SystemServiceManager#unlockUser} </em> 1437 */ unlockUser(int userId, byte[] secret)1438 private void unlockUser(int userId, byte[] secret) { 1439 Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " 1440 + (secret != null ? secret.length : 0)); 1441 // TODO: make this method fully async so we can update UI with progress strings 1442 final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId); 1443 final CountDownLatch latch = new CountDownLatch(1); 1444 final IProgressListener listener = new IProgressListener.Stub() { 1445 @Override 1446 public void onStarted(int id, Bundle extras) throws RemoteException { 1447 Slog.d(TAG, "unlockUser started"); 1448 } 1449 1450 @Override 1451 public void onProgress(int id, int progress, Bundle extras) throws RemoteException { 1452 Slog.d(TAG, "unlockUser progress " + progress); 1453 } 1454 1455 @Override 1456 public void onFinished(int id, Bundle extras) throws RemoteException { 1457 Slog.d(TAG, "unlockUser finished"); 1458 latch.countDown(); 1459 } 1460 }; 1461 1462 try { 1463 mActivityManager.unlockUser(userId, null, secret, listener); 1464 } catch (RemoteException e) { 1465 throw e.rethrowAsRuntimeException(); 1466 } 1467 1468 try { 1469 latch.await(15, TimeUnit.SECONDS); 1470 } catch (InterruptedException e) { 1471 Thread.currentThread().interrupt(); 1472 } 1473 1474 if (isCredentialSharableWithParent(userId)) { 1475 if (!hasUnifiedChallenge(userId)) { 1476 mBiometricDeferredQueue.processPendingLockoutResets(); 1477 } 1478 return; 1479 } 1480 1481 for (UserInfo profile : mUserManager.getProfiles(userId)) { 1482 if (profile.id == userId) continue; 1483 if (!isCredentialSharableWithParent(profile.id)) continue; 1484 1485 if (hasUnifiedChallenge(profile.id)) { 1486 if (mUserManager.isUserRunning(profile.id)) { 1487 // Unlock profile with unified lock 1488 unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */); 1489 } else { 1490 try { 1491 // Profile not ready for unlock yet, but decrypt the unified challenge now 1492 // so it goes into the cache 1493 getDecryptedPasswordForTiedProfile(profile.id); 1494 } catch (GeneralSecurityException | IOException e) { 1495 Slog.d(TAG, "Cache work profile password failed", e); 1496 } 1497 } 1498 } 1499 // Now we have unlocked the parent user and attempted to unlock the profile we should 1500 // show notifications if the profile is still locked. 1501 if (!alreadyUnlocked) { 1502 final long ident = clearCallingIdentity(); 1503 try { 1504 maybeShowEncryptionNotificationForUser(profile.id, "parent unlocked"); 1505 } finally { 1506 restoreCallingIdentity(ident); 1507 } 1508 } 1509 } 1510 1511 mBiometricDeferredQueue.processPendingLockoutResets(); 1512 } 1513 hasUnifiedChallenge(int userId)1514 private boolean hasUnifiedChallenge(int userId) { 1515 return !getSeparateProfileChallengeEnabledInternal(userId) 1516 && mStorage.hasChildProfileLock(userId); 1517 } 1518 getDecryptedPasswordsForAllTiedProfiles(int userId)1519 private Map<Integer, LockscreenCredential> getDecryptedPasswordsForAllTiedProfiles(int userId) { 1520 if (isCredentialSharableWithParent(userId)) { 1521 return null; 1522 } 1523 Map<Integer, LockscreenCredential> result = new ArrayMap<>(); 1524 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1525 final int size = profiles.size(); 1526 for (int i = 0; i < size; i++) { 1527 final UserInfo profile = profiles.get(i); 1528 if (!isCredentialSharableWithParent(profile.id)) { 1529 continue; 1530 } 1531 final int profileUserId = profile.id; 1532 if (getSeparateProfileChallengeEnabledInternal(profileUserId)) { 1533 continue; 1534 } 1535 try { 1536 result.put(profileUserId, getDecryptedPasswordForTiedProfile(profileUserId)); 1537 } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException 1538 | NoSuchPaddingException | InvalidKeyException 1539 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1540 | BadPaddingException | CertificateException | IOException e) { 1541 Slog.e(TAG, "getDecryptedPasswordsForAllTiedProfiles failed for user " + 1542 profileUserId, e); 1543 } 1544 } 1545 return result; 1546 } 1547 1548 /** 1549 * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them 1550 * depending on the parent user's secure state. 1551 * 1552 * When clearing tied work challenges, a pre-computed password table for profiles are required, 1553 * since changing password for profiles requires existing password, and existing passwords can 1554 * only be computed before the parent user's password is cleared. 1555 * 1556 * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this 1557 * method again on profiles. However the recursion is guaranteed to terminate as this method 1558 * terminates when the user is a profile that shares lock credentials with parent. 1559 * (e.g. managed and clone profile). 1560 */ synchronizeUnifiedWorkChallengeForProfiles(int userId, Map<Integer, LockscreenCredential> profilePasswordMap)1561 private void synchronizeUnifiedWorkChallengeForProfiles(int userId, 1562 Map<Integer, LockscreenCredential> profilePasswordMap) { 1563 if (isCredentialSharableWithParent(userId)) { 1564 return; 1565 } 1566 final boolean isSecure = isUserSecure(userId); 1567 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1568 final int size = profiles.size(); 1569 for (int i = 0; i < size; i++) { 1570 final UserInfo profile = profiles.get(i); 1571 final int profileUserId = profile.id; 1572 if (isCredentialSharableWithParent(profileUserId)) { 1573 if (getSeparateProfileChallengeEnabledInternal(profileUserId)) { 1574 continue; 1575 } 1576 if (isSecure) { 1577 tieProfileLockIfNecessary(profileUserId, 1578 LockscreenCredential.createNone()); 1579 } else { 1580 // We use cached work profile password computed before clearing the parent's 1581 // credential, otherwise they get lost 1582 if (profilePasswordMap != null 1583 && profilePasswordMap.containsKey(profileUserId)) { 1584 setLockCredentialInternal(LockscreenCredential.createNone(), 1585 profilePasswordMap.get(profileUserId), 1586 profileUserId, 1587 /* isLockTiedToParent= */ true); 1588 mStorage.removeChildProfileLock(profileUserId); 1589 removeKeystoreProfileKey(profileUserId); 1590 } else { 1591 Slog.wtf(TAG, "Attempt to clear tied challenge, but no password supplied."); 1592 } 1593 } 1594 } 1595 } 1596 } 1597 isProfileWithUnifiedLock(int userId)1598 private boolean isProfileWithUnifiedLock(int userId) { 1599 return isCredentialSharableWithParent(userId) 1600 && !getSeparateProfileChallengeEnabledInternal(userId); 1601 } 1602 isProfileWithSeparatedLock(int userId)1603 private boolean isProfileWithSeparatedLock(int userId) { 1604 return isCredentialSharableWithParent(userId) 1605 && getSeparateProfileChallengeEnabledInternal(userId); 1606 } 1607 1608 /** 1609 * Send credentials for user {@code userId} to {@link RecoverableKeyStoreManager} during an 1610 * unlock operation. 1611 */ sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId)1612 private void sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId) { 1613 // Don't send credentials during the factory reset protection flow. 1614 if (userId == USER_FRP) { 1615 return; 1616 } 1617 1618 // A profile with a unified lock screen stores a randomly generated credential, so skip it. 1619 // Its parent will send credentials for the profile, as it stores the unified lock 1620 // credential. 1621 if (isProfileWithUnifiedLock(userId)) { 1622 return; 1623 } 1624 1625 // RecoverableKeyStoreManager expects null for empty credential. 1626 final byte[] secret = credential.isNone() ? null : credential.getCredential(); 1627 // Send credentials for the user and any child profiles that share its lock screen. 1628 for (int profileId : getProfilesWithSameLockScreen(userId)) { 1629 mRecoverableKeyStoreManager.lockScreenSecretAvailable( 1630 credential.getType(), secret, profileId); 1631 } 1632 } 1633 1634 /** 1635 * Send credentials for user {@code userId} to {@link RecoverableKeyStoreManager} when its 1636 * credentials are set/changed. 1637 */ sendCredentialsOnChangeIfRequired( LockscreenCredential credential, int userId, boolean isLockTiedToParent)1638 private void sendCredentialsOnChangeIfRequired( 1639 LockscreenCredential credential, int userId, boolean isLockTiedToParent) { 1640 // A profile whose lock screen is being tied to its parent's will either have a randomly 1641 // generated credential (creation) or null (removal). We rely on the parent to send its 1642 // credentials for the profile in both cases as it stores the unified lock credential. 1643 if (isLockTiedToParent) { 1644 return; 1645 } 1646 1647 // RecoverableKeyStoreManager expects null for empty credential. 1648 final byte[] secret = credential.isNone() ? null : credential.getCredential(); 1649 // Send credentials for the user and any child profiles that share its lock screen. 1650 for (int profileId : getProfilesWithSameLockScreen(userId)) { 1651 mRecoverableKeyStoreManager.lockScreenSecretChanged( 1652 credential.getType(), secret, profileId); 1653 } 1654 } 1655 1656 /** 1657 * Returns all profiles of {@code userId}, including itself, that have the same lock screen 1658 * challenge. 1659 */ getProfilesWithSameLockScreen(int userId)1660 private Set<Integer> getProfilesWithSameLockScreen(int userId) { 1661 Set<Integer> profiles = new ArraySet<>(); 1662 for (UserInfo profile : mUserManager.getProfiles(userId)) { 1663 if (profile.id == userId 1664 || (profile.profileGroupId == userId 1665 && isProfileWithUnifiedLock(profile.id))) { 1666 profiles.add(profile.id); 1667 } 1668 } 1669 return profiles; 1670 } 1671 1672 // This method should be called by LockPatternUtil only, all internal methods in this class 1673 // should call setLockCredentialInternal. 1674 @Override setLockCredential(LockscreenCredential credential, LockscreenCredential savedCredential, int userId)1675 public boolean setLockCredential(LockscreenCredential credential, 1676 LockscreenCredential savedCredential, int userId) { 1677 1678 if (!mHasSecureLockScreen 1679 && credential != null && credential.getType() != CREDENTIAL_TYPE_NONE) { 1680 throw new UnsupportedOperationException( 1681 "This operation requires secure lock screen feature"); 1682 } 1683 if (!hasPermission(PERMISSION) && !hasPermission(SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS)) { 1684 if (hasPermission(SET_INITIAL_LOCK) && savedCredential.isNone()) { 1685 // SET_INITIAL_LOCK can only be used if credential is not set. 1686 } else { 1687 throw new SecurityException( 1688 "setLockCredential requires SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS or " 1689 + PERMISSION); 1690 } 1691 } 1692 1693 final long identity = Binder.clearCallingIdentity(); 1694 try { 1695 enforceFrpResolved(); 1696 // When changing credential for profiles with unified challenge, some callers 1697 // will pass in empty credential while others will pass in the credential of 1698 // the parent user. setLockCredentialInternal() handles the formal case (empty 1699 // credential) correctly but not the latter. As a stopgap fix, convert the latter 1700 // case to the formal. The long-term fix would be fixing LSS such that it should 1701 // accept only the parent user credential on its public API interfaces, swap it 1702 // with the profile's random credential at that API boundary (i.e. here) and make 1703 // sure LSS internally does not special case profile with unififed challenge: b/80170828 1704 if (!savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { 1705 // Verify the parent credential again, to make sure we have a fresh enough 1706 // auth token such that getDecryptedPasswordForTiedProfile() inside 1707 // setLockCredentialInternal() can function correctly. 1708 verifyCredential(savedCredential, mUserManager.getProfileParent(userId).id, 1709 0 /* flags */); 1710 savedCredential.zeroize(); 1711 savedCredential = LockscreenCredential.createNone(); 1712 } 1713 synchronized (mSeparateChallengeLock) { 1714 if (!setLockCredentialInternal(credential, savedCredential, 1715 userId, /* isLockTiedToParent= */ false)) { 1716 scheduleGc(); 1717 return false; 1718 } 1719 setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null); 1720 notifyPasswordChanged(credential, userId); 1721 } 1722 if (isCredentialSharableWithParent(userId)) { 1723 // Make sure the profile doesn't get locked straight after setting work challenge. 1724 setDeviceUnlockedForUser(userId); 1725 } 1726 notifySeparateProfileChallengeChanged(userId); 1727 onPostPasswordChanged(credential, userId); 1728 scheduleGc(); 1729 return true; 1730 } finally { 1731 Binder.restoreCallingIdentity(identity); 1732 } 1733 } 1734 1735 /** 1736 * @param savedCredential if the user is a profile with 1737 * {@link UserManager#isCredentialSharableWithParent()} with unified challenge and 1738 * savedCredential is empty, LSS will try to re-derive the profile password internally. 1739 * TODO (b/80170828): Fix this so profile password is always passed in. 1740 * @param isLockTiedToParent is {@code true} if {@code userId} is a profile and its new 1741 * credentials are being tied to its parent's credentials. 1742 */ setLockCredentialInternal(LockscreenCredential credential, LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent)1743 private boolean setLockCredentialInternal(LockscreenCredential credential, 1744 LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) { 1745 Objects.requireNonNull(credential); 1746 Objects.requireNonNull(savedCredential); 1747 synchronized (mSpManager) { 1748 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1749 return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId, 1750 isLockTiedToParent); 1751 } 1752 } 1753 1754 if (credential.isNone()) { 1755 clearUserKeyProtection(userId, null); 1756 gateKeeperClearSecureUserId(userId); 1757 mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId); 1758 // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path, 1759 // since it forms part of the state that determines the credential type 1760 // @see getCredentialTypeInternal 1761 setKeyguardStoredQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId); 1762 setKeystorePassword(null, userId); 1763 fixateNewestUserKeyAuth(userId); 1764 synchronizeUnifiedWorkChallengeForProfiles(userId, null); 1765 setUserPasswordMetrics(LockscreenCredential.createNone(), userId); 1766 sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent); 1767 return true; 1768 } 1769 1770 CredentialHash currentHandle = mStorage.readCredentialHash(userId); 1771 if (isProfileWithUnifiedLock(userId)) { 1772 // get credential from keystore when managed/clone profile has unified lock 1773 if (savedCredential.isNone()) { 1774 try { 1775 //TODO: remove as part of b/80170828 1776 savedCredential = getDecryptedPasswordForTiedProfile(userId); 1777 } catch (FileNotFoundException e) { 1778 Slog.i(TAG, "Child profile key not found"); 1779 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1780 | NoSuchAlgorithmException | NoSuchPaddingException 1781 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1782 | BadPaddingException | CertificateException | IOException e) { 1783 Slog.e(TAG, "Failed to decrypt child profile key", e); 1784 } 1785 } 1786 } else { 1787 if (currentHandle.hash == null) { 1788 if (!savedCredential.isNone()) { 1789 Slog.w(TAG, "Saved credential provided, but none stored"); 1790 } 1791 savedCredential.close(); 1792 savedCredential = LockscreenCredential.createNone(); 1793 } 1794 } 1795 synchronized (mSpManager) { 1796 initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId); 1797 return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId, 1798 isLockTiedToParent); 1799 } 1800 } 1801 onPostPasswordChanged(LockscreenCredential newCredential, int userHandle)1802 private void onPostPasswordChanged(LockscreenCredential newCredential, int userHandle) { 1803 if (userHandle == UserHandle.USER_SYSTEM && isDeviceEncryptionEnabled() && 1804 shouldEncryptWithCredentials() && newCredential.isNone()) { 1805 setCredentialRequiredToDecrypt(false); 1806 } 1807 if (newCredential.isPattern()) { 1808 setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle); 1809 } 1810 updatePasswordHistory(newCredential, userHandle); 1811 mContext.getSystemService(TrustManager.class).reportEnabledTrustAgentsChanged(userHandle); 1812 } 1813 1814 /** 1815 * Store the hash of the *current* password in the password history list, if device policy 1816 * enforces password history requirement. 1817 */ updatePasswordHistory(LockscreenCredential password, int userHandle)1818 private void updatePasswordHistory(LockscreenCredential password, int userHandle) { 1819 if (password.isNone()) { 1820 return; 1821 } 1822 if (password.isPattern()) { 1823 // Do not keep track of historical patterns 1824 return; 1825 } 1826 // Add the password to the password history. We assume all 1827 // password hashes have the same length for simplicity of implementation. 1828 String passwordHistory = getString( 1829 LockPatternUtils.PASSWORD_HISTORY_KEY, /* defaultValue= */ null, userHandle); 1830 if (passwordHistory == null) { 1831 passwordHistory = ""; 1832 } 1833 int passwordHistoryLength = getRequestedPasswordHistoryLength(userHandle); 1834 if (passwordHistoryLength == 0) { 1835 passwordHistory = ""; 1836 } else { 1837 final byte[] hashFactor = getHashFactor(password, userHandle); 1838 final byte[] salt = getSalt(userHandle).getBytes(); 1839 String hash = password.passwordToHistoryHash(salt, hashFactor); 1840 if (hash == null) { 1841 Slog.e(TAG, "Compute new style password hash failed, fallback to legacy style"); 1842 hash = password.legacyPasswordToHash(salt); 1843 } 1844 if (TextUtils.isEmpty(passwordHistory)) { 1845 passwordHistory = hash; 1846 } else { 1847 String[] history = passwordHistory.split( 1848 LockPatternUtils.PASSWORD_HISTORY_DELIMITER); 1849 StringJoiner joiner = new StringJoiner(LockPatternUtils.PASSWORD_HISTORY_DELIMITER); 1850 joiner.add(hash); 1851 for (int i = 0; i < passwordHistoryLength - 1 && i < history.length; i++) { 1852 joiner.add(history[i]); 1853 } 1854 passwordHistory = joiner.toString(); 1855 } 1856 } 1857 setString(LockPatternUtils.PASSWORD_HISTORY_KEY, passwordHistory, userHandle); 1858 } 1859 getSalt(int userId)1860 private String getSalt(int userId) { 1861 long salt = getLong(LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 0, userId); 1862 if (salt == 0) { 1863 try { 1864 salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 1865 setLong(LockPatternUtils.LOCK_PASSWORD_SALT_KEY, salt, userId); 1866 Slog.v(TAG, "Initialized lock password salt for user: " + userId); 1867 } catch (NoSuchAlgorithmException e) { 1868 // Throw an exception rather than storing a password we'll never be able to recover 1869 throw new IllegalStateException("Couldn't get SecureRandom number", e); 1870 } 1871 } 1872 return Long.toHexString(salt); 1873 } 1874 getRequestedPasswordHistoryLength(int userId)1875 private int getRequestedPasswordHistoryLength(int userId) { 1876 return mInjector.getDevicePolicyManager().getPasswordHistoryLength(null, userId); 1877 } 1878 isDeviceEncryptionEnabled()1879 private static boolean isDeviceEncryptionEnabled() { 1880 return StorageManager.isEncrypted(); 1881 } 1882 shouldEncryptWithCredentials()1883 private boolean shouldEncryptWithCredentials() { 1884 return isCredentialRequiredToDecrypt() && !isDoNotAskCredentialsOnBootSet(); 1885 } 1886 isDoNotAskCredentialsOnBootSet()1887 private boolean isDoNotAskCredentialsOnBootSet() { 1888 return mInjector.getDevicePolicyManager().getDoNotAskCredentialsOnBoot(); 1889 } 1890 isCredentialRequiredToDecrypt()1891 private boolean isCredentialRequiredToDecrypt() { 1892 final int value = Settings.Global.getInt(mContext.getContentResolver(), 1893 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, -1); 1894 return value != 0; 1895 } 1896 getUserManagerFromCache(int userId)1897 private UserManager getUserManagerFromCache(int userId) { 1898 UserHandle userHandle = UserHandle.of(userId); 1899 if (mUserManagerCache.containsKey(userHandle)) { 1900 return mUserManagerCache.get(userHandle); 1901 } 1902 1903 try { 1904 Context userContext = mContext.createPackageContextAsUser("system", 0, userHandle); 1905 UserManager userManager = userContext.getSystemService(UserManager.class); 1906 mUserManagerCache.put(userHandle, userManager); 1907 return userManager; 1908 } catch (PackageManager.NameNotFoundException e) { 1909 throw new RuntimeException("Failed to create context for user " + userHandle, e); 1910 } 1911 } 1912 isCredentialSharableWithParent(int userId)1913 protected boolean isCredentialSharableWithParent(int userId) { 1914 return getUserManagerFromCache(userId).isCredentialSharableWithParent(); 1915 } 1916 convertResponse(GateKeeperResponse gateKeeperResponse)1917 private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) { 1918 return VerifyCredentialResponse.fromGateKeeperResponse(gateKeeperResponse); 1919 } 1920 setCredentialRequiredToDecrypt(boolean required)1921 private void setCredentialRequiredToDecrypt(boolean required) { 1922 if (isDeviceEncryptionEnabled()) { 1923 Settings.Global.putInt(mContext.getContentResolver(), 1924 Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT, required ? 1 : 0); 1925 } 1926 } 1927 1928 /** Register the given WeakEscrowTokenRemovedListener. */ 1929 @Override registerWeakEscrowTokenRemovedListener( @onNull IWeakEscrowTokenRemovedListener listener)1930 public boolean registerWeakEscrowTokenRemovedListener( 1931 @NonNull IWeakEscrowTokenRemovedListener listener) { 1932 checkManageWeakEscrowTokenMethodUsage(); 1933 final long token = Binder.clearCallingIdentity(); 1934 try { 1935 return mSpManager.registerWeakEscrowTokenRemovedListener(listener); 1936 } finally { 1937 Binder.restoreCallingIdentity(token); 1938 } 1939 } 1940 1941 /** Unregister the given WeakEscrowTokenRemovedListener. */ 1942 @Override unregisterWeakEscrowTokenRemovedListener( @onNull IWeakEscrowTokenRemovedListener listener)1943 public boolean unregisterWeakEscrowTokenRemovedListener( 1944 @NonNull IWeakEscrowTokenRemovedListener listener) { 1945 checkManageWeakEscrowTokenMethodUsage(); 1946 final long token = Binder.clearCallingIdentity(); 1947 try { 1948 return mSpManager.unregisterWeakEscrowTokenRemovedListener(listener); 1949 } finally { 1950 Binder.restoreCallingIdentity(token); 1951 } 1952 } 1953 1954 @Override addWeakEscrowToken(byte[] token, int userId, @NonNull IWeakEscrowTokenActivatedListener listener)1955 public long addWeakEscrowToken(byte[] token, int userId, 1956 @NonNull IWeakEscrowTokenActivatedListener listener) { 1957 checkManageWeakEscrowTokenMethodUsage(); 1958 Objects.requireNonNull(listener, "Listener can not be null."); 1959 EscrowTokenStateChangeCallback internalListener = (handle, userId1) -> { 1960 try { 1961 listener.onWeakEscrowTokenActivated(handle, userId1); 1962 } catch (RemoteException e) { 1963 Slog.e(TAG, "Exception while notifying weak escrow token has been activated", e); 1964 } 1965 }; 1966 final long restoreToken = Binder.clearCallingIdentity(); 1967 try { 1968 return addEscrowToken(token, TOKEN_TYPE_WEAK, userId, internalListener); 1969 } finally { 1970 Binder.restoreCallingIdentity(restoreToken); 1971 } 1972 } 1973 1974 @Override removeWeakEscrowToken(long handle, int userId)1975 public boolean removeWeakEscrowToken(long handle, int userId) { 1976 checkManageWeakEscrowTokenMethodUsage(); 1977 final long token = Binder.clearCallingIdentity(); 1978 try { 1979 return removeEscrowToken(handle, userId); 1980 } finally { 1981 Binder.restoreCallingIdentity(token); 1982 } 1983 } 1984 1985 @Override isWeakEscrowTokenActive(long handle, int userId)1986 public boolean isWeakEscrowTokenActive(long handle, int userId) { 1987 checkManageWeakEscrowTokenMethodUsage(); 1988 final long token = Binder.clearCallingIdentity(); 1989 try { 1990 return isEscrowTokenActive(handle, userId); 1991 } finally { 1992 Binder.restoreCallingIdentity(token); 1993 } 1994 } 1995 1996 @Override isWeakEscrowTokenValid(long handle, byte[] token, int userId)1997 public boolean isWeakEscrowTokenValid(long handle, byte[] token, int userId) { 1998 checkManageWeakEscrowTokenMethodUsage(); 1999 final long restoreToken = Binder.clearCallingIdentity(); 2000 try { 2001 synchronized (mSpManager) { 2002 if (!mSpManager.hasEscrowData(userId)) { 2003 Slog.w(TAG, "Escrow token is disabled on the current user"); 2004 return false; 2005 } 2006 AuthenticationResult authResult = mSpManager.unwrapWeakTokenBasedSyntheticPassword( 2007 getGateKeeperService(), handle, token, userId); 2008 if (authResult.authToken == null) { 2009 Slog.w(TAG, "Invalid escrow token supplied"); 2010 return false; 2011 } 2012 return true; 2013 } 2014 } finally { 2015 Binder.restoreCallingIdentity(restoreToken); 2016 } 2017 } 2018 2019 @VisibleForTesting /** Note: this method is overridden in unit tests */ tieProfileLockToParent(int userId, LockscreenCredential password)2020 protected void tieProfileLockToParent(int userId, LockscreenCredential password) { 2021 if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId); 2022 byte[] encryptionResult; 2023 byte[] iv; 2024 try { 2025 KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); 2026 keyGenerator.init(new SecureRandom()); 2027 SecretKey secretKey = keyGenerator.generateKey(); 2028 try { 2029 mJavaKeyStore.setEntry( 2030 PROFILE_KEY_NAME_ENCRYPT + userId, 2031 new java.security.KeyStore.SecretKeyEntry(secretKey), 2032 new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT) 2033 .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 2034 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 2035 .build()); 2036 mJavaKeyStore.setEntry( 2037 PROFILE_KEY_NAME_DECRYPT + userId, 2038 new java.security.KeyStore.SecretKeyEntry(secretKey), 2039 new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT) 2040 .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 2041 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 2042 .setUserAuthenticationRequired(true) 2043 .setUserAuthenticationValidityDurationSeconds(30) 2044 .build()); 2045 // Key imported, obtain a reference to it. 2046 SecretKey keyStoreEncryptionKey = (SecretKey) mJavaKeyStore.getKey( 2047 PROFILE_KEY_NAME_ENCRYPT + userId, null); 2048 Cipher cipher = Cipher.getInstance( 2049 KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/" 2050 + KeyProperties.ENCRYPTION_PADDING_NONE); 2051 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey); 2052 encryptionResult = cipher.doFinal(password.getCredential()); 2053 iv = cipher.getIV(); 2054 } finally { 2055 // The original key can now be discarded. 2056 mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + userId); 2057 } 2058 } catch (UnrecoverableKeyException 2059 | BadPaddingException | IllegalBlockSizeException | KeyStoreException 2060 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { 2061 throw new IllegalStateException("Failed to encrypt key", e); 2062 } 2063 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 2064 try { 2065 if (iv.length != PROFILE_KEY_IV_SIZE) { 2066 throw new IllegalArgumentException("Invalid iv length: " + iv.length); 2067 } 2068 outputStream.write(iv); 2069 outputStream.write(encryptionResult); 2070 } catch (IOException e) { 2071 throw new IllegalStateException("Failed to concatenate byte arrays", e); 2072 } 2073 mStorage.writeChildProfileLock(userId, outputStream.toByteArray()); 2074 } 2075 setUserKeyProtection(int userId, byte[] key)2076 private void setUserKeyProtection(int userId, byte[] key) { 2077 if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId); 2078 addUserKeyAuth(userId, key); 2079 } 2080 clearUserKeyProtection(int userId, byte[] secret)2081 private void clearUserKeyProtection(int userId, byte[] secret) { 2082 if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId); 2083 final UserInfo userInfo = mUserManager.getUserInfo(userId); 2084 final long callingId = Binder.clearCallingIdentity(); 2085 try { 2086 mStorageManager.clearUserKeyAuth(userId, userInfo.serialNumber, secret); 2087 } catch (RemoteException e) { 2088 throw new IllegalStateException("clearUserKeyAuth failed user=" + userId); 2089 } finally { 2090 Binder.restoreCallingIdentity(callingId); 2091 } 2092 } 2093 secretFromCredential(LockscreenCredential credential)2094 private static byte[] secretFromCredential(LockscreenCredential credential) { 2095 try { 2096 MessageDigest digest = MessageDigest.getInstance("SHA-512"); 2097 // Personalize the hash 2098 byte[] personalization = "Android FBE credential hash".getBytes(); 2099 // Pad it to the block size of the hash function 2100 personalization = Arrays.copyOf(personalization, 128); 2101 digest.update(personalization); 2102 digest.update(credential.getCredential()); 2103 return digest.digest(); 2104 } catch (NoSuchAlgorithmException e) { 2105 throw new IllegalStateException("NoSuchAlgorithmException for SHA-512"); 2106 } 2107 } 2108 isUserKeyUnlocked(int userId)2109 private boolean isUserKeyUnlocked(int userId) { 2110 try { 2111 return mStorageManager.isUserKeyUnlocked(userId); 2112 } catch (RemoteException e) { 2113 Slog.e(TAG, "failed to check user key locked state", e); 2114 return false; 2115 } 2116 } 2117 2118 /** Unlock disk encryption */ unlockUserKey(int userId, byte[] secret)2119 private void unlockUserKey(int userId, byte[] secret) { 2120 final UserInfo userInfo = mUserManager.getUserInfo(userId); 2121 try { 2122 mStorageManager.unlockUserKey(userId, userInfo.serialNumber, secret); 2123 } catch (RemoteException e) { 2124 throw new IllegalStateException("Failed to unlock user key " + userId, e); 2125 2126 } 2127 } 2128 addUserKeyAuth(int userId, byte[] secret)2129 private void addUserKeyAuth(int userId, byte[] secret) { 2130 final UserInfo userInfo = mUserManager.getUserInfo(userId); 2131 final long callingId = Binder.clearCallingIdentity(); 2132 try { 2133 mStorageManager.addUserKeyAuth(userId, userInfo.serialNumber, secret); 2134 } catch (RemoteException e) { 2135 throw new IllegalStateException("Failed to add new key to vold " + userId, e); 2136 } finally { 2137 Binder.restoreCallingIdentity(callingId); 2138 } 2139 } 2140 fixateNewestUserKeyAuth(int userId)2141 private void fixateNewestUserKeyAuth(int userId) { 2142 if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId); 2143 final long callingId = Binder.clearCallingIdentity(); 2144 try { 2145 mStorageManager.fixateNewestUserKeyAuth(userId); 2146 } catch (RemoteException e) { 2147 // OK to ignore the exception as vold would just accept both old and new 2148 // keys if this call fails, and will fix itself during the next boot 2149 Slog.w(TAG, "fixateNewestUserKeyAuth failed", e); 2150 } finally { 2151 Binder.restoreCallingIdentity(callingId); 2152 } 2153 } 2154 2155 @Override resetKeyStore(int userId)2156 public void resetKeyStore(int userId) { 2157 checkWritePermission(userId); 2158 if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId); 2159 List<Integer> profileUserIds = new ArrayList<>(); 2160 List<LockscreenCredential> profileUserDecryptedPasswords = new ArrayList<>(); 2161 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 2162 for (UserInfo pi : profiles) { 2163 // Unlock profile which shares credential with parent with unified lock 2164 if (isCredentialSharableWithParent(pi.id) 2165 && !getSeparateProfileChallengeEnabledInternal(pi.id) 2166 && mStorage.hasChildProfileLock(pi.id)) { 2167 try { 2168 profileUserDecryptedPasswords.add(getDecryptedPasswordForTiedProfile(pi.id)); 2169 profileUserIds.add(pi.id); 2170 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 2171 | NoSuchAlgorithmException | NoSuchPaddingException 2172 | InvalidAlgorithmParameterException | IllegalBlockSizeException 2173 | BadPaddingException | CertificateException | IOException e) { 2174 Slog.e(TAG, "Failed to decrypt child profile key", e); 2175 } 2176 } 2177 } 2178 try { 2179 // Clear all the users credentials could have been installed in for this user. 2180 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) { 2181 for (int uid : SYSTEM_CREDENTIAL_UIDS) { 2182 AndroidKeyStoreMaintenance.clearNamespace(Domain.APP, 2183 UserHandle.getUid(profileId, uid)); 2184 } 2185 } 2186 if (mUserManager.getUserInfo(userId).isPrimary()) { 2187 AndroidKeyStoreMaintenance.clearNamespace(Domain.SELINUX, 2188 KeyProperties.NAMESPACE_WIFI); 2189 } 2190 } finally { 2191 for (int i = 0; i < profileUserIds.size(); ++i) { 2192 int piUserId = profileUserIds.get(i); 2193 LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i); 2194 if (piUserId != -1 && piUserDecryptedPassword != null) { 2195 if (DEBUG) Slog.v(TAG, "Restore tied profile lock"); 2196 tieProfileLockToParent(piUserId, piUserDecryptedPassword); 2197 } 2198 if (piUserDecryptedPassword != null) { 2199 piUserDecryptedPassword.zeroize(); 2200 } 2201 } 2202 } 2203 } 2204 2205 @Override checkCredential(LockscreenCredential credential, int userId, ICheckCredentialProgressCallback progressCallback)2206 public VerifyCredentialResponse checkCredential(LockscreenCredential credential, int userId, 2207 ICheckCredentialProgressCallback progressCallback) { 2208 checkPasswordReadPermission(); 2209 try { 2210 return doVerifyCredential(credential, userId, progressCallback, 0 /* flags */); 2211 } finally { 2212 scheduleGc(); 2213 } 2214 } 2215 2216 @Override 2217 @Nullable verifyCredential(LockscreenCredential credential, int userId, int flags)2218 public VerifyCredentialResponse verifyCredential(LockscreenCredential credential, 2219 int userId, int flags) { 2220 if (!hasPermission(PERMISSION) && !hasPermission(SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS)) { 2221 throw new SecurityException( 2222 "verifyCredential requires SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS or " 2223 + PERMISSION); 2224 } 2225 final long identity = Binder.clearCallingIdentity(); 2226 try { 2227 return doVerifyCredential(credential, userId, null /* progressCallback */, flags); 2228 } finally { 2229 Binder.restoreCallingIdentity(identity); 2230 scheduleGc(); 2231 } 2232 } 2233 2234 @Override verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, long challenge, int userId)2235 public VerifyCredentialResponse verifyGatekeeperPasswordHandle(long gatekeeperPasswordHandle, 2236 long challenge, int userId) { 2237 2238 checkPasswordReadPermission(); 2239 2240 final VerifyCredentialResponse response; 2241 final byte[] gatekeeperPassword; 2242 2243 synchronized (mGatekeeperPasswords) { 2244 gatekeeperPassword = mGatekeeperPasswords.get(gatekeeperPasswordHandle); 2245 } 2246 2247 synchronized (mSpManager) { 2248 if (gatekeeperPassword == null) { 2249 Slog.d(TAG, "No gatekeeper password for handle"); 2250 response = VerifyCredentialResponse.ERROR; 2251 } else { 2252 response = mSpManager.verifyChallengeInternal(getGateKeeperService(), 2253 gatekeeperPassword, challenge, userId); 2254 } 2255 } 2256 return response; 2257 } 2258 2259 @Override removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle)2260 public void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle) { 2261 checkPasswordReadPermission(); 2262 synchronized (mGatekeeperPasswords) { 2263 mGatekeeperPasswords.remove(gatekeeperPasswordHandle); 2264 } 2265 } 2266 2267 /* 2268 * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero 2269 * format. 2270 * @param credential User's lockscreen credential 2271 * @param userId User to verify the credential for 2272 * @param progressCallback Receive progress callbacks 2273 * @param flags See {@link LockPatternUtils.VerifyFlag} 2274 * @return See {@link VerifyCredentialResponse} 2275 */ doVerifyCredential(LockscreenCredential credential, int userId, ICheckCredentialProgressCallback progressCallback, @LockPatternUtils.VerifyFlag int flags)2276 private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential, 2277 int userId, ICheckCredentialProgressCallback progressCallback, 2278 @LockPatternUtils.VerifyFlag int flags) { 2279 if (credential == null || credential.isNone()) { 2280 throw new IllegalArgumentException("Credential can't be null or empty"); 2281 } 2282 if (userId == USER_FRP && mInjector.settingsGlobalGetInt(mContext.getContentResolver(), 2283 Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 2284 Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); 2285 return VerifyCredentialResponse.ERROR; 2286 } 2287 2288 VerifyCredentialResponse response = spBasedDoVerifyCredential(credential, userId, 2289 progressCallback, flags); 2290 2291 // The user employs synthetic password based credential. 2292 if (response != null) { 2293 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2294 sendCredentialsOnUnlockIfRequired(credential, userId); 2295 } 2296 return response; 2297 } 2298 2299 if (userId == USER_FRP) { 2300 Slog.wtf(TAG, "Unexpected FRP credential type, should be SP based."); 2301 return VerifyCredentialResponse.ERROR; 2302 } 2303 2304 final CredentialHash storedHash = mStorage.readCredentialHash(userId); 2305 if (!credential.checkAgainstStoredType(storedHash.type)) { 2306 Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??" 2307 + " stored: " + storedHash.type + " passed in: " + credential.getType()); 2308 return VerifyCredentialResponse.ERROR; 2309 } 2310 2311 response = verifyCredential(userId, storedHash, credential, progressCallback); 2312 2313 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2314 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); 2315 } 2316 2317 return response; 2318 } 2319 2320 @Override verifyTiedProfileChallenge(LockscreenCredential credential, int userId, @LockPatternUtils.VerifyFlag int flags)2321 public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential, 2322 int userId, @LockPatternUtils.VerifyFlag int flags) { 2323 checkPasswordReadPermission(); 2324 if (!isProfileWithUnifiedLock(userId)) { 2325 throw new IllegalArgumentException( 2326 "User id must be managed/clone profile with unified lock"); 2327 } 2328 final int parentProfileId = mUserManager.getProfileParent(userId).id; 2329 // Unlock parent by using parent's challenge 2330 final VerifyCredentialResponse parentResponse = doVerifyCredential( 2331 credential, 2332 parentProfileId, 2333 null /* progressCallback */, 2334 flags); 2335 if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 2336 // Failed, just return parent's response 2337 return parentResponse; 2338 } 2339 2340 try { 2341 // Unlock work profile, and work profile with unified lock must use password only 2342 return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId), 2343 userId, null /* progressCallback */, flags); 2344 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 2345 | NoSuchAlgorithmException | NoSuchPaddingException 2346 | InvalidAlgorithmParameterException | IllegalBlockSizeException 2347 | BadPaddingException | CertificateException | IOException e) { 2348 Slog.e(TAG, "Failed to decrypt child profile key", e); 2349 throw new IllegalStateException("Unable to get tied profile token"); 2350 } finally { 2351 scheduleGc(); 2352 } 2353 } 2354 2355 /** 2356 * Lowest-level credential verification routine that talks to GateKeeper. If verification 2357 * passes, unlock the corresponding user and keystore. Also handles the migration from legacy 2358 * hash to GK. 2359 */ verifyCredential(int userId, CredentialHash storedHash, LockscreenCredential credential, ICheckCredentialProgressCallback progressCallback)2360 private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash, 2361 LockscreenCredential credential, ICheckCredentialProgressCallback progressCallback) { 2362 if ((storedHash == null || storedHash.hash.length == 0) && credential.isNone()) { 2363 // don't need to pass empty credentials to GateKeeper 2364 return VerifyCredentialResponse.OK; 2365 } 2366 2367 if (storedHash == null || storedHash.hash.length == 0 || credential.isNone()) { 2368 return VerifyCredentialResponse.ERROR; 2369 } 2370 2371 // We're potentially going to be doing a bunch of disk I/O below as part 2372 // of unlocking the user, so yell if calling from the main thread. 2373 StrictMode.noteDiskRead(); 2374 2375 GateKeeperResponse gateKeeperResponse; 2376 try { 2377 gateKeeperResponse = getGateKeeperService().verifyChallenge( 2378 userId, 0L /* challenge */, storedHash.hash, credential.getCredential()); 2379 } catch (RemoteException e) { 2380 Slog.e(TAG, "gatekeeper verify failed", e); 2381 gateKeeperResponse = GateKeeperResponse.ERROR; 2382 } 2383 VerifyCredentialResponse response = convertResponse(gateKeeperResponse); 2384 boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll(); 2385 2386 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2387 2388 // credential has matched 2389 2390 if (progressCallback != null) { 2391 try { 2392 progressCallback.onCredentialVerified(); 2393 } catch (RemoteException e) { 2394 Slog.w(TAG, "progressCallback throws exception", e); 2395 } 2396 } 2397 setUserPasswordMetrics(credential, userId); 2398 unlockKeystore(credential.getCredential(), userId); 2399 2400 Slog.i(TAG, "Unlocking user " + userId); 2401 unlockUser(userId, secretFromCredential(credential)); 2402 2403 if (isProfileWithSeparatedLock(userId)) { 2404 setDeviceUnlockedForUser(userId); 2405 } 2406 if (shouldReEnroll) { 2407 setLockCredentialInternal(credential, credential, 2408 userId, /* isLockTiedToParent= */ false); 2409 } else { 2410 // Now that we've cleared of all required GK migration, let's do the final 2411 // migration to synthetic password. 2412 synchronized (mSpManager) { 2413 if (shouldMigrateToSyntheticPasswordLocked(userId)) { 2414 AuthenticationToken auth = initializeSyntheticPasswordLocked( 2415 storedHash.hash, credential, userId); 2416 activateEscrowTokens(auth, userId); 2417 } 2418 } 2419 } 2420 // Use credentials to create recoverable keystore snapshot. 2421 sendCredentialsOnUnlockIfRequired(credential, userId); 2422 2423 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 2424 if (response.getTimeout() > 0) { 2425 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); 2426 } 2427 } 2428 2429 return response; 2430 } 2431 2432 /** 2433 * Keep track of the given user's latest password metric. This should be called 2434 * when the user is authenticating or when a new password is being set. In comparison, 2435 * {@link #notifyPasswordChanged} only needs to be called when the user changes the password. 2436 */ setUserPasswordMetrics(LockscreenCredential password, @UserIdInt int userHandle)2437 private void setUserPasswordMetrics(LockscreenCredential password, @UserIdInt int userHandle) { 2438 synchronized (this) { 2439 mUserPasswordMetrics.put(userHandle, PasswordMetrics.computeForCredential(password)); 2440 } 2441 } 2442 2443 @VisibleForTesting getUserPasswordMetrics(int userHandle)2444 PasswordMetrics getUserPasswordMetrics(int userHandle) { 2445 if (!isUserSecure(userHandle)) { 2446 // for users without password, mUserPasswordMetrics might not be initialized 2447 // since the user never unlock the device manually. In this case, always 2448 // return a default metrics object. This is to distinguish this case from 2449 // the case where during boot user password is unknown yet (returning null here) 2450 return new PasswordMetrics(CREDENTIAL_TYPE_NONE); 2451 } 2452 synchronized (this) { 2453 return mUserPasswordMetrics.get(userHandle); 2454 } 2455 } 2456 loadPasswordMetrics(AuthenticationToken auth, int userHandle)2457 private PasswordMetrics loadPasswordMetrics(AuthenticationToken auth, int userHandle) { 2458 synchronized (mSpManager) { 2459 return mSpManager.getPasswordMetrics(auth, getSyntheticPasswordHandleLocked(userHandle), 2460 userHandle); 2461 } 2462 } 2463 2464 /** 2465 * Call after {@link #setUserPasswordMetrics} so metrics are updated before 2466 * reporting the password changed. 2467 */ notifyPasswordChanged(LockscreenCredential newCredential, @UserIdInt int userId)2468 private void notifyPasswordChanged(LockscreenCredential newCredential, @UserIdInt int userId) { 2469 mHandler.post(() -> { 2470 mInjector.getDevicePolicyManager().reportPasswordChanged( 2471 PasswordMetrics.computeForCredential(newCredential), 2472 userId); 2473 LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId); 2474 }); 2475 } 2476 removeUser(int userId, boolean unknownUser)2477 private void removeUser(int userId, boolean unknownUser) { 2478 Slog.i(TAG, "RemoveUser: " + userId); 2479 removeBiometricsForUser(userId); 2480 mSpManager.removeUser(getGateKeeperService(), userId); 2481 mStrongAuth.removeUser(userId); 2482 2483 AndroidKeyStoreMaintenance.onUserRemoved(userId); 2484 mManagedProfilePasswordCache.removePassword(userId); 2485 2486 gateKeeperClearSecureUserId(userId); 2487 if (unknownUser || isCredentialSharableWithParent(userId)) { 2488 removeKeystoreProfileKey(userId); 2489 } 2490 // Clean up storage last, this is to ensure that cleanupDataForReusedUserIdIfNecessary() 2491 // can make the assumption that no USER_SERIAL_NUMBER_KEY means user is fully removed. 2492 mStorage.removeUser(userId); 2493 } 2494 removeKeystoreProfileKey(int targetUserId)2495 private void removeKeystoreProfileKey(int targetUserId) { 2496 Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId); 2497 try { 2498 mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId); 2499 mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId); 2500 } catch (KeyStoreException e) { 2501 // We have tried our best to remove all keys 2502 Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e); 2503 } 2504 } 2505 2506 @Override registerStrongAuthTracker(IStrongAuthTracker tracker)2507 public void registerStrongAuthTracker(IStrongAuthTracker tracker) { 2508 checkPasswordReadPermission(); 2509 mStrongAuth.registerStrongAuthTracker(tracker); 2510 } 2511 2512 @Override unregisterStrongAuthTracker(IStrongAuthTracker tracker)2513 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) { 2514 checkPasswordReadPermission(); 2515 mStrongAuth.unregisterStrongAuthTracker(tracker); 2516 } 2517 2518 @Override requireStrongAuth(int strongAuthReason, int userId)2519 public void requireStrongAuth(int strongAuthReason, int userId) { 2520 checkWritePermission(userId); 2521 mStrongAuth.requireStrongAuth(strongAuthReason, userId); 2522 } 2523 2524 @Override reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId)2525 public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) { 2526 checkBiometricPermission(); 2527 mStrongAuth.reportSuccessfulBiometricUnlock(isStrongBiometric, userId); 2528 } 2529 2530 @Override scheduleNonStrongBiometricIdleTimeout(int userId)2531 public void scheduleNonStrongBiometricIdleTimeout(int userId) { 2532 checkBiometricPermission(); 2533 mStrongAuth.scheduleNonStrongBiometricIdleTimeout(userId); 2534 } 2535 2536 @Override userPresent(int userId)2537 public void userPresent(int userId) { 2538 checkWritePermission(userId); 2539 mStrongAuth.reportUnlock(userId); 2540 } 2541 2542 @Override getStrongAuthForUser(int userId)2543 public int getStrongAuthForUser(int userId) { 2544 checkPasswordReadPermission(); 2545 return mStrongAuthTracker.getStrongAuthForUser(userId); 2546 } 2547 isCallerShell()2548 private boolean isCallerShell() { 2549 final int callingUid = Binder.getCallingUid(); 2550 return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; 2551 } 2552 enforceShell()2553 private void enforceShell() { 2554 if (!isCallerShell()) { 2555 throw new SecurityException("Caller must be shell"); 2556 } 2557 } 2558 2559 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2560 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 2561 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 2562 enforceShell(); 2563 final int origPid = Binder.getCallingPid(); 2564 final int origUid = Binder.getCallingUid(); 2565 2566 // The original identity is an opaque integer. 2567 final long origId = Binder.clearCallingIdentity(); 2568 Slog.e(TAG, "Caller pid " + origPid + " Caller uid " + origUid); 2569 try { 2570 final LockSettingsShellCommand command = 2571 new LockSettingsShellCommand(new LockPatternUtils(mContext), mContext, origPid, 2572 origUid); 2573 command.exec(this, in, out, err, args, callback, resultReceiver); 2574 } finally { 2575 Binder.restoreCallingIdentity(origId); 2576 } 2577 } 2578 2579 @Override initRecoveryServiceWithSigFile(@onNull String rootCertificateAlias, @NonNull byte[] recoveryServiceCertFile, @NonNull byte[] recoveryServiceSigFile)2580 public void initRecoveryServiceWithSigFile(@NonNull String rootCertificateAlias, 2581 @NonNull byte[] recoveryServiceCertFile, @NonNull byte[] recoveryServiceSigFile) 2582 throws RemoteException { 2583 mRecoverableKeyStoreManager.initRecoveryServiceWithSigFile(rootCertificateAlias, 2584 recoveryServiceCertFile, recoveryServiceSigFile); 2585 } 2586 2587 @Override getKeyChainSnapshot()2588 public @NonNull KeyChainSnapshot getKeyChainSnapshot() throws RemoteException { 2589 return mRecoverableKeyStoreManager.getKeyChainSnapshot(); 2590 } 2591 2592 @Override setSnapshotCreatedPendingIntent(@ullable PendingIntent intent)2593 public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent) 2594 throws RemoteException { 2595 mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent); 2596 } 2597 2598 @Override setServerParams(byte[] serverParams)2599 public void setServerParams(byte[] serverParams) throws RemoteException { 2600 mRecoverableKeyStoreManager.setServerParams(serverParams); 2601 } 2602 2603 @Override setRecoveryStatus(String alias, int status)2604 public void setRecoveryStatus(String alias, int status) throws RemoteException { 2605 mRecoverableKeyStoreManager.setRecoveryStatus(alias, status); 2606 } 2607 2608 @Override getRecoveryStatus()2609 public @NonNull Map getRecoveryStatus() throws RemoteException { 2610 return mRecoverableKeyStoreManager.getRecoveryStatus(); 2611 } 2612 2613 @Override setRecoverySecretTypes(@onNull @eyChainProtectionParams.UserSecretType int[] secretTypes)2614 public void setRecoverySecretTypes(@NonNull @KeyChainProtectionParams.UserSecretType 2615 int[] secretTypes) throws RemoteException { 2616 mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes); 2617 } 2618 2619 @Override getRecoverySecretTypes()2620 public @NonNull int[] getRecoverySecretTypes() throws RemoteException { 2621 return mRecoverableKeyStoreManager.getRecoverySecretTypes(); 2622 2623 } 2624 2625 @Override startRecoverySessionWithCertPath(@onNull String sessionId, @NonNull String rootCertificateAlias, @NonNull RecoveryCertPath verifierCertPath, @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge, @NonNull List<KeyChainProtectionParams> secrets)2626 public @NonNull byte[] startRecoverySessionWithCertPath(@NonNull String sessionId, 2627 @NonNull String rootCertificateAlias, @NonNull RecoveryCertPath verifierCertPath, 2628 @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge, 2629 @NonNull List<KeyChainProtectionParams> secrets) 2630 throws RemoteException { 2631 return mRecoverableKeyStoreManager.startRecoverySessionWithCertPath( 2632 sessionId, rootCertificateAlias, verifierCertPath, vaultParams, vaultChallenge, 2633 secrets); 2634 } 2635 2636 @Override recoverKeyChainSnapshot( @onNull String sessionId, @NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys)2637 public Map<String, String> recoverKeyChainSnapshot( 2638 @NonNull String sessionId, 2639 @NonNull byte[] recoveryKeyBlob, 2640 @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException { 2641 return mRecoverableKeyStoreManager.recoverKeyChainSnapshot( 2642 sessionId, recoveryKeyBlob, applicationKeys); 2643 } 2644 2645 @Override closeSession(@onNull String sessionId)2646 public void closeSession(@NonNull String sessionId) throws RemoteException { 2647 mRecoverableKeyStoreManager.closeSession(sessionId); 2648 } 2649 2650 @Override removeKey(@onNull String alias)2651 public void removeKey(@NonNull String alias) throws RemoteException { 2652 mRecoverableKeyStoreManager.removeKey(alias); 2653 } 2654 2655 @Override generateKey(@onNull String alias)2656 public @Nullable String generateKey(@NonNull String alias) throws RemoteException { 2657 return mRecoverableKeyStoreManager.generateKey(alias); 2658 } 2659 2660 @Override generateKeyWithMetadata( @onNull String alias, @Nullable byte[] metadata)2661 public @Nullable String generateKeyWithMetadata( 2662 @NonNull String alias, @Nullable byte[] metadata) throws RemoteException { 2663 return mRecoverableKeyStoreManager.generateKeyWithMetadata(alias, metadata); 2664 } 2665 2666 @Override importKey(@onNull String alias, @NonNull byte[] keyBytes)2667 public @Nullable String importKey(@NonNull String alias, @NonNull byte[] keyBytes) 2668 throws RemoteException { 2669 return mRecoverableKeyStoreManager.importKey(alias, keyBytes); 2670 } 2671 2672 @Override importKeyWithMetadata(@onNull String alias, @NonNull byte[] keyBytes, @Nullable byte[] metadata)2673 public @Nullable String importKeyWithMetadata(@NonNull String alias, @NonNull byte[] keyBytes, 2674 @Nullable byte[] metadata) throws RemoteException { 2675 return mRecoverableKeyStoreManager.importKeyWithMetadata(alias, keyBytes, metadata); 2676 } 2677 2678 @Override getKey(@onNull String alias)2679 public @Nullable String getKey(@NonNull String alias) throws RemoteException { 2680 return mRecoverableKeyStoreManager.getKey(alias); 2681 } 2682 2683 private static final String[] VALID_SETTINGS = new String[] { 2684 LockPatternUtils.LOCKOUT_PERMANENT_KEY, 2685 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, 2686 LockPatternUtils.PASSWORD_TYPE_KEY, 2687 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 2688 LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 2689 LockPatternUtils.DISABLE_LOCKSCREEN_KEY, 2690 LockPatternUtils.LOCKSCREEN_OPTIONS, 2691 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, 2692 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY, 2693 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, 2694 LockPatternUtils.PASSWORD_HISTORY_KEY, 2695 Secure.LOCK_PATTERN_ENABLED, 2696 Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 2697 Secure.LOCK_PATTERN_VISIBLE, 2698 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED 2699 }; 2700 2701 // Reading these settings needs the contacts permission 2702 private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] { 2703 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 2704 Secure.LOCK_SCREEN_OWNER_INFO 2705 }; 2706 2707 // Reading these settings needs the same permission as checking the password 2708 private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] { 2709 LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 2710 LockPatternUtils.PASSWORD_HISTORY_KEY, 2711 LockPatternUtils.PASSWORD_TYPE_KEY, 2712 SEPARATE_PROFILE_CHALLENGE_KEY 2713 }; 2714 2715 private class GateKeeperDiedRecipient implements IBinder.DeathRecipient { 2716 @Override binderDied()2717 public void binderDied() { 2718 mGateKeeperService.asBinder().unlinkToDeath(this, 0); 2719 mGateKeeperService = null; 2720 } 2721 } 2722 getGateKeeperService()2723 protected synchronized IGateKeeperService getGateKeeperService() { 2724 if (mGateKeeperService != null) { 2725 return mGateKeeperService; 2726 } 2727 2728 final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE); 2729 if (service != null) { 2730 try { 2731 service.linkToDeath(new GateKeeperDiedRecipient(), 0); 2732 } catch (RemoteException e) { 2733 Slog.w(TAG, " Unable to register death recipient", e); 2734 } 2735 mGateKeeperService = IGateKeeperService.Stub.asInterface(service); 2736 return mGateKeeperService; 2737 } 2738 2739 Slog.e(TAG, "Unable to acquire GateKeeperService"); 2740 return null; 2741 } 2742 gateKeeperClearSecureUserId(int userId)2743 private void gateKeeperClearSecureUserId(int userId) { 2744 try { 2745 getGateKeeperService().clearSecureUserId(userId); 2746 } catch (RemoteException e) { 2747 Slog.w(TAG, "Failed to clear SID", e); 2748 } 2749 } 2750 onAuthTokenKnownForUser(@serIdInt int userId, AuthenticationToken auth)2751 private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) { 2752 if (mInjector.isGsiRunning()) { 2753 Slog.w(TAG, "Running in GSI; skipping calls to AuthSecret and RebootEscrow"); 2754 return; 2755 } 2756 2757 mRebootEscrowManager.callToRebootEscrowIfNeeded(userId, auth.getVersion(), 2758 auth.getSyntheticPassword()); 2759 2760 callToAuthSecretIfNeeded(userId, auth); 2761 } 2762 callToAuthSecretIfNeeded(@serIdInt int userId, AuthenticationToken auth)2763 private void callToAuthSecretIfNeeded(@UserIdInt int userId, 2764 AuthenticationToken auth) { 2765 // Pass the primary user's auth secret to the HAL 2766 if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) { 2767 try { 2768 final byte[] rawSecret = auth.deriveVendorAuthSecret(); 2769 final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length); 2770 for (int i = 0; i < rawSecret.length; ++i) { 2771 secret.add(rawSecret[i]); 2772 } 2773 mAuthSecretService.primaryUserCredential(secret); 2774 } catch (RemoteException e) { 2775 Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e); 2776 } 2777 } 2778 } 2779 2780 /** 2781 * Precondition: vold and keystore unlocked. 2782 * 2783 * Create new synthetic password, set up synthetic password blob protected by the supplied 2784 * user credential, and make the newly-created SP blob active. 2785 * 2786 * The invariant under a synthetic password is: 2787 * 1. If user credential exists, then both vold and keystore and protected with keys derived 2788 * from the synthetic password. 2789 * 2. If user credential does not exist, vold and keystore protection are cleared. This is to 2790 * make it consistent with current behaviour. It also allows ActivityManager to call 2791 * unlockUser() with empty secret. 2792 * 3. Once a user is migrated to have synthetic password, its value will never change, no matter 2793 * whether the user changes their lockscreen PIN or clear/reset it. When the user clears its 2794 * lockscreen PIN, we still maintain the existing synthetic password in a password blob 2795 * protected by a default PIN. 2796 * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user 2797 * clears/re-creates their lockscreen PIN. 2798 * 2799 * 2800 * Different cases of calling this method: 2801 * 1. credentialHash != null 2802 * This implies credential != null, a new SP blob will be provisioned, and existing SID 2803 * migrated to associate with the new SP. 2804 * This happens during a normal migration case when the user currently has password. 2805 * 2806 * 2. credentialhash == null and credential == null 2807 * A new SP blob and will be created, while the user has no credentials. 2808 * This can happens when we are activating an escrow token on a unsecured device, during 2809 * which we want to create the SP structure with an empty user credential. 2810 * This could also happen during an untrusted reset to clear password. 2811 * 2812 * 3. credentialhash == null and credential != null 2813 * The user sets a new lockscreen password FOR THE FIRST TIME on a SP-enabled device. 2814 * New credential and new SID will be created 2815 */ 2816 @GuardedBy("mSpManager") 2817 @VisibleForTesting initializeSyntheticPasswordLocked(byte[] credentialHash, LockscreenCredential credential, int userId)2818 protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash, 2819 LockscreenCredential credential, int userId) { 2820 Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId); 2821 Preconditions.checkState( 2822 getSyntheticPasswordHandleLocked(userId) == SyntheticPasswordManager.DEFAULT_HANDLE, 2823 "Cannot reinitialize SP"); 2824 2825 final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid( 2826 getGateKeeperService(), credentialHash, credential, userId); 2827 if (auth == null) { 2828 Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token"); 2829 return null; 2830 } 2831 long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(), 2832 credential, auth, userId); 2833 if (!credential.isNone()) { 2834 if (credentialHash == null) { 2835 // Since when initializing SP, we didn't provide an existing password handle 2836 // for it to migrate SID, we need to create a new SID for the user. 2837 mSpManager.newSidForUser(getGateKeeperService(), auth, userId); 2838 } 2839 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 2840 setUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); 2841 setKeystorePassword(auth.deriveKeyStorePassword(), userId); 2842 } else { 2843 clearUserKeyProtection(userId, null); 2844 setKeystorePassword(null, userId); 2845 gateKeeperClearSecureUserId(userId); 2846 } 2847 fixateNewestUserKeyAuth(userId); 2848 setSyntheticPasswordHandleLocked(handle, userId); 2849 onAuthTokenKnownForUser(userId, auth); 2850 return auth; 2851 } 2852 2853 @VisibleForTesting getSyntheticPasswordHandleLocked(int userId)2854 long getSyntheticPasswordHandleLocked(int userId) { 2855 return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 2856 SyntheticPasswordManager.DEFAULT_HANDLE, userId); 2857 } 2858 setSyntheticPasswordHandleLocked(long handle, int userId)2859 private void setSyntheticPasswordHandleLocked(long handle, int userId) { 2860 final long oldHandle = getSyntheticPasswordHandleLocked(userId); 2861 setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId); 2862 setLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, oldHandle, userId); 2863 setLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, System.currentTimeMillis(), userId); 2864 2865 } 2866 2867 @VisibleForTesting isSyntheticPasswordBasedCredential(int userId)2868 boolean isSyntheticPasswordBasedCredential(int userId) { 2869 synchronized (mSpManager) { 2870 return isSyntheticPasswordBasedCredentialLocked(userId); 2871 } 2872 } 2873 isSyntheticPasswordBasedCredentialLocked(int userId)2874 private boolean isSyntheticPasswordBasedCredentialLocked(int userId) { 2875 if (userId == USER_FRP) { 2876 final int type = mStorage.readPersistentDataBlock().type; 2877 return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER; 2878 } 2879 long handle = getSyntheticPasswordHandleLocked(userId); 2880 return handle != SyntheticPasswordManager.DEFAULT_HANDLE; 2881 } 2882 2883 @VisibleForTesting shouldMigrateToSyntheticPasswordLocked(int userId)2884 protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) { 2885 return getSyntheticPasswordHandleLocked(userId) == SyntheticPasswordManager.DEFAULT_HANDLE; 2886 } 2887 spBasedDoVerifyCredential(LockscreenCredential userCredential, int userId, ICheckCredentialProgressCallback progressCallback, @LockPatternUtils.VerifyFlag int flags)2888 private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential, 2889 int userId, ICheckCredentialProgressCallback progressCallback, 2890 @LockPatternUtils.VerifyFlag int flags) { 2891 final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId); 2892 2893 Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId 2894 + " hasEnrolledBiometrics=" + hasEnrolledBiometrics); 2895 2896 final AuthenticationResult authResult; 2897 VerifyCredentialResponse response; 2898 final boolean requestGkPw = (flags & VERIFY_FLAG_REQUEST_GK_PW_HANDLE) != 0; 2899 2900 synchronized (mSpManager) { 2901 if (!isSyntheticPasswordBasedCredentialLocked(userId)) { 2902 return null; 2903 } 2904 if (userId == USER_FRP) { 2905 return mSpManager.verifyFrpCredential(getGateKeeperService(), 2906 userCredential, progressCallback); 2907 } 2908 2909 long handle = getSyntheticPasswordHandleLocked(userId); 2910 authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( 2911 getGateKeeperService(), handle, userCredential, userId, progressCallback); 2912 response = authResult.gkResponse; 2913 2914 // credential has matched 2915 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2916 mBiometricDeferredQueue.addPendingLockoutResetForUser(userId, 2917 authResult.authToken.deriveGkPassword()); 2918 2919 // perform verifyChallenge with synthetic password which generates the real GK auth 2920 // token and response for the current user 2921 response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, 2922 0L /* challenge */, userId); 2923 if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 2924 // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't 2925 // match the recorded GK password handle. 2926 Slog.wtf(TAG, "verifyChallenge with SP failed."); 2927 return VerifyCredentialResponse.ERROR; 2928 } 2929 } 2930 } 2931 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2932 onCredentialVerified(authResult.authToken, 2933 PasswordMetrics.computeForCredential(userCredential), userId); 2934 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 2935 if (response.getTimeout() > 0) { 2936 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); 2937 } 2938 } 2939 2940 if (response.isMatched() && requestGkPw) { 2941 final long handle = storeGatekeeperPasswordTemporarily( 2942 authResult.authToken.deriveGkPassword()); 2943 return new VerifyCredentialResponse.Builder().setGatekeeperPasswordHandle(handle) 2944 .build(); 2945 } else { 2946 return response; 2947 } 2948 } 2949 2950 /** 2951 * Stores the gatekeeper password temporarily. 2952 * @param gatekeeperPassword unlocked upon successful Synthetic Password 2953 * @return non-zero handle to the gatekeeper password, which can be used for a set amount of 2954 * time. 2955 */ storeGatekeeperPasswordTemporarily(byte[] gatekeeperPassword)2956 private long storeGatekeeperPasswordTemporarily(byte[] gatekeeperPassword) { 2957 long handle = 0L; 2958 2959 synchronized (mGatekeeperPasswords) { 2960 while (handle == 0L || mGatekeeperPasswords.get(handle) != null) { 2961 handle = mRandom.nextLong(); 2962 } 2963 mGatekeeperPasswords.put(handle, gatekeeperPassword); 2964 } 2965 2966 final long finalHandle = handle; 2967 mHandler.postDelayed(() -> { 2968 synchronized (mGatekeeperPasswords) { 2969 Slog.d(TAG, "Removing handle: " + finalHandle); 2970 mGatekeeperPasswords.remove(finalHandle); 2971 } 2972 }, GK_PW_HANDLE_STORE_DURATION_MS); 2973 2974 return handle; 2975 } 2976 onCredentialVerified(AuthenticationToken authToken, PasswordMetrics metrics, int userId)2977 private void onCredentialVerified(AuthenticationToken authToken, PasswordMetrics metrics, 2978 int userId) { 2979 2980 if (metrics != null) { 2981 synchronized (this) { 2982 mUserPasswordMetrics.put(userId, metrics); 2983 } 2984 } else { 2985 Slog.wtf(TAG, "Null metrics after credential verification"); 2986 } 2987 2988 unlockKeystore(authToken.deriveKeyStorePassword(), userId); 2989 2990 { 2991 final byte[] secret = authToken.deriveDiskEncryptionKey(); 2992 unlockUser(userId, secret); 2993 Arrays.fill(secret, (byte) 0); 2994 } 2995 activateEscrowTokens(authToken, userId); 2996 2997 if (isProfileWithSeparatedLock(userId)) { 2998 setDeviceUnlockedForUser(userId); 2999 } 3000 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); 3001 3002 onAuthTokenKnownForUser(userId, authToken); 3003 } 3004 setDeviceUnlockedForUser(int userId)3005 private void setDeviceUnlockedForUser(int userId) { 3006 final TrustManager trustManager = mContext.getSystemService(TrustManager.class); 3007 trustManager.setDeviceLockedForUser(userId, false); 3008 } 3009 3010 /** 3011 * Change the user's lockscreen password by creating a new SP blob and update the handle, based 3012 * on an existing authentication token. Even though a new SP blob is created, the underlying 3013 * synthetic password is never changed. 3014 * 3015 * When clearing credential, we keep the SP unchanged, but clear its password handle so its 3016 * SID is gone. We also clear password from (software-based) keystore and vold, which will be 3017 * added back when new password is set in future. 3018 */ 3019 @GuardedBy("mSpManager") setLockCredentialWithAuthTokenLocked(LockscreenCredential credential, AuthenticationToken auth, int userId)3020 private long setLockCredentialWithAuthTokenLocked(LockscreenCredential credential, 3021 AuthenticationToken auth, int userId) { 3022 if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId); 3023 final int savedCredentialType = getCredentialTypeInternal(userId); 3024 long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(), 3025 credential, auth, userId); 3026 final Map<Integer, LockscreenCredential> profilePasswords; 3027 if (!credential.isNone()) { 3028 // not needed by synchronizeUnifiedWorkChallengeForProfiles() 3029 profilePasswords = null; 3030 3031 if (mSpManager.hasSidForUser(userId)) { 3032 // We are changing password of a secured device, nothing more needed as 3033 // createPasswordBasedSyntheticPassword has already taken care of maintaining 3034 // the password handle and SID unchanged. 3035 3036 //refresh auth token 3037 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 3038 } else { 3039 // A new password is set on a previously-unsecured device, we need to generate 3040 // a new SID, and re-add keys to vold and keystore. 3041 mSpManager.newSidForUser(getGateKeeperService(), auth, userId); 3042 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 3043 setUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); 3044 fixateNewestUserKeyAuth(userId); 3045 setKeystorePassword(auth.deriveKeyStorePassword(), userId); 3046 } 3047 } else { 3048 // Cache all profile password if they use unified work challenge. This will later be 3049 // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles() 3050 profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId); 3051 3052 // we are clearing password of a secured device, so need to nuke SID as well. 3053 mSpManager.clearSidForUser(userId); 3054 gateKeeperClearSecureUserId(userId); 3055 // Clear key from vold so ActivityManager can just unlock the user with empty secret 3056 // during boot. Vold storage needs to be unlocked before manipulation of the keys can 3057 // succeed. 3058 unlockUserKey(userId, auth.deriveDiskEncryptionKey()); 3059 clearUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); 3060 fixateNewestUserKeyAuth(userId); 3061 unlockKeystore(auth.deriveKeyStorePassword(), userId); 3062 setKeystorePassword(null, userId); 3063 removeBiometricsForUser(userId); 3064 } 3065 setSyntheticPasswordHandleLocked(newHandle, userId); 3066 synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords); 3067 3068 setUserPasswordMetrics(credential, userId); 3069 mManagedProfilePasswordCache.removePassword(userId); 3070 if (savedCredentialType != CREDENTIAL_TYPE_NONE) { 3071 mSpManager.destroyAllWeakTokenBasedSyntheticPasswords(userId); 3072 } 3073 3074 if (profilePasswords != null) { 3075 for (Map.Entry<Integer, LockscreenCredential> entry : profilePasswords.entrySet()) { 3076 entry.getValue().zeroize(); 3077 } 3078 } 3079 3080 return newHandle; 3081 } 3082 removeBiometricsForUser(int userId)3083 private void removeBiometricsForUser(int userId) { 3084 removeAllFingerprintForUser(userId); 3085 removeAllFaceForUser(userId); 3086 } 3087 removeAllFingerprintForUser(final int userId)3088 private void removeAllFingerprintForUser(final int userId) { 3089 FingerprintManager mFingerprintManager = mInjector.getFingerprintManager(); 3090 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) { 3091 if (mFingerprintManager.hasEnrolledFingerprints(userId)) { 3092 final CountDownLatch latch = new CountDownLatch(1); 3093 mFingerprintManager.removeAll(userId, fingerprintManagerRemovalCallback(latch)); 3094 try { 3095 latch.await(10000, TimeUnit.MILLISECONDS); 3096 } catch (InterruptedException e) { 3097 Slog.e(TAG, "Latch interrupted when removing fingerprint", e); 3098 } 3099 } 3100 } 3101 } 3102 removeAllFaceForUser(final int userId)3103 private void removeAllFaceForUser(final int userId) { 3104 FaceManager mFaceManager = mInjector.getFaceManager(); 3105 if (mFaceManager != null && mFaceManager.isHardwareDetected()) { 3106 if (mFaceManager.hasEnrolledTemplates(userId)) { 3107 final CountDownLatch latch = new CountDownLatch(1); 3108 mFaceManager.removeAll(userId, faceManagerRemovalCallback(latch)); 3109 try { 3110 latch.await(10000, TimeUnit.MILLISECONDS); 3111 } catch (InterruptedException e) { 3112 Slog.e(TAG, "Latch interrupted when removing face", e); 3113 } 3114 } 3115 } 3116 } 3117 fingerprintManagerRemovalCallback( CountDownLatch latch)3118 private FingerprintManager.RemovalCallback fingerprintManagerRemovalCallback( 3119 CountDownLatch latch) { 3120 return new FingerprintManager.RemovalCallback() { 3121 @Override 3122 public void onRemovalError(@Nullable Fingerprint fp, int errMsgId, CharSequence err) { 3123 Slog.e(TAG, "Unable to remove fingerprint, error: " + err); 3124 latch.countDown(); 3125 } 3126 3127 @Override 3128 public void onRemovalSucceeded(Fingerprint fp, int remaining) { 3129 if (remaining == 0) { 3130 latch.countDown(); 3131 } 3132 } 3133 }; 3134 } 3135 3136 private FaceManager.RemovalCallback faceManagerRemovalCallback(CountDownLatch latch) { 3137 return new FaceManager.RemovalCallback() { 3138 @Override 3139 public void onRemovalError(@Nullable Face face, int errMsgId, CharSequence err) { 3140 Slog.e(TAG, "Unable to remove face, error: " + err); 3141 latch.countDown(); 3142 } 3143 3144 @Override 3145 public void onRemovalSucceeded(Face face, int remaining) { 3146 if (remaining == 0) { 3147 latch.countDown(); 3148 } 3149 } 3150 }; 3151 } 3152 3153 /** 3154 * @param savedCredential if the user is a profile with unified challenge and 3155 * savedCredential is empty, LSS will try to re-derive the profile password internally. 3156 * TODO (b/80170828): Fix this so profile password is always passed in. 3157 */ 3158 @GuardedBy("mSpManager") 3159 private boolean spBasedSetLockCredentialInternalLocked(LockscreenCredential credential, 3160 LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) { 3161 if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId); 3162 if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) { 3163 // get credential from keystore when profile has unified lock 3164 try { 3165 //TODO: remove as part of b/80170828 3166 savedCredential = getDecryptedPasswordForTiedProfile(userId); 3167 } catch (FileNotFoundException e) { 3168 Slog.i(TAG, "Child profile key not found"); 3169 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 3170 | NoSuchAlgorithmException | NoSuchPaddingException 3171 | InvalidAlgorithmParameterException | IllegalBlockSizeException 3172 | BadPaddingException | CertificateException | IOException e) { 3173 Slog.e(TAG, "Failed to decrypt child profile key", e); 3174 } 3175 } 3176 long handle = getSyntheticPasswordHandleLocked(userId); 3177 AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( 3178 getGateKeeperService(), handle, savedCredential, userId, null); 3179 VerifyCredentialResponse response = authResult.gkResponse; 3180 AuthenticationToken auth = authResult.authToken; 3181 3182 if (auth == null) { 3183 if (response == null 3184 || response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { 3185 Slog.w(TAG, "Failed to enroll: incorrect credential."); 3186 return false; 3187 } 3188 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 3189 Slog.w(TAG, "Failed to enroll: rate limit exceeded."); 3190 return false; 3191 } 3192 // Should not be reachable, but just in case. 3193 throw new IllegalStateException("password change failed"); 3194 } 3195 3196 onAuthTokenKnownForUser(userId, auth); 3197 setLockCredentialWithAuthTokenLocked(credential, auth, userId); 3198 mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); 3199 sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent); 3200 return true; 3201 } 3202 3203 /** 3204 * Returns a fixed pseudorandom byte string derived from the user's synthetic password. 3205 * This is used to salt the password history hash to protect the hash against offline 3206 * bruteforcing, since rederiving this value requires a successful authentication. 3207 * If user is a profile with {@link UserManager#isCredentialSharableWithParent()} true and with 3208 * unified challenge, currentCredential is ignored. 3209 */ 3210 @Override 3211 public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) { 3212 checkPasswordReadPermission(); 3213 try { 3214 if (isProfileWithUnifiedLock(userId)) { 3215 try { 3216 currentCredential = getDecryptedPasswordForTiedProfile(userId); 3217 } catch (Exception e) { 3218 Slog.e(TAG, "Failed to get work profile credential", e); 3219 return null; 3220 } 3221 } 3222 synchronized (mSpManager) { 3223 if (!isSyntheticPasswordBasedCredentialLocked(userId)) { 3224 Slog.w(TAG, "Synthetic password not enabled"); 3225 return null; 3226 } 3227 long handle = getSyntheticPasswordHandleLocked(userId); 3228 AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword( 3229 getGateKeeperService(), handle, currentCredential, userId, null); 3230 if (auth.authToken == null) { 3231 Slog.w(TAG, "Current credential is incorrect"); 3232 return null; 3233 } 3234 return auth.authToken.derivePasswordHashFactor(); 3235 } 3236 } finally { 3237 scheduleGc(); 3238 } 3239 } 3240 3241 private long addEscrowToken(@NonNull byte[] token, @TokenType int type, int userId, 3242 @NonNull EscrowTokenStateChangeCallback callback) { 3243 if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type); 3244 synchronized (mSpManager) { 3245 // Migrate to synthetic password based credentials if the user has no password, 3246 // the token can then be activated immediately. 3247 AuthenticationToken auth = null; 3248 if (!isUserSecure(userId)) { 3249 if (shouldMigrateToSyntheticPasswordLocked(userId)) { 3250 auth = initializeSyntheticPasswordLocked( 3251 /* credentialHash */ null, LockscreenCredential.createNone(), userId); 3252 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ { 3253 long pwdHandle = getSyntheticPasswordHandleLocked(userId); 3254 auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(), 3255 pwdHandle, LockscreenCredential.createNone(), userId, null).authToken; 3256 } 3257 } 3258 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 3259 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); 3260 if (!mSpManager.hasEscrowData(userId)) { 3261 throw new SecurityException("Escrow token is disabled on the current user"); 3262 } 3263 } 3264 long handle = mSpManager.createTokenBasedSyntheticPassword(token, type, userId, 3265 callback); 3266 if (auth != null) { 3267 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); 3268 } 3269 return handle; 3270 } 3271 } 3272 3273 private void activateEscrowTokens(AuthenticationToken auth, int userId) { 3274 if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId); 3275 synchronized (mSpManager) { 3276 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); 3277 for (long handle : mSpManager.getPendingTokensForUser(userId)) { 3278 Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId)); 3279 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); 3280 } 3281 } 3282 } 3283 3284 private boolean isEscrowTokenActive(long handle, int userId) { 3285 synchronized (mSpManager) { 3286 return mSpManager.existsHandle(handle, userId); 3287 } 3288 } 3289 3290 @Override 3291 public boolean hasPendingEscrowToken(int userId) { 3292 checkPasswordReadPermission(); 3293 synchronized (mSpManager) { 3294 return !mSpManager.getPendingTokensForUser(userId).isEmpty(); 3295 } 3296 } 3297 3298 private boolean removeEscrowToken(long handle, int userId) { 3299 synchronized (mSpManager) { 3300 if (handle == getSyntheticPasswordHandleLocked(userId)) { 3301 Slog.w(TAG, "Cannot remove password handle"); 3302 return false; 3303 } 3304 if (mSpManager.removePendingToken(handle, userId)) { 3305 return true; 3306 } 3307 if (mSpManager.existsHandle(handle, userId)) { 3308 mSpManager.destroyTokenBasedSyntheticPassword(handle, userId); 3309 return true; 3310 } else { 3311 return false; 3312 } 3313 } 3314 } 3315 3316 private boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle, 3317 byte[] token, int userId) { 3318 boolean result; 3319 synchronized (mSpManager) { 3320 if (!mSpManager.hasEscrowData(userId)) { 3321 throw new SecurityException("Escrow token is disabled on the current user"); 3322 } 3323 if (!isEscrowTokenActive(tokenHandle, userId)) { 3324 Slog.e(TAG, "Unknown or unactivated token: " + Long.toHexString(tokenHandle)); 3325 return false; 3326 } 3327 result = setLockCredentialWithTokenInternalLocked( 3328 credential, tokenHandle, token, userId); 3329 } 3330 if (result) { 3331 synchronized (mSeparateChallengeLock) { 3332 setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null); 3333 } 3334 if (credential.isNone()) { 3335 // If clearing credential, unlock the user manually in order to progress user start 3336 // Call unlockUser() on a handler thread so no lock is held (either by LSS or by 3337 // the caller like DPMS), otherwise it can lead to deadlock. 3338 mHandler.post(() -> unlockUser(userId, null)); 3339 } 3340 notifyPasswordChanged(credential, userId); 3341 notifySeparateProfileChallengeChanged(userId); 3342 } 3343 return result; 3344 } 3345 3346 @GuardedBy("mSpManager") 3347 private boolean setLockCredentialWithTokenInternalLocked(LockscreenCredential credential, 3348 long tokenHandle, byte[] token, int userId) { 3349 final AuthenticationResult result; 3350 result = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(), tokenHandle, 3351 token, userId); 3352 if (result.authToken == null) { 3353 Slog.w(TAG, "Invalid escrow token supplied"); 3354 return false; 3355 } 3356 if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 3357 // Most likely, an untrusted credential reset happened in the past which 3358 // changed the synthetic password 3359 Slog.e(TAG, "Obsolete token: synthetic password derived but it fails GK " 3360 + "verification."); 3361 return false; 3362 } 3363 onAuthTokenKnownForUser(userId, result.authToken); 3364 long oldHandle = getSyntheticPasswordHandleLocked(userId); 3365 setLockCredentialWithAuthTokenLocked(credential, result.authToken, userId); 3366 mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId); 3367 return true; 3368 } 3369 3370 private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) { 3371 AuthenticationResult authResult; 3372 synchronized (mSpManager) { 3373 if (!mSpManager.hasEscrowData(userId)) { 3374 Slog.w(TAG, "Escrow token is disabled on the current user"); 3375 return false; 3376 } 3377 authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(), 3378 tokenHandle, token, userId); 3379 if (authResult.authToken == null) { 3380 Slog.w(TAG, "Invalid escrow token supplied"); 3381 return false; 3382 } 3383 } 3384 3385 onCredentialVerified(authResult.authToken, 3386 loadPasswordMetrics(authResult.authToken, userId), userId); 3387 return true; 3388 } 3389 3390 @Override 3391 public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { 3392 try (LockscreenCredential cred = mManagedProfilePasswordCache.retrievePassword(userId)) { 3393 if (cred == null) { 3394 return false; 3395 } 3396 return doVerifyCredential(cred, userId, null /* progressCallback */, 0 /* flags */) 3397 .getResponseCode() == VerifyCredentialResponse.RESPONSE_OK; 3398 } 3399 } 3400 3401 @Override 3402 public void removeCachedUnifiedChallenge(int userId) { 3403 mManagedProfilePasswordCache.removePassword(userId); 3404 } 3405 3406 static String timestampToString(long timestamp) { 3407 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp)); 3408 } 3409 3410 private static String credentialTypeToString(int credentialType) { 3411 switch (credentialType) { 3412 case CREDENTIAL_TYPE_NONE: 3413 return "None"; 3414 case CREDENTIAL_TYPE_PATTERN: 3415 return "Pattern"; 3416 case CREDENTIAL_TYPE_PIN: 3417 return "Pin"; 3418 case CREDENTIAL_TYPE_PASSWORD: 3419 return "Password"; 3420 default: 3421 return "Unknown " + credentialType; 3422 } 3423 } 3424 3425 @Override 3426 protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 3427 if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return; 3428 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 3429 3430 pw.println("Current lock settings service state:"); 3431 pw.println(); 3432 3433 pw.println("User State:"); 3434 pw.increaseIndent(); 3435 List<UserInfo> users = mUserManager.getUsers(); 3436 for (int user = 0; user < users.size(); user++) { 3437 final int userId = users.get(user).id; 3438 pw.println("User " + userId); 3439 pw.increaseIndent(); 3440 synchronized (mSpManager) { 3441 pw.println(String.format("SP Handle: %x", 3442 getSyntheticPasswordHandleLocked(userId))); 3443 pw.println(String.format("Last changed: %s (%x)", 3444 timestampToString(getLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, 0, userId)), 3445 getLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId))); 3446 } 3447 try { 3448 pw.println(String.format("SID: %x", 3449 getGateKeeperService().getSecureUserId(userId))); 3450 } catch (RemoteException e) { 3451 // ignore. 3452 } 3453 // It's OK to dump the password type since anyone with physical access can just 3454 // observe it from the keyguard directly. 3455 pw.println("Quality: " + getKeyguardStoredQuality(userId)); 3456 pw.println("CredentialType: " + credentialTypeToString( 3457 getCredentialTypeInternal(userId))); 3458 pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId)); 3459 pw.println(String.format("Metrics: %s", 3460 getUserPasswordMetrics(userId) != null ? "known" : "unknown")); 3461 pw.decreaseIndent(); 3462 } 3463 pw.println(); 3464 pw.decreaseIndent(); 3465 3466 pw.println("Keys in namespace:"); 3467 pw.increaseIndent(); 3468 dumpKeystoreKeys(pw); 3469 pw.println(); 3470 pw.decreaseIndent(); 3471 3472 pw.println("Storage:"); 3473 pw.increaseIndent(); 3474 mStorage.dump(pw); 3475 pw.println(); 3476 pw.decreaseIndent(); 3477 3478 pw.println("StrongAuth:"); 3479 pw.increaseIndent(); 3480 mStrongAuth.dump(pw); 3481 pw.println(); 3482 pw.decreaseIndent(); 3483 3484 pw.println("RebootEscrow:"); 3485 pw.increaseIndent(); 3486 mRebootEscrowManager.dump(pw); 3487 pw.println(); 3488 pw.decreaseIndent(); 3489 3490 pw.println("PasswordHandleCount: " + mGatekeeperPasswords.size()); 3491 } 3492 3493 private void dumpKeystoreKeys(IndentingPrintWriter pw) { 3494 try { 3495 final Enumeration<String> aliases = mJavaKeyStore.aliases(); 3496 while (aliases.hasMoreElements()) { 3497 pw.println(aliases.nextElement()); 3498 } 3499 } catch (KeyStoreException e) { 3500 pw.println("Unable to get keys: " + e.toString()); 3501 Slog.d(TAG, "Dump error", e); 3502 } 3503 } 3504 3505 /** 3506 * Cryptographically disable escrow token support for the current user, if the user is not 3507 * managed (either user has a profile owner, or if device is managed). Do not disable 3508 * if we are running an automotive build. 3509 */ 3510 private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) { 3511 final UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal(); 3512 3513 // Managed profile should have escrow enabled 3514 if (userManagerInternal.isUserManaged(userId)) { 3515 Slog.i(TAG, "Managed profile can have escrow token"); 3516 return; 3517 } 3518 3519 // Devices with Device Owner should have escrow enabled on all users. 3520 if (userManagerInternal.isDeviceManaged()) { 3521 Slog.i(TAG, "Corp-owned device can have escrow token"); 3522 return; 3523 } 3524 3525 // If the device is yet to be provisioned (still in SUW), there is still 3526 // a chance that Device Owner will be set on the device later, so postpone 3527 // disabling escrow token for now. 3528 if (!mInjector.getDeviceStateCache().isDeviceProvisioned()) { 3529 Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned"); 3530 return; 3531 } 3532 3533 // Escrow tokens are enabled on automotive builds. 3534 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 3535 return; 3536 } 3537 3538 // Disable escrow token permanently on all other device/user types. 3539 Slog.i(TAG, "Disabling escrow token on user " + userId); 3540 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 3541 mSpManager.destroyEscrowData(userId); 3542 } 3543 } 3544 3545 /** 3546 * Schedules garbage collection to sanitize lockscreen credential remnants in memory. 3547 * 3548 * One source of leftover lockscreen credentials is the unmarshalled binder method arguments. 3549 * Since this method will be called within the binder implementation method, a small delay is 3550 * added before the GC operation to allow the enclosing binder proxy code to complete and 3551 * release references to the argument. 3552 */ 3553 private void scheduleGc() { 3554 mHandler.postDelayed(() -> { 3555 System.gc(); 3556 System.runFinalization(); 3557 System.gc(); 3558 }, 2000); 3559 } 3560 3561 private class DeviceProvisionedObserver extends ContentObserver { 3562 private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor( 3563 Settings.Global.DEVICE_PROVISIONED); 3564 3565 private boolean mRegistered; 3566 3567 public DeviceProvisionedObserver() { 3568 super(null); 3569 } 3570 3571 @Override 3572 public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) { 3573 if (mDeviceProvisionedUri.equals(uri)) { 3574 updateRegistration(); 3575 3576 if (isProvisioned()) { 3577 Slog.i(TAG, "Reporting device setup complete to IGateKeeperService"); 3578 reportDeviceSetupComplete(); 3579 clearFrpCredentialIfOwnerNotSecure(); 3580 } 3581 } 3582 } 3583 3584 public void onSystemReady() { 3585 if (frpCredentialEnabled(mContext)) { 3586 updateRegistration(); 3587 } else { 3588 // If we don't intend to use frpCredentials and we're not provisioned yet, send 3589 // deviceSetupComplete immediately, so gatekeeper can discard any lingering 3590 // credentials immediately. 3591 if (!isProvisioned()) { 3592 Slog.i(TAG, "FRP credential disabled, reporting device setup complete " 3593 + "to Gatekeeper immediately"); 3594 reportDeviceSetupComplete(); 3595 } 3596 } 3597 } 3598 3599 private void reportDeviceSetupComplete() { 3600 try { 3601 getGateKeeperService().reportDeviceSetupComplete(); 3602 } catch (RemoteException e) { 3603 Slog.e(TAG, "Failure reporting to IGateKeeperService", e); 3604 } 3605 } 3606 3607 /** 3608 * Clears the FRP credential if the user that controls it does not have a secure 3609 * lockscreen. 3610 */ 3611 private void clearFrpCredentialIfOwnerNotSecure() { 3612 List<UserInfo> users = mUserManager.getUsers(); 3613 for (UserInfo user : users) { 3614 if (userOwnsFrpCredential(mContext, user)) { 3615 if (!isUserSecure(user.id)) { 3616 mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id, 3617 0, null); 3618 } 3619 return; 3620 } 3621 } 3622 } 3623 3624 private void updateRegistration() { 3625 boolean register = !isProvisioned(); 3626 if (register == mRegistered) { 3627 return; 3628 } 3629 if (register) { 3630 mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri, 3631 false, this); 3632 } else { 3633 mContext.getContentResolver().unregisterContentObserver(this); 3634 } 3635 mRegistered = register; 3636 } 3637 3638 private boolean isProvisioned() { 3639 return Settings.Global.getInt(mContext.getContentResolver(), 3640 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 3641 } 3642 } 3643 3644 private final class LocalService extends LockSettingsInternal { 3645 3646 @Override 3647 public long addEscrowToken(byte[] token, int userId, 3648 EscrowTokenStateChangeCallback callback) { 3649 return LockSettingsService.this.addEscrowToken(token, TOKEN_TYPE_STRONG, userId, 3650 callback); 3651 } 3652 3653 @Override 3654 public boolean removeEscrowToken(long handle, int userId) { 3655 return LockSettingsService.this.removeEscrowToken(handle, userId); 3656 } 3657 3658 @Override 3659 public boolean isEscrowTokenActive(long handle, int userId) { 3660 return LockSettingsService.this.isEscrowTokenActive(handle, userId); 3661 } 3662 3663 @Override 3664 public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle, 3665 byte[] token, int userId) { 3666 if (!mHasSecureLockScreen 3667 && credential != null && credential.getType() != CREDENTIAL_TYPE_NONE) { 3668 throw new UnsupportedOperationException( 3669 "This operation requires secure lock screen feature."); 3670 } 3671 if (!LockSettingsService.this.setLockCredentialWithToken( 3672 credential, tokenHandle, token, userId)) { 3673 return false; 3674 } 3675 onPostPasswordChanged(credential, userId); 3676 return true; 3677 } 3678 3679 @Override 3680 public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) { 3681 return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); 3682 } 3683 3684 @Override 3685 public PasswordMetrics getUserPasswordMetrics(int userHandle) { 3686 final long identity = Binder.clearCallingIdentity(); 3687 try { 3688 if (isProfileWithUnifiedLock(userHandle)) { 3689 // A managed/clone profile with unified challenge is supposed to be protected by 3690 // the parent lockscreen, so asking for its password metrics is not really 3691 // useful, as this method would just return the metrics of the random profile 3692 // password 3693 Slog.w(TAG, "Querying password metrics for unified challenge profile: " 3694 + userHandle); 3695 } 3696 } finally { 3697 Binder.restoreCallingIdentity(identity); 3698 } 3699 return LockSettingsService.this.getUserPasswordMetrics(userHandle); 3700 } 3701 3702 @Override 3703 public boolean prepareRebootEscrow() { 3704 if (!mRebootEscrowManager.prepareRebootEscrow()) { 3705 return false; 3706 } 3707 mStrongAuth.requireStrongAuth(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE, USER_ALL); 3708 return true; 3709 } 3710 3711 @Override 3712 public void setRebootEscrowListener(RebootEscrowListener listener) { 3713 mRebootEscrowManager.setRebootEscrowListener(listener); 3714 } 3715 3716 @Override 3717 public boolean clearRebootEscrow() { 3718 if (!mRebootEscrowManager.clearRebootEscrow()) { 3719 return false; 3720 } 3721 mStrongAuth.noLongerRequireStrongAuth(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE, 3722 USER_ALL); 3723 return true; 3724 } 3725 3726 @Override 3727 public @ArmRebootEscrowErrorCode int armRebootEscrow() { 3728 return mRebootEscrowManager.armRebootEscrowIfNeeded(); 3729 } 3730 3731 @Override 3732 public void refreshStrongAuthTimeout(int userId) { 3733 mStrongAuth.refreshStrongAuthTimeout(userId); 3734 } 3735 } 3736 3737 private class RebootEscrowCallbacks implements RebootEscrowManager.Callbacks { 3738 @Override 3739 public boolean isUserSecure(int userId) { 3740 return LockSettingsService.this.isUserSecure(userId); 3741 } 3742 3743 @Override 3744 public void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId) { 3745 SyntheticPasswordManager.AuthenticationToken 3746 authToken = new SyntheticPasswordManager.AuthenticationToken(spVersion); 3747 authToken.recreateDirectly(syntheticPassword); 3748 synchronized (mSpManager) { 3749 mSpManager.verifyChallenge(getGateKeeperService(), authToken, 0L, userId); 3750 } 3751 onCredentialVerified(authToken, loadPasswordMetrics(authToken, userId), userId); 3752 } 3753 } 3754 } 3755