OSDN Git Service

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