LockSettingsService.java revision 2c8e5383c836d2dfa39b0be6bfa281285667a880
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 17package com.android.server.locksettings; 18 19import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; 20import static android.Manifest.permission.READ_CONTACTS; 21import static android.content.Context.KEYGUARD_SERVICE; 22import static android.content.pm.PackageManager.PERMISSION_GRANTED; 23 24import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; 25import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; 26import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; 27import static com.android.internal.widget.LockPatternUtils.USER_FRP; 28import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; 29import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; 30 31import android.annotation.NonNull; 32import android.annotation.Nullable; 33import android.annotation.UserIdInt; 34import android.app.ActivityManager; 35import android.app.IActivityManager; 36import android.app.KeyguardManager; 37import android.app.Notification; 38import android.app.NotificationManager; 39import android.app.PendingIntent; 40import android.app.admin.DevicePolicyManager; 41import android.app.admin.DevicePolicyManagerInternal; 42import android.app.admin.PasswordMetrics; 43import android.app.backup.BackupManager; 44import android.app.trust.IStrongAuthTracker; 45import android.app.trust.TrustManager; 46import android.content.BroadcastReceiver; 47import android.content.ContentResolver; 48import android.content.Context; 49import android.content.Intent; 50import android.content.IntentFilter; 51import android.content.pm.PackageManager; 52import android.content.pm.UserInfo; 53import android.content.res.Resources; 54import android.database.ContentObserver; 55import android.database.sqlite.SQLiteDatabase; 56import android.hardware.authsecret.V1_0.IAuthSecret; 57import android.net.Uri; 58import android.os.Binder; 59import android.os.Bundle; 60import android.os.Handler; 61import android.os.IBinder; 62import android.os.IProgressListener; 63import android.os.Process; 64import android.os.RemoteException; 65import android.os.ResultReceiver; 66import android.os.ServiceManager; 67import android.os.ShellCallback; 68import android.os.StrictMode; 69import android.os.SystemProperties; 70import android.os.UserHandle; 71import android.os.UserManager; 72import android.os.storage.IStorageManager; 73import android.os.storage.StorageManager; 74import android.provider.Settings; 75import android.provider.Settings.Secure; 76import android.provider.Settings.SettingNotFoundException; 77import android.security.KeyStore; 78import android.security.keystore.AndroidKeyStoreProvider; 79import android.security.keystore.KeyProperties; 80import android.security.keystore.KeyProtection; 81import android.security.keystore.UserNotAuthenticatedException; 82import android.security.keystore.recovery.KeyChainProtectionParams; 83import android.security.keystore.recovery.RecoveryCertPath; 84import android.security.keystore.recovery.WrappedApplicationKey; 85import android.security.keystore.recovery.KeyChainSnapshot; 86import android.service.gatekeeper.GateKeeperResponse; 87import android.service.gatekeeper.IGateKeeperService; 88import android.text.TextUtils; 89import android.util.ArrayMap; 90import android.util.EventLog; 91import android.util.Log; 92import android.util.Slog; 93import android.util.SparseArray; 94 95import com.android.internal.annotations.GuardedBy; 96import com.android.internal.annotations.VisibleForTesting; 97import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 98import com.android.internal.notification.SystemNotificationChannels; 99import com.android.internal.util.ArrayUtils; 100import com.android.internal.util.DumpUtils; 101import com.android.internal.util.Preconditions; 102import com.android.internal.widget.ICheckCredentialProgressCallback; 103import com.android.internal.widget.ILockSettings; 104import com.android.internal.widget.LockPatternUtils; 105import com.android.internal.widget.VerifyCredentialResponse; 106import com.android.server.LocalServices; 107import com.android.server.SystemService; 108import com.android.server.locksettings.LockSettingsStorage.CredentialHash; 109import com.android.server.locksettings.LockSettingsStorage.PersistentData; 110import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; 111import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult; 112import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; 113 114import libcore.util.HexEncoding; 115 116import java.io.ByteArrayOutputStream; 117import java.io.FileDescriptor; 118import java.io.FileNotFoundException; 119import java.io.IOException; 120import java.io.PrintWriter; 121import java.nio.charset.StandardCharsets; 122import java.security.InvalidAlgorithmParameterException; 123import java.security.InvalidKeyException; 124import java.security.KeyStoreException; 125import java.security.MessageDigest; 126import java.security.NoSuchAlgorithmException; 127import java.security.SecureRandom; 128import java.security.UnrecoverableKeyException; 129import java.security.cert.CertificateException; 130import java.util.Arrays; 131import java.util.ArrayList; 132import java.util.List; 133import java.util.Map; 134import java.util.NoSuchElementException; 135import java.util.concurrent.CountDownLatch; 136import java.util.concurrent.TimeUnit; 137 138import javax.crypto.BadPaddingException; 139import javax.crypto.Cipher; 140import javax.crypto.IllegalBlockSizeException; 141import javax.crypto.KeyGenerator; 142import javax.crypto.NoSuchPaddingException; 143import javax.crypto.SecretKey; 144import javax.crypto.spec.GCMParameterSpec; 145 146/** 147 * Keeps the lock pattern/password data and related settings for each user. Used by 148 * LockPatternUtils. Needs to be a service because Settings app also needs to be able to save 149 * lockscreen information for secondary users. 150 * 151 * @hide 152 */ 153public class LockSettingsService extends ILockSettings.Stub { 154 private static final String TAG = "LockSettingsService"; 155 private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE; 156 private static final boolean DEBUG = false; 157 158 private static final int PROFILE_KEY_IV_SIZE = 12; 159 private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge"; 160 private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1; 161 162 // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this 163 // Do not call into ActivityManager while holding mSpManager lock. 164 private final Object mSeparateChallengeLock = new Object(); 165 166 private final DeviceProvisionedObserver mDeviceProvisionedObserver = 167 new DeviceProvisionedObserver(); 168 169 private final Injector mInjector; 170 private final Context mContext; 171 @VisibleForTesting 172 protected final Handler mHandler; 173 @VisibleForTesting 174 protected final LockSettingsStorage mStorage; 175 private final LockSettingsStrongAuth mStrongAuth; 176 private final SynchronizedStrongAuthTracker mStrongAuthTracker; 177 178 private final LockPatternUtils mLockPatternUtils; 179 private final NotificationManager mNotificationManager; 180 private final UserManager mUserManager; 181 private final IActivityManager mActivityManager; 182 private final SyntheticPasswordManager mSpManager; 183 184 private final KeyStore mKeyStore; 185 186 private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; 187 188 private boolean mFirstCallToVold; 189 protected IGateKeeperService mGateKeeperService; 190 protected IAuthSecret mAuthSecretService; 191 192 /** 193 * The UIDs that are used for system credential storage in keystore. 194 */ 195 private static final int[] SYSTEM_CREDENTIAL_UIDS = { 196 Process.WIFI_UID, Process.VPN_UID, 197 Process.ROOT_UID, Process.SYSTEM_UID }; 198 199 // This class manages life cycle events for encrypted users on File Based Encryption (FBE) 200 // devices. The most basic of these is to show/hide notifications about missing features until 201 // the user unlocks the account and credential-encrypted storage is available. 202 public static final class Lifecycle extends SystemService { 203 private LockSettingsService mLockSettingsService; 204 205 public Lifecycle(Context context) { 206 super(context); 207 } 208 209 @Override 210 public void onStart() { 211 AndroidKeyStoreProvider.install(); 212 mLockSettingsService = new LockSettingsService(getContext()); 213 publishBinderService("lock_settings", mLockSettingsService); 214 } 215 216 @Override 217 public void onBootPhase(int phase) { 218 super.onBootPhase(phase); 219 if (phase == PHASE_ACTIVITY_MANAGER_READY) { 220 mLockSettingsService.migrateOldDataAfterSystemReady(); 221 } 222 } 223 224 @Override 225 public void onStartUser(int userHandle) { 226 mLockSettingsService.onStartUser(userHandle); 227 } 228 229 @Override 230 public void onUnlockUser(int userHandle) { 231 mLockSettingsService.onUnlockUser(userHandle); 232 } 233 234 @Override 235 public void onCleanupUser(int userHandle) { 236 mLockSettingsService.onCleanupUser(userHandle); 237 } 238 } 239 240 @VisibleForTesting 241 protected static class SynchronizedStrongAuthTracker 242 extends LockPatternUtils.StrongAuthTracker { 243 public SynchronizedStrongAuthTracker(Context context) { 244 super(context); 245 } 246 247 @Override 248 protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) { 249 synchronized (this) { 250 super.handleStrongAuthRequiredChanged(strongAuthFlags, userId); 251 } 252 } 253 254 @Override 255 public int getStrongAuthForUser(int userId) { 256 synchronized (this) { 257 return super.getStrongAuthForUser(userId); 258 } 259 } 260 261 void register(LockSettingsStrongAuth strongAuth) { 262 strongAuth.registerStrongAuthTracker(this.mStub); 263 } 264 } 265 266 /** 267 * Tie managed profile to primary profile if it is in unified mode and not tied before. 268 * 269 * @param managedUserId Managed profile user Id 270 * @param managedUserPassword Managed profile original password (when it has separated lock). 271 * NULL when it does not have a separated lock before. 272 */ 273 public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) { 274 if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId); 275 // Only for managed profile 276 if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) { 277 return; 278 } 279 // Do not tie managed profile when work challenge is enabled 280 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) { 281 return; 282 } 283 // Do not tie managed profile to parent when it's done already 284 if (mStorage.hasChildProfileLock(managedUserId)) { 285 return; 286 } 287 // Do not tie it to parent when parent does not have a screen lock 288 final int parentId = mUserManager.getProfileParent(managedUserId).id; 289 if (!isUserSecure(parentId)) { 290 if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock"); 291 return; 292 } 293 // Do not tie when the parent has no SID (but does have a screen lock). 294 // This can only happen during an upgrade path where SID is yet to be 295 // generated when the user unlocks for the first time. 296 try { 297 if (getGateKeeperService().getSecureUserId(parentId) == 0) { 298 return; 299 } 300 } catch (RemoteException e) { 301 Slog.e(TAG, "Failed to talk to GateKeeper service", e); 302 return; 303 } 304 if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!"); 305 byte[] randomLockSeed = new byte[] {}; 306 try { 307 randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40); 308 String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed)); 309 final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 310 setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 311 managedUserPassword, quality, managedUserId); 312 // We store a private credential for the managed user that's unlocked by the primary 313 // account holder's credential. As such, the user will never be prompted to enter this 314 // password directly, so we always store a password. 315 setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, managedUserId); 316 tieProfileLockToParent(managedUserId, newPassword); 317 } catch (NoSuchAlgorithmException | RemoteException e) { 318 Slog.e(TAG, "Fail to tie managed profile", e); 319 // Nothing client can do to fix this issue, so we do not throw exception out 320 } 321 } 322 323 static class Injector { 324 325 protected Context mContext; 326 327 public Injector(Context context) { 328 mContext = context; 329 } 330 331 public Context getContext() { 332 return mContext; 333 } 334 335 public Handler getHandler() { 336 return new Handler(); 337 } 338 339 public LockSettingsStorage getStorage() { 340 final LockSettingsStorage storage = new LockSettingsStorage(mContext); 341 storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() { 342 @Override 343 public void initialize(SQLiteDatabase db) { 344 // Get the lockscreen default from a system property, if available 345 boolean lockScreenDisable = SystemProperties.getBoolean( 346 "ro.lockscreen.disable.default", false); 347 if (lockScreenDisable) { 348 storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); 349 } 350 } 351 }); 352 return storage; 353 } 354 355 public LockSettingsStrongAuth getStrongAuth() { 356 return new LockSettingsStrongAuth(mContext); 357 } 358 359 public SynchronizedStrongAuthTracker getStrongAuthTracker() { 360 return new SynchronizedStrongAuthTracker(mContext); 361 } 362 363 public IActivityManager getActivityManager() { 364 return ActivityManager.getService(); 365 } 366 367 public LockPatternUtils getLockPatternUtils() { 368 return new LockPatternUtils(mContext); 369 } 370 371 public NotificationManager getNotificationManager() { 372 return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 373 } 374 375 public UserManager getUserManager() { 376 return (UserManager) mContext.getSystemService(Context.USER_SERVICE); 377 } 378 379 public DevicePolicyManager getDevicePolicyManager() { 380 return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 381 } 382 383 public KeyStore getKeyStore() { 384 return KeyStore.getInstance(); 385 } 386 387 public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) { 388 return RecoverableKeyStoreManager.getInstance(mContext, keyStore); 389 } 390 391 public IStorageManager getStorageManager() { 392 final IBinder service = ServiceManager.getService("mount"); 393 if (service != null) { 394 return IStorageManager.Stub.asInterface(service); 395 } 396 return null; 397 } 398 399 public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { 400 return new SyntheticPasswordManager(getContext(), storage, getUserManager()); 401 } 402 403 public int binderGetCallingUid() { 404 return Binder.getCallingUid(); 405 } 406 } 407 408 public LockSettingsService(Context context) { 409 this(new Injector(context)); 410 } 411 412 @VisibleForTesting 413 protected LockSettingsService(Injector injector) { 414 mInjector = injector; 415 mContext = injector.getContext(); 416 mKeyStore = injector.getKeyStore(); 417 mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore); 418 mHandler = injector.getHandler(); 419 mStrongAuth = injector.getStrongAuth(); 420 mActivityManager = injector.getActivityManager(); 421 422 mLockPatternUtils = injector.getLockPatternUtils(); 423 mFirstCallToVold = true; 424 425 IntentFilter filter = new IntentFilter(); 426 filter.addAction(Intent.ACTION_USER_ADDED); 427 filter.addAction(Intent.ACTION_USER_STARTING); 428 filter.addAction(Intent.ACTION_USER_REMOVED); 429 injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, 430 null, null); 431 432 mStorage = injector.getStorage(); 433 mNotificationManager = injector.getNotificationManager(); 434 mUserManager = injector.getUserManager(); 435 mStrongAuthTracker = injector.getStrongAuthTracker(); 436 mStrongAuthTracker.register(mStrongAuth); 437 438 mSpManager = injector.getSyntheticPasswordManager(mStorage); 439 } 440 441 /** 442 * If the account is credential-encrypted, show notification requesting the user to unlock the 443 * device. 444 */ 445 private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) { 446 final UserInfo user = mUserManager.getUserInfo(userId); 447 if (!user.isManagedProfile()) { 448 // When the user is locked, we communicate it loud-and-clear 449 // on the lockscreen; we only show a notification below for 450 // locked managed profiles. 451 return; 452 } 453 454 final UserHandle userHandle = user.getUserHandle(); 455 final boolean isSecure = isUserSecure(userId); 456 if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) { 457 UserInfo parent = mUserManager.getProfileParent(userId); 458 if (parent != null && 459 mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) && 460 !mUserManager.isQuietModeEnabled(userHandle)) { 461 // Only show notifications for managed profiles once their parent 462 // user is unlocked. 463 showEncryptionNotificationForProfile(userHandle); 464 } 465 } 466 } 467 468 private void showEncryptionNotificationForProfile(UserHandle user) { 469 Resources r = mContext.getResources(); 470 CharSequence title = r.getText( 471 com.android.internal.R.string.user_encrypted_title); 472 CharSequence message = r.getText( 473 com.android.internal.R.string.profile_encrypted_message); 474 CharSequence detail = r.getText( 475 com.android.internal.R.string.profile_encrypted_detail); 476 477 final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE); 478 final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, 479 user.getIdentifier()); 480 if (unlockIntent == null) { 481 return; 482 } 483 unlockIntent.setFlags( 484 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 485 PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent, 486 PendingIntent.FLAG_UPDATE_CURRENT); 487 488 showEncryptionNotification(user, title, message, detail, intent); 489 } 490 491 private void showEncryptionNotification(UserHandle user, CharSequence title, 492 CharSequence message, CharSequence detail, PendingIntent intent) { 493 if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier()); 494 495 // Suppress all notifications on non-FBE devices for now 496 if (!StorageManager.isFileEncryptedNativeOrEmulated()) return; 497 498 Notification notification = 499 new Notification.Builder(mContext, SystemNotificationChannels.SECURITY) 500 .setSmallIcon(com.android.internal.R.drawable.ic_user_secure) 501 .setWhen(0) 502 .setOngoing(true) 503 .setTicker(title) 504 .setColor(mContext.getColor( 505 com.android.internal.R.color.system_notification_accent_color)) 506 .setContentTitle(title) 507 .setContentText(message) 508 .setSubText(detail) 509 .setVisibility(Notification.VISIBILITY_PUBLIC) 510 .setContentIntent(intent) 511 .build(); 512 mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION, 513 notification, user); 514 } 515 516 private void hideEncryptionNotification(UserHandle userHandle) { 517 if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier()); 518 mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION, 519 userHandle); 520 } 521 522 public void onCleanupUser(int userId) { 523 hideEncryptionNotification(new UserHandle(userId)); 524 } 525 526 public void onStartUser(final int userId) { 527 maybeShowEncryptionNotificationForUser(userId); 528 } 529 530 /** 531 * Check if profile got unlocked but the keystore is still locked. This happens on full disk 532 * encryption devices since the profile may not yet be running when we consider unlocking it 533 * during the normal flow. In this case unlock the keystore for the profile. 534 */ 535 private void ensureProfileKeystoreUnlocked(int userId) { 536 final KeyStore ks = KeyStore.getInstance(); 537 if (ks.state(userId) == KeyStore.State.LOCKED 538 && tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) { 539 Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore"); 540 try { 541 // If boot took too long and the password in vold got expired, parent keystore will 542 // be still locked, we ignore this case since the user will be prompted to unlock 543 // the device after boot. 544 unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */); 545 } catch (RemoteException e) { 546 Slog.e(TAG, "Failed to unlock child profile"); 547 } 548 } 549 } 550 551 public void onUnlockUser(final int userId) { 552 // Perform tasks which require locks in LSS on a handler, as we are callbacks from 553 // ActivityManager.unlockUser() 554 mHandler.post(new Runnable() { 555 @Override 556 public void run() { 557 ensureProfileKeystoreUnlocked(userId); 558 // Hide notification first, as tie managed profile lock takes time 559 hideEncryptionNotification(new UserHandle(userId)); 560 561 // Now we have unlocked the parent user we should show notifications 562 // about any profiles that exist. 563 List<UserInfo> profiles = mUserManager.getProfiles(userId); 564 for (int i = 0; i < profiles.size(); i++) { 565 UserInfo profile = profiles.get(i); 566 final boolean isSecure = isUserSecure(profile.id); 567 if (isSecure && profile.isManagedProfile()) { 568 UserHandle userHandle = profile.getUserHandle(); 569 if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) && 570 !mUserManager.isQuietModeEnabled(userHandle)) { 571 showEncryptionNotificationForProfile(userHandle); 572 } 573 } 574 } 575 576 if (mUserManager.getUserInfo(userId).isManagedProfile()) { 577 tieManagedProfileLockIfNecessary(userId, null); 578 } 579 } 580 }); 581 } 582 583 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 584 @Override 585 public void onReceive(Context context, Intent intent) { 586 if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { 587 // Notify keystore that a new user was added. 588 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 589 if (userHandle > UserHandle.USER_SYSTEM) { 590 removeUser(userHandle, /* unknownUser= */ true); 591 } 592 final KeyStore ks = KeyStore.getInstance(); 593 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle); 594 final int parentHandle = parentInfo != null ? parentInfo.id : -1; 595 ks.onUserAdded(userHandle, parentHandle); 596 } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { 597 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 598 mStorage.prefetchUser(userHandle); 599 } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { 600 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 601 if (userHandle > 0) { 602 removeUser(userHandle, /* unknownUser= */ false); 603 } 604 } 605 } 606 }; 607 608 @Override // binder interface 609 public void systemReady() { 610 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { 611 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet 612 } 613 checkWritePermission(UserHandle.USER_SYSTEM); 614 migrateOldData(); 615 try { 616 getGateKeeperService(); 617 mSpManager.initWeaverService(); 618 } catch (RemoteException e) { 619 Slog.e(TAG, "Failure retrieving IGateKeeperService", e); 620 } 621 // Find the AuthSecret HAL 622 try { 623 mAuthSecretService = IAuthSecret.getService(); 624 } catch (NoSuchElementException e) { 625 Slog.i(TAG, "Device doesn't implement AuthSecret HAL"); 626 } catch (RemoteException e) { 627 Slog.w(TAG, "Failed to get AuthSecret HAL", e); 628 } 629 mDeviceProvisionedObserver.onSystemReady(); 630 // TODO: maybe skip this for split system user mode. 631 mStorage.prefetchUser(UserHandle.USER_SYSTEM); 632 mStrongAuth.systemReady(); 633 } 634 635 private void migrateOldData() { 636 // These Settings moved before multi-user was enabled, so we only have to do it for the 637 // root user. 638 if (getString("migrated", null, 0) == null) { 639 final ContentResolver cr = mContext.getContentResolver(); 640 for (String validSetting : VALID_SETTINGS) { 641 String value = Settings.Secure.getString(cr, validSetting); 642 if (value != null) { 643 setString(validSetting, value, 0); 644 } 645 } 646 // No need to move the password / pattern files. They're already in the right place. 647 setString("migrated", "true", 0); 648 Slog.i(TAG, "Migrated lock settings to new location"); 649 } 650 651 // These Settings changed after multi-user was enabled, hence need to be moved per user. 652 if (getString("migrated_user_specific", null, 0) == null) { 653 final ContentResolver cr = mContext.getContentResolver(); 654 List<UserInfo> users = mUserManager.getUsers(); 655 for (int user = 0; user < users.size(); user++) { 656 // Migrate owner info 657 final int userId = users.get(user).id; 658 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO; 659 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId); 660 if (!TextUtils.isEmpty(ownerInfo)) { 661 setString(OWNER_INFO, ownerInfo, userId); 662 Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId); 663 } 664 665 // Migrate owner info enabled. Note there was a bug where older platforms only 666 // stored this value if the checkbox was toggled at least once. The code detects 667 // this case by handling the exception. 668 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 669 boolean enabled; 670 try { 671 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId); 672 enabled = ivalue != 0; 673 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId); 674 } catch (SettingNotFoundException e) { 675 // Setting was never stored. Store it if the string is not empty. 676 if (!TextUtils.isEmpty(ownerInfo)) { 677 setLong(OWNER_INFO_ENABLED, 1, userId); 678 } 679 } 680 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId); 681 } 682 // No need to move the password / pattern files. They're already in the right place. 683 setString("migrated_user_specific", "true", 0); 684 Slog.i(TAG, "Migrated per-user lock settings to new location"); 685 } 686 687 // Migrates biometric weak such that the fallback mechanism becomes the primary. 688 if (getString("migrated_biometric_weak", null, 0) == null) { 689 List<UserInfo> users = mUserManager.getUsers(); 690 for (int i = 0; i < users.size(); i++) { 691 int userId = users.get(i).id; 692 long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 693 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 694 userId); 695 long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 696 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 697 userId); 698 if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { 699 setLong(LockPatternUtils.PASSWORD_TYPE_KEY, 700 alternateType, 701 userId); 702 } 703 setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 704 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 705 userId); 706 } 707 setString("migrated_biometric_weak", "true", 0); 708 Slog.i(TAG, "Migrated biometric weak to use the fallback instead"); 709 } 710 711 // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one 712 // user was present on the system, so if we're upgrading to M and there is more than one 713 // user we disable the flag to remain consistent. 714 if (getString("migrated_lockscreen_disabled", null, 0) == null) { 715 final List<UserInfo> users = mUserManager.getUsers(); 716 final int userCount = users.size(); 717 int switchableUsers = 0; 718 for (int i = 0; i < userCount; i++) { 719 if (users.get(i).supportsSwitchTo()) { 720 switchableUsers++; 721 } 722 } 723 724 if (switchableUsers > 1) { 725 for (int i = 0; i < userCount; i++) { 726 int id = users.get(i).id; 727 728 if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) { 729 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id); 730 } 731 } 732 } 733 734 setString("migrated_lockscreen_disabled", "true", 0); 735 Slog.i(TAG, "Migrated lockscreen disabled flag"); 736 } 737 738 final List<UserInfo> users = mUserManager.getUsers(); 739 for (int i = 0; i < users.size(); i++) { 740 final UserInfo userInfo = users.get(i); 741 if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) { 742 // When managed profile has a unified lock, the password quality stored has 2 743 // possibilities only. 744 // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are 745 // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC. 746 // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for 747 // unified lock. 748 final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 749 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id); 750 if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 751 // Only possible when it's upgraded from nyc dp3 752 Slog.i(TAG, "Migrated tied profile lock type"); 753 setLong(LockPatternUtils.PASSWORD_TYPE_KEY, 754 DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id); 755 } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) { 756 // It should not happen 757 Slog.e(TAG, "Invalid tied profile lock type: " + quality); 758 } 759 } 760 try { 761 final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id; 762 java.security.KeyStore keyStore = 763 java.security.KeyStore.getInstance("AndroidKeyStore"); 764 keyStore.load(null); 765 if (keyStore.containsAlias(alias)) { 766 keyStore.deleteEntry(alias); 767 } 768 } catch (KeyStoreException | NoSuchAlgorithmException | 769 CertificateException | IOException e) { 770 Slog.e(TAG, "Unable to remove tied profile key", e); 771 } 772 } 773 774 boolean isWatch = mContext.getPackageManager().hasSystemFeature( 775 PackageManager.FEATURE_WATCH); 776 // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts 777 // and device management the lockscreen must be re-enabled now for users that upgrade. 778 if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) { 779 final int userCount = users.size(); 780 for (int i = 0; i < userCount; i++) { 781 int id = users.get(i).id; 782 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id); 783 } 784 setString("migrated_wear_lockscreen_disabled", "true", 0); 785 Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices"); 786 } 787 } 788 789 private void migrateOldDataAfterSystemReady() { 790 try { 791 // Migrate the FRP credential to the persistent data block 792 if (LockPatternUtils.frpCredentialEnabled(mContext) 793 && !getBoolean("migrated_frp", false, 0)) { 794 migrateFrpCredential(); 795 setBoolean("migrated_frp", true, 0); 796 Slog.i(TAG, "Migrated migrated_frp."); 797 } 798 } catch (RemoteException e) { 799 Slog.e(TAG, "Unable to migrateOldDataAfterSystemReady", e); 800 } 801 } 802 803 /** 804 * Migrate the credential for the FRP credential owner user if the following are satisfied: 805 * - the user has a secure credential 806 * - the FRP credential is not set up 807 * - the credential is based on a synthetic password. 808 */ 809 private void migrateFrpCredential() throws RemoteException { 810 if (mStorage.readPersistentDataBlock() != PersistentData.NONE) { 811 return; 812 } 813 for (UserInfo userInfo : mUserManager.getUsers()) { 814 if (userOwnsFrpCredential(mContext, userInfo) && isUserSecure(userInfo.id)) { 815 synchronized (mSpManager) { 816 if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) { 817 int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 818 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id); 819 820 mSpManager.migrateFrpPasswordLocked( 821 getSyntheticPasswordHandleLocked(userInfo.id), 822 userInfo, 823 redactActualQualityToMostLenientEquivalentQuality(actualQuality)); 824 } 825 } 826 return; 827 } 828 } 829 } 830 831 /** 832 * Returns the lowest password quality that still presents the same UI for entering it. 833 * 834 * For the FRP credential, we do not want to leak the actual quality of the password, only what 835 * kind of UI it requires. However, when migrating, we only know the actual quality, not the 836 * originally requested quality; since this is only used to determine what input variant to 837 * present to the user, we just assume the lowest possible quality was requested. 838 */ 839 private int redactActualQualityToMostLenientEquivalentQuality(int quality) { 840 switch (quality) { 841 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 842 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 843 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 844 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 845 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 846 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 847 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 848 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 849 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 850 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 851 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK: 852 default: 853 return quality; 854 } 855 } 856 857 private final void checkWritePermission(int userId) { 858 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite"); 859 } 860 861 private final void checkPasswordReadPermission(int userId) { 862 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead"); 863 } 864 865 private final void checkPasswordHavePermission(int userId) { 866 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { 867 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet 868 } 869 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave"); 870 } 871 872 private final void checkReadPermission(String requestedKey, int userId) { 873 final int callingUid = Binder.getCallingUid(); 874 875 for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) { 876 String key = READ_CONTACTS_PROTECTED_SETTINGS[i]; 877 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS) 878 != PackageManager.PERMISSION_GRANTED) { 879 throw new SecurityException("uid=" + callingUid 880 + " needs permission " + READ_CONTACTS + " to read " 881 + requestedKey + " for user " + userId); 882 } 883 } 884 885 for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) { 886 String key = READ_PASSWORD_PROTECTED_SETTINGS[i]; 887 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION) 888 != PackageManager.PERMISSION_GRANTED) { 889 throw new SecurityException("uid=" + callingUid 890 + " needs permission " + PERMISSION + " to read " 891 + requestedKey + " for user " + userId); 892 } 893 } 894 } 895 896 @Override 897 public boolean getSeparateProfileChallengeEnabled(int userId) { 898 checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId); 899 synchronized (mSeparateChallengeLock) { 900 return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId); 901 } 902 } 903 904 @Override 905 public void setSeparateProfileChallengeEnabled(int userId, boolean enabled, 906 String managedUserPassword) { 907 checkWritePermission(userId); 908 synchronized (mSeparateChallengeLock) { 909 setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword); 910 } 911 notifySeparateProfileChallengeChanged(userId); 912 } 913 914 @GuardedBy("mSeparateChallengeLock") 915 private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId, boolean enabled, 916 String managedUserPassword) { 917 setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId); 918 if (enabled) { 919 mStorage.removeChildProfileLock(userId); 920 removeKeystoreProfileKey(userId); 921 } else { 922 tieManagedProfileLockIfNecessary(userId, managedUserPassword); 923 } 924 } 925 926 private void notifySeparateProfileChallengeChanged(int userId) { 927 final DevicePolicyManagerInternal dpmi = LocalServices.getService( 928 DevicePolicyManagerInternal.class); 929 if (dpmi != null) { 930 dpmi.reportSeparateProfileChallengeChanged(userId); 931 } 932 } 933 934 @Override 935 public void setBoolean(String key, boolean value, int userId) { 936 checkWritePermission(userId); 937 setStringUnchecked(key, userId, value ? "1" : "0"); 938 } 939 940 @Override 941 public void setLong(String key, long value, int userId) { 942 checkWritePermission(userId); 943 setStringUnchecked(key, userId, Long.toString(value)); 944 } 945 946 @Override 947 public void setString(String key, String value, int userId) { 948 checkWritePermission(userId); 949 setStringUnchecked(key, userId, value); 950 } 951 952 private void setStringUnchecked(String key, int userId, String value) { 953 Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user"); 954 955 mStorage.writeKeyValue(key, value, userId); 956 if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) { 957 BackupManager.dataChanged("com.android.providers.settings"); 958 } 959 } 960 961 @Override 962 public boolean getBoolean(String key, boolean defaultValue, int userId) { 963 checkReadPermission(key, userId); 964 String value = getStringUnchecked(key, null, userId); 965 return TextUtils.isEmpty(value) ? 966 defaultValue : (value.equals("1") || value.equals("true")); 967 } 968 969 @Override 970 public long getLong(String key, long defaultValue, int userId) { 971 checkReadPermission(key, userId); 972 String value = getStringUnchecked(key, null, userId); 973 return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value); 974 } 975 976 @Override 977 public String getString(String key, String defaultValue, int userId) { 978 checkReadPermission(key, userId); 979 return getStringUnchecked(key, defaultValue, userId); 980 } 981 982 public String getStringUnchecked(String key, String defaultValue, int userId) { 983 if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) { 984 long ident = Binder.clearCallingIdentity(); 985 try { 986 return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0"; 987 } finally { 988 Binder.restoreCallingIdentity(ident); 989 } 990 } 991 992 if (userId == USER_FRP) { 993 return getFrpStringUnchecked(key); 994 } 995 996 if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) { 997 key = Settings.Secure.LOCK_PATTERN_ENABLED; 998 } 999 1000 return mStorage.readKeyValue(key, defaultValue, userId); 1001 } 1002 1003 private String getFrpStringUnchecked(String key) { 1004 if (LockPatternUtils.PASSWORD_TYPE_KEY.equals(key)) { 1005 return String.valueOf(readFrpPasswordQuality()); 1006 } 1007 return null; 1008 } 1009 1010 private int readFrpPasswordQuality() { 1011 return mStorage.readPersistentDataBlock().qualityForUi; 1012 } 1013 1014 @Override 1015 public boolean havePassword(int userId) throws RemoteException { 1016 checkPasswordHavePermission(userId); 1017 synchronized (mSpManager) { 1018 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1019 long handle = getSyntheticPasswordHandleLocked(userId); 1020 return mSpManager.getCredentialType(handle, userId) == 1021 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 1022 } 1023 } 1024 // Do we need a permissions check here? 1025 return mStorage.hasPassword(userId); 1026 } 1027 1028 @Override 1029 public boolean havePattern(int userId) throws RemoteException { 1030 checkPasswordHavePermission(userId); 1031 synchronized (mSpManager) { 1032 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1033 long handle = getSyntheticPasswordHandleLocked(userId); 1034 return mSpManager.getCredentialType(handle, userId) == 1035 LockPatternUtils.CREDENTIAL_TYPE_PATTERN; 1036 } 1037 } 1038 // Do we need a permissions check here? 1039 return mStorage.hasPattern(userId); 1040 } 1041 1042 private boolean isUserSecure(int userId) { 1043 synchronized (mSpManager) { 1044 try { 1045 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1046 long handle = getSyntheticPasswordHandleLocked(userId); 1047 return mSpManager.getCredentialType(handle, userId) != 1048 LockPatternUtils.CREDENTIAL_TYPE_NONE; 1049 } 1050 } catch (RemoteException e) { 1051 // fall through 1052 } 1053 } 1054 return mStorage.hasCredential(userId); 1055 } 1056 1057 private void setKeystorePassword(String password, int userHandle) { 1058 final KeyStore ks = KeyStore.getInstance(); 1059 ks.onUserPasswordChanged(userHandle, password); 1060 } 1061 1062 private void unlockKeystore(String password, int userHandle) { 1063 if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle); 1064 final KeyStore ks = KeyStore.getInstance(); 1065 ks.unlock(userHandle, password); 1066 } 1067 1068 @VisibleForTesting 1069 protected String getDecryptedPasswordForTiedProfile(int userId) 1070 throws KeyStoreException, UnrecoverableKeyException, 1071 NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, 1072 InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, 1073 CertificateException, IOException { 1074 if (DEBUG) Slog.v(TAG, "Get child profile decrytped key"); 1075 byte[] storedData = mStorage.readChildProfileLock(userId); 1076 if (storedData == null) { 1077 throw new FileNotFoundException("Child profile lock file not found"); 1078 } 1079 byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE); 1080 byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE, 1081 storedData.length); 1082 byte[] decryptionResult; 1083 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore"); 1084 keyStore.load(null); 1085 SecretKey decryptionKey = (SecretKey) keyStore.getKey( 1086 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null); 1087 1088 Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 1089 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); 1090 1091 cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv)); 1092 decryptionResult = cipher.doFinal(encryptedPassword); 1093 return new String(decryptionResult, StandardCharsets.UTF_8); 1094 } 1095 1096 private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated) 1097 throws RemoteException { 1098 try { 1099 doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle), 1100 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 1101 false, 0 /* no challenge */, profileHandle, null /* progressCallback */); 1102 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1103 | NoSuchAlgorithmException | NoSuchPaddingException 1104 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1105 | BadPaddingException | CertificateException | IOException e) { 1106 if (e instanceof FileNotFoundException) { 1107 Slog.i(TAG, "Child profile key not found"); 1108 } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) { 1109 Slog.i(TAG, "Parent keystore seems locked, ignoring"); 1110 } else { 1111 Slog.e(TAG, "Failed to decrypt child profile key", e); 1112 } 1113 } 1114 } 1115 1116 private void unlockUser(int userId, byte[] token, byte[] secret) { 1117 // TODO: make this method fully async so we can update UI with progress strings 1118 final CountDownLatch latch = new CountDownLatch(1); 1119 final IProgressListener listener = new IProgressListener.Stub() { 1120 @Override 1121 public void onStarted(int id, Bundle extras) throws RemoteException { 1122 Log.d(TAG, "unlockUser started"); 1123 } 1124 1125 @Override 1126 public void onProgress(int id, int progress, Bundle extras) throws RemoteException { 1127 Log.d(TAG, "unlockUser progress " + progress); 1128 } 1129 1130 @Override 1131 public void onFinished(int id, Bundle extras) throws RemoteException { 1132 Log.d(TAG, "unlockUser finished"); 1133 latch.countDown(); 1134 } 1135 }; 1136 1137 try { 1138 mActivityManager.unlockUser(userId, token, secret, listener); 1139 } catch (RemoteException e) { 1140 throw e.rethrowAsRuntimeException(); 1141 } 1142 1143 try { 1144 latch.await(15, TimeUnit.SECONDS); 1145 } catch (InterruptedException e) { 1146 Thread.currentThread().interrupt(); 1147 } 1148 try { 1149 if (!mUserManager.getUserInfo(userId).isManagedProfile()) { 1150 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1151 for (UserInfo pi : profiles) { 1152 // Unlock managed profile with unified lock 1153 if (tiedManagedProfileReadyToUnlock(pi)) { 1154 unlockChildProfile(pi.id, false /* ignoreUserNotAuthenticated */); 1155 } 1156 } 1157 } 1158 } catch (RemoteException e) { 1159 Log.d(TAG, "Failed to unlock child profile", e); 1160 } 1161 } 1162 1163 private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) { 1164 return userInfo.isManagedProfile() 1165 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id) 1166 && mStorage.hasChildProfileLock(userInfo.id) 1167 && mUserManager.isUserRunning(userInfo.id); 1168 } 1169 1170 private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) { 1171 if (mUserManager.getUserInfo(userId).isManagedProfile()) { 1172 return null; 1173 } 1174 Map<Integer, String> result = new ArrayMap<Integer, String>(); 1175 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1176 final int size = profiles.size(); 1177 for (int i = 0; i < size; i++) { 1178 final UserInfo profile = profiles.get(i); 1179 if (!profile.isManagedProfile()) { 1180 continue; 1181 } 1182 final int managedUserId = profile.id; 1183 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) { 1184 continue; 1185 } 1186 try { 1187 result.put(managedUserId, getDecryptedPasswordForTiedProfile(managedUserId)); 1188 } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException 1189 | NoSuchPaddingException | InvalidKeyException 1190 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1191 | BadPaddingException | CertificateException | IOException e) { 1192 Slog.e(TAG, "getDecryptedPasswordsForAllTiedProfiles failed for user " + 1193 managedUserId, e); 1194 } 1195 } 1196 return result; 1197 } 1198 1199 /** 1200 * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them 1201 * depending on the parent user's secure state. 1202 * 1203 * When clearing tied work challenges, a pre-computed password table for profiles are required, 1204 * since changing password for profiles requires existing password, and existing passwords can 1205 * only be computed before the parent user's password is cleared. 1206 * 1207 * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this 1208 * method again on profiles. However the recursion is guaranteed to terminate as this method 1209 * terminates when the user is a managed profile. 1210 */ 1211 private void synchronizeUnifiedWorkChallengeForProfiles(int userId, 1212 Map<Integer, String> profilePasswordMap) throws RemoteException { 1213 if (mUserManager.getUserInfo(userId).isManagedProfile()) { 1214 return; 1215 } 1216 final boolean isSecure = isUserSecure(userId); 1217 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1218 final int size = profiles.size(); 1219 for (int i = 0; i < size; i++) { 1220 final UserInfo profile = profiles.get(i); 1221 if (profile.isManagedProfile()) { 1222 final int managedUserId = profile.id; 1223 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) { 1224 continue; 1225 } 1226 if (isSecure) { 1227 tieManagedProfileLockIfNecessary(managedUserId, null); 1228 } else { 1229 // We use cached work profile password computed before clearing the parent's 1230 // credential, otherwise they get lost 1231 if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) { 1232 setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, 1233 profilePasswordMap.get(managedUserId), 1234 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); 1235 } else { 1236 Slog.wtf(TAG, "clear tied profile challenges, but no password supplied."); 1237 // Supplying null here would lead to untrusted credential change 1238 setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null, 1239 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId); 1240 } 1241 mStorage.removeChildProfileLock(managedUserId); 1242 removeKeystoreProfileKey(managedUserId); 1243 } 1244 } 1245 } 1246 } 1247 1248 private boolean isManagedProfileWithUnifiedLock(int userId) { 1249 return mUserManager.getUserInfo(userId).isManagedProfile() 1250 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId); 1251 } 1252 1253 private boolean isManagedProfileWithSeparatedLock(int userId) { 1254 return mUserManager.getUserInfo(userId).isManagedProfile() 1255 && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId); 1256 } 1257 1258 // This method should be called by LockPatternUtil only, all internal methods in this class 1259 // should call setLockCredentialInternal. 1260 @Override 1261 public void setLockCredential(String credential, int type, String savedCredential, 1262 int requestedQuality, int userId) 1263 throws RemoteException { 1264 checkWritePermission(userId); 1265 synchronized (mSeparateChallengeLock) { 1266 setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId); 1267 setSeparateProfileChallengeEnabledLocked(userId, true, null); 1268 notifyPasswordChanged(userId); 1269 } 1270 notifySeparateProfileChallengeChanged(userId); 1271 } 1272 1273 private void setLockCredentialInternal(String credential, int credentialType, 1274 String savedCredential, int requestedQuality, int userId) throws RemoteException { 1275 // Normalize savedCredential and credential such that empty string is always represented 1276 // as null. 1277 if (TextUtils.isEmpty(savedCredential)) { 1278 savedCredential = null; 1279 } 1280 if (TextUtils.isEmpty(credential)) { 1281 credential = null; 1282 } 1283 synchronized (mSpManager) { 1284 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 1285 spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, 1286 requestedQuality, userId); 1287 return; 1288 } 1289 } 1290 1291 if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { 1292 if (credential != null) { 1293 Slog.wtf(TAG, "CredentialType is none, but credential is non-null."); 1294 } 1295 clearUserKeyProtection(userId); 1296 getGateKeeperService().clearSecureUserId(userId); 1297 mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId); 1298 setKeystorePassword(null, userId); 1299 fixateNewestUserKeyAuth(userId); 1300 synchronizeUnifiedWorkChallengeForProfiles(userId, null); 1301 notifyActivePasswordMetricsAvailable(null, userId); 1302 mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); 1303 return; 1304 } 1305 if (credential == null) { 1306 throw new RemoteException("Null credential with mismatched credential type"); 1307 } 1308 1309 CredentialHash currentHandle = mStorage.readCredentialHash(userId); 1310 if (isManagedProfileWithUnifiedLock(userId)) { 1311 // get credential from keystore when managed profile has unified lock 1312 if (savedCredential == null) { 1313 try { 1314 savedCredential = getDecryptedPasswordForTiedProfile(userId); 1315 } catch (FileNotFoundException e) { 1316 Slog.i(TAG, "Child profile key not found"); 1317 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1318 | NoSuchAlgorithmException | NoSuchPaddingException 1319 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1320 | BadPaddingException | CertificateException | IOException e) { 1321 Slog.e(TAG, "Failed to decrypt child profile key", e); 1322 } 1323 } 1324 } else { 1325 if (currentHandle.hash == null) { 1326 if (savedCredential != null) { 1327 Slog.w(TAG, "Saved credential provided, but none stored"); 1328 } 1329 savedCredential = null; 1330 } 1331 } 1332 synchronized (mSpManager) { 1333 if (shouldMigrateToSyntheticPasswordLocked(userId)) { 1334 initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, 1335 currentHandle.type, requestedQuality, userId); 1336 spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential, 1337 requestedQuality, userId); 1338 return; 1339 } 1340 } 1341 if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId); 1342 byte[] enrolledHandle = enrollCredential(currentHandle.hash, savedCredential, credential, 1343 userId); 1344 if (enrolledHandle != null) { 1345 CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType); 1346 mStorage.writeCredentialHash(willStore, userId); 1347 // push new secret and auth token to vold 1348 GateKeeperResponse gkResponse = getGateKeeperService() 1349 .verifyChallenge(userId, 0, willStore.hash, credential.getBytes()); 1350 setUserKeyProtection(userId, credential, convertResponse(gkResponse)); 1351 fixateNewestUserKeyAuth(userId); 1352 // Refresh the auth token 1353 doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */); 1354 synchronizeUnifiedWorkChallengeForProfiles(userId, null); 1355 mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, 1356 userId); 1357 } else { 1358 throw new RemoteException("Failed to enroll " + 1359 (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" 1360 : "pattern")); 1361 } 1362 } 1363 1364 private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) { 1365 return VerifyCredentialResponse.fromGateKeeperResponse(gateKeeperResponse); 1366 } 1367 1368 @VisibleForTesting 1369 protected void tieProfileLockToParent(int userId, String password) { 1370 if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId); 1371 byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8); 1372 byte[] encryptionResult; 1373 byte[] iv; 1374 try { 1375 KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); 1376 keyGenerator.init(new SecureRandom()); 1377 SecretKey secretKey = keyGenerator.generateKey(); 1378 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore"); 1379 keyStore.load(null); 1380 try { 1381 keyStore.setEntry( 1382 LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, 1383 new java.security.KeyStore.SecretKeyEntry(secretKey), 1384 new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT) 1385 .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 1386 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1387 .build()); 1388 keyStore.setEntry( 1389 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, 1390 new java.security.KeyStore.SecretKeyEntry(secretKey), 1391 new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT) 1392 .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 1393 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 1394 .setUserAuthenticationRequired(true) 1395 .setUserAuthenticationValidityDurationSeconds(30) 1396 .setCriticalToDeviceEncryption(true) 1397 .build()); 1398 // Key imported, obtain a reference to it. 1399 SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey( 1400 LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null); 1401 Cipher cipher = Cipher.getInstance( 1402 KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/" 1403 + KeyProperties.ENCRYPTION_PADDING_NONE); 1404 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey); 1405 encryptionResult = cipher.doFinal(randomLockSeed); 1406 iv = cipher.getIV(); 1407 } finally { 1408 // The original key can now be discarded. 1409 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId); 1410 } 1411 } catch (CertificateException | UnrecoverableKeyException 1412 | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException 1413 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { 1414 throw new RuntimeException("Failed to encrypt key", e); 1415 } 1416 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 1417 try { 1418 if (iv.length != PROFILE_KEY_IV_SIZE) { 1419 throw new RuntimeException("Invalid iv length: " + iv.length); 1420 } 1421 outputStream.write(iv); 1422 outputStream.write(encryptionResult); 1423 } catch (IOException e) { 1424 throw new RuntimeException("Failed to concatenate byte arrays", e); 1425 } 1426 mStorage.writeChildProfileLock(userId, outputStream.toByteArray()); 1427 } 1428 1429 private byte[] enrollCredential(byte[] enrolledHandle, 1430 String enrolledCredential, String toEnroll, int userId) 1431 throws RemoteException { 1432 checkWritePermission(userId); 1433 byte[] enrolledCredentialBytes = enrolledCredential == null 1434 ? null 1435 : enrolledCredential.getBytes(); 1436 byte[] toEnrollBytes = toEnroll == null 1437 ? null 1438 : toEnroll.getBytes(); 1439 GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle, 1440 enrolledCredentialBytes, toEnrollBytes); 1441 1442 if (response == null) { 1443 return null; 1444 } 1445 1446 byte[] hash = response.getPayload(); 1447 if (hash != null) { 1448 setKeystorePassword(toEnroll, userId); 1449 } else { 1450 // Should not happen 1451 Slog.e(TAG, "Throttled while enrolling a password"); 1452 } 1453 return hash; 1454 } 1455 1456 private void setAuthlessUserKeyProtection(int userId, byte[] key) throws RemoteException { 1457 if (DEBUG) Slog.d(TAG, "setAuthlessUserKeyProtectiond: user=" + userId); 1458 addUserKeyAuth(userId, null, key); 1459 } 1460 1461 private void setUserKeyProtection(int userId, String credential, VerifyCredentialResponse vcr) 1462 throws RemoteException { 1463 if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId); 1464 if (vcr == null) { 1465 throw new RemoteException("Null response verifying a credential we just set"); 1466 } 1467 if (vcr.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 1468 throw new RemoteException("Non-OK response verifying a credential we just set: " 1469 + vcr.getResponseCode()); 1470 } 1471 byte[] token = vcr.getPayload(); 1472 if (token == null) { 1473 throw new RemoteException("Empty payload verifying a credential we just set"); 1474 } 1475 addUserKeyAuth(userId, token, secretFromCredential(credential)); 1476 } 1477 1478 private void clearUserKeyProtection(int userId) throws RemoteException { 1479 if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId); 1480 addUserKeyAuth(userId, null, null); 1481 } 1482 1483 private static byte[] secretFromCredential(String credential) throws RemoteException { 1484 try { 1485 MessageDigest digest = MessageDigest.getInstance("SHA-512"); 1486 // Personalize the hash 1487 byte[] personalization = "Android FBE credential hash" 1488 .getBytes(StandardCharsets.UTF_8); 1489 // Pad it to the block size of the hash function 1490 personalization = Arrays.copyOf(personalization, 128); 1491 digest.update(personalization); 1492 digest.update(credential.getBytes(StandardCharsets.UTF_8)); 1493 return digest.digest(); 1494 } catch (NoSuchAlgorithmException e) { 1495 throw new RuntimeException("NoSuchAlgorithmException for SHA-512"); 1496 } 1497 } 1498 1499 private void addUserKeyAuth(int userId, byte[] token, byte[] secret) 1500 throws RemoteException { 1501 final UserInfo userInfo = mUserManager.getUserInfo(userId); 1502 final IStorageManager storageManager = mInjector.getStorageManager(); 1503 final long callingId = Binder.clearCallingIdentity(); 1504 try { 1505 storageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret); 1506 } finally { 1507 Binder.restoreCallingIdentity(callingId); 1508 } 1509 } 1510 1511 private void fixateNewestUserKeyAuth(int userId) 1512 throws RemoteException { 1513 if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId); 1514 final IStorageManager storageManager = mInjector.getStorageManager(); 1515 final long callingId = Binder.clearCallingIdentity(); 1516 try { 1517 storageManager.fixateNewestUserKeyAuth(userId); 1518 } finally { 1519 Binder.restoreCallingIdentity(callingId); 1520 } 1521 } 1522 1523 @Override 1524 public void resetKeyStore(int userId) throws RemoteException { 1525 checkWritePermission(userId); 1526 if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId); 1527 int managedUserId = -1; 1528 String managedUserDecryptedPassword = null; 1529 final List<UserInfo> profiles = mUserManager.getProfiles(userId); 1530 for (UserInfo pi : profiles) { 1531 // Unlock managed profile with unified lock 1532 if (pi.isManagedProfile() 1533 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id) 1534 && mStorage.hasChildProfileLock(pi.id)) { 1535 try { 1536 if (managedUserId == -1) { 1537 managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id); 1538 managedUserId = pi.id; 1539 } else { 1540 // Should not happen 1541 Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId 1542 + ", uid2:" + pi.id); 1543 } 1544 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1545 | NoSuchAlgorithmException | NoSuchPaddingException 1546 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1547 | BadPaddingException | CertificateException | IOException e) { 1548 Slog.e(TAG, "Failed to decrypt child profile key", e); 1549 } 1550 } 1551 } 1552 try { 1553 // Clear all the users credentials could have been installed in for this user. 1554 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) { 1555 for (int uid : SYSTEM_CREDENTIAL_UIDS) { 1556 mKeyStore.clearUid(UserHandle.getUid(profileId, uid)); 1557 } 1558 } 1559 } finally { 1560 if (managedUserId != -1 && managedUserDecryptedPassword != null) { 1561 if (DEBUG) Slog.v(TAG, "Restore tied profile lock"); 1562 tieProfileLockToParent(managedUserId, managedUserDecryptedPassword); 1563 } 1564 } 1565 } 1566 1567 @Override 1568 public VerifyCredentialResponse checkCredential(String credential, int type, int userId, 1569 ICheckCredentialProgressCallback progressCallback) throws RemoteException { 1570 checkPasswordReadPermission(userId); 1571 return doVerifyCredential(credential, type, false, 0, userId, progressCallback); 1572 } 1573 1574 @Override 1575 public VerifyCredentialResponse verifyCredential(String credential, int type, long challenge, 1576 int userId) throws RemoteException { 1577 checkPasswordReadPermission(userId); 1578 return doVerifyCredential(credential, type, true, challenge, userId, 1579 null /* progressCallback */); 1580 } 1581 1582 /** 1583 * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero 1584 * format. 1585 */ 1586 private VerifyCredentialResponse doVerifyCredential(String credential, int credentialType, 1587 boolean hasChallenge, long challenge, int userId, 1588 ICheckCredentialProgressCallback progressCallback) throws RemoteException { 1589 if (TextUtils.isEmpty(credential)) { 1590 throw new IllegalArgumentException("Credential can't be null or empty"); 1591 } 1592 if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(), 1593 Settings.Global.DEVICE_PROVISIONED, 0) != 0) { 1594 Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); 1595 return VerifyCredentialResponse.ERROR; 1596 } 1597 VerifyCredentialResponse response = null; 1598 response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge, 1599 userId, progressCallback); 1600 // The user employs synthetic password based credential. 1601 if (response != null) { 1602 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 1603 mRecoverableKeyStoreManager.lockScreenSecretAvailable(credentialType, credential, 1604 userId); 1605 } 1606 return response; 1607 } 1608 1609 if (userId == USER_FRP) { 1610 Slog.wtf(TAG, "Unexpected FRP credential type, should be SP based."); 1611 return VerifyCredentialResponse.ERROR; 1612 } 1613 1614 final CredentialHash storedHash = mStorage.readCredentialHash(userId); 1615 if (storedHash.type != credentialType) { 1616 Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??" 1617 + " stored: " + storedHash.type + " passed in: " + credentialType); 1618 return VerifyCredentialResponse.ERROR; 1619 } 1620 1621 boolean shouldReEnrollBaseZero = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN 1622 && storedHash.isBaseZeroPattern; 1623 1624 String credentialToVerify; 1625 if (shouldReEnrollBaseZero) { 1626 credentialToVerify = LockPatternUtils.patternStringToBaseZero(credential); 1627 } else { 1628 credentialToVerify = credential; 1629 } 1630 1631 response = verifyCredential(userId, storedHash, credentialToVerify, 1632 hasChallenge, challenge, progressCallback); 1633 1634 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 1635 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); 1636 if (shouldReEnrollBaseZero) { 1637 setLockCredentialInternal(credential, storedHash.type, credentialToVerify, 1638 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId); 1639 } 1640 } 1641 1642 return response; 1643 } 1644 1645 @Override 1646 public VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type, 1647 long challenge, int userId) throws RemoteException { 1648 checkPasswordReadPermission(userId); 1649 if (!isManagedProfileWithUnifiedLock(userId)) { 1650 throw new RemoteException("User id must be managed profile with unified lock"); 1651 } 1652 final int parentProfileId = mUserManager.getProfileParent(userId).id; 1653 // Unlock parent by using parent's challenge 1654 final VerifyCredentialResponse parentResponse = doVerifyCredential( 1655 credential, 1656 type, 1657 true /* hasChallenge */, 1658 challenge, 1659 parentProfileId, 1660 null /* progressCallback */); 1661 if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 1662 // Failed, just return parent's response 1663 return parentResponse; 1664 } 1665 1666 try { 1667 // Unlock work profile, and work profile with unified lock must use password only 1668 return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId), 1669 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 1670 true, 1671 challenge, 1672 userId, null /* progressCallback */); 1673 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 1674 | NoSuchAlgorithmException | NoSuchPaddingException 1675 | InvalidAlgorithmParameterException | IllegalBlockSizeException 1676 | BadPaddingException | CertificateException | IOException e) { 1677 Slog.e(TAG, "Failed to decrypt child profile key", e); 1678 throw new RemoteException("Unable to get tied profile token"); 1679 } 1680 } 1681 1682 /** 1683 * Lowest-level credential verification routine that talks to GateKeeper. If verification 1684 * passes, unlock the corresponding user and keystore. Also handles the migration from legacy 1685 * hash to GK. 1686 */ 1687 private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash, 1688 String credential, boolean hasChallenge, long challenge, 1689 ICheckCredentialProgressCallback progressCallback) throws RemoteException { 1690 if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) { 1691 // don't need to pass empty credentials to GateKeeper 1692 return VerifyCredentialResponse.OK; 1693 } 1694 1695 if (storedHash == null || TextUtils.isEmpty(credential)) { 1696 return VerifyCredentialResponse.ERROR; 1697 } 1698 1699 // We're potentially going to be doing a bunch of disk I/O below as part 1700 // of unlocking the user, so yell if calling from the main thread. 1701 StrictMode.noteDiskRead(); 1702 1703 if (storedHash.version == CredentialHash.VERSION_LEGACY) { 1704 final byte[] hash; 1705 if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) { 1706 hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(credential)); 1707 } else { 1708 hash = mLockPatternUtils.passwordToHash(credential, userId); 1709 } 1710 if (Arrays.equals(hash, storedHash.hash)) { 1711 if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) { 1712 unlockKeystore(LockPatternUtils.patternStringToBaseZero(credential), userId); 1713 } else { 1714 unlockKeystore(credential, userId); 1715 } 1716 // Users with legacy credentials don't have credential-backed 1717 // FBE keys, so just pass through a fake token/secret 1718 Slog.i(TAG, "Unlocking user with fake token: " + userId); 1719 final byte[] fakeToken = String.valueOf(userId).getBytes(); 1720 unlockUser(userId, fakeToken, fakeToken); 1721 1722 // migrate credential to GateKeeper 1723 setLockCredentialInternal(credential, storedHash.type, null, 1724 storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN 1725 ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING 1726 : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 1727 /* TODO(roosa): keep the same password quality */, userId); 1728 if (!hasChallenge) { 1729 notifyActivePasswordMetricsAvailable(credential, userId); 1730 // Use credentials to create recoverable keystore snapshot. 1731 mRecoverableKeyStoreManager.lockScreenSecretAvailable( 1732 storedHash.type, credential, userId); 1733 return VerifyCredentialResponse.OK; 1734 } 1735 // Fall through to get the auth token. Technically this should never happen, 1736 // as a user that had a legacy credential would have to unlock their device 1737 // before getting to a flow with a challenge, but supporting for consistency. 1738 } else { 1739 return VerifyCredentialResponse.ERROR; 1740 } 1741 } 1742 GateKeeperResponse gateKeeperResponse = getGateKeeperService() 1743 .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes()); 1744 VerifyCredentialResponse response = convertResponse(gateKeeperResponse); 1745 boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll(); 1746 1747 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 1748 1749 // credential has matched 1750 1751 if (progressCallback != null) { 1752 progressCallback.onCredentialVerified(); 1753 } 1754 notifyActivePasswordMetricsAvailable(credential, userId); 1755 unlockKeystore(credential, userId); 1756 1757 Slog.i(TAG, "Unlocking user " + userId + " with token length " 1758 + response.getPayload().length); 1759 unlockUser(userId, response.getPayload(), secretFromCredential(credential)); 1760 1761 if (isManagedProfileWithSeparatedLock(userId)) { 1762 TrustManager trustManager = 1763 (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); 1764 trustManager.setDeviceLockedForUser(userId, false); 1765 } 1766 int reEnrollQuality = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN 1767 ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING 1768 : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 1769 /* TODO(roosa): keep the same password quality */; 1770 if (shouldReEnroll) { 1771 setLockCredentialInternal(credential, storedHash.type, credential, 1772 reEnrollQuality, userId); 1773 } else { 1774 // Now that we've cleared of all required GK migration, let's do the final 1775 // migration to synthetic password. 1776 synchronized (mSpManager) { 1777 if (shouldMigrateToSyntheticPasswordLocked(userId)) { 1778 AuthenticationToken auth = initializeSyntheticPasswordLocked( 1779 storedHash.hash, credential, storedHash.type, reEnrollQuality, 1780 userId); 1781 activateEscrowTokens(auth, userId); 1782 } 1783 } 1784 } 1785 // Use credentials to create recoverable keystore snapshot. 1786 mRecoverableKeyStoreManager.lockScreenSecretAvailable(storedHash.type, credential, 1787 userId); 1788 1789 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 1790 if (response.getTimeout() > 0) { 1791 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); 1792 } 1793 } 1794 1795 return response; 1796 } 1797 1798 /** 1799 * Call this method to notify DPMS regarding the latest password metric. This should be called 1800 * when the user is authenticating or when a new password is being set. 1801 */ 1802 private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) { 1803 final PasswordMetrics metrics; 1804 if (password == null) { 1805 metrics = new PasswordMetrics(); 1806 } else { 1807 metrics = PasswordMetrics.computeForPassword(password); 1808 metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId); 1809 } 1810 1811 // Asynchronous to avoid dead lock 1812 mHandler.post(() -> { 1813 DevicePolicyManager dpm = (DevicePolicyManager) 1814 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 1815 dpm.setActivePasswordState(metrics, userId); 1816 }); 1817 } 1818 1819 /** 1820 * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before 1821 * reporting the password changed. 1822 */ 1823 private void notifyPasswordChanged(@UserIdInt int userId) { 1824 // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering 1825 mHandler.post(() -> { 1826 DevicePolicyManager dpm = (DevicePolicyManager) 1827 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 1828 dpm.reportPasswordChanged(userId); 1829 }); 1830 } 1831 1832 @Override 1833 public boolean checkVoldPassword(int userId) throws RemoteException { 1834 if (!mFirstCallToVold) { 1835 return false; 1836 } 1837 mFirstCallToVold = false; 1838 1839 checkPasswordReadPermission(userId); 1840 1841 // There's no guarantee that this will safely connect, but if it fails 1842 // we will simply show the lock screen when we shouldn't, so relatively 1843 // benign. There is an outside chance something nasty would happen if 1844 // this service restarted before vold stales out the password in this 1845 // case. The nastiness is limited to not showing the lock screen when 1846 // we should, within the first minute of decrypting the phone if this 1847 // service can't connect to vold, it restarts, and then the new instance 1848 // does successfully connect. 1849 final IStorageManager service = mInjector.getStorageManager(); 1850 String password; 1851 long identity = Binder.clearCallingIdentity(); 1852 try { 1853 password = service.getPassword(); 1854 service.clearPassword(); 1855 } finally { 1856 Binder.restoreCallingIdentity(identity); 1857 } 1858 if (password == null) { 1859 return false; 1860 } 1861 1862 try { 1863 if (mLockPatternUtils.isLockPatternEnabled(userId)) { 1864 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, userId, 1865 null /* progressCallback */) 1866 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) { 1867 return true; 1868 } 1869 } 1870 } catch (Exception e) { 1871 } 1872 1873 try { 1874 if (mLockPatternUtils.isLockPasswordEnabled(userId)) { 1875 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId, 1876 null /* progressCallback */) 1877 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) { 1878 return true; 1879 } 1880 } 1881 } catch (Exception e) { 1882 } 1883 1884 return false; 1885 } 1886 1887 private void removeUser(int userId, boolean unknownUser) { 1888 mSpManager.removeUser(userId); 1889 mStorage.removeUser(userId); 1890 mStrongAuth.removeUser(userId); 1891 tryRemoveUserFromSpCacheLater(userId); 1892 1893 final KeyStore ks = KeyStore.getInstance(); 1894 ks.onUserRemoved(userId); 1895 1896 try { 1897 final IGateKeeperService gk = getGateKeeperService(); 1898 if (gk != null) { 1899 gk.clearSecureUserId(userId); 1900 } 1901 } catch (RemoteException ex) { 1902 Slog.w(TAG, "unable to clear GK secure user id"); 1903 } 1904 if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) { 1905 removeKeystoreProfileKey(userId); 1906 } 1907 } 1908 1909 private void removeKeystoreProfileKey(int targetUserId) { 1910 if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId); 1911 try { 1912 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore"); 1913 keyStore.load(null); 1914 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId); 1915 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId); 1916 } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException 1917 | IOException e) { 1918 // We have tried our best to remove all keys 1919 Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e); 1920 } 1921 } 1922 1923 @Override 1924 public void registerStrongAuthTracker(IStrongAuthTracker tracker) { 1925 checkPasswordReadPermission(UserHandle.USER_ALL); 1926 mStrongAuth.registerStrongAuthTracker(tracker); 1927 } 1928 1929 @Override 1930 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) { 1931 checkPasswordReadPermission(UserHandle.USER_ALL); 1932 mStrongAuth.unregisterStrongAuthTracker(tracker); 1933 } 1934 1935 @Override 1936 public void requireStrongAuth(int strongAuthReason, int userId) { 1937 checkWritePermission(userId); 1938 mStrongAuth.requireStrongAuth(strongAuthReason, userId); 1939 } 1940 1941 @Override 1942 public void userPresent(int userId) { 1943 checkWritePermission(userId); 1944 mStrongAuth.reportUnlock(userId); 1945 } 1946 1947 @Override 1948 public int getStrongAuthForUser(int userId) { 1949 checkPasswordReadPermission(userId); 1950 return mStrongAuthTracker.getStrongAuthForUser(userId); 1951 } 1952 1953 private boolean isCallerShell() { 1954 final int callingUid = Binder.getCallingUid(); 1955 return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; 1956 } 1957 1958 private void enforceShell() { 1959 if (!isCallerShell()) { 1960 throw new SecurityException("Caller must be shell"); 1961 } 1962 } 1963 1964 @Override 1965 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1966 String[] args, ShellCallback callback, ResultReceiver resultReceiver) 1967 throws RemoteException { 1968 enforceShell(); 1969 final long origId = Binder.clearCallingIdentity(); 1970 try { 1971 (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec( 1972 this, in, out, err, args, callback, resultReceiver); 1973 } finally { 1974 Binder.restoreCallingIdentity(origId); 1975 } 1976 } 1977 1978 @Override 1979 public void initRecoveryService(@NonNull String rootCertificateAlias, 1980 @NonNull byte[] signedPublicKeyList) throws RemoteException { 1981 mRecoverableKeyStoreManager.initRecoveryService(rootCertificateAlias, 1982 signedPublicKeyList); 1983 } 1984 1985 @Override 1986 public KeyChainSnapshot getKeyChainSnapshot() throws RemoteException { 1987 return mRecoverableKeyStoreManager.getKeyChainSnapshot(); 1988 } 1989 1990 public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent) 1991 throws RemoteException { 1992 mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent); 1993 } 1994 1995 public Map getRecoverySnapshotVersions() throws RemoteException { 1996 return mRecoverableKeyStoreManager.getRecoverySnapshotVersions(); 1997 } 1998 1999 @Override 2000 public void setServerParams(byte[] serverParams) throws RemoteException { 2001 mRecoverableKeyStoreManager.setServerParams(serverParams); 2002 } 2003 2004 @Override 2005 public void setRecoveryStatus(String alias, int status) throws RemoteException { 2006 mRecoverableKeyStoreManager.setRecoveryStatus(alias, status); 2007 } 2008 2009 public Map getRecoveryStatus() throws RemoteException { 2010 return mRecoverableKeyStoreManager.getRecoveryStatus(); 2011 } 2012 2013 @Override 2014 public void setRecoverySecretTypes(@NonNull @KeyChainProtectionParams.UserSecretType 2015 int[] secretTypes) throws RemoteException { 2016 mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes); 2017 } 2018 2019 @Override 2020 public int[] getRecoverySecretTypes() throws RemoteException { 2021 return mRecoverableKeyStoreManager.getRecoverySecretTypes(); 2022 2023 } 2024 2025 @Override 2026 public int[] getPendingRecoverySecretTypes() throws RemoteException { 2027 throw new SecurityException("Not implemented"); 2028 } 2029 2030 @Override 2031 public void recoverySecretAvailable(@NonNull KeyChainProtectionParams recoverySecret) 2032 throws RemoteException { 2033 mRecoverableKeyStoreManager.recoverySecretAvailable(recoverySecret); 2034 } 2035 2036 @Override 2037 public byte[] startRecoverySession(@NonNull String sessionId, 2038 @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams, 2039 @NonNull byte[] vaultChallenge, @NonNull List<KeyChainProtectionParams> secrets) 2040 throws RemoteException { 2041 return mRecoverableKeyStoreManager.startRecoverySession(sessionId, verifierPublicKey, 2042 vaultParams, vaultChallenge, secrets); 2043 } 2044 2045 @Override 2046 public byte[] startRecoverySessionWithCertPath(@NonNull String sessionId, 2047 @NonNull RecoveryCertPath verifierCertPath, @NonNull byte[] vaultParams, 2048 @NonNull byte[] vaultChallenge, @NonNull List<KeyChainProtectionParams> secrets) 2049 throws RemoteException { 2050 return mRecoverableKeyStoreManager.startRecoverySessionWithCertPath( 2051 sessionId, verifierCertPath, vaultParams, vaultChallenge, secrets); 2052 } 2053 2054 public void closeSession(@NonNull String sessionId) throws RemoteException { 2055 mRecoverableKeyStoreManager.closeSession(sessionId); 2056 } 2057 2058 @Override 2059 public Map<String, byte[]> recoverKeys(@NonNull String sessionId, 2060 @NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys) 2061 throws RemoteException { 2062 return mRecoverableKeyStoreManager.recoverKeys( 2063 sessionId, recoveryKeyBlob, applicationKeys); 2064 } 2065 2066 @Override 2067 public void removeKey(@NonNull String alias) throws RemoteException { 2068 mRecoverableKeyStoreManager.removeKey(alias); 2069 } 2070 2071 @Override 2072 public byte[] generateAndStoreKey(@NonNull String alias) throws RemoteException { 2073 return mRecoverableKeyStoreManager.generateAndStoreKey(alias); 2074 } 2075 2076 @Override 2077 public String generateKey(@NonNull String alias) throws RemoteException { 2078 return mRecoverableKeyStoreManager.generateKey(alias); 2079 } 2080 2081 @Override 2082 public String importKey(@NonNull String alias, byte[] keyBytes) throws RemoteException { 2083 return mRecoverableKeyStoreManager.importKey(alias, keyBytes); 2084 } 2085 2086 @Override 2087 public String getKey(@NonNull String alias) throws RemoteException { 2088 return mRecoverableKeyStoreManager.getKey(alias); 2089 } 2090 2091 private static final String[] VALID_SETTINGS = new String[] { 2092 LockPatternUtils.LOCKOUT_PERMANENT_KEY, 2093 LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, 2094 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, 2095 LockPatternUtils.PASSWORD_TYPE_KEY, 2096 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 2097 LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 2098 LockPatternUtils.DISABLE_LOCKSCREEN_KEY, 2099 LockPatternUtils.LOCKSCREEN_OPTIONS, 2100 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, 2101 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY, 2102 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, 2103 LockPatternUtils.PASSWORD_HISTORY_KEY, 2104 Secure.LOCK_PATTERN_ENABLED, 2105 Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 2106 Secure.LOCK_PATTERN_VISIBLE, 2107 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED 2108 }; 2109 2110 // Reading these settings needs the contacts permission 2111 private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] { 2112 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 2113 Secure.LOCK_SCREEN_OWNER_INFO 2114 }; 2115 2116 // Reading these settings needs the same permission as checking the password 2117 private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] { 2118 LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 2119 LockPatternUtils.PASSWORD_HISTORY_KEY, 2120 LockPatternUtils.PASSWORD_TYPE_KEY, 2121 SEPARATE_PROFILE_CHALLENGE_KEY 2122 }; 2123 2124 private static final String[] SETTINGS_TO_BACKUP = new String[] { 2125 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 2126 Secure.LOCK_SCREEN_OWNER_INFO, 2127 Secure.LOCK_PATTERN_VISIBLE, 2128 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS 2129 }; 2130 2131 private class GateKeeperDiedRecipient implements IBinder.DeathRecipient { 2132 @Override 2133 public void binderDied() { 2134 mGateKeeperService.asBinder().unlinkToDeath(this, 0); 2135 mGateKeeperService = null; 2136 } 2137 } 2138 2139 protected synchronized IGateKeeperService getGateKeeperService() 2140 throws RemoteException { 2141 if (mGateKeeperService != null) { 2142 return mGateKeeperService; 2143 } 2144 2145 final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE); 2146 if (service != null) { 2147 service.linkToDeath(new GateKeeperDiedRecipient(), 0); 2148 mGateKeeperService = IGateKeeperService.Stub.asInterface(service); 2149 return mGateKeeperService; 2150 } 2151 2152 Slog.e(TAG, "Unable to acquire GateKeeperService"); 2153 return null; 2154 } 2155 2156 /** 2157 * A user's synthetic password does not change so it must be cached in certain circumstances to 2158 * enable untrusted credential reset. 2159 * 2160 * Untrusted credential reset will be removed in a future version (b/68036371) at which point 2161 * this cache is no longer needed as the SP will always be known when changing the user's 2162 * credential. 2163 */ 2164 @GuardedBy("mSpManager") 2165 private SparseArray<AuthenticationToken> mSpCache = new SparseArray(); 2166 2167 private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) { 2168 // Preemptively cache the SP and then try to remove it in a handler. 2169 Slog.i(TAG, "Caching SP for user " + userId); 2170 synchronized (mSpManager) { 2171 mSpCache.put(userId, auth); 2172 } 2173 tryRemoveUserFromSpCacheLater(userId); 2174 2175 // Pass the primary user's auth secret to the HAL 2176 if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) { 2177 try { 2178 final byte[] rawSecret = auth.deriveVendorAuthSecret(); 2179 final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length); 2180 for (int i = 0; i < rawSecret.length; ++i) { 2181 secret.add(rawSecret[i]); 2182 } 2183 mAuthSecretService.primaryUserCredential(secret); 2184 } catch (RemoteException e) { 2185 Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e); 2186 } 2187 } 2188 } 2189 2190 private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) { 2191 mHandler.post(() -> { 2192 if (!shouldCacheSpForUser(userId)) { 2193 // The transition from 'should not cache' to 'should cache' can only happen if 2194 // certain admin apps are installed after provisioning e.g. via adb. This is not 2195 // a common case and we do not seamlessly support; it may result in the SP not 2196 // being cached when it is needed. The cache can be re-populated by verifying 2197 // the credential again. 2198 Slog.i(TAG, "Removing SP from cache for user " + userId); 2199 synchronized (mSpManager) { 2200 mSpCache.remove(userId); 2201 } 2202 } 2203 }); 2204 } 2205 2206 /** Do not hold any of the locks from this service when calling. */ 2207 private boolean shouldCacheSpForUser(@UserIdInt int userId) { 2208 // Before the user setup has completed, an admin could be installed that requires the SP to 2209 // be cached (see below). 2210 if (Settings.Secure.getIntForUser(mContext.getContentResolver(), 2211 Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) { 2212 return true; 2213 } 2214 2215 // If the user has an admin which can perform an untrusted credential reset, the SP needs to 2216 // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first 2217 // place so caching is not necessary. 2218 final DevicePolicyManagerInternal dpmi = LocalServices.getService( 2219 DevicePolicyManagerInternal.class); 2220 if (dpmi == null) { 2221 return false; 2222 } 2223 return dpmi.canUserHaveUntrustedCredentialReset(userId); 2224 } 2225 2226 /** 2227 * Precondition: vold and keystore unlocked. 2228 * 2229 * Create new synthetic password, set up synthetic password blob protected by the supplied 2230 * user credential, and make the newly-created SP blob active. 2231 * 2232 * The invariant under a synthetic password is: 2233 * 1. If user credential exists, then both vold and keystore and protected with keys derived 2234 * from the synthetic password. 2235 * 2. If user credential does not exist, vold and keystore protection are cleared. This is to 2236 * make it consistent with current behaviour. It also allows ActivityManager to call 2237 * unlockUser() with empty secret. 2238 * 3. Once a user is migrated to have synthetic password, its value will never change, no matter 2239 * whether the user changes his lockscreen PIN or clear/reset it. When the user clears its 2240 * lockscreen PIN, we still maintain the existing synthetic password in a password blob 2241 * protected by a default PIN. 2242 * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user 2243 * clears/re-creates his lockscreen PIN. 2244 * 2245 * 2246 * Different cases of calling this method: 2247 * 1. credentialHash != null 2248 * This implies credential != null, a new SP blob will be provisioned, and existing SID 2249 * migrated to associate with the new SP. 2250 * This happens during a normal migration case when the user currently has password. 2251 * 2252 * 2. credentialhash == null and credential == null 2253 * A new SP blob and will be created, while the user has no credentials. 2254 * This can happens when we are activating an escrow token on a unsecured device, during 2255 * which we want to create the SP structure with an empty user credential. 2256 * This could also happen during an untrusted reset to clear password. 2257 * 2258 * 3. credentialhash == null and credential != null 2259 * This is the untrusted credential reset, OR the user sets a new lockscreen password 2260 * FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created 2261 */ 2262 @GuardedBy("mSpManager") 2263 @VisibleForTesting 2264 protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash, 2265 String credential, int credentialType, int requestedQuality, 2266 int userId) throws RemoteException { 2267 Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId); 2268 final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid( 2269 getGateKeeperService(), credentialHash, credential, userId); 2270 onAuthTokenKnownForUser(userId, auth); 2271 if (auth == null) { 2272 Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token"); 2273 return null; 2274 } 2275 long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(), 2276 credential, credentialType, auth, requestedQuality, userId); 2277 if (credential != null) { 2278 if (credentialHash == null) { 2279 // Since when initializing SP, we didn't provide an existing password handle 2280 // for it to migrate SID, we need to create a new SID for the user. 2281 mSpManager.newSidForUser(getGateKeeperService(), auth, userId); 2282 } 2283 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 2284 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); 2285 setKeystorePassword(auth.deriveKeyStorePassword(), userId); 2286 } else { 2287 clearUserKeyProtection(userId); 2288 setKeystorePassword(null, userId); 2289 getGateKeeperService().clearSecureUserId(userId); 2290 } 2291 fixateNewestUserKeyAuth(userId); 2292 setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId); 2293 return auth; 2294 } 2295 2296 private long getSyntheticPasswordHandleLocked(int userId) { 2297 return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 2298 SyntheticPasswordManager.DEFAULT_HANDLE, userId); 2299 } 2300 2301 private boolean isSyntheticPasswordBasedCredentialLocked(int userId) throws RemoteException { 2302 if (userId == USER_FRP) { 2303 final int type = mStorage.readPersistentDataBlock().type; 2304 return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER; 2305 } 2306 long handle = getSyntheticPasswordHandleLocked(userId); 2307 // This is a global setting 2308 long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 2309 SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM); 2310 return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE; 2311 } 2312 2313 @VisibleForTesting 2314 protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) throws RemoteException { 2315 long handle = getSyntheticPasswordHandleLocked(userId); 2316 // This is a global setting 2317 long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 2318 SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM); 2319 return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE; 2320 } 2321 2322 private void enableSyntheticPasswordLocked() throws RemoteException { 2323 setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM); 2324 } 2325 2326 private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int 2327 credentialType, boolean hasChallenge, long challenge, int userId, 2328 ICheckCredentialProgressCallback progressCallback) throws RemoteException { 2329 if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId); 2330 if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { 2331 userCredential = null; 2332 } 2333 2334 final AuthenticationResult authResult; 2335 VerifyCredentialResponse response; 2336 synchronized (mSpManager) { 2337 if (!isSyntheticPasswordBasedCredentialLocked(userId)) { 2338 return null; 2339 } 2340 if (userId == USER_FRP) { 2341 return mSpManager.verifyFrpCredential(getGateKeeperService(), 2342 userCredential, credentialType, progressCallback); 2343 } 2344 2345 long handle = getSyntheticPasswordHandleLocked(userId); 2346 authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( 2347 getGateKeeperService(), handle, userCredential, userId, progressCallback); 2348 2349 if (authResult.credentialType != credentialType) { 2350 Slog.e(TAG, "Credential type mismatch."); 2351 return VerifyCredentialResponse.ERROR; 2352 } 2353 response = authResult.gkResponse; 2354 // credential has matched 2355 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2356 // perform verifyChallenge with synthetic password which generates the real GK auth 2357 // token and response for the current user 2358 response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, 2359 challenge, userId); 2360 if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 2361 // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't 2362 // match the recorded GK password handle. 2363 Slog.wtf(TAG, "verifyChallenge with SP failed."); 2364 return VerifyCredentialResponse.ERROR; 2365 } 2366 } 2367 } 2368 2369 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { 2370 notifyActivePasswordMetricsAvailable(userCredential, userId); 2371 unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId); 2372 2373 final byte[] secret = authResult.authToken.deriveDiskEncryptionKey(); 2374 Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length); 2375 unlockUser(userId, null, secret); 2376 2377 activateEscrowTokens(authResult.authToken, userId); 2378 2379 if (isManagedProfileWithSeparatedLock(userId)) { 2380 TrustManager trustManager = 2381 (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); 2382 trustManager.setDeviceLockedForUser(userId, false); 2383 } 2384 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); 2385 2386 onAuthTokenKnownForUser(userId, authResult.authToken); 2387 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { 2388 if (response.getTimeout() > 0) { 2389 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); 2390 } 2391 } 2392 2393 return response; 2394 } 2395 2396 /** 2397 * Change the user's lockscreen password by creating a new SP blob and update the handle, based 2398 * on an existing authentication token. Even though a new SP blob is created, the underlying 2399 * synthetic password is never changed. 2400 * 2401 * When clearing credential, we keep the SP unchanged, but clear its password handle so its 2402 * SID is gone. We also clear password from (software-based) keystore and vold, which will be 2403 * added back when new password is set in future. 2404 */ 2405 @GuardedBy("mSpManager") 2406 private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType, 2407 AuthenticationToken auth, int requestedQuality, int userId) throws RemoteException { 2408 if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId); 2409 long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(), 2410 credential, credentialType, auth, requestedQuality, userId); 2411 final Map<Integer, String> profilePasswords; 2412 if (credential != null) { 2413 // // not needed by synchronizeUnifiedWorkChallengeForProfiles() 2414 profilePasswords = null; 2415 2416 if (mSpManager.hasSidForUser(userId)) { 2417 // We are changing password of a secured device, nothing more needed as 2418 // createPasswordBasedSyntheticPassword has already taken care of maintaining 2419 // the password handle and SID unchanged. 2420 2421 //refresh auth token 2422 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 2423 } else { 2424 // A new password is set on a previously-unsecured device, we need to generate 2425 // a new SID, and re-add keys to vold and keystore. 2426 mSpManager.newSidForUser(getGateKeeperService(), auth, userId); 2427 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId); 2428 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey()); 2429 fixateNewestUserKeyAuth(userId); 2430 setKeystorePassword(auth.deriveKeyStorePassword(), userId); 2431 } 2432 } else { 2433 // Cache all profile password if they use unified work challenge. This will later be 2434 // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles() 2435 profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId); 2436 2437 // we are clearing password of a secured device, so need to nuke SID as well. 2438 mSpManager.clearSidForUser(userId); 2439 getGateKeeperService().clearSecureUserId(userId); 2440 // Clear key from vold so ActivityManager can just unlock the user with empty secret 2441 // during boot. 2442 clearUserKeyProtection(userId); 2443 fixateNewestUserKeyAuth(userId); 2444 setKeystorePassword(null, userId); 2445 } 2446 setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId); 2447 synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords); 2448 2449 notifyActivePasswordMetricsAvailable(credential, userId); 2450 return newHandle; 2451 } 2452 2453 @GuardedBy("mSpManager") 2454 private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType, 2455 String savedCredential, int requestedQuality, int userId) throws RemoteException { 2456 if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId); 2457 if (isManagedProfileWithUnifiedLock(userId)) { 2458 // get credential from keystore when managed profile has unified lock 2459 try { 2460 savedCredential = getDecryptedPasswordForTiedProfile(userId); 2461 } catch (FileNotFoundException e) { 2462 Slog.i(TAG, "Child profile key not found"); 2463 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException 2464 | NoSuchAlgorithmException | NoSuchPaddingException 2465 | InvalidAlgorithmParameterException | IllegalBlockSizeException 2466 | BadPaddingException | CertificateException | IOException e) { 2467 Slog.e(TAG, "Failed to decrypt child profile key", e); 2468 } 2469 } 2470 long handle = getSyntheticPasswordHandleLocked(userId); 2471 AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( 2472 getGateKeeperService(), handle, savedCredential, userId, null); 2473 VerifyCredentialResponse response = authResult.gkResponse; 2474 AuthenticationToken auth = authResult.authToken; 2475 2476 // If existing credential is provided, then it must match. 2477 if (savedCredential != null && auth == null) { 2478 throw new RemoteException("Failed to enroll " + 2479 (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" 2480 : "pattern")); 2481 } 2482 2483 boolean untrustedReset = false; 2484 if (auth != null) { 2485 onAuthTokenKnownForUser(userId, auth); 2486 } else if (response != null 2487 && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { 2488 // We are performing an untrusted credential change, by DevicePolicyManager or other 2489 // internal callers that don't provide the existing credential 2490 Slog.w(TAG, "Untrusted credential change invoked"); 2491 // Try to get a cached auth token, so we can keep SP unchanged. 2492 auth = mSpCache.get(userId); 2493 untrustedReset = true; 2494 } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { 2495 Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " + 2496 (response != null ? "rate limit exceeded" : "failed")); 2497 return; 2498 } 2499 2500 if (auth != null) { 2501 if (untrustedReset) { 2502 // Force change the current SID to mantain existing behaviour that an untrusted 2503 // reset leads to a change of SID. If the untrusted reset is for clearing the 2504 // current password, the nuking of the SID will be done in 2505 // setLockCredentialWithAuthTokenLocked next 2506 mSpManager.newSidForUser(getGateKeeperService(), auth, userId); 2507 } 2508 setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality, 2509 userId); 2510 mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); 2511 } else { 2512 throw new IllegalStateException( 2513 "Untrusted credential reset not possible without cached SP"); 2514 // Could call initializeSyntheticPasswordLocked(null, credential, credentialType, 2515 // requestedQuality, userId) instead if we still allow untrusted reset that changes 2516 // synthetic password. That would invalidate existing escrow tokens though. 2517 } 2518 mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); 2519 } 2520 2521 @Override 2522 public long addEscrowToken(byte[] token, int userId) throws RemoteException { 2523 ensureCallerSystemUid(); 2524 if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId); 2525 synchronized (mSpManager) { 2526 enableSyntheticPasswordLocked(); 2527 // Migrate to synthetic password based credentials if the user has no password, 2528 // the token can then be activated immediately. 2529 AuthenticationToken auth = null; 2530 if (!isUserSecure(userId)) { 2531 if (shouldMigrateToSyntheticPasswordLocked(userId)) { 2532 auth = initializeSyntheticPasswordLocked(null, null, 2533 LockPatternUtils.CREDENTIAL_TYPE_NONE, 2534 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId); 2535 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ { 2536 long pwdHandle = getSyntheticPasswordHandleLocked(userId); 2537 auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(), 2538 pwdHandle, null, userId, null).authToken; 2539 } 2540 } 2541 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 2542 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); 2543 if (!mSpManager.hasEscrowData(userId)) { 2544 throw new SecurityException("Escrow token is disabled on the current user"); 2545 } 2546 } 2547 long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId); 2548 if (auth != null) { 2549 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); 2550 } 2551 return handle; 2552 } 2553 } 2554 2555 private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException { 2556 if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId); 2557 synchronized (mSpManager) { 2558 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); 2559 for (long handle : mSpManager.getPendingTokensForUser(userId)) { 2560 Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId)); 2561 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); 2562 } 2563 } 2564 } 2565 2566 @Override 2567 public boolean isEscrowTokenActive(long handle, int userId) throws RemoteException { 2568 ensureCallerSystemUid(); 2569 synchronized (mSpManager) { 2570 return mSpManager.existsHandle(handle, userId); 2571 } 2572 } 2573 2574 @Override 2575 public boolean removeEscrowToken(long handle, int userId) throws RemoteException { 2576 ensureCallerSystemUid(); 2577 synchronized (mSpManager) { 2578 if (handle == getSyntheticPasswordHandleLocked(userId)) { 2579 Slog.w(TAG, "Cannot remove password handle"); 2580 return false; 2581 } 2582 if (mSpManager.removePendingToken(handle, userId)) { 2583 return true; 2584 } 2585 if (mSpManager.existsHandle(handle, userId)) { 2586 mSpManager.destroyTokenBasedSyntheticPassword(handle, userId); 2587 return true; 2588 } else { 2589 return false; 2590 } 2591 } 2592 } 2593 2594 @Override 2595 public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle, 2596 byte[] token, int requestedQuality, int userId) throws RemoteException { 2597 ensureCallerSystemUid(); 2598 boolean result; 2599 synchronized (mSpManager) { 2600 if (!mSpManager.hasEscrowData(userId)) { 2601 throw new SecurityException("Escrow token is disabled on the current user"); 2602 } 2603 result = setLockCredentialWithTokenInternal(credential, type, tokenHandle, token, 2604 requestedQuality, userId); 2605 } 2606 if (result) { 2607 synchronized (mSeparateChallengeLock) { 2608 setSeparateProfileChallengeEnabledLocked(userId, true, null); 2609 } 2610 notifyPasswordChanged(userId); 2611 notifySeparateProfileChallengeChanged(userId); 2612 } 2613 return result; 2614 } 2615 2616 private boolean setLockCredentialWithTokenInternal(String credential, int type, 2617 long tokenHandle, byte[] token, int requestedQuality, int userId) throws RemoteException { 2618 final AuthenticationResult result; 2619 synchronized (mSpManager) { 2620 result = mSpManager.unwrapTokenBasedSyntheticPassword( 2621 getGateKeeperService(), tokenHandle, token, userId); 2622 if (result.authToken == null) { 2623 Slog.w(TAG, "Invalid escrow token supplied"); 2624 return false; 2625 } 2626 if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { 2627 // Most likely, an untrusted credential reset happened in the past which 2628 // changed the synthetic password 2629 Slog.e(TAG, "Obsolete token: synthetic password derived but it fails GK " 2630 + "verification."); 2631 return false; 2632 } 2633 // Update PASSWORD_TYPE_KEY since it's needed by notifyActivePasswordMetricsAvailable() 2634 // called by setLockCredentialWithAuthTokenLocked(). 2635 // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740 2636 setLong(LockPatternUtils.PASSWORD_TYPE_KEY, requestedQuality, userId); 2637 long oldHandle = getSyntheticPasswordHandleLocked(userId); 2638 setLockCredentialWithAuthTokenLocked(credential, type, result.authToken, 2639 requestedQuality, userId); 2640 mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId); 2641 } 2642 onAuthTokenKnownForUser(userId, result.authToken); 2643 return true; 2644 } 2645 2646 @Override 2647 public void unlockUserWithToken(long tokenHandle, byte[] token, int userId) 2648 throws RemoteException { 2649 ensureCallerSystemUid(); 2650 AuthenticationResult authResult; 2651 synchronized (mSpManager) { 2652 if (!mSpManager.hasEscrowData(userId)) { 2653 throw new SecurityException("Escrow token is disabled on the current user"); 2654 } 2655 authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(), 2656 tokenHandle, token, userId); 2657 if (authResult.authToken == null) { 2658 Slog.w(TAG, "Invalid escrow token supplied"); 2659 return; 2660 } 2661 } 2662 unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey()); 2663 onAuthTokenKnownForUser(userId, authResult.authToken); 2664 } 2665 2666 @Override 2667 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){ 2668 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 2669 2670 pw.println("Current lock settings service state:"); 2671 pw.println(String.format("SP Enabled = %b", 2672 mLockPatternUtils.isSyntheticPasswordEnabled())); 2673 2674 List<UserInfo> users = mUserManager.getUsers(); 2675 for (int user = 0; user < users.size(); user++) { 2676 final int userId = users.get(user).id; 2677 pw.println(" User " + userId); 2678 synchronized (mSpManager) { 2679 pw.println(String.format(" SP Handle = %x", 2680 getSyntheticPasswordHandleLocked(userId))); 2681 } 2682 try { 2683 pw.println(String.format(" SID = %x", 2684 getGateKeeperService().getSecureUserId(userId))); 2685 } catch (RemoteException e) { 2686 // ignore. 2687 } 2688 } 2689 } 2690 2691 private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) { 2692 long ident = Binder.clearCallingIdentity(); 2693 try { 2694 // Managed profile should have escrow enabled 2695 if (mUserManager.getUserInfo(userId).isManagedProfile()) { 2696 Slog.i(TAG, "Managed profile can have escrow token"); 2697 return; 2698 } 2699 DevicePolicyManager dpm = mInjector.getDevicePolicyManager(); 2700 // Devices with Device Owner should have escrow enabled on all users. 2701 if (dpm.getDeviceOwnerComponentOnAnyUser() != null) { 2702 Slog.i(TAG, "Corp-owned device can have escrow token"); 2703 return; 2704 } 2705 // We could also have a profile owner on the given (non-managed) user for unicorn cases 2706 if (dpm.getProfileOwnerAsUser(userId) != null) { 2707 Slog.i(TAG, "User with profile owner can have escrow token"); 2708 return; 2709 } 2710 // If the device is yet to be provisioned (still in SUW), there is still 2711 // a chance that Device Owner will be set on the device later, so postpone 2712 // disabling escrow token for now. 2713 if (!dpm.isDeviceProvisioned()) { 2714 Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned"); 2715 return; 2716 } 2717 2718 // Escrow tokens are enabled on automotive builds. 2719 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 2720 return; 2721 } 2722 2723 // Disable escrow token permanently on all other device/user types. 2724 Slog.i(TAG, "Disabling escrow token on user " + userId); 2725 if (isSyntheticPasswordBasedCredentialLocked(userId)) { 2726 mSpManager.destroyEscrowData(userId); 2727 } 2728 } catch (RemoteException e) { 2729 Slog.e(TAG, "disableEscrowTokenOnNonManagedDevices", e); 2730 } finally { 2731 Binder.restoreCallingIdentity(ident); 2732 } 2733 } 2734 2735 private void ensureCallerSystemUid() throws SecurityException { 2736 final int callingUid = mInjector.binderGetCallingUid(); 2737 if (callingUid != Process.SYSTEM_UID) { 2738 throw new SecurityException("Only system can call this API."); 2739 } 2740 } 2741 2742 private class DeviceProvisionedObserver extends ContentObserver { 2743 private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor( 2744 Settings.Global.DEVICE_PROVISIONED); 2745 private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor( 2746 Settings.Secure.USER_SETUP_COMPLETE); 2747 2748 private boolean mRegistered; 2749 2750 public DeviceProvisionedObserver() { 2751 super(null); 2752 } 2753 2754 @Override 2755 public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) { 2756 if (mDeviceProvisionedUri.equals(uri)) { 2757 updateRegistration(); 2758 2759 if (isProvisioned()) { 2760 Slog.i(TAG, "Reporting device setup complete to IGateKeeperService"); 2761 reportDeviceSetupComplete(); 2762 clearFrpCredentialIfOwnerNotSecure(); 2763 } 2764 } else if (mUserSetupCompleteUri.equals(uri)) { 2765 tryRemoveUserFromSpCacheLater(userId); 2766 } 2767 } 2768 2769 public void onSystemReady() { 2770 if (frpCredentialEnabled(mContext)) { 2771 updateRegistration(); 2772 } else { 2773 // If we don't intend to use frpCredentials and we're not provisioned yet, send 2774 // deviceSetupComplete immediately, so gatekeeper can discard any lingering 2775 // credentials immediately. 2776 if (!isProvisioned()) { 2777 Slog.i(TAG, "FRP credential disabled, reporting device setup complete " 2778 + "to Gatekeeper immediately"); 2779 reportDeviceSetupComplete(); 2780 } 2781 } 2782 } 2783 2784 private void reportDeviceSetupComplete() { 2785 try { 2786 getGateKeeperService().reportDeviceSetupComplete(); 2787 } catch (RemoteException e) { 2788 Slog.e(TAG, "Failure reporting to IGateKeeperService", e); 2789 } 2790 } 2791 2792 /** 2793 * Clears the FRP credential if the user that controls it does not have a secure 2794 * lockscreen. 2795 */ 2796 private void clearFrpCredentialIfOwnerNotSecure() { 2797 List<UserInfo> users = mUserManager.getUsers(); 2798 for (UserInfo user : users) { 2799 if (userOwnsFrpCredential(mContext, user)) { 2800 if (!isUserSecure(user.id)) { 2801 mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id, 2802 0, null); 2803 } 2804 return; 2805 } 2806 } 2807 } 2808 2809 private void updateRegistration() { 2810 boolean register = !isProvisioned(); 2811 if (register == mRegistered) { 2812 return; 2813 } 2814 if (register) { 2815 mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri, 2816 false, this); 2817 mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri, 2818 false, this, UserHandle.USER_ALL); 2819 } else { 2820 mContext.getContentResolver().unregisterContentObserver(this); 2821 } 2822 mRegistered = register; 2823 } 2824 2825 private boolean isProvisioned() { 2826 return Settings.Global.getInt(mContext.getContentResolver(), 2827 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 2828 } 2829 } 2830} 2831