Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server;
     18 
     19 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
     20 import static android.Manifest.permission.READ_CONTACTS;
     21 import static android.content.Context.KEYGUARD_SERVICE;
     22 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
     23 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
     24 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
     25 
     26 import android.annotation.UserIdInt;
     27 import android.app.ActivityManager;
     28 import android.app.IActivityManager;
     29 import android.app.KeyguardManager;
     30 import android.app.Notification;
     31 import android.app.NotificationManager;
     32 import android.app.PendingIntent;
     33 import android.app.admin.DevicePolicyManager;
     34 import android.app.admin.PasswordMetrics;
     35 import android.app.backup.BackupManager;
     36 import android.app.trust.IStrongAuthTracker;
     37 import android.app.trust.TrustManager;
     38 import android.content.BroadcastReceiver;
     39 import android.content.ContentResolver;
     40 import android.content.Context;
     41 import android.content.Intent;
     42 import android.content.IntentFilter;
     43 import android.content.pm.PackageManager;
     44 import android.content.pm.UserInfo;
     45 import android.content.res.Resources;
     46 import android.database.sqlite.SQLiteDatabase;
     47 import android.os.Binder;
     48 import android.os.Bundle;
     49 import android.os.Handler;
     50 import android.os.IBinder;
     51 import android.os.IProgressListener;
     52 import android.os.Process;
     53 import android.os.RemoteException;
     54 import android.os.ResultReceiver;
     55 import android.os.ServiceManager;
     56 import android.os.ShellCallback;
     57 import android.os.StrictMode;
     58 import android.os.SystemProperties;
     59 import android.os.UserHandle;
     60 import android.os.UserManager;
     61 import android.os.storage.IStorageManager;
     62 import android.os.storage.StorageManager;
     63 import android.provider.Settings;
     64 import android.provider.Settings.Secure;
     65 import android.provider.Settings.SettingNotFoundException;
     66 import android.security.GateKeeper;
     67 import android.security.KeyStore;
     68 import android.security.keystore.AndroidKeyStoreProvider;
     69 import android.security.keystore.KeyProperties;
     70 import android.security.keystore.KeyProtection;
     71 import android.service.gatekeeper.GateKeeperResponse;
     72 import android.service.gatekeeper.IGateKeeperService;
     73 import android.text.TextUtils;
     74 import android.util.ArrayMap;
     75 import android.util.Log;
     76 import android.util.Slog;
     77 
     78 import com.android.internal.annotations.VisibleForTesting;
     79 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
     80 import com.android.internal.notification.SystemNotificationChannels;
     81 import com.android.internal.util.ArrayUtils;
     82 import com.android.internal.util.DumpUtils;
     83 import com.android.internal.widget.ICheckCredentialProgressCallback;
     84 import com.android.internal.widget.ILockSettings;
     85 import com.android.internal.widget.LockPatternUtils;
     86 import com.android.internal.widget.VerifyCredentialResponse;
     87 import com.android.server.LockSettingsStorage.CredentialHash;
     88 import com.android.server.SyntheticPasswordManager.AuthenticationResult;
     89 import com.android.server.SyntheticPasswordManager.AuthenticationToken;
     90 
     91 import libcore.util.HexEncoding;
     92 
     93 import java.io.ByteArrayOutputStream;
     94 import java.io.FileDescriptor;
     95 import java.io.FileNotFoundException;
     96 import java.io.IOException;
     97 import java.io.PrintWriter;
     98 import java.nio.charset.StandardCharsets;
     99 import java.security.InvalidAlgorithmParameterException;
    100 import java.security.InvalidKeyException;
    101 import java.security.KeyStoreException;
    102 import java.security.MessageDigest;
    103 import java.security.NoSuchAlgorithmException;
    104 import java.security.SecureRandom;
    105 import java.security.UnrecoverableKeyException;
    106 import java.security.cert.CertificateException;
    107 import java.util.ArrayList;
    108 import java.util.Arrays;
    109 import java.util.List;
    110 import java.util.Map;
    111 import java.util.concurrent.CountDownLatch;
    112 import java.util.concurrent.TimeUnit;
    113 
    114 import javax.crypto.BadPaddingException;
    115 import javax.crypto.Cipher;
    116 import javax.crypto.IllegalBlockSizeException;
    117 import javax.crypto.KeyGenerator;
    118 import javax.crypto.NoSuchPaddingException;
    119 import javax.crypto.SecretKey;
    120 import javax.crypto.spec.GCMParameterSpec;
    121 
    122 /**
    123  * Keeps the lock pattern/password data and related settings for each user. Used by
    124  * LockPatternUtils. Needs to be a service because Settings app also needs to be able to save
    125  * lockscreen information for secondary users.
    126  *
    127  * @hide
    128  */
    129 public class LockSettingsService extends ILockSettings.Stub {
    130     private static final String TAG = "LockSettingsService";
    131     private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
    132     private static final boolean DEBUG = false;
    133 
    134     private static final int PROFILE_KEY_IV_SIZE = 12;
    135     private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
    136 
    137     // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
    138     private final Object mSeparateChallengeLock = new Object();
    139 
    140     private final Injector mInjector;
    141     private final Context mContext;
    142     private final Handler mHandler;
    143     @VisibleForTesting
    144     protected final LockSettingsStorage mStorage;
    145     private final LockSettingsStrongAuth mStrongAuth;
    146     private final SynchronizedStrongAuthTracker mStrongAuthTracker;
    147 
    148     private final LockPatternUtils mLockPatternUtils;
    149     private final NotificationManager mNotificationManager;
    150     private final UserManager mUserManager;
    151     private final IActivityManager mActivityManager;
    152 
    153     private final KeyStore mKeyStore;
    154 
    155     private boolean mFirstCallToVold;
    156     protected IGateKeeperService mGateKeeperService;
    157     private SyntheticPasswordManager mSpManager;
    158 
    159     /**
    160      * The UIDs that are used for system credential storage in keystore.
    161      */
    162     private static final int[] SYSTEM_CREDENTIAL_UIDS = {
    163             Process.WIFI_UID, Process.VPN_UID,
    164             Process.ROOT_UID, Process.SYSTEM_UID };
    165 
    166     // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
    167     // devices. The most basic of these is to show/hide notifications about missing features until
    168     // the user unlocks the account and credential-encrypted storage is available.
    169     public static final class Lifecycle extends SystemService {
    170         private LockSettingsService mLockSettingsService;
    171 
    172         public Lifecycle(Context context) {
    173             super(context);
    174         }
    175 
    176         @Override
    177         public void onStart() {
    178             AndroidKeyStoreProvider.install();
    179             mLockSettingsService = new LockSettingsService(getContext());
    180             publishBinderService("lock_settings", mLockSettingsService);
    181         }
    182 
    183         @Override
    184         public void onStartUser(int userHandle) {
    185             mLockSettingsService.onStartUser(userHandle);
    186         }
    187 
    188         @Override
    189         public void onUnlockUser(int userHandle) {
    190             mLockSettingsService.onUnlockUser(userHandle);
    191         }
    192 
    193         @Override
    194         public void onCleanupUser(int userHandle) {
    195             mLockSettingsService.onCleanupUser(userHandle);
    196         }
    197     }
    198 
    199     @VisibleForTesting
    200     protected static class SynchronizedStrongAuthTracker
    201             extends LockPatternUtils.StrongAuthTracker {
    202         public SynchronizedStrongAuthTracker(Context context) {
    203             super(context);
    204         }
    205 
    206         @Override
    207         protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) {
    208             synchronized (this) {
    209                 super.handleStrongAuthRequiredChanged(strongAuthFlags, userId);
    210             }
    211         }
    212 
    213         @Override
    214         public int getStrongAuthForUser(int userId) {
    215             synchronized (this) {
    216                 return super.getStrongAuthForUser(userId);
    217             }
    218         }
    219 
    220         void register(LockSettingsStrongAuth strongAuth) {
    221             strongAuth.registerStrongAuthTracker(this.mStub);
    222         }
    223     }
    224 
    225     /**
    226      * Tie managed profile to primary profile if it is in unified mode and not tied before.
    227      *
    228      * @param managedUserId Managed profile user Id
    229      * @param managedUserPassword Managed profile original password (when it has separated lock).
    230      *            NULL when it does not have a separated lock before.
    231      */
    232     public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
    233         if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
    234         // Only for managed profile
    235         if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
    236             return;
    237         }
    238         // Do not tie managed profile when work challenge is enabled
    239         if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
    240             return;
    241         }
    242         // Do not tie managed profile to parent when it's done already
    243         if (mStorage.hasChildProfileLock(managedUserId)) {
    244             return;
    245         }
    246         // Do not tie it to parent when parent does not have a screen lock
    247         final int parentId = mUserManager.getProfileParent(managedUserId).id;
    248         if (!isUserSecure(parentId)) {
    249             if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
    250             return;
    251         }
    252         // Do not tie when the parent has no SID (but does have a screen lock).
    253         // This can only happen during an upgrade path where SID is yet to be
    254         // generated when the user unlocks for the first time.
    255         try {
    256             if (getGateKeeperService().getSecureUserId(parentId) == 0) {
    257                 return;
    258             }
    259         } catch (RemoteException e) {
    260             Slog.e(TAG, "Failed to talk to GateKeeper service", e);
    261             return;
    262         }
    263         if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
    264         byte[] randomLockSeed = new byte[] {};
    265         try {
    266             randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
    267             String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
    268             setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
    269                     managedUserPassword, managedUserId);
    270             // We store a private credential for the managed user that's unlocked by the primary
    271             // account holder's credential. As such, the user will never be prompted to enter this
    272             // password directly, so we always store a password.
    273             setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
    274                     DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, managedUserId);
    275             tieProfileLockToParent(managedUserId, newPassword);
    276         } catch (NoSuchAlgorithmException | RemoteException e) {
    277             Slog.e(TAG, "Fail to tie managed profile", e);
    278             // Nothing client can do to fix this issue, so we do not throw exception out
    279         }
    280     }
    281 
    282     static class Injector {
    283 
    284         protected Context mContext;
    285 
    286         public Injector(Context context) {
    287             mContext = context;
    288         }
    289 
    290         public Context getContext() {
    291             return mContext;
    292         }
    293 
    294         public Handler getHandler() {
    295             return new Handler();
    296         }
    297 
    298         public LockSettingsStorage getStorage() {
    299             final LockSettingsStorage storage = new LockSettingsStorage(mContext);
    300             storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
    301                 @Override
    302                 public void initialize(SQLiteDatabase db) {
    303                     // Get the lockscreen default from a system property, if available
    304                     boolean lockScreenDisable = SystemProperties.getBoolean(
    305                             "ro.lockscreen.disable.default", false);
    306                     if (lockScreenDisable) {
    307                         storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
    308                     }
    309                 }
    310             });
    311             return storage;
    312         }
    313 
    314         public LockSettingsStrongAuth getStrongAuth() {
    315             return new LockSettingsStrongAuth(mContext);
    316         }
    317 
    318         public SynchronizedStrongAuthTracker getStrongAuthTracker() {
    319             return new SynchronizedStrongAuthTracker(mContext);
    320         }
    321 
    322         public IActivityManager getActivityManager() {
    323             return ActivityManager.getService();
    324         }
    325 
    326         public LockPatternUtils getLockPatternUtils() {
    327             return new LockPatternUtils(mContext);
    328         }
    329 
    330         public NotificationManager getNotificationManager() {
    331             return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    332         }
    333 
    334         public UserManager getUserManager() {
    335             return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    336         }
    337 
    338         public DevicePolicyManager getDevicePolicyManager() {
    339             return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
    340         }
    341 
    342         public KeyStore getKeyStore() {
    343             return KeyStore.getInstance();
    344         }
    345 
    346         public IStorageManager getStorageManager() {
    347             final IBinder service = ServiceManager.getService("mount");
    348             if (service != null) {
    349                 return IStorageManager.Stub.asInterface(service);
    350             }
    351             return null;
    352         }
    353 
    354         public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
    355             return new SyntheticPasswordManager(storage);
    356         }
    357 
    358         public int binderGetCallingUid() {
    359             return Binder.getCallingUid();
    360         }
    361     }
    362 
    363     public LockSettingsService(Context context) {
    364         this(new Injector(context));
    365     }
    366 
    367     @VisibleForTesting
    368     protected LockSettingsService(Injector injector) {
    369         mInjector = injector;
    370         mContext = injector.getContext();
    371         mKeyStore = injector.getKeyStore();
    372         mHandler = injector.getHandler();
    373         mStrongAuth = injector.getStrongAuth();
    374         mActivityManager = injector.getActivityManager();
    375 
    376         mLockPatternUtils = injector.getLockPatternUtils();
    377         mFirstCallToVold = true;
    378 
    379         IntentFilter filter = new IntentFilter();
    380         filter.addAction(Intent.ACTION_USER_ADDED);
    381         filter.addAction(Intent.ACTION_USER_STARTING);
    382         filter.addAction(Intent.ACTION_USER_REMOVED);
    383         injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
    384                 null, null);
    385 
    386         mStorage = injector.getStorage();
    387         mNotificationManager = injector.getNotificationManager();
    388         mUserManager = injector.getUserManager();
    389         mStrongAuthTracker = injector.getStrongAuthTracker();
    390         mStrongAuthTracker.register(mStrongAuth);
    391 
    392         mSpManager = injector.getSyntheticPasswordManager(mStorage);
    393     }
    394 
    395     /**
    396      * If the account is credential-encrypted, show notification requesting the user to unlock the
    397      * device.
    398      */
    399     private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
    400         final UserInfo user = mUserManager.getUserInfo(userId);
    401         if (!user.isManagedProfile()) {
    402             // When the user is locked, we communicate it loud-and-clear
    403             // on the lockscreen; we only show a notification below for
    404             // locked managed profiles.
    405             return;
    406         }
    407 
    408         final UserHandle userHandle = user.getUserHandle();
    409         final boolean isSecure = isUserSecure(userId);
    410         if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
    411             UserInfo parent = mUserManager.getProfileParent(userId);
    412             if (parent != null &&
    413                     mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
    414                     !mUserManager.isQuietModeEnabled(userHandle)) {
    415                 // Only show notifications for managed profiles once their parent
    416                 // user is unlocked.
    417                 showEncryptionNotificationForProfile(userHandle);
    418             }
    419         }
    420     }
    421 
    422     private void showEncryptionNotificationForProfile(UserHandle user) {
    423         Resources r = mContext.getResources();
    424         CharSequence title = r.getText(
    425                 com.android.internal.R.string.user_encrypted_title);
    426         CharSequence message = r.getText(
    427                 com.android.internal.R.string.profile_encrypted_message);
    428         CharSequence detail = r.getText(
    429                 com.android.internal.R.string.profile_encrypted_detail);
    430 
    431         final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
    432         final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
    433                 user.getIdentifier());
    434         if (unlockIntent == null) {
    435             return;
    436         }
    437         unlockIntent.setFlags(
    438                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    439         PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
    440                 PendingIntent.FLAG_UPDATE_CURRENT);
    441 
    442         showEncryptionNotification(user, title, message, detail, intent);
    443     }
    444 
    445     private void showEncryptionNotification(UserHandle user, CharSequence title,
    446             CharSequence message, CharSequence detail, PendingIntent intent) {
    447         if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
    448 
    449         // Suppress all notifications on non-FBE devices for now
    450         if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
    451 
    452         Notification notification =
    453                 new Notification.Builder(mContext, SystemNotificationChannels.SECURITY)
    454                         .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
    455                         .setWhen(0)
    456                         .setOngoing(true)
    457                         .setTicker(title)
    458                         .setColor(mContext.getColor(
    459                                 com.android.internal.R.color.system_notification_accent_color))
    460                         .setContentTitle(title)
    461                         .setContentText(message)
    462                         .setSubText(detail)
    463                         .setVisibility(Notification.VISIBILITY_PUBLIC)
    464                         .setContentIntent(intent)
    465                         .build();
    466         mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
    467             notification, user);
    468     }
    469 
    470     private void hideEncryptionNotification(UserHandle userHandle) {
    471         if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
    472         mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
    473             userHandle);
    474     }
    475 
    476     public void onCleanupUser(int userId) {
    477         hideEncryptionNotification(new UserHandle(userId));
    478     }
    479 
    480     public void onStartUser(final int userId) {
    481         maybeShowEncryptionNotificationForUser(userId);
    482     }
    483 
    484     public void onUnlockUser(final int userId) {
    485         // Perform tasks which require locks in LSS on a handler, as we are callbacks from
    486         // ActivityManager.unlockUser()
    487         mHandler.post(new Runnable() {
    488             @Override
    489             public void run() {
    490                 // Hide notification first, as tie managed profile lock takes time
    491                 hideEncryptionNotification(new UserHandle(userId));
    492 
    493                 // Now we have unlocked the parent user we should show notifications
    494                 // about any profiles that exist.
    495                 List<UserInfo> profiles = mUserManager.getProfiles(userId);
    496                 for (int i = 0; i < profiles.size(); i++) {
    497                     UserInfo profile = profiles.get(i);
    498                     final boolean isSecure = isUserSecure(profile.id);
    499                     if (isSecure && profile.isManagedProfile()) {
    500                         UserHandle userHandle = profile.getUserHandle();
    501                         if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
    502                                 !mUserManager.isQuietModeEnabled(userHandle)) {
    503                             showEncryptionNotificationForProfile(userHandle);
    504                         }
    505                     }
    506                 }
    507 
    508                 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
    509                     tieManagedProfileLockIfNecessary(userId, null);
    510                 }
    511             }
    512         });
    513     }
    514 
    515     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    516         @Override
    517         public void onReceive(Context context, Intent intent) {
    518             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
    519                 // Notify keystore that a new user was added.
    520                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
    521                 if (userHandle > UserHandle.USER_SYSTEM) {
    522                     removeUser(userHandle, /* unknownUser= */ true);
    523                 }
    524                 final KeyStore ks = KeyStore.getInstance();
    525                 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
    526                 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
    527                 ks.onUserAdded(userHandle, parentHandle);
    528             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
    529                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
    530                 mStorage.prefetchUser(userHandle);
    531             } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
    532                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
    533                 if (userHandle > 0) {
    534                     removeUser(userHandle, /* unknownUser= */ false);
    535                 }
    536             }
    537         }
    538     };
    539 
    540     @Override // binder interface
    541     public void systemReady() {
    542         migrateOldData();
    543         try {
    544             getGateKeeperService();
    545         } catch (RemoteException e) {
    546             Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
    547         }
    548         // TODO: maybe skip this for split system user mode.
    549         mStorage.prefetchUser(UserHandle.USER_SYSTEM);
    550     }
    551 
    552     private void migrateOldData() {
    553         try {
    554             // These Settings moved before multi-user was enabled, so we only have to do it for the
    555             // root user.
    556             if (getString("migrated", null, 0) == null) {
    557                 final ContentResolver cr = mContext.getContentResolver();
    558                 for (String validSetting : VALID_SETTINGS) {
    559                     String value = Settings.Secure.getString(cr, validSetting);
    560                     if (value != null) {
    561                         setString(validSetting, value, 0);
    562                     }
    563                 }
    564                 // No need to move the password / pattern files. They're already in the right place.
    565                 setString("migrated", "true", 0);
    566                 Slog.i(TAG, "Migrated lock settings to new location");
    567             }
    568 
    569             // These Settings changed after multi-user was enabled, hence need to be moved per user.
    570             if (getString("migrated_user_specific", null, 0) == null) {
    571                 final ContentResolver cr = mContext.getContentResolver();
    572                 List<UserInfo> users = mUserManager.getUsers();
    573                 for (int user = 0; user < users.size(); user++) {
    574                     // Migrate owner info
    575                     final int userId = users.get(user).id;
    576                     final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
    577                     String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
    578                     if (!TextUtils.isEmpty(ownerInfo)) {
    579                         setString(OWNER_INFO, ownerInfo, userId);
    580                         Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
    581                     }
    582 
    583                     // Migrate owner info enabled. Note there was a bug where older platforms only
    584                     // stored this value if the checkbox was toggled at least once. The code detects
    585                     // this case by handling the exception.
    586                     final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
    587                     boolean enabled;
    588                     try {
    589                         int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
    590                         enabled = ivalue != 0;
    591                         setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
    592                     } catch (SettingNotFoundException e) {
    593                         // Setting was never stored. Store it if the string is not empty.
    594                         if (!TextUtils.isEmpty(ownerInfo)) {
    595                             setLong(OWNER_INFO_ENABLED, 1, userId);
    596                         }
    597                     }
    598                     Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
    599                 }
    600                 // No need to move the password / pattern files. They're already in the right place.
    601                 setString("migrated_user_specific", "true", 0);
    602                 Slog.i(TAG, "Migrated per-user lock settings to new location");
    603             }
    604 
    605             // Migrates biometric weak such that the fallback mechanism becomes the primary.
    606             if (getString("migrated_biometric_weak", null, 0) == null) {
    607                 List<UserInfo> users = mUserManager.getUsers();
    608                 for (int i = 0; i < users.size(); i++) {
    609                     int userId = users.get(i).id;
    610                     long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
    611                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    612                             userId);
    613                     long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
    614                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    615                             userId);
    616                     if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
    617                         setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
    618                                 alternateType,
    619                                 userId);
    620                     }
    621                     setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
    622                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    623                             userId);
    624                 }
    625                 setString("migrated_biometric_weak", "true", 0);
    626                 Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
    627             }
    628 
    629             // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one
    630             // user was present on the system, so if we're upgrading to M and there is more than one
    631             // user we disable the flag to remain consistent.
    632             if (getString("migrated_lockscreen_disabled", null, 0) == null) {
    633                 final List<UserInfo> users = mUserManager.getUsers();
    634                 final int userCount = users.size();
    635                 int switchableUsers = 0;
    636                 for (int i = 0; i < userCount; i++) {
    637                     if (users.get(i).supportsSwitchTo()) {
    638                         switchableUsers++;
    639                     }
    640                 }
    641 
    642                 if (switchableUsers > 1) {
    643                     for (int i = 0; i < userCount; i++) {
    644                         int id = users.get(i).id;
    645 
    646                         if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
    647                             setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
    648                         }
    649                     }
    650                 }
    651 
    652                 setString("migrated_lockscreen_disabled", "true", 0);
    653                 Slog.i(TAG, "Migrated lockscreen disabled flag");
    654             }
    655 
    656             final List<UserInfo> users = mUserManager.getUsers();
    657             for (int i = 0; i < users.size(); i++) {
    658                 final UserInfo userInfo = users.get(i);
    659                 if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
    660                     // When managed profile has a unified lock, the password quality stored has 2
    661                     // possibilities only.
    662                     // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
    663                     // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
    664                     // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
    665                     // unified lock.
    666                     final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
    667                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
    668                     if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    669                         // Only possible when it's upgraded from nyc dp3
    670                         Slog.i(TAG, "Migrated tied profile lock type");
    671                         setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
    672                                 DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
    673                     } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
    674                         // It should not happen
    675                         Slog.e(TAG, "Invalid tied profile lock type: " + quality);
    676                     }
    677                 }
    678                 try {
    679                     final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
    680                     java.security.KeyStore keyStore =
    681                             java.security.KeyStore.getInstance("AndroidKeyStore");
    682                     keyStore.load(null);
    683                     if (keyStore.containsAlias(alias)) {
    684                         keyStore.deleteEntry(alias);
    685                     }
    686                 } catch (KeyStoreException | NoSuchAlgorithmException |
    687                         CertificateException | IOException e) {
    688                     Slog.e(TAG, "Unable to remove tied profile key", e);
    689                 }
    690             }
    691 
    692             boolean isWatch = mContext.getPackageManager().hasSystemFeature(
    693                     PackageManager.FEATURE_WATCH);
    694             // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts
    695             // and device management the lockscreen must be re-enabled now for users that upgrade.
    696             if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
    697                 final int userCount = users.size();
    698                 for (int i = 0; i < userCount; i++) {
    699                     int id = users.get(i).id;
    700                     setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
    701                 }
    702                 setString("migrated_wear_lockscreen_disabled", "true", 0);
    703                 Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
    704             }
    705         } catch (RemoteException re) {
    706             Slog.e(TAG, "Unable to migrate old data", re);
    707         }
    708     }
    709 
    710     private final void checkWritePermission(int userId) {
    711         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
    712     }
    713 
    714     private final void checkPasswordReadPermission(int userId) {
    715         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
    716     }
    717 
    718     private final void checkReadPermission(String requestedKey, int userId) {
    719         final int callingUid = Binder.getCallingUid();
    720 
    721         for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
    722             String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
    723             if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
    724                     != PackageManager.PERMISSION_GRANTED) {
    725                 throw new SecurityException("uid=" + callingUid
    726                         + " needs permission " + READ_CONTACTS + " to read "
    727                         + requestedKey + " for user " + userId);
    728             }
    729         }
    730 
    731         for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
    732             String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
    733             if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
    734                     != PackageManager.PERMISSION_GRANTED) {
    735                 throw new SecurityException("uid=" + callingUid
    736                         + " needs permission " + PERMISSION + " to read "
    737                         + requestedKey + " for user " + userId);
    738             }
    739         }
    740     }
    741 
    742     @Override
    743     public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
    744         checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
    745         synchronized (mSeparateChallengeLock) {
    746             return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
    747         }
    748     }
    749 
    750     @Override
    751     public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
    752             String managedUserPassword) throws RemoteException {
    753         checkWritePermission(userId);
    754         synchronized (mSeparateChallengeLock) {
    755             setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
    756             if (enabled) {
    757                 mStorage.removeChildProfileLock(userId);
    758                 removeKeystoreProfileKey(userId);
    759             } else {
    760                 tieManagedProfileLockIfNecessary(userId, managedUserPassword);
    761             }
    762         }
    763     }
    764 
    765     @Override
    766     public void setBoolean(String key, boolean value, int userId) throws RemoteException {
    767         checkWritePermission(userId);
    768         setStringUnchecked(key, userId, value ? "1" : "0");
    769     }
    770 
    771     @Override
    772     public void setLong(String key, long value, int userId) throws RemoteException {
    773         checkWritePermission(userId);
    774         setStringUnchecked(key, userId, Long.toString(value));
    775     }
    776 
    777     @Override
    778     public void setString(String key, String value, int userId) throws RemoteException {
    779         checkWritePermission(userId);
    780         setStringUnchecked(key, userId, value);
    781     }
    782 
    783     private void setStringUnchecked(String key, int userId, String value) {
    784         mStorage.writeKeyValue(key, value, userId);
    785         if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
    786             BackupManager.dataChanged("com.android.providers.settings");
    787         }
    788     }
    789 
    790     @Override
    791     public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
    792         checkReadPermission(key, userId);
    793         String value = getStringUnchecked(key, null, userId);
    794         return TextUtils.isEmpty(value) ?
    795                 defaultValue : (value.equals("1") || value.equals("true"));
    796     }
    797 
    798     @Override
    799     public long getLong(String key, long defaultValue, int userId) throws RemoteException {
    800         checkReadPermission(key, userId);
    801         String value = getStringUnchecked(key, null, userId);
    802         return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
    803     }
    804 
    805     @Override
    806     public String getString(String key, String defaultValue, int userId) throws RemoteException {
    807         checkReadPermission(key, userId);
    808         return getStringUnchecked(key, defaultValue, userId);
    809     }
    810 
    811     public String getStringUnchecked(String key, String defaultValue, int userId) {
    812         if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
    813             long ident = Binder.clearCallingIdentity();
    814             try {
    815                 return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
    816             } finally {
    817                 Binder.restoreCallingIdentity(ident);
    818             }
    819         }
    820 
    821         if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
    822             key = Settings.Secure.LOCK_PATTERN_ENABLED;
    823         }
    824 
    825         return mStorage.readKeyValue(key, defaultValue, userId);
    826     }
    827 
    828     @Override
    829     public boolean havePassword(int userId) throws RemoteException {
    830         synchronized (mSpManager) {
    831             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
    832                 long handle = getSyntheticPasswordHandleLocked(userId);
    833                 return mSpManager.getCredentialType(handle, userId) ==
    834                         LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
    835             }
    836         }
    837         // Do we need a permissions check here?
    838         return mStorage.hasPassword(userId);
    839     }
    840 
    841     @Override
    842     public boolean havePattern(int userId) throws RemoteException {
    843         synchronized (mSpManager) {
    844             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
    845                 long handle = getSyntheticPasswordHandleLocked(userId);
    846                 return mSpManager.getCredentialType(handle, userId) ==
    847                         LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
    848             }
    849         }
    850         // Do we need a permissions check here?
    851         return mStorage.hasPattern(userId);
    852     }
    853 
    854     private boolean isUserSecure(int userId) {
    855         synchronized (mSpManager) {
    856             try {
    857                 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
    858                     long handle = getSyntheticPasswordHandleLocked(userId);
    859                     return mSpManager.getCredentialType(handle, userId) !=
    860                             LockPatternUtils.CREDENTIAL_TYPE_NONE;
    861                 }
    862             } catch (RemoteException e) {
    863                 // fall through
    864             }
    865         }
    866         return mStorage.hasCredential(userId);
    867     }
    868 
    869     private void setKeystorePassword(String password, int userHandle) {
    870         final KeyStore ks = KeyStore.getInstance();
    871         ks.onUserPasswordChanged(userHandle, password);
    872     }
    873 
    874     private void unlockKeystore(String password, int userHandle) {
    875         if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
    876         final KeyStore ks = KeyStore.getInstance();
    877         ks.unlock(userHandle, password);
    878     }
    879 
    880     @VisibleForTesting
    881     protected String getDecryptedPasswordForTiedProfile(int userId)
    882             throws KeyStoreException, UnrecoverableKeyException,
    883             NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
    884             InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
    885             CertificateException, IOException {
    886         if (DEBUG) Slog.v(TAG, "Get child profile decrytped key");
    887         byte[] storedData = mStorage.readChildProfileLock(userId);
    888         if (storedData == null) {
    889             throw new FileNotFoundException("Child profile lock file not found");
    890         }
    891         byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
    892         byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
    893                 storedData.length);
    894         byte[] decryptionResult;
    895         java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
    896         keyStore.load(null);
    897         SecretKey decryptionKey = (SecretKey) keyStore.getKey(
    898                 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
    899 
    900         Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
    901                 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
    902 
    903         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
    904         decryptionResult = cipher.doFinal(encryptedPassword);
    905         return new String(decryptionResult, StandardCharsets.UTF_8);
    906     }
    907 
    908     private void unlockChildProfile(int profileHandle) throws RemoteException {
    909         try {
    910             doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
    911                     LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
    912                     false, 0 /* no challenge */, profileHandle, null /* progressCallback */);
    913         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
    914                 | NoSuchAlgorithmException | NoSuchPaddingException
    915                 | InvalidAlgorithmParameterException | IllegalBlockSizeException
    916                 | BadPaddingException | CertificateException | IOException e) {
    917             if (e instanceof FileNotFoundException) {
    918                 Slog.i(TAG, "Child profile key not found");
    919             } else {
    920                 Slog.e(TAG, "Failed to decrypt child profile key", e);
    921             }
    922         }
    923     }
    924 
    925     private void unlockUser(int userId, byte[] token, byte[] secret) {
    926         // TODO: make this method fully async so we can update UI with progress strings
    927         final CountDownLatch latch = new CountDownLatch(1);
    928         final IProgressListener listener = new IProgressListener.Stub() {
    929             @Override
    930             public void onStarted(int id, Bundle extras) throws RemoteException {
    931                 Log.d(TAG, "unlockUser started");
    932             }
    933 
    934             @Override
    935             public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
    936                 Log.d(TAG, "unlockUser progress " + progress);
    937             }
    938 
    939             @Override
    940             public void onFinished(int id, Bundle extras) throws RemoteException {
    941                 Log.d(TAG, "unlockUser finished");
    942                 latch.countDown();
    943             }
    944         };
    945 
    946         try {
    947             mActivityManager.unlockUser(userId, token, secret, listener);
    948         } catch (RemoteException e) {
    949             throw e.rethrowAsRuntimeException();
    950         }
    951 
    952         try {
    953             latch.await(15, TimeUnit.SECONDS);
    954         } catch (InterruptedException e) {
    955             Thread.currentThread().interrupt();
    956         }
    957         try {
    958             if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
    959                 final List<UserInfo> profiles = mUserManager.getProfiles(userId);
    960                 for (UserInfo pi : profiles) {
    961                     // Unlock managed profile with unified lock
    962                     if (pi.isManagedProfile()
    963                             && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
    964                             && mStorage.hasChildProfileLock(pi.id)
    965                             && mUserManager.isUserRunning(pi.id)) {
    966                         unlockChildProfile(pi.id);
    967                     }
    968                 }
    969             }
    970         } catch (RemoteException e) {
    971             Log.d(TAG, "Failed to unlock child profile", e);
    972         }
    973     }
    974 
    975     private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
    976         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
    977             return null;
    978         }
    979         Map<Integer, String> result = new ArrayMap<Integer, String>();
    980         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
    981         final int size = profiles.size();
    982         for (int i = 0; i < size; i++) {
    983             final UserInfo profile = profiles.get(i);
    984             if (!profile.isManagedProfile()) {
    985                 continue;
    986             }
    987             final int managedUserId = profile.id;
    988             if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
    989                 continue;
    990             }
    991             try {
    992                 result.put(userId, getDecryptedPasswordForTiedProfile(userId));
    993             } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException
    994                     | NoSuchPaddingException | InvalidKeyException
    995                     | InvalidAlgorithmParameterException | IllegalBlockSizeException
    996                     | BadPaddingException | CertificateException | IOException e) {
    997                 // ignore
    998             }
    999         }
   1000         return result;
   1001     }
   1002 
   1003     /**
   1004      * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
   1005      * depending on the parent user's secure state.
   1006      *
   1007      * When clearing tied work challenges, a pre-computed password table for profiles are required,
   1008      * since changing password for profiles requires existing password, and existing passwords can
   1009      * only be computed before the parent user's password is cleared.
   1010      *
   1011      * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
   1012      * method again on profiles. However the recursion is guaranteed to terminate as this method
   1013      * terminates when the user is a managed profile.
   1014      */
   1015     private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
   1016             Map<Integer, String> profilePasswordMap) throws RemoteException {
   1017         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
   1018             return;
   1019         }
   1020         final boolean isSecure = isUserSecure(userId);
   1021         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
   1022         final int size = profiles.size();
   1023         for (int i = 0; i < size; i++) {
   1024             final UserInfo profile = profiles.get(i);
   1025             if (profile.isManagedProfile()) {
   1026                 final int managedUserId = profile.id;
   1027                 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
   1028                     continue;
   1029                 }
   1030                 if (isSecure) {
   1031                     tieManagedProfileLockIfNecessary(managedUserId, null);
   1032                 } else {
   1033                     // We use cached work profile password computed before clearing the parent's
   1034                     // credential, otherwise they get lost
   1035                     if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) {
   1036                         setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
   1037                                 profilePasswordMap.get(managedUserId), managedUserId);
   1038                     } else {
   1039                         Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
   1040                         // Supplying null here would lead to untrusted credential change
   1041                         setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
   1042                                 managedUserId);
   1043                     }
   1044                     mStorage.removeChildProfileLock(managedUserId);
   1045                     removeKeystoreProfileKey(managedUserId);
   1046                 }
   1047             }
   1048         }
   1049     }
   1050 
   1051     private boolean isManagedProfileWithUnifiedLock(int userId) {
   1052         return mUserManager.getUserInfo(userId).isManagedProfile()
   1053                 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
   1054     }
   1055 
   1056     private boolean isManagedProfileWithSeparatedLock(int userId) {
   1057         return mUserManager.getUserInfo(userId).isManagedProfile()
   1058                 && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
   1059     }
   1060 
   1061     // This method should be called by LockPatternUtil only, all internal methods in this class
   1062     // should call setLockCredentialInternal.
   1063     @Override
   1064     public void setLockCredential(String credential, int type, String savedCredential, int userId)
   1065             throws RemoteException {
   1066         checkWritePermission(userId);
   1067         synchronized (mSeparateChallengeLock) {
   1068             setLockCredentialInternal(credential, type, savedCredential, userId);
   1069             setSeparateProfileChallengeEnabled(userId, true, null);
   1070             notifyPasswordChanged(userId);
   1071         }
   1072     }
   1073 
   1074     private void setLockCredentialInternal(String credential, int credentialType,
   1075             String savedCredential, int userId) throws RemoteException {
   1076         // Normalize savedCredential and credential such that empty string is always represented
   1077         // as null.
   1078         if (TextUtils.isEmpty(savedCredential)) {
   1079             savedCredential = null;
   1080         }
   1081         if (TextUtils.isEmpty(credential)) {
   1082             credential = null;
   1083         }
   1084         synchronized (mSpManager) {
   1085             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
   1086                 spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential,
   1087                         userId);
   1088                 return;
   1089             }
   1090         }
   1091         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
   1092             if (credential != null) {
   1093                 Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
   1094             }
   1095             clearUserKeyProtection(userId);
   1096             getGateKeeperService().clearSecureUserId(userId);
   1097             mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
   1098             setKeystorePassword(null, userId);
   1099             fixateNewestUserKeyAuth(userId);
   1100             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
   1101             notifyActivePasswordMetricsAvailable(null, userId);
   1102             return;
   1103         }
   1104         if (credential == null) {
   1105             throw new RemoteException("Null credential with mismatched credential type");
   1106         }
   1107 
   1108         CredentialHash currentHandle = mStorage.readCredentialHash(userId);
   1109         if (isManagedProfileWithUnifiedLock(userId)) {
   1110             // get credential from keystore when managed profile has unified lock
   1111             if (savedCredential == null) {
   1112                 try {
   1113                     savedCredential = getDecryptedPasswordForTiedProfile(userId);
   1114                 } catch (FileNotFoundException e) {
   1115                     Slog.i(TAG, "Child profile key not found");
   1116                 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
   1117                         | NoSuchAlgorithmException | NoSuchPaddingException
   1118                         | InvalidAlgorithmParameterException | IllegalBlockSizeException
   1119                         | BadPaddingException | CertificateException | IOException e) {
   1120                     Slog.e(TAG, "Failed to decrypt child profile key", e);
   1121                 }
   1122             }
   1123         } else {
   1124             if (currentHandle.hash == null) {
   1125                 if (savedCredential != null) {
   1126                     Slog.w(TAG, "Saved credential provided, but none stored");
   1127                 }
   1128                 savedCredential = null;
   1129             }
   1130         }
   1131         synchronized (mSpManager) {
   1132             if (shouldMigrateToSyntheticPasswordLocked(userId)) {
   1133                 initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential,
   1134                         currentHandle.type, userId);
   1135                 spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential,
   1136                         userId);
   1137                 return;
   1138             }
   1139         }
   1140         if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
   1141         byte[] enrolledHandle = enrollCredential(currentHandle.hash, savedCredential, credential,
   1142                 userId);
   1143         if (enrolledHandle != null) {
   1144             CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType);
   1145             mStorage.writeCredentialHash(willStore, userId);
   1146             // push new secret and auth token to vold
   1147             GateKeeperResponse gkResponse = getGateKeeperService()
   1148                     .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
   1149             setUserKeyProtection(userId, credential, convertResponse(gkResponse));
   1150             fixateNewestUserKeyAuth(userId);
   1151             // Refresh the auth token
   1152             doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
   1153             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
   1154         } else {
   1155             throw new RemoteException("Failed to enroll " +
   1156                     (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
   1157                             : "pattern"));
   1158         }
   1159     }
   1160 
   1161     private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) {
   1162         VerifyCredentialResponse response;
   1163         int responseCode = gateKeeperResponse.getResponseCode();
   1164         if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
   1165             response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
   1166         } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
   1167             byte[] token = gateKeeperResponse.getPayload();
   1168             if (token == null) {
   1169                 // something's wrong if there's no payload with a challenge
   1170                 Slog.e(TAG, "verifyChallenge response had no associated payload");
   1171                 response = VerifyCredentialResponse.ERROR;
   1172             } else {
   1173                 response = new VerifyCredentialResponse(token);
   1174             }
   1175         } else {
   1176             response = VerifyCredentialResponse.ERROR;
   1177         }
   1178         return response;
   1179     }
   1180 
   1181     @VisibleForTesting
   1182     protected void tieProfileLockToParent(int userId, String password) {
   1183         if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
   1184         byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
   1185         byte[] encryptionResult;
   1186         byte[] iv;
   1187         try {
   1188             KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
   1189             keyGenerator.init(new SecureRandom());
   1190             SecretKey secretKey = keyGenerator.generateKey();
   1191             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
   1192             keyStore.load(null);
   1193             try {
   1194                 keyStore.setEntry(
   1195                         LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
   1196                         new java.security.KeyStore.SecretKeyEntry(secretKey),
   1197                         new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
   1198                                 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
   1199                                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
   1200                                 .build());
   1201                 keyStore.setEntry(
   1202                         LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
   1203                         new java.security.KeyStore.SecretKeyEntry(secretKey),
   1204                         new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
   1205                                 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
   1206                                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
   1207                                 .setUserAuthenticationRequired(true)
   1208                                 .setUserAuthenticationValidityDurationSeconds(30)
   1209                                 .build());
   1210                 // Key imported, obtain a reference to it.
   1211                 SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
   1212                         LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
   1213                 Cipher cipher = Cipher.getInstance(
   1214                         KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
   1215                                 + KeyProperties.ENCRYPTION_PADDING_NONE);
   1216                 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
   1217                 encryptionResult = cipher.doFinal(randomLockSeed);
   1218                 iv = cipher.getIV();
   1219             } finally {
   1220                 // The original key can now be discarded.
   1221                 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
   1222             }
   1223         } catch (CertificateException | UnrecoverableKeyException
   1224                 | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
   1225                 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
   1226             throw new RuntimeException("Failed to encrypt key", e);
   1227         }
   1228         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
   1229         try {
   1230             if (iv.length != PROFILE_KEY_IV_SIZE) {
   1231                 throw new RuntimeException("Invalid iv length: " + iv.length);
   1232             }
   1233             outputStream.write(iv);
   1234             outputStream.write(encryptionResult);
   1235         } catch (IOException e) {
   1236             throw new RuntimeException("Failed to concatenate byte arrays", e);
   1237         }
   1238         mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
   1239     }
   1240 
   1241     private byte[] enrollCredential(byte[] enrolledHandle,
   1242             String enrolledCredential, String toEnroll, int userId)
   1243             throws RemoteException {
   1244         checkWritePermission(userId);
   1245         byte[] enrolledCredentialBytes = enrolledCredential == null
   1246                 ? null
   1247                 : enrolledCredential.getBytes();
   1248         byte[] toEnrollBytes = toEnroll == null
   1249                 ? null
   1250                 : toEnroll.getBytes();
   1251         GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
   1252                 enrolledCredentialBytes, toEnrollBytes);
   1253 
   1254         if (response == null) {
   1255             return null;
   1256         }
   1257 
   1258         byte[] hash = response.getPayload();
   1259         if (hash != null) {
   1260             setKeystorePassword(toEnroll, userId);
   1261         } else {
   1262             // Should not happen
   1263             Slog.e(TAG, "Throttled while enrolling a password");
   1264         }
   1265         return hash;
   1266     }
   1267 
   1268     private void setAuthlessUserKeyProtection(int userId, byte[] key) throws RemoteException {
   1269         if (DEBUG) Slog.d(TAG, "setAuthlessUserKeyProtectiond: user=" + userId);
   1270         addUserKeyAuth(userId, null, key);
   1271     }
   1272 
   1273     private void setUserKeyProtection(int userId, String credential, VerifyCredentialResponse vcr)
   1274             throws RemoteException {
   1275         if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
   1276         if (vcr == null) {
   1277             throw new RemoteException("Null response verifying a credential we just set");
   1278         }
   1279         if (vcr.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
   1280             throw new RemoteException("Non-OK response verifying a credential we just set: "
   1281                     + vcr.getResponseCode());
   1282         }
   1283         byte[] token = vcr.getPayload();
   1284         if (token == null) {
   1285             throw new RemoteException("Empty payload verifying a credential we just set");
   1286         }
   1287         addUserKeyAuth(userId, token, secretFromCredential(credential));
   1288     }
   1289 
   1290     private void clearUserKeyProtection(int userId) throws RemoteException {
   1291         if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
   1292         addUserKeyAuth(userId, null, null);
   1293     }
   1294 
   1295     private static byte[] secretFromCredential(String credential) throws RemoteException {
   1296         try {
   1297             MessageDigest digest = MessageDigest.getInstance("SHA-512");
   1298             // Personalize the hash
   1299             byte[] personalization = "Android FBE credential hash"
   1300                     .getBytes(StandardCharsets.UTF_8);
   1301             // Pad it to the block size of the hash function
   1302             personalization = Arrays.copyOf(personalization, 128);
   1303             digest.update(personalization);
   1304             digest.update(credential.getBytes(StandardCharsets.UTF_8));
   1305             return digest.digest();
   1306         } catch (NoSuchAlgorithmException e) {
   1307             throw new RuntimeException("NoSuchAlgorithmException for SHA-512");
   1308         }
   1309     }
   1310 
   1311     private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
   1312             throws RemoteException {
   1313         final UserInfo userInfo = mUserManager.getUserInfo(userId);
   1314         final IStorageManager storageManager = mInjector.getStorageManager();
   1315         final long callingId = Binder.clearCallingIdentity();
   1316         try {
   1317             storageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
   1318         } finally {
   1319             Binder.restoreCallingIdentity(callingId);
   1320         }
   1321     }
   1322 
   1323     private void fixateNewestUserKeyAuth(int userId)
   1324             throws RemoteException {
   1325         if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId);
   1326         final IStorageManager storageManager = mInjector.getStorageManager();
   1327         final long callingId = Binder.clearCallingIdentity();
   1328         try {
   1329             storageManager.fixateNewestUserKeyAuth(userId);
   1330         } finally {
   1331             Binder.restoreCallingIdentity(callingId);
   1332         }
   1333     }
   1334 
   1335     @Override
   1336     public void resetKeyStore(int userId) throws RemoteException {
   1337         checkWritePermission(userId);
   1338         if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
   1339         int managedUserId = -1;
   1340         String managedUserDecryptedPassword = null;
   1341         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
   1342         for (UserInfo pi : profiles) {
   1343             // Unlock managed profile with unified lock
   1344             if (pi.isManagedProfile()
   1345                     && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
   1346                     && mStorage.hasChildProfileLock(pi.id)) {
   1347                 try {
   1348                     if (managedUserId == -1) {
   1349                         managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id);
   1350                         managedUserId = pi.id;
   1351                     } else {
   1352                         // Should not happen
   1353                         Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId
   1354                                 + ", uid2:" + pi.id);
   1355                     }
   1356                 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
   1357                         | NoSuchAlgorithmException | NoSuchPaddingException
   1358                         | InvalidAlgorithmParameterException | IllegalBlockSizeException
   1359                         | BadPaddingException | CertificateException | IOException e) {
   1360                     Slog.e(TAG, "Failed to decrypt child profile key", e);
   1361                 }
   1362             }
   1363         }
   1364         try {
   1365             // Clear all the users credentials could have been installed in for this user.
   1366             for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
   1367                 for (int uid : SYSTEM_CREDENTIAL_UIDS) {
   1368                     mKeyStore.clearUid(UserHandle.getUid(profileId, uid));
   1369                 }
   1370             }
   1371         } finally {
   1372             if (managedUserId != -1 && managedUserDecryptedPassword != null) {
   1373                 if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
   1374                 tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
   1375             }
   1376         }
   1377     }
   1378 
   1379     @Override
   1380     public VerifyCredentialResponse checkCredential(String credential, int type, int userId,
   1381             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
   1382         checkPasswordReadPermission(userId);
   1383         return doVerifyCredential(credential, type, false, 0, userId, progressCallback);
   1384     }
   1385 
   1386     @Override
   1387     public VerifyCredentialResponse verifyCredential(String credential, int type, long challenge,
   1388             int userId) throws RemoteException {
   1389         checkPasswordReadPermission(userId);
   1390         return doVerifyCredential(credential, type, true, challenge, userId,
   1391                 null /* progressCallback */);
   1392     }
   1393 
   1394     /**
   1395      * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
   1396      * format.
   1397      */
   1398     private VerifyCredentialResponse doVerifyCredential(String credential, int credentialType,
   1399             boolean hasChallenge, long challenge, int userId,
   1400             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
   1401         if (TextUtils.isEmpty(credential)) {
   1402             throw new IllegalArgumentException("Credential can't be null or empty");
   1403         }
   1404         synchronized (mSpManager) {
   1405             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
   1406                 VerifyCredentialResponse response = spBasedDoVerifyCredentialLocked(credential,
   1407                         credentialType, hasChallenge, challenge, userId, progressCallback);
   1408                 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
   1409                     mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
   1410                 }
   1411                 return response;
   1412             }
   1413         }
   1414         CredentialHash storedHash = mStorage.readCredentialHash(userId);
   1415         if (storedHash.type != credentialType) {
   1416             Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
   1417                     + " stored: " + storedHash.type + " passed in: " + credentialType);
   1418             return VerifyCredentialResponse.ERROR;
   1419         }
   1420 
   1421         boolean shouldReEnrollBaseZero = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
   1422                 && storedHash.isBaseZeroPattern;
   1423 
   1424         String credentialToVerify;
   1425         if (shouldReEnrollBaseZero) {
   1426             credentialToVerify = LockPatternUtils.patternStringToBaseZero(credential);
   1427         } else {
   1428             credentialToVerify = credential;
   1429         }
   1430 
   1431         VerifyCredentialResponse response = verifyCredential(userId, storedHash, credentialToVerify,
   1432                 hasChallenge, challenge, progressCallback);
   1433 
   1434         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
   1435             mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
   1436             if (shouldReEnrollBaseZero) {
   1437                 setLockCredentialInternal(credential, storedHash.type, credentialToVerify, userId);
   1438             }
   1439         }
   1440 
   1441         return response;
   1442     }
   1443 
   1444     @Override
   1445     public VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type,
   1446             long challenge, int userId) throws RemoteException {
   1447         checkPasswordReadPermission(userId);
   1448         if (!isManagedProfileWithUnifiedLock(userId)) {
   1449             throw new RemoteException("User id must be managed profile with unified lock");
   1450         }
   1451         final int parentProfileId = mUserManager.getProfileParent(userId).id;
   1452         // Unlock parent by using parent's challenge
   1453         final VerifyCredentialResponse parentResponse = doVerifyCredential(
   1454                 credential,
   1455                 type,
   1456                 true /* hasChallenge */,
   1457                 challenge,
   1458                 parentProfileId,
   1459                 null /* progressCallback */);
   1460         if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
   1461             // Failed, just return parent's response
   1462             return parentResponse;
   1463         }
   1464 
   1465         try {
   1466             // Unlock work profile, and work profile with unified lock must use password only
   1467             return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
   1468                     LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
   1469                     true,
   1470                     challenge,
   1471                     userId, null /* progressCallback */);
   1472         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
   1473                 | NoSuchAlgorithmException | NoSuchPaddingException
   1474                 | InvalidAlgorithmParameterException | IllegalBlockSizeException
   1475                 | BadPaddingException | CertificateException | IOException e) {
   1476             Slog.e(TAG, "Failed to decrypt child profile key", e);
   1477             throw new RemoteException("Unable to get tied profile token");
   1478         }
   1479     }
   1480 
   1481     /**
   1482      * Lowest-level credential verification routine that talks to GateKeeper. If verification
   1483      * passes, unlock the corresponding user and keystore. Also handles the migration from legacy
   1484      * hash to GK.
   1485      */
   1486     private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
   1487             String credential, boolean hasChallenge, long challenge,
   1488             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
   1489         if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
   1490             // don't need to pass empty credentials to GateKeeper
   1491             return VerifyCredentialResponse.OK;
   1492         }
   1493 
   1494         if (storedHash == null || TextUtils.isEmpty(credential)) {
   1495             return VerifyCredentialResponse.ERROR;
   1496         }
   1497 
   1498         // We're potentially going to be doing a bunch of disk I/O below as part
   1499         // of unlocking the user, so yell if calling from the main thread.
   1500         StrictMode.noteDiskRead();
   1501 
   1502         if (storedHash.version == CredentialHash.VERSION_LEGACY) {
   1503             final byte[] hash;
   1504             if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
   1505                 hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(credential));
   1506             } else {
   1507                 hash = mLockPatternUtils.passwordToHash(credential, userId);
   1508             }
   1509             if (Arrays.equals(hash, storedHash.hash)) {
   1510                 if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
   1511                     unlockKeystore(LockPatternUtils.patternStringToBaseZero(credential), userId);
   1512                 } else {
   1513                     unlockKeystore(credential, userId);
   1514                 }
   1515                 // Users with legacy credentials don't have credential-backed
   1516                 // FBE keys, so just pass through a fake token/secret
   1517                 Slog.i(TAG, "Unlocking user with fake token: " + userId);
   1518                 final byte[] fakeToken = String.valueOf(userId).getBytes();
   1519                 unlockUser(userId, fakeToken, fakeToken);
   1520 
   1521                 // migrate credential to GateKeeper
   1522                 setLockCredentialInternal(credential, storedHash.type, null, userId);
   1523                 if (!hasChallenge) {
   1524                     notifyActivePasswordMetricsAvailable(credential, userId);
   1525                     return VerifyCredentialResponse.OK;
   1526                 }
   1527                 // Fall through to get the auth token. Technically this should never happen,
   1528                 // as a user that had a legacy credential would have to unlock their device
   1529                 // before getting to a flow with a challenge, but supporting for consistency.
   1530             } else {
   1531                 return VerifyCredentialResponse.ERROR;
   1532             }
   1533         }
   1534         GateKeeperResponse gateKeeperResponse = getGateKeeperService()
   1535                 .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
   1536         VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
   1537         boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
   1538 
   1539         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
   1540 
   1541             // credential has matched
   1542 
   1543             if (progressCallback != null) {
   1544                 progressCallback.onCredentialVerified();
   1545             }
   1546             notifyActivePasswordMetricsAvailable(credential, userId);
   1547             unlockKeystore(credential, userId);
   1548 
   1549             Slog.i(TAG, "Unlocking user " + userId + " with token length "
   1550                     + response.getPayload().length);
   1551             unlockUser(userId, response.getPayload(), secretFromCredential(credential));
   1552 
   1553             if (isManagedProfileWithSeparatedLock(userId)) {
   1554                 TrustManager trustManager =
   1555                         (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
   1556                 trustManager.setDeviceLockedForUser(userId, false);
   1557             }
   1558             if (shouldReEnroll) {
   1559                 setLockCredentialInternal(credential, storedHash.type, credential, userId);
   1560             } else {
   1561                 // Now that we've cleared of all required GK migration, let's do the final
   1562                 // migration to synthetic password.
   1563                 synchronized (mSpManager) {
   1564                     if (shouldMigrateToSyntheticPasswordLocked(userId)) {
   1565                         AuthenticationToken auth = initializeSyntheticPasswordLocked(
   1566                                 storedHash.hash, credential, storedHash.type, userId);
   1567                         activateEscrowTokens(auth, userId);
   1568                     }
   1569                 }
   1570             }
   1571         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
   1572             if (response.getTimeout() > 0) {
   1573                 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
   1574             }
   1575         }
   1576 
   1577         return response;
   1578     }
   1579 
   1580     private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
   1581         final PasswordMetrics metrics;
   1582         if (password == null) {
   1583             metrics = new PasswordMetrics();
   1584         } else {
   1585             metrics = PasswordMetrics.computeForPassword(password);
   1586             metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
   1587         }
   1588 
   1589         // Asynchronous to avoid dead lock
   1590         mHandler.post(() -> {
   1591             DevicePolicyManager dpm = (DevicePolicyManager)
   1592                     mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
   1593             dpm.setActivePasswordState(metrics, userId);
   1594         });
   1595     }
   1596 
   1597     /**
   1598      * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
   1599      * reporting the password changed.
   1600      */
   1601     private void notifyPasswordChanged(@UserIdInt int userId) {
   1602         // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
   1603         mHandler.post(() -> {
   1604             DevicePolicyManager dpm = (DevicePolicyManager)
   1605                     mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
   1606             dpm.reportPasswordChanged(userId);
   1607         });
   1608     }
   1609 
   1610     @Override
   1611     public boolean checkVoldPassword(int userId) throws RemoteException {
   1612         if (!mFirstCallToVold) {
   1613             return false;
   1614         }
   1615         mFirstCallToVold = false;
   1616 
   1617         checkPasswordReadPermission(userId);
   1618 
   1619         // There's no guarantee that this will safely connect, but if it fails
   1620         // we will simply show the lock screen when we shouldn't, so relatively
   1621         // benign. There is an outside chance something nasty would happen if
   1622         // this service restarted before vold stales out the password in this
   1623         // case. The nastiness is limited to not showing the lock screen when
   1624         // we should, within the first minute of decrypting the phone if this
   1625         // service can't connect to vold, it restarts, and then the new instance
   1626         // does successfully connect.
   1627         final IStorageManager service = mInjector.getStorageManager();
   1628         String password;
   1629         long identity = Binder.clearCallingIdentity();
   1630         try {
   1631             password = service.getPassword();
   1632             service.clearPassword();
   1633         } finally {
   1634             Binder.restoreCallingIdentity(identity);
   1635         }
   1636         if (password == null) {
   1637             return false;
   1638         }
   1639 
   1640         try {
   1641             if (mLockPatternUtils.isLockPatternEnabled(userId)) {
   1642                 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, userId,
   1643                         null /* progressCallback */)
   1644                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
   1645                     return true;
   1646                 }
   1647             }
   1648         } catch (Exception e) {
   1649         }
   1650 
   1651         try {
   1652             if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
   1653                 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId,
   1654                         null /* progressCallback */)
   1655                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
   1656                     return true;
   1657                 }
   1658             }
   1659         } catch (Exception e) {
   1660         }
   1661 
   1662         return false;
   1663     }
   1664 
   1665     private void removeUser(int userId, boolean unknownUser) {
   1666         mStorage.removeUser(userId);
   1667         mStrongAuth.removeUser(userId);
   1668 
   1669         final KeyStore ks = KeyStore.getInstance();
   1670         ks.onUserRemoved(userId);
   1671 
   1672         try {
   1673             final IGateKeeperService gk = getGateKeeperService();
   1674             if (gk != null) {
   1675                 gk.clearSecureUserId(userId);
   1676             }
   1677         } catch (RemoteException ex) {
   1678             Slog.w(TAG, "unable to clear GK secure user id");
   1679         }
   1680         if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
   1681             removeKeystoreProfileKey(userId);
   1682         }
   1683     }
   1684 
   1685     private void removeKeystoreProfileKey(int targetUserId) {
   1686         if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
   1687         try {
   1688             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
   1689             keyStore.load(null);
   1690             keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
   1691             keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
   1692         } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
   1693                 | IOException e) {
   1694             // We have tried our best to remove all keys
   1695             Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
   1696         }
   1697     }
   1698 
   1699     @Override
   1700     public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
   1701         checkPasswordReadPermission(UserHandle.USER_ALL);
   1702         mStrongAuth.registerStrongAuthTracker(tracker);
   1703     }
   1704 
   1705     @Override
   1706     public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
   1707         checkPasswordReadPermission(UserHandle.USER_ALL);
   1708         mStrongAuth.unregisterStrongAuthTracker(tracker);
   1709     }
   1710 
   1711     @Override
   1712     public void requireStrongAuth(int strongAuthReason, int userId) {
   1713         checkWritePermission(userId);
   1714         mStrongAuth.requireStrongAuth(strongAuthReason, userId);
   1715     }
   1716 
   1717     @Override
   1718     public void userPresent(int userId) {
   1719         checkWritePermission(userId);
   1720         mStrongAuth.reportUnlock(userId);
   1721     }
   1722 
   1723     @Override
   1724     public int getStrongAuthForUser(int userId) {
   1725         checkPasswordReadPermission(userId);
   1726         return mStrongAuthTracker.getStrongAuthForUser(userId);
   1727     }
   1728 
   1729     private boolean isCallerShell() {
   1730         final int callingUid = Binder.getCallingUid();
   1731         return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
   1732     }
   1733 
   1734     private void enforceShell() {
   1735         if (!isCallerShell()) {
   1736             throw new SecurityException("Caller must be shell");
   1737         }
   1738     }
   1739 
   1740     @Override
   1741     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
   1742             String[] args, ShellCallback callback, ResultReceiver resultReceiver)
   1743             throws RemoteException {
   1744         enforceShell();
   1745         final long origId = Binder.clearCallingIdentity();
   1746         try {
   1747             (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
   1748                     this, in, out, err, args, callback, resultReceiver);
   1749         } finally {
   1750             Binder.restoreCallingIdentity(origId);
   1751         }
   1752     }
   1753 
   1754     private static final String[] VALID_SETTINGS = new String[] {
   1755             LockPatternUtils.LOCKOUT_PERMANENT_KEY,
   1756             LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
   1757             LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
   1758             LockPatternUtils.PASSWORD_TYPE_KEY,
   1759             LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
   1760             LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
   1761             LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
   1762             LockPatternUtils.LOCKSCREEN_OPTIONS,
   1763             LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
   1764             LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
   1765             LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
   1766             LockPatternUtils.PASSWORD_HISTORY_KEY,
   1767             Secure.LOCK_PATTERN_ENABLED,
   1768             Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
   1769             Secure.LOCK_PATTERN_VISIBLE,
   1770             Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
   1771     };
   1772 
   1773     // Reading these settings needs the contacts permission
   1774     private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
   1775             Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
   1776             Secure.LOCK_SCREEN_OWNER_INFO
   1777     };
   1778 
   1779     // Reading these settings needs the same permission as checking the password
   1780     private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
   1781             LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
   1782             LockPatternUtils.PASSWORD_HISTORY_KEY,
   1783             LockPatternUtils.PASSWORD_TYPE_KEY,
   1784             SEPARATE_PROFILE_CHALLENGE_KEY
   1785     };
   1786 
   1787     private static final String[] SETTINGS_TO_BACKUP = new String[] {
   1788             Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
   1789             Secure.LOCK_SCREEN_OWNER_INFO
   1790     };
   1791 
   1792     private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
   1793         @Override
   1794         public void binderDied() {
   1795             mGateKeeperService.asBinder().unlinkToDeath(this, 0);
   1796             mGateKeeperService = null;
   1797         }
   1798     }
   1799 
   1800     protected synchronized IGateKeeperService getGateKeeperService()
   1801             throws RemoteException {
   1802         if (mGateKeeperService != null) {
   1803             return mGateKeeperService;
   1804         }
   1805 
   1806         final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
   1807         if (service != null) {
   1808             service.linkToDeath(new GateKeeperDiedRecipient(), 0);
   1809             mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
   1810             return mGateKeeperService;
   1811         }
   1812 
   1813         Slog.e(TAG, "Unable to acquire GateKeeperService");
   1814         return null;
   1815     }
   1816 
   1817     /**
   1818      * Precondition: vold and keystore unlocked.
   1819      *
   1820      * Create new synthetic password, set up synthetic password blob protected by the supplied
   1821      * user credential, and make the newly-created SP blob active.
   1822      *
   1823      * The invariant under a synthetic password is:
   1824      * 1. If user credential exists, then both vold and keystore and protected with keys derived
   1825      *     from the synthetic password.
   1826      * 2. If user credential does not exist, vold and keystore protection are cleared. This is to
   1827      *     make it consistent with current behaviour. It also allows ActivityManager to call
   1828      *     unlockUser() with empty secret.
   1829      * 3. Once a user is migrated to have synthetic password, its value will never change, no matter
   1830      *     whether the user changes his lockscreen PIN or clear/reset it. When the user clears its
   1831      *     lockscreen PIN, we still maintain the existing synthetic password in a password blob
   1832      *     protected by a default PIN. The only exception is when the DPC performs an untrusted
   1833      *     credential change, in which case we have no way to derive the existing synthetic password
   1834      *     and has to create a new one.
   1835      * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user
   1836      *     clears/re-creates his lockscreen PIN.
   1837      *
   1838      *
   1839      * Different cases of calling this method:
   1840      * 1. credentialHash != null
   1841      *     This implies credential != null, a new SP blob will be provisioned, and existing SID
   1842      *     migrated to associate with the new SP.
   1843      *     This happens during a normal migration case when the user currently has password.
   1844      *
   1845      * 2. credentialhash == null and credential == null
   1846      *     A new SP blob and a new SID will be created, while the user has no credentials.
   1847      *     This can happens when we are activating an escrow token on a unsecured device, during
   1848      *     which we want to create the SP structure with an empty user credential.
   1849      *
   1850      * 3. credentialhash == null and credential != null
   1851      *     This is the untrusted credential reset, OR the user sets a new lockscreen password
   1852      *     FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
   1853      */
   1854     private AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
   1855             String credential, int credentialType, int userId) throws RemoteException {
   1856         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
   1857         AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(getGateKeeperService(),
   1858                 credentialHash, credential, userId);
   1859         if (auth == null) {
   1860             Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
   1861             return null;
   1862         }
   1863         long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
   1864                 credential, credentialType, auth, userId);
   1865         if (credential != null) {
   1866             if (credentialHash == null) {
   1867                 // Since when initializing SP, we didn't provide an existing password handle
   1868                 // for it to migrate SID, we need to create a new SID for the user.
   1869                 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
   1870             }
   1871             mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
   1872             setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
   1873             setKeystorePassword(auth.deriveKeyStorePassword(), userId);
   1874         } else {
   1875             clearUserKeyProtection(userId);
   1876             setKeystorePassword(null, userId);
   1877             getGateKeeperService().clearSecureUserId(userId);
   1878         }
   1879         fixateNewestUserKeyAuth(userId);
   1880         setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
   1881         return auth;
   1882     }
   1883 
   1884     private long getSyntheticPasswordHandleLocked(int userId) {
   1885         try {
   1886             return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId);
   1887         } catch (RemoteException e) {
   1888             return SyntheticPasswordManager.DEFAULT_HANDLE;
   1889         }
   1890     }
   1891 
   1892     private boolean isSyntheticPasswordBasedCredentialLocked(int userId) throws RemoteException {
   1893         long handle = getSyntheticPasswordHandleLocked(userId);
   1894         // This is a global setting
   1895         long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
   1896       return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
   1897     }
   1898 
   1899     private boolean shouldMigrateToSyntheticPasswordLocked(int userId) throws RemoteException {
   1900         long handle = getSyntheticPasswordHandleLocked(userId);
   1901         // This is a global setting
   1902         long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
   1903         return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
   1904     }
   1905 
   1906     private void enableSyntheticPasswordLocked() throws RemoteException {
   1907         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
   1908     }
   1909 
   1910     private VerifyCredentialResponse spBasedDoVerifyCredentialLocked(String userCredential, int
   1911             credentialType, boolean hasChallenge, long challenge, int userId,
   1912             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
   1913         if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredentialLocked: user=" + userId);
   1914         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
   1915             userCredential = null;
   1916         }
   1917         long handle = getSyntheticPasswordHandleLocked(userId);
   1918         AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
   1919                 getGateKeeperService(), handle, userCredential, userId);
   1920 
   1921         VerifyCredentialResponse response = authResult.gkResponse;
   1922         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
   1923             // credential has matched
   1924             // perform verifyChallenge with synthetic password which generates the real auth
   1925             // token for the current user
   1926             response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
   1927                     challenge, userId);
   1928             if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
   1929                 Slog.wtf(TAG, "verifyChallenge with SP failed.");
   1930                 return VerifyCredentialResponse.ERROR;
   1931             }
   1932             if (progressCallback != null) {
   1933                 progressCallback.onCredentialVerified();
   1934             }
   1935             notifyActivePasswordMetricsAvailable(userCredential, userId);
   1936             unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
   1937 
   1938             final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
   1939             Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
   1940             unlockUser(userId, null, secret);
   1941 
   1942             if (isManagedProfileWithSeparatedLock(userId)) {
   1943                 TrustManager trustManager =
   1944                         (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
   1945                 trustManager.setDeviceLockedForUser(userId, false);
   1946             }
   1947             activateEscrowTokens(authResult.authToken, userId);
   1948         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
   1949             if (response.getTimeout() > 0) {
   1950                 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
   1951             }
   1952         }
   1953 
   1954         return response;
   1955     }
   1956 
   1957     /**
   1958      * Change the user's lockscreen password by creating a new SP blob and update the handle, based
   1959      * on an existing authentication token. Even though a new SP blob is created, the underlying
   1960      * synthetic password is never changed.
   1961      *
   1962      * When clearing credential, we keep the SP unchanged, but clear its password handle so its
   1963      * SID is gone. We also clear password from (software-based) keystore and vold, which will be
   1964      * added back when new password is set in future.
   1965      */
   1966     private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType,
   1967             AuthenticationToken auth, int userId) throws RemoteException {
   1968         if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
   1969         long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
   1970                 credential, credentialType, auth, userId);
   1971         final Map<Integer, String> profilePasswords;
   1972         if (credential != null) {
   1973             // // not needed by synchronizeUnifiedWorkChallengeForProfiles()
   1974             profilePasswords = null;
   1975 
   1976             if (mSpManager.hasSidForUser(userId)) {
   1977                 // We are changing password of a secured device, nothing more needed as
   1978                 // createPasswordBasedSyntheticPassword has already taken care of maintaining
   1979                 // the password handle and SID unchanged.
   1980 
   1981                 //refresh auth token
   1982                 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
   1983             } else {
   1984                 // A new password is set on a previously-unsecured device, we need to generate
   1985                 // a new SID, and re-add keys to vold and keystore.
   1986                 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
   1987                 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
   1988                 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
   1989                 fixateNewestUserKeyAuth(userId);
   1990                 setKeystorePassword(auth.deriveKeyStorePassword(), userId);
   1991             }
   1992         } else {
   1993             // Cache all profile password if they use unified work challenge. This will later be
   1994             // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
   1995             profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
   1996 
   1997             // we are clearing password of a secured device, so need to nuke SID as well.
   1998             mSpManager.clearSidForUser(userId);
   1999             getGateKeeperService().clearSecureUserId(userId);
   2000             // Clear key from vold so ActivityManager can just unlock the user with empty secret
   2001             // during boot.
   2002             clearUserKeyProtection(userId);
   2003             fixateNewestUserKeyAuth(userId);
   2004             setKeystorePassword(null, userId);
   2005         }
   2006         setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
   2007         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
   2008         return newHandle;
   2009     }
   2010 
   2011     private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType,
   2012             String savedCredential, int userId) throws RemoteException {
   2013         if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
   2014         if (isManagedProfileWithUnifiedLock(userId)) {
   2015             // get credential from keystore when managed profile has unified lock
   2016             try {
   2017                 savedCredential = getDecryptedPasswordForTiedProfile(userId);
   2018             } catch (FileNotFoundException e) {
   2019                 Slog.i(TAG, "Child profile key not found");
   2020             } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
   2021                     | NoSuchAlgorithmException | NoSuchPaddingException
   2022                     | InvalidAlgorithmParameterException | IllegalBlockSizeException
   2023                     | BadPaddingException | CertificateException | IOException e) {
   2024                 Slog.e(TAG, "Failed to decrypt child profile key", e);
   2025             }
   2026         }
   2027         long handle = getSyntheticPasswordHandleLocked(userId);
   2028         AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
   2029                 getGateKeeperService(), handle, savedCredential, userId);
   2030         VerifyCredentialResponse response = authResult.gkResponse;
   2031         AuthenticationToken auth = authResult.authToken;
   2032         if (auth != null) {
   2033             // We are performing a trusted credential change i.e. a correct existing credential
   2034             // is provided
   2035             setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, userId);
   2036             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
   2037         } else if (response != null
   2038                 && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR){
   2039             // We are performing an untrusted credential change i.e. by DevicePolicyManager.
   2040             // So provision a new SP and SID. This would invalidate existing escrow tokens.
   2041             // Still support this for now but this flow will be removed in the next release.
   2042 
   2043             Slog.w(TAG, "Untrusted credential change invoked");
   2044             initializeSyntheticPasswordLocked(null, credential, credentialType, userId);
   2045             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
   2046             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
   2047         } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
   2048             Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
   2049                     (response != null ? "rate limit exceeded" : "failed"));
   2050             return;
   2051         }
   2052         notifyActivePasswordMetricsAvailable(credential, userId);
   2053 
   2054     }
   2055 
   2056     @Override
   2057     public long addEscrowToken(byte[] token, int userId) throws RemoteException {
   2058         ensureCallerSystemUid();
   2059         if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
   2060         synchronized (mSpManager) {
   2061             enableSyntheticPasswordLocked();
   2062             // Migrate to synthetic password based credentials if the user has no password,
   2063             // the token can then be activated immediately.
   2064             AuthenticationToken auth = null;
   2065             if (!isUserSecure(userId)) {
   2066                 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
   2067                     auth = initializeSyntheticPasswordLocked(null, null,
   2068                             LockPatternUtils.CREDENTIAL_TYPE_NONE, userId);
   2069                 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ {
   2070                     long pwdHandle = getSyntheticPasswordHandleLocked(userId);
   2071                     auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
   2072                             pwdHandle, null, userId).authToken;
   2073                 }
   2074             }
   2075             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
   2076                 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
   2077                 if (!mSpManager.hasEscrowData(userId)) {
   2078                     throw new SecurityException("Escrow token is disabled on the current user");
   2079                 }
   2080             }
   2081             long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
   2082             if (auth != null) {
   2083                 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
   2084             }
   2085             return handle;
   2086         }
   2087     }
   2088 
   2089     private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
   2090         if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
   2091         disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
   2092         synchronized (mSpManager) {
   2093             for (long handle : mSpManager.getPendingTokensForUser(userId)) {
   2094                 Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
   2095                 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
   2096             }
   2097         }
   2098     }
   2099 
   2100     @Override
   2101     public boolean isEscrowTokenActive(long handle, int userId) throws RemoteException {
   2102         ensureCallerSystemUid();
   2103         synchronized (mSpManager) {
   2104             return mSpManager.existsHandle(handle, userId);
   2105         }
   2106     }
   2107 
   2108     @Override
   2109     public boolean removeEscrowToken(long handle, int userId) throws RemoteException {
   2110         ensureCallerSystemUid();
   2111         synchronized (mSpManager) {
   2112             if (handle == getSyntheticPasswordHandleLocked(userId)) {
   2113                 Slog.w(TAG, "Cannot remove password handle");
   2114                 return false;
   2115             }
   2116             if (mSpManager.removePendingToken(handle, userId)) {
   2117                 return true;
   2118             }
   2119             if (mSpManager.existsHandle(handle, userId)) {
   2120                 mSpManager.destroyTokenBasedSyntheticPassword(handle, userId);
   2121                 return true;
   2122             } else {
   2123                 return false;
   2124             }
   2125         }
   2126     }
   2127 
   2128     @Override
   2129     public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
   2130             byte[] token, int userId) throws RemoteException {
   2131         ensureCallerSystemUid();
   2132         boolean result;
   2133         synchronized (mSpManager) {
   2134             if (!mSpManager.hasEscrowData(userId)) {
   2135                 throw new SecurityException("Escrow token is disabled on the current user");
   2136             }
   2137             result = setLockCredentialWithTokenInternal(credential, type, tokenHandle, token,
   2138                     userId);
   2139         }
   2140         if (result) {
   2141             synchronized (mSeparateChallengeLock) {
   2142                 setSeparateProfileChallengeEnabled(userId, true, null);
   2143             }
   2144             notifyPasswordChanged(userId);
   2145         }
   2146         return result;
   2147     }
   2148 
   2149     private boolean setLockCredentialWithTokenInternal(String credential, int type,
   2150             long tokenHandle, byte[] token, int userId) throws RemoteException {
   2151         synchronized (mSpManager) {
   2152             AuthenticationResult result = mSpManager.unwrapTokenBasedSyntheticPassword(
   2153                     getGateKeeperService(), tokenHandle, token, userId);
   2154             if (result.authToken == null) {
   2155                 Slog.w(TAG, "Invalid escrow token supplied");
   2156                 return false;
   2157             }
   2158             long oldHandle = getSyntheticPasswordHandleLocked(userId);
   2159             setLockCredentialWithAuthTokenLocked(credential, type, result.authToken, userId);
   2160             mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
   2161             return true;
   2162         }
   2163     }
   2164 
   2165     @Override
   2166     public void unlockUserWithToken(long tokenHandle, byte[] token, int userId)
   2167             throws RemoteException {
   2168         ensureCallerSystemUid();
   2169         AuthenticationResult authResult;
   2170         synchronized (mSpManager) {
   2171             if (!mSpManager.hasEscrowData(userId)) {
   2172                 throw new SecurityException("Escrow token is disabled on the current user");
   2173             }
   2174             authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(),
   2175                     tokenHandle, token, userId);
   2176             if (authResult.authToken == null) {
   2177                 Slog.w(TAG, "Invalid escrow token supplied");
   2178                 return;
   2179             }
   2180         }
   2181         unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
   2182     }
   2183 
   2184     @Override
   2185     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
   2186         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   2187 
   2188         pw.println("Current lock settings service state:");
   2189         pw.println(String.format("SP Enabled = %b",
   2190                 mLockPatternUtils.isSyntheticPasswordEnabled()));
   2191 
   2192         List<UserInfo> users = mUserManager.getUsers();
   2193         for (int user = 0; user < users.size(); user++) {
   2194             final int userId = users.get(user).id;
   2195             pw.println("    User " + userId);
   2196             synchronized (mSpManager) {
   2197                 pw.println(String.format("        SP Handle = %x",
   2198                         getSyntheticPasswordHandleLocked(userId)));
   2199             }
   2200             try {
   2201                 pw.println(String.format("        SID = %x",
   2202                         getGateKeeperService().getSecureUserId(userId)));
   2203             } catch (RemoteException e) {
   2204                 // ignore.
   2205             }
   2206         }
   2207     }
   2208 
   2209     private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
   2210         long ident = Binder.clearCallingIdentity();
   2211         try {
   2212             // Managed profile should have escrow enabled
   2213             if (mUserManager.getUserInfo(userId).isManagedProfile()) {
   2214                 Slog.i(TAG, "Managed profile can have escrow token");
   2215                 return;
   2216             }
   2217             DevicePolicyManager dpm = mInjector.getDevicePolicyManager();
   2218             // Devices with Device Owner should have escrow enabled on all users.
   2219             if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
   2220                 Slog.i(TAG, "Corp-owned device can have escrow token");
   2221                 return;
   2222             }
   2223             // We could also have a profile owner on the given (non-managed) user for unicorn cases
   2224             if (dpm.getProfileOwnerAsUser(userId) != null) {
   2225                 Slog.i(TAG, "User with profile owner can have escrow token");
   2226                 return;
   2227             }
   2228             // If the device is yet to be provisioned (still in SUW), there is still
   2229             // a chance that Device Owner will be set on the device later, so postpone
   2230             // disabling escrow token for now.
   2231             if (!dpm.isDeviceProvisioned()) {
   2232                 Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
   2233                 return;
   2234             }
   2235 
   2236             // Escrow tokens are enabled on automotive builds.
   2237             if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
   2238                 return;
   2239             }
   2240 
   2241             // Disable escrow token permanently on all other device/user types.
   2242             Slog.i(TAG, "Disabling escrow token on user " + userId);
   2243             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
   2244                 mSpManager.destroyEscrowData(userId);
   2245             }
   2246         } catch (RemoteException e) {
   2247             Slog.e(TAG, "disableEscrowTokenOnNonManagedDevices", e);
   2248         } finally {
   2249             Binder.restoreCallingIdentity(ident);
   2250         }
   2251     }
   2252 
   2253     private void ensureCallerSystemUid() throws SecurityException {
   2254         final int callingUid = mInjector.binderGetCallingUid();
   2255         if (callingUid != Process.SYSTEM_UID) {
   2256             throw new SecurityException("Only system can call this API.");
   2257         }
   2258     }
   2259 }
   2260