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