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