OSDN Git Service

e26630bc4aee00b2bc434ac466c05c9e5f1305eb
[android-x86/frameworks-base.git] / services / core / java / com / android / server / LockSettingsService.java
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     private final Object mSeparateChallengeLock = new Object();
138
139     private final Injector mInjector;
140     private final Context mContext;
141     private final Handler mHandler;
142     @VisibleForTesting
143     protected final LockSettingsStorage mStorage;
144     private final LockSettingsStrongAuth mStrongAuth;
145     private final SynchronizedStrongAuthTracker mStrongAuthTracker;
146
147     private final LockPatternUtils mLockPatternUtils;
148     private final NotificationManager mNotificationManager;
149     private final UserManager mUserManager;
150     private final IActivityManager mActivityManager;
151
152     private final KeyStore mKeyStore;
153
154     private boolean mFirstCallToVold;
155     protected IGateKeeperService mGateKeeperService;
156     private SyntheticPasswordManager mSpManager;
157
158     /**
159      * The UIDs that are used for system credential storage in keystore.
160      */
161     private static final int[] SYSTEM_CREDENTIAL_UIDS = {
162             Process.WIFI_UID, Process.VPN_UID,
163             Process.ROOT_UID };
164
165     // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
166     // devices. The most basic of these is to show/hide notifications about missing features until
167     // the user unlocks the account and credential-encrypted storage is available.
168     public static final class Lifecycle extends SystemService {
169         private LockSettingsService mLockSettingsService;
170
171         public Lifecycle(Context context) {
172             super(context);
173         }
174
175         @Override
176         public void onStart() {
177             AndroidKeyStoreProvider.install();
178             mLockSettingsService = new LockSettingsService(getContext());
179             publishBinderService("lock_settings", mLockSettingsService);
180         }
181
182         @Override
183         public void onStartUser(int userHandle) {
184             mLockSettingsService.onStartUser(userHandle);
185         }
186
187         @Override
188         public void onUnlockUser(int userHandle) {
189             mLockSettingsService.onUnlockUser(userHandle);
190         }
191
192         @Override
193         public void onCleanupUser(int userHandle) {
194             mLockSettingsService.onCleanupUser(userHandle);
195         }
196     }
197
198     @VisibleForTesting
199     protected static class SynchronizedStrongAuthTracker
200             extends LockPatternUtils.StrongAuthTracker {
201         public SynchronizedStrongAuthTracker(Context context) {
202             super(context);
203         }
204
205         @Override
206         protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) {
207             synchronized (this) {
208                 super.handleStrongAuthRequiredChanged(strongAuthFlags, userId);
209             }
210         }
211
212         @Override
213         public int getStrongAuthForUser(int userId) {
214             synchronized (this) {
215                 return super.getStrongAuthForUser(userId);
216             }
217         }
218
219         void register(LockSettingsStrongAuth strongAuth) {
220             strongAuth.registerStrongAuthTracker(this.mStub);
221         }
222     }
223
224     /**
225      * Tie managed profile to primary profile if it is in unified mode and not tied before.
226      *
227      * @param managedUserId Managed profile user Id
228      * @param managedUserPassword Managed profile original password (when it has separated lock).
229      *            NULL when it does not have a separated lock before.
230      */
231     public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
232         if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
233         // Only for managed profile
234         if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
235             return;
236         }
237         // Do not tie managed profile when work challenge is enabled
238         if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
239             return;
240         }
241         // Do not tie managed profile to parent when it's done already
242         if (mStorage.hasChildProfileLock(managedUserId)) {
243             return;
244         }
245         // Do not tie it to parent when parent does not have a screen lock
246         final int parentId = mUserManager.getProfileParent(managedUserId).id;
247         if (!isUserSecure(parentId)) {
248             if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
249             return;
250         }
251         // Do not tie when the parent has no SID (but does have a screen lock).
252         // This can only happen during an upgrade path where SID is yet to be
253         // generated when the user unlocks for the first time.
254         try {
255             if (getGateKeeperService().getSecureUserId(parentId) == 0) {
256                 return;
257             }
258         } catch (RemoteException e) {
259             Slog.e(TAG, "Failed to talk to GateKeeper service", e);
260             return;
261         }
262         if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
263         byte[] randomLockSeed = new byte[] {};
264         try {
265             randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
266             String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
267             setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
268                     managedUserPassword, managedUserId);
269             // We store a private credential for the managed user that's unlocked by the primary
270             // account holder's credential. As such, the user will never be prompted to enter this
271             // password directly, so we always store a password.
272             setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
273                     DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, managedUserId);
274             tieProfileLockToParent(managedUserId, newPassword);
275         } catch (NoSuchAlgorithmException | RemoteException e) {
276             Slog.e(TAG, "Fail to tie managed profile", e);
277             // Nothing client can do to fix this issue, so we do not throw exception out
278         }
279     }
280
281     static class Injector {
282
283         protected Context mContext;
284
285         public Injector(Context context) {
286             mContext = context;
287         }
288
289         public Context getContext() {
290             return mContext;
291         }
292
293         public Handler getHandler() {
294             return new Handler();
295         }
296
297         public LockSettingsStorage getStorage() {
298             final LockSettingsStorage storage = new LockSettingsStorage(mContext);
299             storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
300                 @Override
301                 public void initialize(SQLiteDatabase db) {
302                     // Get the lockscreen default from a system property, if available
303                     boolean lockScreenDisable = SystemProperties.getBoolean(
304                             "ro.lockscreen.disable.default", false);
305                     if (lockScreenDisable) {
306                         storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
307                     }
308                 }
309             });
310             return storage;
311         }
312
313         public LockSettingsStrongAuth getStrongAuth() {
314             return new LockSettingsStrongAuth(mContext);
315         }
316
317         public SynchronizedStrongAuthTracker getStrongAuthTracker() {
318             return new SynchronizedStrongAuthTracker(mContext);
319         }
320
321         public IActivityManager getActivityManager() {
322             return ActivityManager.getService();
323         }
324
325         public LockPatternUtils getLockPatternUtils() {
326             return new LockPatternUtils(mContext);
327         }
328
329         public NotificationManager getNotificationManager() {
330             return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
331         }
332
333         public UserManager getUserManager() {
334             return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
335         }
336
337         public DevicePolicyManager getDevicePolicyManager() {
338             return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
339         }
340
341         public KeyStore getKeyStore() {
342             return KeyStore.getInstance();
343         }
344
345         public IStorageManager getStorageManager() {
346             final IBinder service = ServiceManager.getService("mount");
347             if (service != null) {
348                 return IStorageManager.Stub.asInterface(service);
349             }
350             return null;
351         }
352
353         public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
354             return new SyntheticPasswordManager(storage);
355         }
356
357         public int binderGetCallingUid() {
358             return Binder.getCallingUid();
359         }
360     }
361
362     public LockSettingsService(Context context) {
363         this(new Injector(context));
364     }
365
366     @VisibleForTesting
367     protected LockSettingsService(Injector injector) {
368         mInjector = injector;
369         mContext = injector.getContext();
370         mKeyStore = injector.getKeyStore();
371         mHandler = injector.getHandler();
372         mStrongAuth = injector.getStrongAuth();
373         mActivityManager = injector.getActivityManager();
374
375         mLockPatternUtils = injector.getLockPatternUtils();
376         mFirstCallToVold = true;
377
378         IntentFilter filter = new IntentFilter();
379         filter.addAction(Intent.ACTION_USER_ADDED);
380         filter.addAction(Intent.ACTION_USER_STARTING);
381         filter.addAction(Intent.ACTION_USER_REMOVED);
382         injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
383                 null, null);
384
385         mStorage = injector.getStorage();
386         mNotificationManager = injector.getNotificationManager();
387         mUserManager = injector.getUserManager();
388         mStrongAuthTracker = injector.getStrongAuthTracker();
389         mStrongAuthTracker.register(mStrongAuth);
390
391         mSpManager = injector.getSyntheticPasswordManager(mStorage);
392     }
393
394     /**
395      * If the account is credential-encrypted, show notification requesting the user to unlock the
396      * device.
397      */
398     private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
399         final UserInfo user = mUserManager.getUserInfo(userId);
400         if (!user.isManagedProfile()) {
401             // When the user is locked, we communicate it loud-and-clear
402             // on the lockscreen; we only show a notification below for
403             // locked managed profiles.
404             return;
405         }
406
407         final UserHandle userHandle = user.getUserHandle();
408         final boolean isSecure = isUserSecure(userId);
409         if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
410             UserInfo parent = mUserManager.getProfileParent(userId);
411             if (parent != null &&
412                     mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
413                     !mUserManager.isQuietModeEnabled(userHandle)) {
414                 // Only show notifications for managed profiles once their parent
415                 // user is unlocked.
416                 showEncryptionNotificationForProfile(userHandle);
417             }
418         }
419     }
420
421     private void showEncryptionNotificationForProfile(UserHandle user) {
422         Resources r = mContext.getResources();
423         CharSequence title = r.getText(
424                 com.android.internal.R.string.user_encrypted_title);
425         CharSequence message = r.getText(
426                 com.android.internal.R.string.profile_encrypted_message);
427         CharSequence detail = r.getText(
428                 com.android.internal.R.string.profile_encrypted_detail);
429
430         final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
431         final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
432                 user.getIdentifier());
433         if (unlockIntent == null) {
434             return;
435         }
436         unlockIntent.setFlags(
437                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
438         PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
439                 PendingIntent.FLAG_UPDATE_CURRENT);
440
441         showEncryptionNotification(user, title, message, detail, intent);
442     }
443
444     private void showEncryptionNotification(UserHandle user, CharSequence title,
445             CharSequence message, CharSequence detail, PendingIntent intent) {
446         if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
447
448         // Suppress all notifications on non-FBE devices for now
449         if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
450
451         Notification notification =
452                 new Notification.Builder(mContext, SystemNotificationChannels.SECURITY)
453                         .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
454                         .setWhen(0)
455                         .setOngoing(true)
456                         .setTicker(title)
457                         .setColor(mContext.getColor(
458                                 com.android.internal.R.color.system_notification_accent_color))
459                         .setContentTitle(title)
460                         .setContentText(message)
461                         .setSubText(detail)
462                         .setVisibility(Notification.VISIBILITY_PUBLIC)
463                         .setContentIntent(intent)
464                         .build();
465         mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
466             notification, user);
467     }
468
469     private void hideEncryptionNotification(UserHandle userHandle) {
470         if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
471         mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
472             userHandle);
473     }
474
475     public void onCleanupUser(int userId) {
476         hideEncryptionNotification(new UserHandle(userId));
477     }
478
479     public void onStartUser(final int userId) {
480         maybeShowEncryptionNotificationForUser(userId);
481     }
482
483     public void onUnlockUser(final int userId) {
484         // Perform tasks which require locks in LSS on a handler, as we are callbacks from
485         // ActivityManager.unlockUser()
486         mHandler.post(new Runnable() {
487             @Override
488             public void run() {
489                 // Hide notification first, as tie managed profile lock takes time
490                 hideEncryptionNotification(new UserHandle(userId));
491
492                 // Now we have unlocked the parent user we should show notifications
493                 // about any profiles that exist.
494                 List<UserInfo> profiles = mUserManager.getProfiles(userId);
495                 for (int i = 0; i < profiles.size(); i++) {
496                     UserInfo profile = profiles.get(i);
497                     final boolean isSecure = isUserSecure(profile.id);
498                     if (isSecure && profile.isManagedProfile()) {
499                         UserHandle userHandle = profile.getUserHandle();
500                         if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
501                                 !mUserManager.isQuietModeEnabled(userHandle)) {
502                             showEncryptionNotificationForProfile(userHandle);
503                         }
504                     }
505                 }
506
507                 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
508                     tieManagedProfileLockIfNecessary(userId, null);
509                 }
510             }
511         });
512     }
513
514     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
515         @Override
516         public void onReceive(Context context, Intent intent) {
517             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
518                 // Notify keystore that a new user was added.
519                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
520                 if (userHandle > UserHandle.USER_SYSTEM) {
521                     removeUser(userHandle, /* unknownUser= */ true);
522                 }
523                 final KeyStore ks = KeyStore.getInstance();
524                 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
525                 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
526                 ks.onUserAdded(userHandle, parentHandle);
527             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
528                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
529                 mStorage.prefetchUser(userHandle);
530             } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
531                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
532                 if (userHandle > 0) {
533                     removeUser(userHandle, /* unknownUser= */ false);
534                 }
535             }
536         }
537     };
538
539     @Override // binder interface
540     public void systemReady() {
541         migrateOldData();
542         try {
543             getGateKeeperService();
544         } catch (RemoteException e) {
545             Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
546         }
547         // TODO: maybe skip this for split system user mode.
548         mStorage.prefetchUser(UserHandle.USER_SYSTEM);
549     }
550
551     private void migrateOldData() {
552         try {
553             // These Settings moved before multi-user was enabled, so we only have to do it for the
554             // root user.
555             if (getString("migrated", null, 0) == null) {
556                 final ContentResolver cr = mContext.getContentResolver();
557                 for (String validSetting : VALID_SETTINGS) {
558                     String value = Settings.Secure.getString(cr, validSetting);
559                     if (value != null) {
560                         setString(validSetting, value, 0);
561                     }
562                 }
563                 // No need to move the password / pattern files. They're already in the right place.
564                 setString("migrated", "true", 0);
565                 Slog.i(TAG, "Migrated lock settings to new location");
566             }
567
568             // These Settings changed after multi-user was enabled, hence need to be moved per user.
569             if (getString("migrated_user_specific", null, 0) == null) {
570                 final ContentResolver cr = mContext.getContentResolver();
571                 List<UserInfo> users = mUserManager.getUsers();
572                 for (int user = 0; user < users.size(); user++) {
573                     // Migrate owner info
574                     final int userId = users.get(user).id;
575                     final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
576                     String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
577                     if (!TextUtils.isEmpty(ownerInfo)) {
578                         setString(OWNER_INFO, ownerInfo, userId);
579                         Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
580                     }
581
582                     // Migrate owner info enabled. Note there was a bug where older platforms only
583                     // stored this value if the checkbox was toggled at least once. The code detects
584                     // this case by handling the exception.
585                     final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
586                     boolean enabled;
587                     try {
588                         int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
589                         enabled = ivalue != 0;
590                         setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
591                     } catch (SettingNotFoundException e) {
592                         // Setting was never stored. Store it if the string is not empty.
593                         if (!TextUtils.isEmpty(ownerInfo)) {
594                             setLong(OWNER_INFO_ENABLED, 1, userId);
595                         }
596                     }
597                     Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
598                 }
599                 // No need to move the password / pattern files. They're already in the right place.
600                 setString("migrated_user_specific", "true", 0);
601                 Slog.i(TAG, "Migrated per-user lock settings to new location");
602             }
603
604             // Migrates biometric weak such that the fallback mechanism becomes the primary.
605             if (getString("migrated_biometric_weak", null, 0) == null) {
606                 List<UserInfo> users = mUserManager.getUsers();
607                 for (int i = 0; i < users.size(); i++) {
608                     int userId = users.get(i).id;
609                     long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
610                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
611                             userId);
612                     long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
613                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
614                             userId);
615                     if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
616                         setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
617                                 alternateType,
618                                 userId);
619                     }
620                     setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
621                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
622                             userId);
623                 }
624                 setString("migrated_biometric_weak", "true", 0);
625                 Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
626             }
627
628             // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one
629             // user was present on the system, so if we're upgrading to M and there is more than one
630             // user we disable the flag to remain consistent.
631             if (getString("migrated_lockscreen_disabled", null, 0) == null) {
632                 final List<UserInfo> users = mUserManager.getUsers();
633                 final int userCount = users.size();
634                 int switchableUsers = 0;
635                 for (int i = 0; i < userCount; i++) {
636                     if (users.get(i).supportsSwitchTo()) {
637                         switchableUsers++;
638                     }
639                 }
640
641                 if (switchableUsers > 1) {
642                     for (int i = 0; i < userCount; i++) {
643                         int id = users.get(i).id;
644
645                         if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
646                             setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
647                         }
648                     }
649                 }
650
651                 setString("migrated_lockscreen_disabled", "true", 0);
652                 Slog.i(TAG, "Migrated lockscreen disabled flag");
653             }
654
655             final List<UserInfo> users = mUserManager.getUsers();
656             for (int i = 0; i < users.size(); i++) {
657                 final UserInfo userInfo = users.get(i);
658                 if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
659                     // When managed profile has a unified lock, the password quality stored has 2
660                     // possibilities only.
661                     // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
662                     // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
663                     // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
664                     // unified lock.
665                     final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
666                             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
667                     if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
668                         // Only possible when it's upgraded from nyc dp3
669                         Slog.i(TAG, "Migrated tied profile lock type");
670                         setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
671                                 DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
672                     } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
673                         // It should not happen
674                         Slog.e(TAG, "Invalid tied profile lock type: " + quality);
675                     }
676                 }
677                 try {
678                     final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
679                     java.security.KeyStore keyStore =
680                             java.security.KeyStore.getInstance("AndroidKeyStore");
681                     keyStore.load(null);
682                     if (keyStore.containsAlias(alias)) {
683                         keyStore.deleteEntry(alias);
684                     }
685                 } catch (KeyStoreException | NoSuchAlgorithmException |
686                         CertificateException | IOException e) {
687                     Slog.e(TAG, "Unable to remove tied profile key", e);
688                 }
689             }
690
691             boolean isWatch = mContext.getPackageManager().hasSystemFeature(
692                     PackageManager.FEATURE_WATCH);
693             // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts
694             // and device management the lockscreen must be re-enabled now for users that upgrade.
695             if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
696                 final int userCount = users.size();
697                 for (int i = 0; i < userCount; i++) {
698                     int id = users.get(i).id;
699                     setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
700                 }
701                 setString("migrated_wear_lockscreen_disabled", "true", 0);
702                 Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
703             }
704         } catch (RemoteException re) {
705             Slog.e(TAG, "Unable to migrate old data", re);
706         }
707     }
708
709     private final void checkWritePermission(int userId) {
710         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
711     }
712
713     private final void checkPasswordReadPermission(int userId) {
714         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
715     }
716
717     private final void checkReadPermission(String requestedKey, int userId) {
718         final int callingUid = Binder.getCallingUid();
719
720         for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
721             String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
722             if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
723                     != PackageManager.PERMISSION_GRANTED) {
724                 throw new SecurityException("uid=" + callingUid
725                         + " needs permission " + READ_CONTACTS + " to read "
726                         + requestedKey + " for user " + userId);
727             }
728         }
729
730         for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
731             String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
732             if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
733                     != PackageManager.PERMISSION_GRANTED) {
734                 throw new SecurityException("uid=" + callingUid
735                         + " needs permission " + PERMISSION + " to read "
736                         + requestedKey + " for user " + userId);
737             }
738         }
739     }
740
741     @Override
742     public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
743         checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
744         synchronized (mSeparateChallengeLock) {
745             return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
746         }
747     }
748
749     @Override
750     public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
751             String managedUserPassword) throws RemoteException {
752         checkWritePermission(userId);
753         synchronized (mSeparateChallengeLock) {
754             setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
755             if (enabled) {
756                 mStorage.removeChildProfileLock(userId);
757                 removeKeystoreProfileKey(userId);
758             } else {
759                 tieManagedProfileLockIfNecessary(userId, managedUserPassword);
760             }
761         }
762     }
763
764     @Override
765     public void setBoolean(String key, boolean value, int userId) throws RemoteException {
766         checkWritePermission(userId);
767         setStringUnchecked(key, userId, value ? "1" : "0");
768     }
769
770     @Override
771     public void setLong(String key, long value, int userId) throws RemoteException {
772         checkWritePermission(userId);
773         setStringUnchecked(key, userId, Long.toString(value));
774     }
775
776     @Override
777     public void setString(String key, String value, int userId) throws RemoteException {
778         checkWritePermission(userId);
779         setStringUnchecked(key, userId, value);
780     }
781
782     private void setStringUnchecked(String key, int userId, String value) {
783         mStorage.writeKeyValue(key, value, userId);
784         if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
785             BackupManager.dataChanged("com.android.providers.settings");
786         }
787     }
788
789     @Override
790     public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
791         checkReadPermission(key, userId);
792         String value = getStringUnchecked(key, null, userId);
793         return TextUtils.isEmpty(value) ?
794                 defaultValue : (value.equals("1") || value.equals("true"));
795     }
796
797     @Override
798     public long getLong(String key, long defaultValue, int userId) throws RemoteException {
799         checkReadPermission(key, userId);
800         String value = getStringUnchecked(key, null, userId);
801         return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
802     }
803
804     @Override
805     public String getString(String key, String defaultValue, int userId) throws RemoteException {
806         checkReadPermission(key, userId);
807         return getStringUnchecked(key, defaultValue, userId);
808     }
809
810     public String getStringUnchecked(String key, String defaultValue, int userId) {
811         if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
812             long ident = Binder.clearCallingIdentity();
813             try {
814                 return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
815             } finally {
816                 Binder.restoreCallingIdentity(ident);
817             }
818         }
819
820         if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
821             key = Settings.Secure.LOCK_PATTERN_ENABLED;
822         }
823
824         return mStorage.readKeyValue(key, defaultValue, userId);
825     }
826
827     @Override
828     public boolean havePassword(int userId) throws RemoteException {
829         synchronized (mSpManager) {
830             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
831                 long handle = getSyntheticPasswordHandleLocked(userId);
832                 return mSpManager.getCredentialType(handle, userId) ==
833                         LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
834             }
835         }
836         // Do we need a permissions check here?
837         return mStorage.hasPassword(userId);
838     }
839
840     @Override
841     public boolean havePattern(int userId) throws RemoteException {
842         synchronized (mSpManager) {
843             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
844                 long handle = getSyntheticPasswordHandleLocked(userId);
845                 return mSpManager.getCredentialType(handle, userId) ==
846                         LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
847             }
848         }
849         // Do we need a permissions check here?
850         return mStorage.hasPattern(userId);
851     }
852
853     private boolean isUserSecure(int userId) {
854         synchronized (mSpManager) {
855             try {
856                 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
857                     long handle = getSyntheticPasswordHandleLocked(userId);
858                     return mSpManager.getCredentialType(handle, userId) !=
859                             LockPatternUtils.CREDENTIAL_TYPE_NONE;
860                 }
861             } catch (RemoteException e) {
862                 // fall through
863             }
864         }
865         return mStorage.hasCredential(userId);
866     }
867
868     private void setKeystorePassword(String password, int userHandle) {
869         final KeyStore ks = KeyStore.getInstance();
870         ks.onUserPasswordChanged(userHandle, password);
871     }
872
873     private void unlockKeystore(String password, int userHandle) {
874         if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
875         final KeyStore ks = KeyStore.getInstance();
876         ks.unlock(userHandle, password);
877     }
878
879     @VisibleForTesting
880     protected String getDecryptedPasswordForTiedProfile(int userId)
881             throws KeyStoreException, UnrecoverableKeyException,
882             NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
883             InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
884             CertificateException, IOException {
885         if (DEBUG) Slog.v(TAG, "Get child profile decrytped key");
886         byte[] storedData = mStorage.readChildProfileLock(userId);
887         if (storedData == null) {
888             throw new FileNotFoundException("Child profile lock file not found");
889         }
890         byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
891         byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
892                 storedData.length);
893         byte[] decryptionResult;
894         java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
895         keyStore.load(null);
896         SecretKey decryptionKey = (SecretKey) keyStore.getKey(
897                 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
898
899         Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
900                 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
901
902         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
903         decryptionResult = cipher.doFinal(encryptedPassword);
904         return new String(decryptionResult, StandardCharsets.UTF_8);
905     }
906
907     private void unlockChildProfile(int profileHandle) throws RemoteException {
908         try {
909             doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
910                     LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
911                     false, 0 /* no challenge */, profileHandle, null /* progressCallback */);
912         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
913                 | NoSuchAlgorithmException | NoSuchPaddingException
914                 | InvalidAlgorithmParameterException | IllegalBlockSizeException
915                 | BadPaddingException | CertificateException | IOException e) {
916             if (e instanceof FileNotFoundException) {
917                 Slog.i(TAG, "Child profile key not found");
918             } else {
919                 Slog.e(TAG, "Failed to decrypt child profile key", e);
920             }
921         }
922     }
923
924     private void unlockUser(int userId, byte[] token, byte[] secret) {
925         // TODO: make this method fully async so we can update UI with progress strings
926         final CountDownLatch latch = new CountDownLatch(1);
927         final IProgressListener listener = new IProgressListener.Stub() {
928             @Override
929             public void onStarted(int id, Bundle extras) throws RemoteException {
930                 Log.d(TAG, "unlockUser started");
931             }
932
933             @Override
934             public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
935                 Log.d(TAG, "unlockUser progress " + progress);
936             }
937
938             @Override
939             public void onFinished(int id, Bundle extras) throws RemoteException {
940                 Log.d(TAG, "unlockUser finished");
941                 latch.countDown();
942             }
943         };
944
945         try {
946             mActivityManager.unlockUser(userId, token, secret, listener);
947         } catch (RemoteException e) {
948             throw e.rethrowAsRuntimeException();
949         }
950
951         try {
952             latch.await(15, TimeUnit.SECONDS);
953         } catch (InterruptedException e) {
954             Thread.currentThread().interrupt();
955         }
956         try {
957             if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
958                 final List<UserInfo> profiles = mUserManager.getProfiles(userId);
959                 for (UserInfo pi : profiles) {
960                     // Unlock managed profile with unified lock
961                     if (pi.isManagedProfile()
962                             && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
963                             && mStorage.hasChildProfileLock(pi.id)
964                             && mUserManager.isUserRunning(pi.id)
965                             && !mUserManager.isUserUnlocked(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                         initializeSyntheticPasswordLocked(storedHash.hash, credential,
1566                                 storedHash.type, userId);
1567                     }
1568                 }
1569             }
1570         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
1571             if (response.getTimeout() > 0) {
1572                 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
1573             }
1574         }
1575
1576         return response;
1577     }
1578
1579     private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
1580         final PasswordMetrics metrics;
1581         if (password == null) {
1582             metrics = new PasswordMetrics();
1583         } else {
1584             metrics = PasswordMetrics.computeForPassword(password);
1585             metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
1586         }
1587
1588         // Asynchronous to avoid dead lock
1589         mHandler.post(() -> {
1590             DevicePolicyManager dpm = (DevicePolicyManager)
1591                     mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
1592             dpm.setActivePasswordState(metrics, userId);
1593         });
1594     }
1595
1596     /**
1597      * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
1598      * reporting the password changed.
1599      */
1600     private void notifyPasswordChanged(@UserIdInt int userId) {
1601         // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
1602         mHandler.post(() -> {
1603             DevicePolicyManager dpm = (DevicePolicyManager)
1604                     mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
1605             dpm.reportPasswordChanged(userId);
1606         });
1607     }
1608
1609     @Override
1610     public boolean checkVoldPassword(int userId) throws RemoteException {
1611         if (!mFirstCallToVold) {
1612             return false;
1613         }
1614         mFirstCallToVold = false;
1615
1616         checkPasswordReadPermission(userId);
1617
1618         // There's no guarantee that this will safely connect, but if it fails
1619         // we will simply show the lock screen when we shouldn't, so relatively
1620         // benign. There is an outside chance something nasty would happen if
1621         // this service restarted before vold stales out the password in this
1622         // case. The nastiness is limited to not showing the lock screen when
1623         // we should, within the first minute of decrypting the phone if this
1624         // service can't connect to vold, it restarts, and then the new instance
1625         // does successfully connect.
1626         final IStorageManager service = mInjector.getStorageManager();
1627         String password;
1628         long identity = Binder.clearCallingIdentity();
1629         try {
1630             password = service.getPassword();
1631             service.clearPassword();
1632         } finally {
1633             Binder.restoreCallingIdentity(identity);
1634         }
1635         if (password == null) {
1636             return false;
1637         }
1638
1639         try {
1640             if (mLockPatternUtils.isLockPatternEnabled(userId)) {
1641                 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, userId,
1642                         null /* progressCallback */)
1643                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
1644                     return true;
1645                 }
1646             }
1647         } catch (Exception e) {
1648         }
1649
1650         try {
1651             if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
1652                 if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId,
1653                         null /* progressCallback */)
1654                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
1655                     return true;
1656                 }
1657             }
1658         } catch (Exception e) {
1659         }
1660
1661         return false;
1662     }
1663
1664     private void removeUser(int userId, boolean unknownUser) {
1665         mStorage.removeUser(userId);
1666         mStrongAuth.removeUser(userId);
1667
1668         final KeyStore ks = KeyStore.getInstance();
1669         ks.onUserRemoved(userId);
1670
1671         try {
1672             final IGateKeeperService gk = getGateKeeperService();
1673             if (gk != null) {
1674                 gk.clearSecureUserId(userId);
1675             }
1676         } catch (RemoteException ex) {
1677             Slog.w(TAG, "unable to clear GK secure user id");
1678         }
1679         if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
1680             removeKeystoreProfileKey(userId);
1681         }
1682     }
1683
1684     private void removeKeystoreProfileKey(int targetUserId) {
1685         if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
1686         try {
1687             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1688             keyStore.load(null);
1689             keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
1690             keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
1691         } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
1692                 | IOException e) {
1693             // We have tried our best to remove all keys
1694             Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
1695         }
1696     }
1697
1698     @Override
1699     public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
1700         checkPasswordReadPermission(UserHandle.USER_ALL);
1701         mStrongAuth.registerStrongAuthTracker(tracker);
1702     }
1703
1704     @Override
1705     public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
1706         checkPasswordReadPermission(UserHandle.USER_ALL);
1707         mStrongAuth.unregisterStrongAuthTracker(tracker);
1708     }
1709
1710     @Override
1711     public void requireStrongAuth(int strongAuthReason, int userId) {
1712         checkWritePermission(userId);
1713         mStrongAuth.requireStrongAuth(strongAuthReason, userId);
1714     }
1715
1716     @Override
1717     public void userPresent(int userId) {
1718         checkWritePermission(userId);
1719         mStrongAuth.reportUnlock(userId);
1720     }
1721
1722     @Override
1723     public int getStrongAuthForUser(int userId) {
1724         checkPasswordReadPermission(userId);
1725         return mStrongAuthTracker.getStrongAuthForUser(userId);
1726     }
1727
1728     private boolean isCallerShell() {
1729         final int callingUid = Binder.getCallingUid();
1730         return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
1731     }
1732
1733     private void enforceShell() {
1734         if (!isCallerShell()) {
1735             throw new SecurityException("Caller must be shell");
1736         }
1737     }
1738
1739     @Override
1740     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
1741             String[] args, ShellCallback callback, ResultReceiver resultReceiver)
1742             throws RemoteException {
1743         enforceShell();
1744         final long origId = Binder.clearCallingIdentity();
1745         try {
1746             (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
1747                     this, in, out, err, args, callback, resultReceiver);
1748         } finally {
1749             Binder.restoreCallingIdentity(origId);
1750         }
1751     }
1752
1753     private static final String[] VALID_SETTINGS = new String[] {
1754             LockPatternUtils.LOCKOUT_PERMANENT_KEY,
1755             LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
1756             LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
1757             LockPatternUtils.PASSWORD_TYPE_KEY,
1758             LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
1759             LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
1760             LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
1761             LockPatternUtils.LOCKSCREEN_OPTIONS,
1762             LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
1763             LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
1764             LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
1765             LockPatternUtils.PASSWORD_HISTORY_KEY,
1766             Secure.LOCK_PATTERN_ENABLED,
1767             Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
1768             Secure.LOCK_PATTERN_VISIBLE,
1769             Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
1770     };
1771
1772     // Reading these settings needs the contacts permission
1773     private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
1774             Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
1775             Secure.LOCK_SCREEN_OWNER_INFO
1776     };
1777
1778     // Reading these settings needs the same permission as checking the password
1779     private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
1780             LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
1781             LockPatternUtils.PASSWORD_HISTORY_KEY,
1782             LockPatternUtils.PASSWORD_TYPE_KEY,
1783             SEPARATE_PROFILE_CHALLENGE_KEY
1784     };
1785
1786     private static final String[] SETTINGS_TO_BACKUP = new String[] {
1787             Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
1788             Secure.LOCK_SCREEN_OWNER_INFO
1789     };
1790
1791     private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
1792         @Override
1793         public void binderDied() {
1794             mGateKeeperService.asBinder().unlinkToDeath(this, 0);
1795             mGateKeeperService = null;
1796         }
1797     }
1798
1799     protected synchronized IGateKeeperService getGateKeeperService()
1800             throws RemoteException {
1801         if (mGateKeeperService != null) {
1802             return mGateKeeperService;
1803         }
1804
1805         final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
1806         if (service != null) {
1807             service.linkToDeath(new GateKeeperDiedRecipient(), 0);
1808             mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
1809             return mGateKeeperService;
1810         }
1811
1812         Slog.e(TAG, "Unable to acquire GateKeeperService");
1813         return null;
1814     }
1815
1816     /**
1817      * Precondition: vold and keystore unlocked.
1818      *
1819      * Create new synthetic password, set up synthetic password blob protected by the supplied
1820      * user credential, and make the newly-created SP blob active.
1821      *
1822      * The invariant under a synthetic password is:
1823      * 1. If user credential exists, then both vold and keystore and protected with keys derived
1824      *     from the synthetic password.
1825      * 2. If user credential does not exist, vold and keystore protection are cleared. This is to
1826      *     make it consistent with current behaviour. It also allows ActivityManager to call
1827      *     unlockUser() with empty secret.
1828      * 3. Once a user is migrated to have synthetic password, its value will never change, no matter
1829      *     whether the user changes his lockscreen PIN or clear/reset it. When the user clears its
1830      *     lockscreen PIN, we still maintain the existing synthetic password in a password blob
1831      *     protected by a default PIN. The only exception is when the DPC performs an untrusted
1832      *     credential change, in which case we have no way to derive the existing synthetic password
1833      *     and has to create a new one.
1834      * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user
1835      *     clears/re-creates his lockscreen PIN.
1836      *
1837      *
1838      * Different cases of calling this method:
1839      * 1. credentialHash != null
1840      *     This implies credential != null, a new SP blob will be provisioned, and existing SID
1841      *     migrated to associate with the new SP.
1842      *     This happens during a normal migration case when the user currently has password.
1843      *
1844      * 2. credentialhash == null and credential == null
1845      *     A new SP blob and a new SID will be created, while the user has no credentials.
1846      *     This can happens when we are activating an escrow token on a unsecured device, during
1847      *     which we want to create the SP structure with an empty user credential.
1848      *
1849      * 3. credentialhash == null and credential != null
1850      *     This is the untrusted credential reset, OR the user sets a new lockscreen password
1851      *     FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
1852      */
1853     private AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
1854             String credential, int credentialType, int userId) throws RemoteException {
1855         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
1856         AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(getGateKeeperService(),
1857                 credentialHash, credential, userId);
1858         if (auth == null) {
1859             Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
1860             return null;
1861         }
1862         long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
1863                 credential, credentialType, auth, userId);
1864         if (credential != null) {
1865             if (credentialHash == null) {
1866                 // Since when initializing SP, we didn't provide an existing password handle
1867                 // for it to migrate SID, we need to create a new SID for the user.
1868                 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
1869             }
1870             mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
1871             setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
1872             setKeystorePassword(auth.deriveKeyStorePassword(), userId);
1873         } else {
1874             clearUserKeyProtection(userId);
1875             setKeystorePassword(null, userId);
1876             getGateKeeperService().clearSecureUserId(userId);
1877         }
1878         fixateNewestUserKeyAuth(userId);
1879         setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
1880         return auth;
1881     }
1882
1883     private long getSyntheticPasswordHandleLocked(int userId) {
1884         try {
1885             return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId);
1886         } catch (RemoteException e) {
1887             return SyntheticPasswordManager.DEFAULT_HANDLE;
1888         }
1889     }
1890
1891     private boolean isSyntheticPasswordBasedCredentialLocked(int userId) throws RemoteException {
1892         long handle = getSyntheticPasswordHandleLocked(userId);
1893         // This is a global setting
1894         long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
1895       return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
1896     }
1897
1898     private boolean shouldMigrateToSyntheticPasswordLocked(int userId) throws RemoteException {
1899         long handle = getSyntheticPasswordHandleLocked(userId);
1900         // This is a global setting
1901         long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
1902         return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
1903     }
1904
1905     private void enableSyntheticPasswordLocked() throws RemoteException {
1906         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
1907     }
1908
1909     private VerifyCredentialResponse spBasedDoVerifyCredentialLocked(String userCredential, int
1910             credentialType, boolean hasChallenge, long challenge, int userId,
1911             ICheckCredentialProgressCallback progressCallback) throws RemoteException {
1912         if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredentialLocked: user=" + userId);
1913         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
1914             userCredential = null;
1915         }
1916         long handle = getSyntheticPasswordHandleLocked(userId);
1917         AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
1918                 getGateKeeperService(), handle, userCredential, userId);
1919
1920         VerifyCredentialResponse response = authResult.gkResponse;
1921         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
1922             // credential has matched
1923             // perform verifyChallenge with synthetic password which generates the real auth
1924             // token for the current user
1925             response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
1926                     challenge, userId);
1927             if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
1928                 Slog.wtf(TAG, "verifyChallenge with SP failed.");
1929                 return VerifyCredentialResponse.ERROR;
1930             }
1931             if (progressCallback != null) {
1932                 progressCallback.onCredentialVerified();
1933             }
1934             notifyActivePasswordMetricsAvailable(userCredential, userId);
1935             unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
1936
1937             final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
1938             Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
1939             unlockUser(userId, null, secret);
1940
1941             if (isManagedProfileWithSeparatedLock(userId)) {
1942                 TrustManager trustManager =
1943                         (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
1944                 trustManager.setDeviceLockedForUser(userId, false);
1945             }
1946             activateEscrowTokens(authResult.authToken, userId);
1947         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
1948             if (response.getTimeout() > 0) {
1949                 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
1950             }
1951         }
1952
1953         return response;
1954     }
1955
1956     /**
1957      * Change the user's lockscreen password by creating a new SP blob and update the handle, based
1958      * on an existing authentication token. Even though a new SP blob is created, the underlying
1959      * synthetic password is never changed.
1960      *
1961      * When clearing credential, we keep the SP unchanged, but clear its password handle so its
1962      * SID is gone. We also clear password from (software-based) keystore and vold, which will be
1963      * added back when new password is set in future.
1964      */
1965     private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType,
1966             AuthenticationToken auth, int userId) throws RemoteException {
1967         if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
1968         long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
1969                 credential, credentialType, auth, userId);
1970         final Map<Integer, String> profilePasswords;
1971         if (credential != null) {
1972             // // not needed by synchronizeUnifiedWorkChallengeForProfiles()
1973             profilePasswords = null;
1974
1975             if (mSpManager.hasSidForUser(userId)) {
1976                 // We are changing password of a secured device, nothing more needed as
1977                 // createPasswordBasedSyntheticPassword has already taken care of maintaining
1978                 // the password handle and SID unchanged.
1979
1980                 //refresh auth token
1981                 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
1982             } else {
1983                 // A new password is set on a previously-unsecured device, we need to generate
1984                 // a new SID, and re-add keys to vold and keystore.
1985                 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
1986                 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
1987                 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
1988                 fixateNewestUserKeyAuth(userId);
1989                 setKeystorePassword(auth.deriveKeyStorePassword(), userId);
1990             }
1991         } else {
1992             // Cache all profile password if they use unified work challenge. This will later be
1993             // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
1994             profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
1995
1996             // we are clearing password of a secured device, so need to nuke SID as well.
1997             mSpManager.clearSidForUser(userId);
1998             getGateKeeperService().clearSecureUserId(userId);
1999             // Clear key from vold so ActivityManager can just unlock the user with empty secret
2000             // during boot.
2001             clearUserKeyProtection(userId);
2002             fixateNewestUserKeyAuth(userId);
2003             setKeystorePassword(null, userId);
2004         }
2005         setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
2006         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
2007         return newHandle;
2008     }
2009
2010     private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType,
2011             String savedCredential, int userId) throws RemoteException {
2012         if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
2013         if (isManagedProfileWithUnifiedLock(userId)) {
2014             // get credential from keystore when managed profile has unified lock
2015             try {
2016                 savedCredential = getDecryptedPasswordForTiedProfile(userId);
2017             } catch (FileNotFoundException e) {
2018                 Slog.i(TAG, "Child profile key not found");
2019             } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
2020                     | NoSuchAlgorithmException | NoSuchPaddingException
2021                     | InvalidAlgorithmParameterException | IllegalBlockSizeException
2022                     | BadPaddingException | CertificateException | IOException e) {
2023                 Slog.e(TAG, "Failed to decrypt child profile key", e);
2024             }
2025         }
2026         long handle = getSyntheticPasswordHandleLocked(userId);
2027         AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
2028                 getGateKeeperService(), handle, savedCredential, userId);
2029         VerifyCredentialResponse response = authResult.gkResponse;
2030         AuthenticationToken auth = authResult.authToken;
2031         if (auth != null) {
2032             // We are performing a trusted credential change i.e. a correct existing credential
2033             // is provided
2034             setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, userId);
2035             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
2036         } else if (response != null
2037                 && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR){
2038             // We are performing an untrusted credential change i.e. by DevicePolicyManager.
2039             // So provision a new SP and SID. This would invalidate existing escrow tokens.
2040             // Still support this for now but this flow will be removed in the next release.
2041
2042             Slog.w(TAG, "Untrusted credential change invoked");
2043             initializeSyntheticPasswordLocked(null, credential, credentialType, userId);
2044             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
2045             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
2046         } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
2047             Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
2048                     (response != null ? "rate limit exceeded" : "failed"));
2049             return;
2050         }
2051         notifyActivePasswordMetricsAvailable(credential, userId);
2052
2053     }
2054
2055     @Override
2056     public long addEscrowToken(byte[] token, int userId) throws RemoteException {
2057         ensureCallerSystemUid();
2058         if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
2059         synchronized (mSpManager) {
2060             enableSyntheticPasswordLocked();
2061             // Migrate to synthetic password based credentials if the user has no password,
2062             // the token can then be activated immediately.
2063             AuthenticationToken auth = null;
2064             if (!isUserSecure(userId)) {
2065                 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
2066                     auth = initializeSyntheticPasswordLocked(null, null,
2067                             LockPatternUtils.CREDENTIAL_TYPE_NONE, userId);
2068                 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ {
2069                     long pwdHandle = getSyntheticPasswordHandleLocked(userId);
2070                     auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
2071                             pwdHandle, null, userId).authToken;
2072                 }
2073             }
2074             disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
2075             if (!mSpManager.hasEscrowData(userId)) {
2076                 throw new SecurityException("Escrow token is disabled on the current user");
2077             }
2078             long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
2079             if (auth != null) {
2080                 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
2081             }
2082             return handle;
2083         }
2084     }
2085
2086     private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
2087         if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
2088         synchronized (mSpManager) {
2089             for (long handle : mSpManager.getPendingTokensForUser(userId)) {
2090                 Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
2091                 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
2092             }
2093         }
2094     }
2095
2096     @Override
2097     public boolean isEscrowTokenActive(long handle, int userId) throws RemoteException {
2098         ensureCallerSystemUid();
2099         synchronized (mSpManager) {
2100             return mSpManager.existsHandle(handle, userId);
2101         }
2102     }
2103
2104     @Override
2105     public boolean removeEscrowToken(long handle, int userId) throws RemoteException {
2106         ensureCallerSystemUid();
2107         synchronized (mSpManager) {
2108             if (handle == getSyntheticPasswordHandleLocked(userId)) {
2109                 Slog.w(TAG, "Cannot remove password handle");
2110                 return false;
2111             }
2112             if (mSpManager.removePendingToken(handle, userId)) {
2113                 return true;
2114             }
2115             if (mSpManager.existsHandle(handle, userId)) {
2116                 mSpManager.destroyTokenBasedSyntheticPassword(handle, userId);
2117                 return true;
2118             } else {
2119                 return false;
2120             }
2121         }
2122     }
2123
2124     @Override
2125     public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
2126             byte[] token, int userId) throws RemoteException {
2127         ensureCallerSystemUid();
2128         boolean result;
2129         synchronized (mSpManager) {
2130             if (!mSpManager.hasEscrowData(userId)) {
2131                 throw new SecurityException("Escrow token is disabled on the current user");
2132             }
2133             result = setLockCredentialWithTokenInternal(credential, type, tokenHandle, token,
2134                     userId);
2135         }
2136         if (result) {
2137             synchronized (mSeparateChallengeLock) {
2138                 setSeparateProfileChallengeEnabled(userId, true, null);
2139             }
2140             notifyPasswordChanged(userId);
2141         }
2142         return result;
2143     }
2144
2145     private boolean setLockCredentialWithTokenInternal(String credential, int type,
2146             long tokenHandle, byte[] token, int userId) throws RemoteException {
2147         synchronized (mSpManager) {
2148             AuthenticationResult result = mSpManager.unwrapTokenBasedSyntheticPassword(
2149                     getGateKeeperService(), tokenHandle, token, userId);
2150             if (result.authToken == null) {
2151                 Slog.w(TAG, "Invalid escrow token supplied");
2152                 return false;
2153             }
2154             long oldHandle = getSyntheticPasswordHandleLocked(userId);
2155             setLockCredentialWithAuthTokenLocked(credential, type, result.authToken, userId);
2156             mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
2157             return true;
2158         }
2159     }
2160
2161     @Override
2162     public void unlockUserWithToken(long tokenHandle, byte[] token, int userId)
2163             throws RemoteException {
2164         ensureCallerSystemUid();
2165         AuthenticationResult authResult;
2166         synchronized (mSpManager) {
2167             if (!mSpManager.hasEscrowData(userId)) {
2168                 throw new SecurityException("Escrow token is disabled on the current user");
2169             }
2170             authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(),
2171                     tokenHandle, token, userId);
2172             if (authResult.authToken == null) {
2173                 Slog.w(TAG, "Invalid escrow token supplied");
2174                 return;
2175             }
2176         }
2177         unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
2178     }
2179
2180     @Override
2181     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
2182         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2183
2184         synchronized (this) {
2185             pw.println("Current lock settings service state:");
2186             pw.println(String.format("SP Enabled = %b",
2187                     mLockPatternUtils.isSyntheticPasswordEnabled()));
2188
2189             List<UserInfo> users = mUserManager.getUsers();
2190             for (int user = 0; user < users.size(); user++) {
2191                 final int userId = users.get(user).id;
2192                 pw.println("    User " + userId);
2193                 pw.println(String.format("        SP Handle = %x",
2194                         getSyntheticPasswordHandleLocked(userId)));
2195                 try {
2196                     pw.println(String.format("        SID = %x",
2197                             getGateKeeperService().getSecureUserId(userId)));
2198                 } catch (RemoteException e) {
2199                     // ignore.
2200                 }
2201             }
2202         }
2203     }
2204
2205     private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
2206         long ident = Binder.clearCallingIdentity();
2207         try {
2208             // Managed profile should have escrow enabled
2209             if (mUserManager.getUserInfo(userId).isManagedProfile()) {
2210                 Slog.i(TAG, "Managed profile can have escrow token");
2211                 return;
2212             }
2213             DevicePolicyManager dpm = mInjector.getDevicePolicyManager();
2214             // Devices with Device Owner should have escrow enabled on all users.
2215             if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
2216                 Slog.i(TAG, "Corp-owned device can have escrow token");
2217                 return;
2218             }
2219             // We could also have a profile owner on the given (non-managed) user for unicorn cases
2220             if (dpm.getProfileOwnerAsUser(userId) != null) {
2221                 Slog.i(TAG, "User with profile owner can have escrow token");
2222                 return;
2223             }
2224             // If the device is yet to be provisioned (still in SUW), there is still
2225             // a chance that Device Owner will be set on the device later, so postpone
2226             // disabling escrow token for now.
2227             if (!dpm.isDeviceProvisioned()) {
2228                 Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
2229                 return;
2230             }
2231
2232             // Escrow tokens are enabled on automotive builds.
2233             if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
2234                 return;
2235             }
2236
2237             // Disable escrow token permanently on all other device/user types.
2238             Slog.i(TAG, "Disabling escrow token on user " + userId);
2239             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
2240                 mSpManager.destroyEscrowData(userId);
2241             }
2242         } catch (RemoteException e) {
2243             Slog.e(TAG, "disableEscrowTokenOnNonManagedDevices", e);
2244         } finally {
2245             Binder.restoreCallingIdentity(ident);
2246         }
2247     }
2248
2249     private void ensureCallerSystemUid() throws SecurityException {
2250         final int callingUid = mInjector.binderGetCallingUid();
2251         if (callingUid != Process.SYSTEM_UID) {
2252             throw new SecurityException("Only system can call this API.");
2253         }
2254     }
2255 }