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