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