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