blob: a4e7ac4d272bc1b9dcc0dfb64cac13d6d9b810fe [file] [log] [blame]
Amith Yamasani52c489c2012-03-28 11:42:42 -07001/*
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
Andrew Scull507d11c2017-05-03 17:19:01 +010017package com.android.server.locksettings;
Amith Yamasani52c489c2012-03-28 11:42:42 -070018
Rubin Xu1de89b32016-11-30 20:03:13 +000019import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
20import static android.Manifest.permission.READ_CONTACTS;
21import static android.content.Context.KEYGUARD_SERVICE;
Adrian Roosb953e182017-08-17 17:58:26 +020022import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Adrian Roos7374d3a2017-03-31 14:14:53 -070023
Pavel Grafov19a4fb32019-03-15 12:55:12 +000024import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
25import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
Rubin Xu5e891bc2019-10-14 10:22:23 +010026import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
Pavel Grafov19a4fb32019-03-15 12:55:12 +000027import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
Rubin Xu5e891bc2019-10-14 10:22:23 +010028import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
Ram Periathiruvadi32d53552019-02-19 13:25:46 -080029import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
Rubin Xu5e891bc2019-10-14 10:22:23 +010030import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT;
Rubin Xu3bf722a2016-12-15 16:07:38 +000031import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
32import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
Bo Zhuc7048342019-01-03 14:04:58 -080033import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
Adrian Roos7374d3a2017-03-31 14:14:53 -070034import static com.android.internal.widget.LockPatternUtils.USER_FRP;
35import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
Adrian Roos454f53f2017-08-08 14:56:42 +020036import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
Rubin Xu1de89b32016-11-30 20:03:13 +000037
Kevin Chynbc29dd72019-06-13 11:47:54 -070038import android.annotation.IntDef;
Dmitry Dementyev1aa96132017-12-11 11:33:12 -080039import android.annotation.NonNull;
40import android.annotation.Nullable;
Andrew Scull5daf2732016-11-14 15:02:45 +000041import android.annotation.UserIdInt;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080042import android.app.ActivityManager;
Rubin Xu0cbc19e2016-12-09 14:00:21 +000043import android.app.IActivityManager;
Kenny Guyb1b30262016-02-09 16:02:35 +000044import android.app.KeyguardManager;
Jim Miller4f93c582016-01-27 19:05:43 -080045import android.app.Notification;
46import android.app.NotificationManager;
47import android.app.PendingIntent;
Adrian Roos230635e2015-01-07 20:50:29 +010048import android.app.admin.DevicePolicyManager;
Pavel Grafov28939982017-10-03 15:11:52 +010049import android.app.admin.DevicePolicyManagerInternal;
Rubin Xu0f1e56d2019-08-23 13:34:25 +010050import android.app.admin.DeviceStateCache;
Andrew Scull5daf2732016-11-14 15:02:45 +000051import android.app.admin.PasswordMetrics;
Amith Yamasani072543f2015-02-13 11:09:45 -080052import android.app.backup.BackupManager;
Adrian Roosb5e47222015-08-14 15:53:06 -070053import android.app.trust.IStrongAuthTracker;
Clara Bayarri56878a92015-10-29 15:43:55 +000054import android.app.trust.TrustManager;
Robin Leef0246a82014-08-13 09:50:25 +010055import android.content.BroadcastReceiver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070056import android.content.ContentResolver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070057import android.content.Context;
Robin Leef0246a82014-08-13 09:50:25 +010058import android.content.Intent;
59import android.content.IntentFilter;
Jim Miller158fe192013-04-17 15:23:55 -070060import android.content.pm.PackageManager;
Jim Miller187ec582013-04-15 18:27:54 -070061import android.content.pm.UserInfo;
Jim Miller4f93c582016-01-27 19:05:43 -080062import android.content.res.Resources;
Adrian Roos7374d3a2017-03-31 14:14:53 -070063import android.database.ContentObserver;
Amith Yamasani52c489c2012-03-28 11:42:42 -070064import android.database.sqlite.SQLiteDatabase;
Andrew Sculle6527c12018-01-05 18:33:58 +000065import android.hardware.authsecret.V1_0.IAuthSecret;
Kevin Chyna38653c2019-02-11 17:46:21 -080066import android.hardware.biometrics.BiometricManager;
Alex Johnston6183cf92019-10-03 15:59:03 +010067import android.hardware.face.Face;
Kevin Chyna38653c2019-02-11 17:46:21 -080068import android.hardware.face.FaceManager;
Alex Johnston6183cf92019-10-03 15:59:03 +010069import android.hardware.fingerprint.Fingerprint;
70import android.hardware.fingerprint.FingerprintManager;
Adrian Roos7374d3a2017-03-31 14:14:53 -070071import android.net.Uri;
Amith Yamasani52c489c2012-03-28 11:42:42 -070072import android.os.Binder;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060073import android.os.Bundle;
Ricky Waib0cdf382016-05-16 17:28:04 +010074import android.os.Handler;
Paul Lawrence945490c2014-03-27 16:37:28 +000075import android.os.IBinder;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060076import android.os.IProgressListener;
Ricky Wai4613fe42016-05-24 11:11:42 +010077import android.os.Process;
Amith Yamasani52c489c2012-03-28 11:42:42 -070078import android.os.RemoteException;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -070079import android.os.ResultReceiver;
Paul Lawrence945490c2014-03-27 16:37:28 +000080import android.os.ServiceManager;
Rubin Xu1de89b32016-11-30 20:03:13 +000081import android.os.ShellCallback;
Jeff Sharkeyeddf5182016-08-09 16:36:08 -060082import android.os.StrictMode;
Amith Yamasanid1645f82012-06-12 11:53:26 -070083import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070084import android.os.UserHandle;
Jim Miller187ec582013-04-15 18:27:54 -070085import android.os.UserManager;
Rubin Xu0f1e56d2019-08-23 13:34:25 +010086import android.os.UserManagerInternal;
Rubin Xu1de89b32016-11-30 20:03:13 +000087import android.os.storage.IStorageManager;
88import android.os.storage.StorageManager;
Amith Yamasani52c489c2012-03-28 11:42:42 -070089import android.provider.Settings;
90import android.provider.Settings.Secure;
Jim Miller187ec582013-04-15 18:27:54 -070091import android.provider.Settings.SettingNotFoundException;
Jim Millerde1af082013-09-11 14:58:26 -070092import android.security.KeyStore;
Ricky Waidc283a82016-03-24 19:55:08 +000093import android.security.keystore.AndroidKeyStoreProvider;
94import android.security.keystore.KeyProperties;
95import android.security.keystore.KeyProtection;
Pavel Grafov0acc4bf2017-08-23 12:20:54 +010096import android.security.keystore.UserNotAuthenticatedException;
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -080097import android.security.keystore.recovery.KeyChainProtectionParams;
Bo Zhuc7048342019-01-03 14:04:58 -080098import android.security.keystore.recovery.KeyChainSnapshot;
Bo Zhu7c1972f2018-02-22 21:43:52 -080099import android.security.keystore.recovery.RecoveryCertPath;
Robert Berry81ee34b2018-01-23 11:59:59 +0000100import android.security.keystore.recovery.WrappedApplicationKey;
Andres Morales23974272015-05-14 22:42:26 -0700101import android.service.gatekeeper.GateKeeperResponse;
Andres Morales8fa56652015-03-31 09:19:50 -0700102import android.service.gatekeeper.IGateKeeperService;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700103import android.text.TextUtils;
Rubin Xua55b1682017-01-31 10:06:56 +0000104import android.util.ArrayMap;
Annie Meng086ddc82019-03-29 17:43:35 +0000105import android.util.ArraySet;
Adrian Roosb953e182017-08-17 17:58:26 +0200106import android.util.EventLog;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700107import android.util.Slog;
Andrew Scull1416bd02018-01-05 18:33:58 +0000108import android.util.SparseArray;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700109
Pavel Grafov28939982017-10-03 15:11:52 +0100110import com.android.internal.annotations.GuardedBy;
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000111import com.android.internal.annotations.VisibleForTesting;
Chris Wren282cfef2017-03-27 15:01:44 -0400112import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500113import com.android.internal.notification.SystemNotificationChannels;
Amith Yamasani072543f2015-02-13 11:09:45 -0800114import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600115import com.android.internal.util.DumpUtils;
Rubin Xue2f925f2019-08-14 16:53:55 +0100116import com.android.internal.util.IndentingPrintWriter;
Adrian Roos7374d3a2017-03-31 14:14:53 -0700117import com.android.internal.util.Preconditions;
Jorim Jaggie8fde5d2016-06-30 23:41:37 -0700118import com.android.internal.widget.ICheckCredentialProgressCallback;
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800119import com.android.internal.widget.ILockSettings;
120import com.android.internal.widget.LockPatternUtils;
Rubin Xufcd49f92017-08-24 18:21:52 +0100121import com.android.internal.widget.LockSettingsInternal;
Rubin Xua58125d2019-09-06 20:11:48 +0100122import com.android.internal.widget.LockscreenCredential;
Andres Morales23974272015-05-14 22:42:26 -0700123import com.android.internal.widget.VerifyCredentialResponse;
Pavel Grafov28939982017-10-03 15:11:52 +0100124import com.android.server.LocalServices;
Alex Johnston6183cf92019-10-03 15:59:03 +0100125import com.android.server.ServiceThread;
Andrew Scull507d11c2017-05-03 17:19:01 +0100126import com.android.server.SystemService;
127import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
Dmitry Dementyev1aa96132017-12-11 11:33:12 -0800128import com.android.server.locksettings.LockSettingsStorage.PersistentData;
Andrew Scull507d11c2017-05-03 17:19:01 +0100129import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
130import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
Bo Zhuc7048342019-01-03 14:04:58 -0800131import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100132import com.android.server.wm.WindowManagerInternal;
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800133
Ricky Waidc283a82016-03-24 19:55:08 +0000134import libcore.util.HexEncoding;
135
136import java.io.ByteArrayOutputStream;
Jorim Jaggi2fef6f72016-11-01 19:06:25 -0700137import java.io.FileDescriptor;
Ricky Waidc283a82016-03-24 19:55:08 +0000138import java.io.FileNotFoundException;
139import java.io.IOException;
Rubin Xu3bf722a2016-12-15 16:07:38 +0000140import java.io.PrintWriter;
Ricky Waidc283a82016-03-24 19:55:08 +0000141import java.security.InvalidAlgorithmParameterException;
142import java.security.InvalidKeyException;
143import java.security.KeyStoreException;
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +0000144import java.security.MessageDigest;
145import java.security.NoSuchAlgorithmException;
Ricky Waidc283a82016-03-24 19:55:08 +0000146import java.security.SecureRandom;
147import java.security.UnrecoverableKeyException;
148import java.security.cert.CertificateException;
Rubin Xue2f925f2019-08-14 16:53:55 +0100149import java.text.SimpleDateFormat;
Andrew Sculle6527c12018-01-05 18:33:58 +0000150import java.util.ArrayList;
Bo Zhuc7048342019-01-03 14:04:58 -0800151import java.util.Arrays;
Rubin Xue2f925f2019-08-14 16:53:55 +0100152import java.util.Date;
Jim Miller187ec582013-04-15 18:27:54 -0700153import java.util.List;
Rubin Xua55b1682017-01-31 10:06:56 +0000154import java.util.Map;
Andrew Sculle6527c12018-01-05 18:33:58 +0000155import java.util.NoSuchElementException;
Annie Meng086ddc82019-03-29 17:43:35 +0000156import java.util.Set;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -0600157import java.util.concurrent.CountDownLatch;
158import java.util.concurrent.TimeUnit;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700159
Ricky Waidc283a82016-03-24 19:55:08 +0000160import javax.crypto.BadPaddingException;
161import javax.crypto.Cipher;
162import javax.crypto.IllegalBlockSizeException;
163import javax.crypto.KeyGenerator;
164import javax.crypto.NoSuchPaddingException;
165import javax.crypto.SecretKey;
166import javax.crypto.spec.GCMParameterSpec;
167
Amith Yamasani52c489c2012-03-28 11:42:42 -0700168/**
Rubin Xu1de89b32016-11-30 20:03:13 +0000169 * Keeps the lock pattern/password data and related settings for each user. Used by
170 * LockPatternUtils. Needs to be a service because Settings app also needs to be able to save
171 * lockscreen information for secondary users.
172 *
Amith Yamasani52c489c2012-03-28 11:42:42 -0700173 * @hide
174 */
175public class LockSettingsService extends ILockSettings.Stub {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700176 private static final String TAG = "LockSettingsService";
Jim Miller4f93c582016-01-27 19:05:43 -0800177 private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
Jim Miller4f93c582016-01-27 19:05:43 -0800178 private static final boolean DEBUG = false;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700179
Ricky Waidc283a82016-03-24 19:55:08 +0000180 private static final int PROFILE_KEY_IV_SIZE = 12;
181 private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
Rubin Xue2f925f2019-08-14 16:53:55 +0100182 private static final String PREV_SYNTHETIC_PASSWORD_HANDLE_KEY = "prev-sp-handle";
183 private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts";
Rubin Xu1de89b32016-11-30 20:03:13 +0000184
Kevin Chynbc29dd72019-06-13 11:47:54 -0700185 // No challenge provided
186 private static final int CHALLENGE_NONE = 0;
187 // Challenge was provided from the external caller (non-LockSettingsService)
188 private static final int CHALLENGE_FROM_CALLER = 1;
189 // Challenge was generated from within LockSettingsService, for resetLockout. When challenge
190 // type is set to internal, LSS will revokeChallenge after all profiles for that user are
191 // unlocked.
192 private static final int CHALLENGE_INTERNAL = 2;
193
194 @IntDef({CHALLENGE_NONE,
195 CHALLENGE_FROM_CALLER,
196 CHALLENGE_INTERNAL})
Rubin Xua7587272019-07-30 17:14:28 +0100197 @interface ChallengeType {}
Kevin Chynbc29dd72019-06-13 11:47:54 -0700198
Rubin Xua0a0d352017-05-15 16:18:01 +0000199 // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
Rubin Xue94a7702017-06-20 17:29:57 +0100200 // Do not call into ActivityManager while holding mSpManager lock.
Ricky Waidc283a82016-03-24 19:55:08 +0000201 private final Object mSeparateChallengeLock = new Object();
202
Adrian Roos7374d3a2017-03-31 14:14:53 -0700203 private final DeviceProvisionedObserver mDeviceProvisionedObserver =
204 new DeviceProvisionedObserver();
205
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000206 private final Injector mInjector;
Amith Yamasani52c489c2012-03-28 11:42:42 -0700207 private final Context mContext;
Rubin Xu7cf45092017-08-28 11:47:35 +0100208 @VisibleForTesting
209 protected final Handler mHandler;
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000210 @VisibleForTesting
211 protected final LockSettingsStorage mStorage;
Rakesh Iyera7aa4d62016-01-19 17:27:23 -0800212 private final LockSettingsStrongAuth mStrongAuth;
Victor Changa0940d32016-05-16 19:36:08 +0100213 private final SynchronizedStrongAuthTracker mStrongAuthTracker;
Adrian Roos261d5ab2014-10-29 14:42:38 +0100214
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000215 private final LockPatternUtils mLockPatternUtils;
216 private final NotificationManager mNotificationManager;
217 private final UserManager mUserManager;
Rubin Xuca7007b2019-03-25 11:44:41 +0000218 private final IStorageManager mStorageManager;
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000219 private final IActivityManager mActivityManager;
Andrew Scull8fc2ec82017-05-19 10:50:36 +0100220 private final SyntheticPasswordManager mSpManager;
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000221
222 private final KeyStore mKeyStore;
223
Dmitry Dementyev1aa96132017-12-11 11:33:12 -0800224 private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
225
Paul Lawrence945490c2014-03-27 16:37:28 +0000226 private boolean mFirstCallToVold;
Rubin Xu19854862019-08-15 16:37:23 +0100227 // Current password metric for all users on the device. Updated when user unlocks
228 // the device or changes password. Removed when user is stopped.
229 @GuardedBy("this")
230 final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>();
231
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000232 protected IGateKeeperService mGateKeeperService;
Andrew Sculle6527c12018-01-05 18:33:58 +0000233 protected IAuthSecret mAuthSecretService;
Rubin Xu3bf722a2016-12-15 16:07:38 +0000234
David Anderson6ebc25b2019-02-12 16:25:56 -0800235 private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
236
Ricky Wai4613fe42016-05-24 11:11:42 +0100237 /**
238 * The UIDs that are used for system credential storage in keystore.
239 */
Rubin Xu1de89b32016-11-30 20:03:13 +0000240 private static final int[] SYSTEM_CREDENTIAL_UIDS = {
241 Process.WIFI_UID, Process.VPN_UID,
Rubin Xu24b89b12017-04-26 19:44:16 +0100242 Process.ROOT_UID, Process.SYSTEM_UID };
Andres Morales23974272015-05-14 22:42:26 -0700243
Jim Miller4f93c582016-01-27 19:05:43 -0800244 // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
245 // devices. The most basic of these is to show/hide notifications about missing features until
246 // the user unlocks the account and credential-encrypted storage is available.
247 public static final class Lifecycle extends SystemService {
248 private LockSettingsService mLockSettingsService;
249
250 public Lifecycle(Context context) {
251 super(context);
252 }
253
254 @Override
255 public void onStart() {
Ricky Waidc283a82016-03-24 19:55:08 +0000256 AndroidKeyStoreProvider.install();
Jim Miller4f93c582016-01-27 19:05:43 -0800257 mLockSettingsService = new LockSettingsService(getContext());
258 publishBinderService("lock_settings", mLockSettingsService);
259 }
260
261 @Override
Adrian Roos60dcbbf2017-08-08 16:19:33 +0200262 public void onBootPhase(int phase) {
263 super.onBootPhase(phase);
264 if (phase == PHASE_ACTIVITY_MANAGER_READY) {
265 mLockSettingsService.migrateOldDataAfterSystemReady();
266 }
267 }
268
269 @Override
Andrew Scull85a63bc2016-10-24 13:47:47 +0100270 public void onStartUser(int userHandle) {
271 mLockSettingsService.onStartUser(userHandle);
Jim Miller4f93c582016-01-27 19:05:43 -0800272 }
273
274 @Override
275 public void onUnlockUser(int userHandle) {
276 mLockSettingsService.onUnlockUser(userHandle);
277 }
278
279 @Override
280 public void onCleanupUser(int userHandle) {
281 mLockSettingsService.onCleanupUser(userHandle);
282 }
283 }
284
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000285 @VisibleForTesting
286 protected static class SynchronizedStrongAuthTracker
287 extends LockPatternUtils.StrongAuthTracker {
Victor Changa0940d32016-05-16 19:36:08 +0100288 public SynchronizedStrongAuthTracker(Context context) {
289 super(context);
290 }
291
292 @Override
293 protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) {
294 synchronized (this) {
295 super.handleStrongAuthRequiredChanged(strongAuthFlags, userId);
296 }
297 }
298
299 @Override
300 public int getStrongAuthForUser(int userId) {
301 synchronized (this) {
302 return super.getStrongAuthForUser(userId);
303 }
304 }
305
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000306 void register(LockSettingsStrongAuth strongAuth) {
307 strongAuth.registerStrongAuthTracker(this.mStub);
Victor Changa0940d32016-05-16 19:36:08 +0100308 }
309 }
310
Kevin Chynbc29dd72019-06-13 11:47:54 -0700311 private class PendingResetLockout {
312 final int mUserId;
313 final byte[] mHAT;
314 PendingResetLockout(int userId, byte[] hat) {
315 mUserId = userId;
316 mHAT = hat;
317 }
318 }
319
Rubin Xubb883202019-10-09 11:22:53 +0100320 private LockscreenCredential generateRandomProfilePassword() {
321 byte[] randomLockSeed = new byte[] {};
322 try {
323 randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
324 char[] newPasswordChars = HexEncoding.encode(randomLockSeed);
325 byte[] newPassword = new byte[newPasswordChars.length];
326 for (int i = 0; i < newPasswordChars.length; i++) {
327 newPassword[i] = (byte) newPasswordChars[i];
328 }
329 LockscreenCredential credential =
330 LockscreenCredential.createManagedPassword(newPassword);
331 Arrays.fill(newPasswordChars, '\u0000');
332 Arrays.fill(newPassword, (byte) 0);
333 Arrays.fill(randomLockSeed, (byte) 0);
334 return credential;
335 } catch (NoSuchAlgorithmException e) {
Rubin Xu5e891bc2019-10-14 10:22:23 +0100336 throw new IllegalStateException("Fail to generate profile password", e);
Rubin Xubb883202019-10-09 11:22:53 +0100337 }
338 }
339
Ricky Waidc283a82016-03-24 19:55:08 +0000340 /**
341 * Tie managed profile to primary profile if it is in unified mode and not tied before.
342 *
343 * @param managedUserId Managed profile user Id
344 * @param managedUserPassword Managed profile original password (when it has separated lock).
Ricky Waidc283a82016-03-24 19:55:08 +0000345 */
Rubin Xubb883202019-10-09 11:22:53 +0100346 public void tieManagedProfileLockIfNecessary(int managedUserId,
347 LockscreenCredential managedUserPassword) {
Ricky Waidc283a82016-03-24 19:55:08 +0000348 if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
349 // Only for managed profile
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000350 if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
Ricky Waidc283a82016-03-24 19:55:08 +0000351 return;
352 }
353 // Do not tie managed profile when work challenge is enabled
354 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
355 return;
356 }
357 // Do not tie managed profile to parent when it's done already
358 if (mStorage.hasChildProfileLock(managedUserId)) {
359 return;
360 }
361 // Do not tie it to parent when parent does not have a screen lock
362 final int parentId = mUserManager.getProfileParent(managedUserId).id;
Rubin Xua55b1682017-01-31 10:06:56 +0000363 if (!isUserSecure(parentId)) {
Ricky Waidc283a82016-03-24 19:55:08 +0000364 if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
365 return;
366 }
Rubin Xubfc7faaf2016-11-22 15:18:32 +0000367 // Do not tie when the parent has no SID (but does have a screen lock).
368 // This can only happen during an upgrade path where SID is yet to be
369 // generated when the user unlocks for the first time.
370 try {
371 if (getGateKeeperService().getSecureUserId(parentId) == 0) {
372 return;
373 }
374 } catch (RemoteException e) {
375 Slog.e(TAG, "Failed to talk to GateKeeper service", e);
376 return;
377 }
Ricky Waidc283a82016-03-24 19:55:08 +0000378 if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
Rubin Xubb883202019-10-09 11:22:53 +0100379 try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
Rubin Xubb883202019-10-09 11:22:53 +0100380 setLockCredentialInternal(unifiedProfilePassword, managedUserPassword, managedUserId,
381 false, /* isLockTiedToParent= */ true);
Rubin Xubb883202019-10-09 11:22:53 +0100382 tieProfileLockToParent(managedUserId, unifiedProfilePassword);
Ricky Waidc283a82016-03-24 19:55:08 +0000383 }
384 }
385
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000386 static class Injector {
Jim Millerde1af082013-09-11 14:58:26 -0700387
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000388 protected Context mContext;
389
390 public Injector(Context context) {
391 mContext = context;
392 }
393
394 public Context getContext() {
395 return mContext;
396 }
397
Alex Johnston6183cf92019-10-03 15:59:03 +0100398 public ServiceThread getServiceThread() {
399 ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
400 true /*allowIo*/);
401 handlerThread.start();
402 return handlerThread;
403 }
404
405 public Handler getHandler(ServiceThread handlerThread) {
406 return new Handler(handlerThread.getLooper());
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000407 }
408
409 public LockSettingsStorage getStorage() {
410 final LockSettingsStorage storage = new LockSettingsStorage(mContext);
411 storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
412 @Override
413 public void initialize(SQLiteDatabase db) {
414 // Get the lockscreen default from a system property, if available
415 boolean lockScreenDisable = SystemProperties.getBoolean(
416 "ro.lockscreen.disable.default", false);
417 if (lockScreenDisable) {
418 storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
419 }
420 }
421 });
422 return storage;
423 }
424
425 public LockSettingsStrongAuth getStrongAuth() {
426 return new LockSettingsStrongAuth(mContext);
427 }
428
429 public SynchronizedStrongAuthTracker getStrongAuthTracker() {
430 return new SynchronizedStrongAuthTracker(mContext);
431 }
432
433 public IActivityManager getActivityManager() {
434 return ActivityManager.getService();
435 }
436
437 public LockPatternUtils getLockPatternUtils() {
438 return new LockPatternUtils(mContext);
439 }
440
441 public NotificationManager getNotificationManager() {
442 return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
443 }
444
445 public UserManager getUserManager() {
446 return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
447 }
448
Rubin Xu0f1e56d2019-08-23 13:34:25 +0100449 public UserManagerInternal getUserManagerInternal() {
450 return LocalServices.getService(UserManagerInternal.class);
451 }
452
Rubin Xu19854862019-08-15 16:37:23 +0100453 /**
454 * Return the {@link DevicePolicyManager} object.
455 *
456 * Since LockSettingsService is considered a lower-level component than DevicePolicyManager,
457 * do NOT hold any lock in this class while calling into DevicePolicyManager to prevent
458 * the risk of deadlock.
459 */
Rubin Xu8b30ec32017-03-05 00:47:09 +0000460 public DevicePolicyManager getDevicePolicyManager() {
461 return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
462 }
463
Rubin Xu0f1e56d2019-08-23 13:34:25 +0100464 public DeviceStateCache getDeviceStateCache() {
465 return DeviceStateCache.getInstance();
466 }
467
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000468 public KeyStore getKeyStore() {
469 return KeyStore.getInstance();
470 }
471
Dmitry Dementyev29b9de52018-01-31 16:09:32 -0800472 public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
473 return RecoverableKeyStoreManager.getInstance(mContext, keyStore);
Dmitry Dementyev1aa96132017-12-11 11:33:12 -0800474 }
475
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000476 public IStorageManager getStorageManager() {
477 final IBinder service = ServiceManager.getService("mount");
478 if (service != null) {
479 return IStorageManager.Stub.asInterface(service);
480 }
481 return null;
482 }
Rubin Xu3bf722a2016-12-15 16:07:38 +0000483
484 public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
David Anderson28dea682019-02-20 13:37:51 -0800485 return new SyntheticPasswordManager(getContext(), storage, getUserManager(),
486 new PasswordSlotManager());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000487 }
488
Kevin Chyn28623b62019-06-11 11:43:33 -0700489 public boolean hasEnrolledBiometrics(int userId) {
Kevin Chyn71db85f2019-05-14 15:32:47 -0700490 BiometricManager bm = mContext.getSystemService(BiometricManager.class);
Kevin Chyn27f92312019-07-26 12:41:33 -0700491 return bm.hasEnrolledBiometrics(userId);
Kevin Chyncf1a62e2019-02-21 11:11:59 -0800492 }
493
Rubin Xu3bf722a2016-12-15 16:07:38 +0000494 public int binderGetCallingUid() {
495 return Binder.getCallingUid();
496 }
David Anderson6ebc25b2019-02-12 16:25:56 -0800497
498 public boolean isGsiRunning() {
499 return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
500 }
Alex Johnston6183cf92019-10-03 15:59:03 +0100501
502 public FingerprintManager getFingerprintManager() {
503 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
504 return (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
505 } else {
506 return null;
507 }
508 }
509
510 public FaceManager getFaceManager() {
511 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
512 return (FaceManager) mContext.getSystemService(Context.FACE_SERVICE);
513 } else {
514 return null;
515 }
516 }
517
Rubin Xu5e891bc2019-10-14 10:22:23 +0100518 public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName,
519 int defaultValue) {
520 return Settings.Global.getInt(contentResolver, keyName, defaultValue);
521 }
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000522 }
523
524 public LockSettingsService(Context context) {
525 this(new Injector(context));
526 }
527
528 @VisibleForTesting
529 protected LockSettingsService(Injector injector) {
530 mInjector = injector;
531 mContext = injector.getContext();
532 mKeyStore = injector.getKeyStore();
Dmitry Dementyev29b9de52018-01-31 16:09:32 -0800533 mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
Alex Johnston6183cf92019-10-03 15:59:03 +0100534 mHandler = injector.getHandler(injector.getServiceThread());
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000535 mStrongAuth = injector.getStrongAuth();
536 mActivityManager = injector.getActivityManager();
537
538 mLockPatternUtils = injector.getLockPatternUtils();
Paul Lawrence945490c2014-03-27 16:37:28 +0000539 mFirstCallToVold = true;
Robin Leef0246a82014-08-13 09:50:25 +0100540
541 IntentFilter filter = new IntentFilter();
542 filter.addAction(Intent.ACTION_USER_ADDED);
Adrian Roos3dcae682014-10-29 14:43:56 +0100543 filter.addAction(Intent.ACTION_USER_STARTING);
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100544 filter.addAction(Intent.ACTION_USER_REMOVED);
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000545 injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
546 null, null);
Adrian Roos261d5ab2014-10-29 14:42:38 +0100547
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000548 mStorage = injector.getStorage();
549 mNotificationManager = injector.getNotificationManager();
550 mUserManager = injector.getUserManager();
Rubin Xuca7007b2019-03-25 11:44:41 +0000551 mStorageManager = injector.getStorageManager();
Rubin Xu0cbc19e2016-12-09 14:00:21 +0000552 mStrongAuthTracker = injector.getStrongAuthTracker();
553 mStrongAuthTracker.register(mStrongAuth);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000554
555 mSpManager = injector.getSyntheticPasswordManager(mStorage);
Rubin Xufcd49f92017-08-24 18:21:52 +0100556
557 LocalServices.addService(LockSettingsInternal.class, new LocalService());
Jim Miller4f93c582016-01-27 19:05:43 -0800558 }
559
560 /**
Rubin Xu1de89b32016-11-30 20:03:13 +0000561 * If the account is credential-encrypted, show notification requesting the user to unlock the
562 * device.
Jim Miller4f93c582016-01-27 19:05:43 -0800563 */
Andrew Scull85a63bc2016-10-24 13:47:47 +0100564 private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
565 final UserInfo user = mUserManager.getUserInfo(userId);
566 if (!user.isManagedProfile()) {
567 // When the user is locked, we communicate it loud-and-clear
568 // on the lockscreen; we only show a notification below for
569 // locked managed profiles.
570 return;
571 }
572
Irina Dumitrescue13ce662019-05-09 17:50:50 +0100573 if (isUserKeyUnlocked(userId)) {
574 // If storage is not locked, the user will be automatically unlocked so there is
575 // no need to show the notification.
576 return;
577 }
578
Andrew Scull85a63bc2016-10-24 13:47:47 +0100579 final UserHandle userHandle = user.getUserHandle();
Rubin Xua55b1682017-01-31 10:06:56 +0000580 final boolean isSecure = isUserSecure(userId);
Andrew Scull85a63bc2016-10-24 13:47:47 +0100581 if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
582 UserInfo parent = mUserManager.getProfileParent(userId);
583 if (parent != null &&
584 mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
585 !mUserManager.isQuietModeEnabled(userHandle)) {
586 // Only show notifications for managed profiles once their parent
587 // user is unlocked.
588 showEncryptionNotificationForProfile(userHandle);
Jim Miller4f93c582016-01-27 19:05:43 -0800589 }
Jim Miller4f93c582016-01-27 19:05:43 -0800590 }
591 }
592
Kenny Guyb1b30262016-02-09 16:02:35 +0000593 private void showEncryptionNotificationForProfile(UserHandle user) {
594 Resources r = mContext.getResources();
595 CharSequence title = r.getText(
Rubin Xu897750a2019-04-30 17:15:03 +0100596 com.android.internal.R.string.profile_encrypted_title);
Kenny Guyb1b30262016-02-09 16:02:35 +0000597 CharSequence message = r.getText(
598 com.android.internal.R.string.profile_encrypted_message);
599 CharSequence detail = r.getText(
600 com.android.internal.R.string.profile_encrypted_detail);
601
602 final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
Rubin Xu1de89b32016-11-30 20:03:13 +0000603 final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
604 user.getIdentifier());
Kenny Guyb1b30262016-02-09 16:02:35 +0000605 if (unlockIntent == null) {
606 return;
607 }
Rubin Xu1de89b32016-11-30 20:03:13 +0000608 unlockIntent.setFlags(
609 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Kenny Guyb1b30262016-02-09 16:02:35 +0000610 PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
611 PendingIntent.FLAG_UPDATE_CURRENT);
612
613 showEncryptionNotification(user, title, message, detail, intent);
614 }
615
Rubin Xu1de89b32016-11-30 20:03:13 +0000616 private void showEncryptionNotification(UserHandle user, CharSequence title,
617 CharSequence message, CharSequence detail, PendingIntent intent) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000618 if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
Jeff Sharkey4a399362016-05-26 09:47:43 -0600619
620 // Suppress all notifications on non-FBE devices for now
621 if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
622
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500623 Notification notification =
Rubin Xu897750a2019-04-30 17:15:03 +0100624 new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500625 .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
626 .setWhen(0)
627 .setOngoing(true)
628 .setTicker(title)
629 .setColor(mContext.getColor(
630 com.android.internal.R.color.system_notification_accent_color))
631 .setContentTitle(title)
632 .setContentText(message)
633 .setSubText(detail)
634 .setVisibility(Notification.VISIBILITY_PUBLIC)
635 .setContentIntent(intent)
636 .build();
Chris Wren282cfef2017-03-27 15:01:44 -0400637 mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
638 notification, user);
Jim Miller4f93c582016-01-27 19:05:43 -0800639 }
640
Andrew Scull85a63bc2016-10-24 13:47:47 +0100641 private void hideEncryptionNotification(UserHandle userHandle) {
Rubin Xu1de89b32016-11-30 20:03:13 +0000642 if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
Chris Wren282cfef2017-03-27 15:01:44 -0400643 mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
644 userHandle);
Jim Miller4f93c582016-01-27 19:05:43 -0800645 }
646
647 public void onCleanupUser(int userId) {
648 hideEncryptionNotification(new UserHandle(userId));
Erin Yan324d75e2019-05-16 17:22:21 -0700649 // User is stopped with its CE key evicted. Restore strong auth requirement to the default
650 // flags after boot since stopping and restarting a user later is equivalent to rebooting
651 // the device.
652 int strongAuthRequired = LockPatternUtils.StrongAuthTracker.getDefaultFlags(mContext);
653 requireStrongAuth(strongAuthRequired, userId);
Rubin Xu19854862019-08-15 16:37:23 +0100654 synchronized (this) {
655 mUserPasswordMetrics.remove(userId);
656 }
Jim Miller4f93c582016-01-27 19:05:43 -0800657 }
658
Andrew Scull85a63bc2016-10-24 13:47:47 +0100659 public void onStartUser(final int userId) {
660 maybeShowEncryptionNotificationForUser(userId);
661 }
662
Pavel Grafov0acc4bf2017-08-23 12:20:54 +0100663 /**
664 * Check if profile got unlocked but the keystore is still locked. This happens on full disk
665 * encryption devices since the profile may not yet be running when we consider unlocking it
666 * during the normal flow. In this case unlock the keystore for the profile.
667 */
668 private void ensureProfileKeystoreUnlocked(int userId) {
669 final KeyStore ks = KeyStore.getInstance();
670 if (ks.state(userId) == KeyStore.State.LOCKED
671 && tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) {
672 Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore");
Rubin Xuca6ece52019-07-31 15:02:13 +0100673 // If boot took too long and the password in vold got expired, parent keystore will
674 // be still locked, we ignore this case since the user will be prompted to unlock
675 // the device after boot.
676 unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */,
677 CHALLENGE_NONE, 0 /* challenge */, null /* resetLockouts */);
Pavel Grafov0acc4bf2017-08-23 12:20:54 +0100678 }
679 }
680
Ricky Waib0cdf382016-05-16 17:28:04 +0100681 public void onUnlockUser(final int userId) {
Rubin Xua55b1682017-01-31 10:06:56 +0000682 // Perform tasks which require locks in LSS on a handler, as we are callbacks from
683 // ActivityManager.unlockUser()
684 mHandler.post(new Runnable() {
685 @Override
686 public void run() {
Pavel Grafov0acc4bf2017-08-23 12:20:54 +0100687 ensureProfileKeystoreUnlocked(userId);
Rubin Xua55b1682017-01-31 10:06:56 +0000688 // Hide notification first, as tie managed profile lock takes time
689 hideEncryptionNotification(new UserHandle(userId));
Ricky Waib0cdf382016-05-16 17:28:04 +0100690
Rubin Xua55b1682017-01-31 10:06:56 +0000691 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
Rubin Xubb883202019-10-09 11:22:53 +0100692 tieManagedProfileLockIfNecessary(userId, LockscreenCredential.createNone());
Ricky Waib0cdf382016-05-16 17:28:04 +0100693 }
Andrew Scullf49794b2018-04-13 12:01:25 +0100694
695 // If the user doesn't have a credential, try and derive their secret for the
696 // AuthSecret HAL. The secret will have been enrolled if the user previously set a
697 // credential and still needs to be passed to the HAL once that credential is
698 // removed.
699 if (mUserManager.getUserInfo(userId).isPrimary() && !isUserSecure(userId)) {
700 tryDeriveAuthTokenForUnsecuredPrimaryUser(userId);
701 }
Kenny Guyb1b30262016-02-09 16:02:35 +0000702 }
Rubin Xua55b1682017-01-31 10:06:56 +0000703 });
Amith Yamasani52c489c2012-03-28 11:42:42 -0700704 }
705
Andrew Scullf49794b2018-04-13 12:01:25 +0100706 private void tryDeriveAuthTokenForUnsecuredPrimaryUser(@UserIdInt int userId) {
707 synchronized (mSpManager) {
708 // Make sure the user has a synthetic password to derive
709 if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
710 return;
711 }
712
Rubin Xuca6ece52019-07-31 15:02:13 +0100713 final long handle = getSyntheticPasswordHandleLocked(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +0100714 AuthenticationResult result =
Rubin Xubb883202019-10-09 11:22:53 +0100715 mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
716 handle, LockscreenCredential.createNone(), userId, null);
Rubin Xuca6ece52019-07-31 15:02:13 +0100717 if (result.authToken != null) {
718 Slog.i(TAG, "Retrieved auth token for user " + userId);
719 onAuthTokenKnownForUser(userId, result.authToken);
720 } else {
721 Slog.e(TAG, "Auth token not available for user " + userId);
Andrew Scullf49794b2018-04-13 12:01:25 +0100722 }
723 }
724 }
725
Robin Leef0246a82014-08-13 09:50:25 +0100726 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
727 @Override
728 public void onReceive(Context context, Intent intent) {
Robin Lee1096cf82014-09-01 16:52:47 +0100729 if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
Chad Brubaker83ce0952015-05-12 13:00:02 -0700730 // Notify keystore that a new user was added.
Robin Leef0246a82014-08-13 09:50:25 +0100731 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
Amith Yamasanif11a5742016-06-16 08:20:07 -0700732 if (userHandle > UserHandle.USER_SYSTEM) {
733 removeUser(userHandle, /* unknownUser= */ true);
734 }
Robin Lee49d810c2014-09-23 13:50:22 +0100735 final KeyStore ks = KeyStore.getInstance();
Ricky Waidc283a82016-03-24 19:55:08 +0000736 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
Chad Brubaker83ce0952015-05-12 13:00:02 -0700737 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
738 ks.onUserAdded(userHandle, parentHandle);
Adrian Roos3dcae682014-10-29 14:43:56 +0100739 } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
740 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
741 mStorage.prefetchUser(userHandle);
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100742 } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
743 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
744 if (userHandle > 0) {
Amith Yamasanif11a5742016-06-16 08:20:07 -0700745 removeUser(userHandle, /* unknownUser= */ false);
Adrian Roosdb0f76e2015-01-07 22:19:38 +0100746 }
Robin Leef0246a82014-08-13 09:50:25 +0100747 }
748 }
749 };
750
Jim Miller4f93c582016-01-27 19:05:43 -0800751 @Override // binder interface
Amith Yamasani52c489c2012-03-28 11:42:42 -0700752 public void systemReady() {
Adrian Roosb953e182017-08-17 17:58:26 +0200753 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
754 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet
755 }
756 checkWritePermission(UserHandle.USER_SYSTEM);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700757 migrateOldData();
Rubin Xuca6ece52019-07-31 15:02:13 +0100758 getGateKeeperService();
759 mSpManager.initWeaverService();
Andrew Sculle6527c12018-01-05 18:33:58 +0000760 // Find the AuthSecret HAL
761 try {
762 mAuthSecretService = IAuthSecret.getService();
763 } catch (NoSuchElementException e) {
764 Slog.i(TAG, "Device doesn't implement AuthSecret HAL");
765 } catch (RemoteException e) {
766 Slog.w(TAG, "Failed to get AuthSecret HAL", e);
767 }
Adrian Roos7374d3a2017-03-31 14:14:53 -0700768 mDeviceProvisionedObserver.onSystemReady();
Xiaohui Chen7c696362015-09-16 09:56:14 -0700769 // TODO: maybe skip this for split system user mode.
770 mStorage.prefetchUser(UserHandle.USER_SYSTEM);
Amith Yamasani52c489c2012-03-28 11:42:42 -0700771 }
772
773 private void migrateOldData() {
Rubin Xufe354472017-11-21 12:05:06 +0000774 // These Settings moved before multi-user was enabled, so we only have to do it for the
775 // root user.
776 if (getString("migrated", null, 0) == null) {
777 final ContentResolver cr = mContext.getContentResolver();
778 for (String validSetting : VALID_SETTINGS) {
779 String value = Settings.Secure.getString(cr, validSetting);
780 if (value != null) {
781 setString(validSetting, value, 0);
Jim Miller187ec582013-04-15 18:27:54 -0700782 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700783 }
Rubin Xufe354472017-11-21 12:05:06 +0000784 // No need to move the password / pattern files. They're already in the right place.
785 setString("migrated", "true", 0);
786 Slog.i(TAG, "Migrated lock settings to new location");
787 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700788
Rubin Xufe354472017-11-21 12:05:06 +0000789 // These Settings changed after multi-user was enabled, hence need to be moved per user.
790 if (getString("migrated_user_specific", null, 0) == null) {
791 final ContentResolver cr = mContext.getContentResolver();
792 List<UserInfo> users = mUserManager.getUsers();
793 for (int user = 0; user < users.size(); user++) {
794 // Migrate owner info
795 final int userId = users.get(user).id;
796 final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
797 String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
798 if (!TextUtils.isEmpty(ownerInfo)) {
799 setString(OWNER_INFO, ownerInfo, userId);
800 Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
Adrian Roos43830582015-04-21 16:04:43 -0700801 }
802
Rubin Xufe354472017-11-21 12:05:06 +0000803 // Migrate owner info enabled. Note there was a bug where older platforms only
804 // stored this value if the checkbox was toggled at least once. The code detects
805 // this case by handling the exception.
806 final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
807 boolean enabled;
Ricky Wai97c8f8d2016-07-13 17:57:45 +0100808 try {
Rubin Xufe354472017-11-21 12:05:06 +0000809 int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
810 enabled = ivalue != 0;
811 setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
812 } catch (SettingNotFoundException e) {
813 // Setting was never stored. Store it if the string is not empty.
814 if (!TextUtils.isEmpty(ownerInfo)) {
815 setLong(OWNER_INFO_ENABLED, 1, userId);
Ricky Wai97c8f8d2016-07-13 17:57:45 +0100816 }
Rubin Xufe354472017-11-21 12:05:06 +0000817 }
818 Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
819 }
820 // No need to move the password / pattern files. They're already in the right place.
821 setString("migrated_user_specific", "true", 0);
822 Slog.i(TAG, "Migrated per-user lock settings to new location");
823 }
824
825 // Migrates biometric weak such that the fallback mechanism becomes the primary.
826 if (getString("migrated_biometric_weak", null, 0) == null) {
827 List<UserInfo> users = mUserManager.getUsers();
828 for (int i = 0; i < users.size(); i++) {
829 int userId = users.get(i).id;
830 long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
831 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
832 userId);
833 long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
834 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
835 userId);
836 if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
837 setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
838 alternateType,
839 userId);
840 }
841 setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
842 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
843 userId);
844 }
845 setString("migrated_biometric_weak", "true", 0);
846 Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
847 }
848
849 // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one
850 // user was present on the system, so if we're upgrading to M and there is more than one
851 // user we disable the flag to remain consistent.
852 if (getString("migrated_lockscreen_disabled", null, 0) == null) {
853 final List<UserInfo> users = mUserManager.getUsers();
854 final int userCount = users.size();
855 int switchableUsers = 0;
856 for (int i = 0; i < userCount; i++) {
857 if (users.get(i).supportsSwitchTo()) {
858 switchableUsers++;
Ricky Wai97c8f8d2016-07-13 17:57:45 +0100859 }
Ricky Wai7b9eb412016-05-12 17:29:12 +0100860 }
Greg Plesureb2e4532016-11-02 17:10:27 -0400861
Rubin Xufe354472017-11-21 12:05:06 +0000862 if (switchableUsers > 1) {
Greg Plesureb2e4532016-11-02 17:10:27 -0400863 for (int i = 0; i < userCount; i++) {
864 int id = users.get(i).id;
Rubin Xufe354472017-11-21 12:05:06 +0000865
866 if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
867 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
868 }
Greg Plesureb2e4532016-11-02 17:10:27 -0400869 }
Greg Plesureb2e4532016-11-02 17:10:27 -0400870 }
Rubin Xufe354472017-11-21 12:05:06 +0000871
872 setString("migrated_lockscreen_disabled", "true", 0);
873 Slog.i(TAG, "Migrated lockscreen disabled flag");
874 }
875
Rubin Xufe354472017-11-21 12:05:06 +0000876 boolean isWatch = mContext.getPackageManager().hasSystemFeature(
877 PackageManager.FEATURE_WATCH);
878 // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts
879 // and device management the lockscreen must be re-enabled now for users that upgrade.
880 if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
Rubin Xu7b76f332019-11-08 12:10:12 +0000881 final List<UserInfo> users = mUserManager.getUsers();
Rubin Xufe354472017-11-21 12:05:06 +0000882 final int userCount = users.size();
883 for (int i = 0; i < userCount; i++) {
884 int id = users.get(i).id;
885 setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
886 }
887 setString("migrated_wear_lockscreen_disabled", "true", 0);
888 Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700889 }
890 }
891
Adrian Roos60dcbbf2017-08-08 16:19:33 +0200892 private void migrateOldDataAfterSystemReady() {
Rubin Xuca6ece52019-07-31 15:02:13 +0100893 // Migrate the FRP credential to the persistent data block
894 if (LockPatternUtils.frpCredentialEnabled(mContext)
895 && !getBoolean("migrated_frp", false, 0)) {
896 migrateFrpCredential();
897 setBoolean("migrated_frp", true, 0);
898 Slog.i(TAG, "Migrated migrated_frp.");
Adrian Roos60dcbbf2017-08-08 16:19:33 +0200899 }
900 }
901
902 /**
903 * Migrate the credential for the FRP credential owner user if the following are satisfied:
904 * - the user has a secure credential
905 * - the FRP credential is not set up
906 * - the credential is based on a synthetic password.
907 */
Rubin Xuca6ece52019-07-31 15:02:13 +0100908 private void migrateFrpCredential() {
Adrian Roos60dcbbf2017-08-08 16:19:33 +0200909 if (mStorage.readPersistentDataBlock() != PersistentData.NONE) {
910 return;
911 }
912 for (UserInfo userInfo : mUserManager.getUsers()) {
Adrian Roos2adc2632017-09-05 17:01:42 +0200913 if (userOwnsFrpCredential(mContext, userInfo) && isUserSecure(userInfo.id)) {
Adrian Roos60dcbbf2017-08-08 16:19:33 +0200914 synchronized (mSpManager) {
915 if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) {
916 int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
917 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
918
919 mSpManager.migrateFrpPasswordLocked(
920 getSyntheticPasswordHandleLocked(userInfo.id),
921 userInfo,
922 redactActualQualityToMostLenientEquivalentQuality(actualQuality));
923 }
924 }
925 return;
926 }
927 }
928 }
929
930 /**
931 * Returns the lowest password quality that still presents the same UI for entering it.
932 *
933 * For the FRP credential, we do not want to leak the actual quality of the password, only what
934 * kind of UI it requires. However, when migrating, we only know the actual quality, not the
935 * originally requested quality; since this is only used to determine what input variant to
936 * present to the user, we just assume the lowest possible quality was requested.
937 */
938 private int redactActualQualityToMostLenientEquivalentQuality(int quality) {
939 switch (quality) {
940 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
941 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
942 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
943 return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
944 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
945 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
946 return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
947 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
948 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
949 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
950 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
951 default:
952 return quality;
953 }
954 }
955
Jim Miller5ecd8112013-01-09 18:50:26 -0800956 private final void checkWritePermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800957 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700958 }
959
Jim Miller5ecd8112013-01-09 18:50:26 -0800960 private final void checkPasswordReadPermission(int userId) {
Jim Miller505329b2013-11-08 13:25:36 -0800961 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
Amith Yamasani52c489c2012-03-28 11:42:42 -0700962 }
963
Adrian Roosb953e182017-08-17 17:58:26 +0200964 private final void checkPasswordHavePermission(int userId) {
965 if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
966 EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet
967 }
968 mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
969 }
970
Jim Miller158fe192013-04-17 15:23:55 -0700971 private final void checkReadPermission(String requestedKey, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -0700972 final int callingUid = Binder.getCallingUid();
Adrian Roos001b00d2015-02-24 17:08:48 +0100973
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +0000974 for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
975 String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
976 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
Jim Miller158fe192013-04-17 15:23:55 -0700977 != PackageManager.PERMISSION_GRANTED) {
978 throw new SecurityException("uid=" + callingUid
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +0000979 + " needs permission " + READ_CONTACTS + " to read "
Jim Miller158fe192013-04-17 15:23:55 -0700980 + requestedKey + " for user " + userId);
981 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700982 }
Adrian Roos001b00d2015-02-24 17:08:48 +0100983
984 for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
985 String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
986 if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
987 != PackageManager.PERMISSION_GRANTED) {
988 throw new SecurityException("uid=" + callingUid
989 + " needs permission " + PERMISSION + " to read "
990 + requestedKey + " for user " + userId);
991 }
992 }
Amith Yamasani52c489c2012-03-28 11:42:42 -0700993 }
994
995 @Override
Rubin Xufe354472017-11-21 12:05:06 +0000996 public boolean getSeparateProfileChallengeEnabled(int userId) {
Ricky Wai7f405f12016-05-31 12:05:05 +0100997 checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
Rubin Xuba6fef52019-10-25 11:10:43 +0100998 return getSeparateProfileChallengeEnabledInternal(userId);
999 }
1000
1001 private boolean getSeparateProfileChallengeEnabledInternal(int userId) {
Ricky Waidc283a82016-03-24 19:55:08 +00001002 synchronized (mSeparateChallengeLock) {
Rubin Xuba6fef52019-10-25 11:10:43 +01001003 return getBooleanUnchecked(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001004 }
1005 }
1006
1007 @Override
1008 public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
Rubin Xubb883202019-10-09 11:22:53 +01001009 LockscreenCredential managedUserPassword) {
Ricky Wai7f405f12016-05-31 12:05:05 +01001010 checkWritePermission(userId);
Lenka Trochtova66c492a2018-12-06 11:29:21 +01001011 if (!mLockPatternUtils.hasSecureLockScreen()) {
1012 throw new UnsupportedOperationException(
1013 "This operation requires secure lock screen feature.");
1014 }
Ricky Waidc283a82016-03-24 19:55:08 +00001015 synchronized (mSeparateChallengeLock) {
Rubin Xubb883202019-10-09 11:22:53 +01001016 setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword != null
1017 ? managedUserPassword : LockscreenCredential.createNone());
Ricky Waidc283a82016-03-24 19:55:08 +00001018 }
Pavel Grafov28939982017-10-03 15:11:52 +01001019 notifySeparateProfileChallengeChanged(userId);
1020 }
1021
1022 @GuardedBy("mSeparateChallengeLock")
Rich Canningsf64ec632019-02-21 12:40:36 -08001023 private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId,
Rubin Xubb883202019-10-09 11:22:53 +01001024 boolean enabled, LockscreenCredential managedUserPassword) {
Pavel Grafovf10ae7e2018-06-25 12:13:38 +01001025 final boolean old = getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
Pavel Grafov28939982017-10-03 15:11:52 +01001026 setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
Pavel Grafovf10ae7e2018-06-25 12:13:38 +01001027 try {
1028 if (enabled) {
1029 mStorage.removeChildProfileLock(userId);
1030 removeKeystoreProfileKey(userId);
1031 } else {
1032 tieManagedProfileLockIfNecessary(userId, managedUserPassword);
1033 }
1034 } catch (IllegalStateException e) {
1035 setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, old, userId);
1036 throw e;
Pavel Grafov28939982017-10-03 15:11:52 +01001037 }
1038 }
1039
1040 private void notifySeparateProfileChallengeChanged(int userId) {
Rubin Xu0f1e56d2019-08-23 13:34:25 +01001041 // LSS cannot call into DPM directly, otherwise it will cause deadlock.
1042 // In this case, calling DPM on a handler thread is OK since DPM doesn't
1043 // expect reportSeparateProfileChallengeChanged() to happen synchronously.
1044 mHandler.post(() -> {
1045 final DevicePolicyManagerInternal dpmi = LocalServices.getService(
1046 DevicePolicyManagerInternal.class);
1047 if (dpmi != null) {
1048 dpmi.reportSeparateProfileChallengeChanged(userId);
1049 }
1050 });
Ricky Waidc283a82016-03-24 19:55:08 +00001051 }
1052
1053 @Override
Rubin Xufe354472017-11-21 12:05:06 +00001054 public void setBoolean(String key, boolean value, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001055 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +01001056 setStringUnchecked(key, userId, value ? "1" : "0");
Amith Yamasani52c489c2012-03-28 11:42:42 -07001057 }
1058
1059 @Override
Rubin Xufe354472017-11-21 12:05:06 +00001060 public void setLong(String key, long value, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001061 checkWritePermission(userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001062 setLongUnchecked(key, value, userId);
1063 }
1064
1065 private void setLongUnchecked(String key, long value, int userId) {
Adrian Roos261d5ab2014-10-29 14:42:38 +01001066 setStringUnchecked(key, userId, Long.toString(value));
Amith Yamasani52c489c2012-03-28 11:42:42 -07001067 }
1068
1069 @Override
Rubin Xufe354472017-11-21 12:05:06 +00001070 public void setString(String key, String value, int userId) {
Amith Yamasani52c489c2012-03-28 11:42:42 -07001071 checkWritePermission(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +01001072 setStringUnchecked(key, userId, value);
1073 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07001074
Adrian Roos261d5ab2014-10-29 14:42:38 +01001075 private void setStringUnchecked(String key, int userId, String value) {
Adrian Roos7374d3a2017-03-31 14:14:53 -07001076 Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user");
1077
Adrian Roos261d5ab2014-10-29 14:42:38 +01001078 mStorage.writeKeyValue(key, value, userId);
Amith Yamasani072543f2015-02-13 11:09:45 -08001079 if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
1080 BackupManager.dataChanged("com.android.providers.settings");
1081 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07001082 }
1083
1084 @Override
Adrian Roos60dcbbf2017-08-08 16:19:33 +02001085 public boolean getBoolean(String key, boolean defaultValue, int userId) {
Jim Miller158fe192013-04-17 15:23:55 -07001086 checkReadPermission(key, userId);
Rubin Xuba6fef52019-10-25 11:10:43 +01001087 return getBooleanUnchecked(key, defaultValue, userId);
1088 }
1089
1090 private boolean getBooleanUnchecked(String key, boolean defaultValue, int userId) {
Adrian Roos9dd16eb2015-01-08 16:20:49 +01001091 String value = getStringUnchecked(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001092 return TextUtils.isEmpty(value) ?
1093 defaultValue : (value.equals("1") || value.equals("true"));
1094 }
1095
1096 @Override
Adrian Roos60dcbbf2017-08-08 16:19:33 +02001097 public long getLong(String key, long defaultValue, int userId) {
Jim Miller158fe192013-04-17 15:23:55 -07001098 checkReadPermission(key, userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001099 return getLongUnchecked(key, defaultValue, userId);
1100 }
1101
1102 private long getLongUnchecked(String key, long defaultValue, int userId) {
Adrian Roos9dd16eb2015-01-08 16:20:49 +01001103 String value = getStringUnchecked(key, null, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001104 return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
1105 }
1106
1107 @Override
Adrian Roos60dcbbf2017-08-08 16:19:33 +02001108 public String getString(String key, String defaultValue, int userId) {
Jim Miller158fe192013-04-17 15:23:55 -07001109 checkReadPermission(key, userId);
Adrian Roos9dd16eb2015-01-08 16:20:49 +01001110 return getStringUnchecked(key, defaultValue, userId);
1111 }
1112
Rubin Xu5e891bc2019-10-14 10:22:23 +01001113 private String getStringUnchecked(String key, String defaultValue, int userId) {
Adrian Roos9dd16eb2015-01-08 16:20:49 +01001114 if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
Adrian Roos7811d9f2015-07-27 15:10:13 -07001115 long ident = Binder.clearCallingIdentity();
1116 try {
1117 return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
1118 } finally {
1119 Binder.restoreCallingIdentity(ident);
1120 }
Adrian Roos9dd16eb2015-01-08 16:20:49 +01001121 }
Adrian Roos7374d3a2017-03-31 14:14:53 -07001122 if (userId == USER_FRP) {
Rubin Xu5e891bc2019-10-14 10:22:23 +01001123 return null;
Adrian Roos7374d3a2017-03-31 14:14:53 -07001124 }
1125
Bryce Lee46145962015-12-14 14:39:10 -08001126 if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
1127 key = Settings.Secure.LOCK_PATTERN_ENABLED;
1128 }
1129
Adrian Roos261d5ab2014-10-29 14:42:38 +01001130 return mStorage.readKeyValue(key, defaultValue, userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001131 }
1132
Rubin Xu5e891bc2019-10-14 10:22:23 +01001133 private void setKeyguardStoredQuality(int quality, int userId) {
1134 if (DEBUG) Slog.d(TAG, "setKeyguardStoredQuality: user=" + userId + " quality=" + quality);
1135 setLongUnchecked(LockPatternUtils.PASSWORD_TYPE_KEY, quality, userId);
Adrian Roos7374d3a2017-03-31 14:14:53 -07001136 }
1137
Rubin Xu5e891bc2019-10-14 10:22:23 +01001138 private int getKeyguardStoredQuality(int userId) {
1139 return (int) getLongUnchecked(LockPatternUtils.PASSWORD_TYPE_KEY,
1140 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
Adrian Roos7374d3a2017-03-31 14:14:53 -07001141 }
1142
Adrian Roos4f788452014-05-22 20:45:59 +02001143 @Override
Rubin Xu5e891bc2019-10-14 10:22:23 +01001144 public int getCredentialType(int userId) {
Adrian Roosb953e182017-08-17 17:58:26 +02001145 checkPasswordHavePermission(userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001146 return getCredentialTypeInternal(userId);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001147 }
1148
Rubin Xu5e891bc2019-10-14 10:22:23 +01001149 // TODO: this is a hot path, can we optimize it?
1150 /**
1151 * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
1152 * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
1153 * {@link #CREDENTIAL_TYPE_PASSWORD}
1154 */
1155 public int getCredentialTypeInternal(int userId) {
1156 if (userId == USER_FRP) {
1157 return getFrpCredentialType();
1158 }
Rubin Xu3bf722a2016-12-15 16:07:38 +00001159 synchronized (mSpManager) {
1160 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
Pavel Grafov19a4fb32019-03-15 12:55:12 +00001161 final long handle = getSyntheticPasswordHandleLocked(userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001162 int rawType = mSpManager.getCredentialType(handle, userId);
1163 if (rawType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
1164 return rawType;
1165 }
1166 return pinOrPasswordQualityToCredentialType(getKeyguardStoredQuality(userId));
Rubin Xu3bf722a2016-12-15 16:07:38 +00001167 }
1168 }
Rubin Xu5e891bc2019-10-14 10:22:23 +01001169 // Intentional duplication of the getKeyguardStoredQuality() call above since this is a
1170 // unlikely code path (device with pre-synthetic password credential). We want to skip
1171 // calling getKeyguardStoredQuality whenever possible.
1172 final int savedQuality = getKeyguardStoredQuality(userId);
1173 if (savedQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
1174 && mStorage.hasPattern(userId)) {
1175 return CREDENTIAL_TYPE_PATTERN;
1176 }
1177 if (savedQuality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
1178 && mStorage.hasPassword(userId)) {
1179 return pinOrPasswordQualityToCredentialType(savedQuality);
1180 }
1181 return CREDENTIAL_TYPE_NONE;
1182 }
1183
1184 private int getFrpCredentialType() {
1185 PersistentData data = mStorage.readPersistentDataBlock();
1186 if (data.type != PersistentData.TYPE_SP && data.type != PersistentData.TYPE_SP_WEAVER) {
1187 return CREDENTIAL_TYPE_NONE;
1188 }
1189 int credentialType = SyntheticPasswordManager.getFrpCredentialType(data.payload);
1190 if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
1191 return credentialType;
1192 }
1193 return pinOrPasswordQualityToCredentialType(data.qualityForUi);
1194 }
1195
1196 private static int pinOrPasswordQualityToCredentialType(int quality) {
1197 if (LockPatternUtils.isQualityAlphabeticPassword(quality)) {
1198 return CREDENTIAL_TYPE_PASSWORD;
1199 }
1200 if (LockPatternUtils.isQualityNumericPin(quality)) {
1201 return CREDENTIAL_TYPE_PIN;
1202 }
1203 throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality);
Amith Yamasani52c489c2012-03-28 11:42:42 -07001204 }
1205
Rubin Xua55b1682017-01-31 10:06:56 +00001206 private boolean isUserSecure(int userId) {
Rubin Xu5e891bc2019-10-14 10:22:23 +01001207 return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE;
Rubin Xua55b1682017-01-31 10:06:56 +00001208 }
1209
Rich Canningsf64ec632019-02-21 12:40:36 -08001210 private void setKeystorePassword(byte[] password, int userHandle) {
Robin Leef0246a82014-08-13 09:50:25 +01001211 final KeyStore ks = KeyStore.getInstance();
Rich Canningsf64ec632019-02-21 12:40:36 -08001212 // TODO(b/120484642): Update keystore to accept byte[] passwords
1213 String passwordString = password == null ? null : new String(password);
1214 ks.onUserPasswordChanged(userHandle, passwordString);
Chad Brubakera91a8502015-05-07 10:02:22 -07001215 }
1216
Rich Canningsf64ec632019-02-21 12:40:36 -08001217 private void unlockKeystore(byte[] password, int userHandle) {
Ricky Waidc283a82016-03-24 19:55:08 +00001218 if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
Rich Canningsf64ec632019-02-21 12:40:36 -08001219 // TODO(b/120484642): Update keystore to accept byte[] passwords
1220 String passwordString = password == null ? null : new String(password);
Chad Brubakera91a8502015-05-07 10:02:22 -07001221 final KeyStore ks = KeyStore.getInstance();
Rich Canningsf64ec632019-02-21 12:40:36 -08001222 ks.unlock(userHandle, passwordString);
Ricky Waidc283a82016-03-24 19:55:08 +00001223 }
Chad Brubakera91a8502015-05-07 10:02:22 -07001224
Rubin Xubb883202019-10-09 11:22:53 +01001225 @VisibleForTesting /** Note: this method is overridden in unit tests */
1226 protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId)
Ricky Waidc283a82016-03-24 19:55:08 +00001227 throws KeyStoreException, UnrecoverableKeyException,
1228 NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
1229 InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
1230 CertificateException, IOException {
Rich Canningsf64ec632019-02-21 12:40:36 -08001231 if (DEBUG) Slog.v(TAG, "Get child profile decrypted key");
Ricky Waidc283a82016-03-24 19:55:08 +00001232 byte[] storedData = mStorage.readChildProfileLock(userId);
1233 if (storedData == null) {
1234 throw new FileNotFoundException("Child profile lock file not found");
1235 }
1236 byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
1237 byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
1238 storedData.length);
1239 byte[] decryptionResult;
1240 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1241 keyStore.load(null);
1242 SecretKey decryptionKey = (SecretKey) keyStore.getKey(
Ricky Waid3982442016-05-24 19:27:08 +01001243 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
Ricky Waidc283a82016-03-24 19:55:08 +00001244
1245 Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
1246 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
1247
1248 cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
1249 decryptionResult = cipher.doFinal(encryptedPassword);
Rubin Xubb883202019-10-09 11:22:53 +01001250 LockscreenCredential credential = LockscreenCredential.createManagedPassword(
1251 decryptionResult);
1252 Arrays.fill(decryptionResult, (byte) 0);
1253 return credential;
Ricky Waidc283a82016-03-24 19:55:08 +00001254 }
1255
Kevin Chyn97d0a5b2019-06-11 12:52:17 -07001256 private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001257 @ChallengeType int challengeType, long challenge,
Rubin Xuca6ece52019-07-31 15:02:13 +01001258 @Nullable ArrayList<PendingResetLockout> resetLockouts) {
Ricky Waidc283a82016-03-24 19:55:08 +00001259 try {
Rubin Xu1de89b32016-11-30 20:03:13 +00001260 doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
Kevin Chynbc29dd72019-06-13 11:47:54 -07001261 challengeType, challenge, profileHandle, null /* progressCallback */,
1262 resetLockouts);
Ricky Waidc283a82016-03-24 19:55:08 +00001263 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1264 | NoSuchAlgorithmException | NoSuchPaddingException
1265 | InvalidAlgorithmParameterException | IllegalBlockSizeException
1266 | BadPaddingException | CertificateException | IOException e) {
1267 if (e instanceof FileNotFoundException) {
1268 Slog.i(TAG, "Child profile key not found");
Pavel Grafov0acc4bf2017-08-23 12:20:54 +01001269 } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) {
1270 Slog.i(TAG, "Parent keystore seems locked, ignoring");
Clara Bayarri0a587d22016-02-23 14:49:41 -08001271 } else {
Ricky Waidc283a82016-03-24 19:55:08 +00001272 Slog.e(TAG, "Failed to decrypt child profile key", e);
Clara Bayarri0a587d22016-02-23 14:49:41 -08001273 }
Jim Millerde1af082013-09-11 14:58:26 -07001274 }
1275 }
1276
Kevin Chyn97d0a5b2019-06-11 12:52:17 -07001277 private void unlockUser(int userId, byte[] token, byte[] secret) {
Kevin Chynbc29dd72019-06-13 11:47:54 -07001278 unlockUser(userId, token, secret, CHALLENGE_NONE, 0 /* challenge */, null);
Kevin Chyn97d0a5b2019-06-11 12:52:17 -07001279 }
1280
Rubin Xuca7007b2019-03-25 11:44:41 +00001281 /**
1282 * Unlock the user (both storage and user state) and its associated managed profiles
1283 * synchronously.
1284 *
1285 * <em>Be very careful about the risk of deadlock here: ActivityManager.unlockUser()
1286 * can end up calling into other system services to process user unlock request (via
1287 * {@link com.android.server.SystemServiceManager#unlockUser} </em>
1288 */
Kevin Chyn97d0a5b2019-06-11 12:52:17 -07001289 private void unlockUser(int userId, byte[] token, byte[] secret,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001290 @ChallengeType int challengeType, long challenge,
1291 @Nullable ArrayList<PendingResetLockout> resetLockouts) {
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001292 // TODO: make this method fully async so we can update UI with progress strings
Pavel Grafovb9b2c692019-05-24 14:07:55 +01001293 final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001294 final CountDownLatch latch = new CountDownLatch(1);
1295 final IProgressListener listener = new IProgressListener.Stub() {
1296 @Override
1297 public void onStarted(int id, Bundle extras) throws RemoteException {
Rubin Xue1beaf02019-10-22 11:36:51 +01001298 Slog.d(TAG, "unlockUser started");
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001299 }
1300
1301 @Override
1302 public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
Rubin Xue1beaf02019-10-22 11:36:51 +01001303 Slog.d(TAG, "unlockUser progress " + progress);
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001304 }
1305
1306 @Override
1307 public void onFinished(int id, Bundle extras) throws RemoteException {
Rubin Xue1beaf02019-10-22 11:36:51 +01001308 Slog.d(TAG, "unlockUser finished");
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001309 latch.countDown();
1310 }
1311 };
1312
Jeff Sharkey8924e872015-11-30 12:52:10 -07001313 try {
Rubin Xu0cbc19e2016-12-09 14:00:21 +00001314 mActivityManager.unlockUser(userId, token, secret, listener);
Jeff Sharkey8924e872015-11-30 12:52:10 -07001315 } catch (RemoteException e) {
1316 throw e.rethrowAsRuntimeException();
1317 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001318
1319 try {
1320 latch.await(15, TimeUnit.SECONDS);
1321 } catch (InterruptedException e) {
1322 Thread.currentThread().interrupt();
1323 }
Pavel Grafovb9b2c692019-05-24 14:07:55 +01001324
1325 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1326 return;
1327 }
1328
1329 for (UserInfo profile : mUserManager.getProfiles(userId)) {
1330 // Unlock managed profile with unified lock
1331 if (tiedManagedProfileReadyToUnlock(profile)) {
Rubin Xuca6ece52019-07-31 15:02:13 +01001332 // Must pass the challenge on for resetLockout, so it's not over-written, which
1333 // causes LockSettingsService to revokeChallenge inappropriately.
1334 unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */,
1335 challengeType, challenge, resetLockouts);
Ricky Waidc283a82016-03-24 19:55:08 +00001336 }
Pavel Grafovb9b2c692019-05-24 14:07:55 +01001337 // Now we have unlocked the parent user and attempted to unlock the profile we should
1338 // show notifications if the profile is still locked.
1339 if (!alreadyUnlocked) {
1340 long ident = clearCallingIdentity();
1341 try {
1342 maybeShowEncryptionNotificationForUser(profile.id);
1343 } finally {
1344 restoreCallingIdentity(ident);
1345 }
1346 }
1347
Ricky Waidc283a82016-03-24 19:55:08 +00001348 }
Kevin Chynbc29dd72019-06-13 11:47:54 -07001349
1350 if (resetLockouts != null && !resetLockouts.isEmpty()) {
1351 mHandler.post(() -> {
1352 final BiometricManager bm = mContext.getSystemService(BiometricManager.class);
1353 final PackageManager pm = mContext.getPackageManager();
1354 for (int i = 0; i < resetLockouts.size(); i++) {
Kevin Chyn91c70b62019-06-13 13:20:41 -07001355 bm.setActiveUser(resetLockouts.get(i).mUserId);
Kevin Chynbc29dd72019-06-13 11:47:54 -07001356 bm.resetLockout(resetLockouts.get(i).mHAT);
1357 }
1358 if (challengeType == CHALLENGE_INTERNAL
1359 && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
1360 mContext.getSystemService(FaceManager.class).revokeChallenge();
1361 }
1362 });
1363 }
Jeff Sharkey8924e872015-11-30 12:52:10 -07001364 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07001365
Pavel Grafov0acc4bf2017-08-23 12:20:54 +01001366 private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) {
1367 return userInfo.isManagedProfile()
1368 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id)
1369 && mStorage.hasChildProfileLock(userInfo.id)
1370 && mUserManager.isUserRunning(userInfo.id);
1371 }
1372
Rubin Xubb883202019-10-09 11:22:53 +01001373 private Map<Integer, LockscreenCredential> getDecryptedPasswordsForAllTiedProfiles(int userId) {
Rubin Xua55b1682017-01-31 10:06:56 +00001374 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1375 return null;
Andres Morales8fa56652015-03-31 09:19:50 -07001376 }
Rubin Xubb883202019-10-09 11:22:53 +01001377 Map<Integer, LockscreenCredential> result = new ArrayMap<>();
Rubin Xua55b1682017-01-31 10:06:56 +00001378 final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1379 final int size = profiles.size();
1380 for (int i = 0; i < size; i++) {
1381 final UserInfo profile = profiles.get(i);
1382 if (!profile.isManagedProfile()) {
1383 continue;
1384 }
1385 final int managedUserId = profile.id;
1386 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
1387 continue;
1388 }
1389 try {
Rubin Xu4f988c92017-09-12 16:25:26 +01001390 result.put(managedUserId, getDecryptedPasswordForTiedProfile(managedUserId));
Rubin Xua55b1682017-01-31 10:06:56 +00001391 } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException
1392 | NoSuchPaddingException | InvalidKeyException
1393 | InvalidAlgorithmParameterException | IllegalBlockSizeException
1394 | BadPaddingException | CertificateException | IOException e) {
Rubin Xu4f988c92017-09-12 16:25:26 +01001395 Slog.e(TAG, "getDecryptedPasswordsForAllTiedProfiles failed for user " +
1396 managedUserId, e);
Rubin Xua55b1682017-01-31 10:06:56 +00001397 }
1398 }
1399 return result;
Amith Yamasani52c489c2012-03-28 11:42:42 -07001400 }
1401
Rubin Xua55b1682017-01-31 10:06:56 +00001402 /**
1403 * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
1404 * depending on the parent user's secure state.
1405 *
1406 * When clearing tied work challenges, a pre-computed password table for profiles are required,
1407 * since changing password for profiles requires existing password, and existing passwords can
1408 * only be computed before the parent user's password is cleared.
1409 *
1410 * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
1411 * method again on profiles. However the recursion is guaranteed to terminate as this method
1412 * terminates when the user is a managed profile.
1413 */
1414 private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
Rubin Xubb883202019-10-09 11:22:53 +01001415 Map<Integer, LockscreenCredential> profilePasswordMap) {
Ricky Waidc283a82016-03-24 19:55:08 +00001416 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1417 return;
1418 }
Rubin Xua55b1682017-01-31 10:06:56 +00001419 final boolean isSecure = isUserSecure(userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001420 final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1421 final int size = profiles.size();
1422 for (int i = 0; i < size; i++) {
1423 final UserInfo profile = profiles.get(i);
1424 if (profile.isManagedProfile()) {
1425 final int managedUserId = profile.id;
1426 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
1427 continue;
1428 }
1429 if (isSecure) {
Rubin Xubb883202019-10-09 11:22:53 +01001430 tieManagedProfileLockIfNecessary(managedUserId,
1431 LockscreenCredential.createNone());
Ricky Waidc283a82016-03-24 19:55:08 +00001432 } else {
Rubin Xua55b1682017-01-31 10:06:56 +00001433 // We use cached work profile password computed before clearing the parent's
1434 // credential, otherwise they get lost
Rubin Xubb883202019-10-09 11:22:53 +01001435 if (profilePasswordMap != null
1436 && profilePasswordMap.containsKey(managedUserId)) {
1437 setLockCredentialInternal(LockscreenCredential.createNone(),
Adrian Roos7374d3a2017-03-31 14:14:53 -07001438 profilePasswordMap.get(managedUserId),
Rubin Xubb883202019-10-09 11:22:53 +01001439 managedUserId,
Annie Meng086ddc82019-03-29 17:43:35 +00001440 false, /* isLockTiedToParent= */ true);
Rubin Xua55b1682017-01-31 10:06:56 +00001441 } else {
1442 Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
Rubin Xubb883202019-10-09 11:22:53 +01001443 // Attempt an untrusted reset by supplying an empty credential.
1444 setLockCredentialInternal(LockscreenCredential.createNone(),
1445 LockscreenCredential.createNone(),
1446 managedUserId,
Annie Meng086ddc82019-03-29 17:43:35 +00001447 true, /* isLockTiedToParent= */ true);
Rubin Xua55b1682017-01-31 10:06:56 +00001448 }
Ricky Waidc283a82016-03-24 19:55:08 +00001449 mStorage.removeChildProfileLock(managedUserId);
1450 removeKeystoreProfileKey(managedUserId);
1451 }
1452 }
1453 }
1454 }
Andres Morales8fa56652015-03-31 09:19:50 -07001455
Ricky Waidc283a82016-03-24 19:55:08 +00001456 private boolean isManagedProfileWithUnifiedLock(int userId) {
1457 return mUserManager.getUserInfo(userId).isManagedProfile()
1458 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
1459 }
1460
1461 private boolean isManagedProfileWithSeparatedLock(int userId) {
1462 return mUserManager.getUserInfo(userId).isManagedProfile()
1463 && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
1464 }
1465
Annie Meng086ddc82019-03-29 17:43:35 +00001466 /**
1467 * Send credentials for user {@code userId} to {@link RecoverableKeyStoreManager} during an
1468 * unlock operation.
1469 */
Rubin Xubb883202019-10-09 11:22:53 +01001470 private void sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId) {
Annie Meng086ddc82019-03-29 17:43:35 +00001471 // Don't send credentials during the factory reset protection flow.
1472 if (userId == USER_FRP) {
1473 return;
1474 }
1475
1476 // A profile with a unified lock screen stores a randomly generated credential, so skip it.
1477 // Its parent will send credentials for the profile, as it stores the unified lock
1478 // credential.
1479 if (isManagedProfileWithUnifiedLock(userId)) {
1480 return;
1481 }
1482
Rubin Xubb883202019-10-09 11:22:53 +01001483 // RecoverableKeyStoreManager expects null for empty credential.
1484 final byte[] secret = credential.isNone() ? null : credential.getCredential();
Annie Meng086ddc82019-03-29 17:43:35 +00001485 // Send credentials for the user and any child profiles that share its lock screen.
1486 for (int profileId : getProfilesWithSameLockScreen(userId)) {
1487 mRecoverableKeyStoreManager.lockScreenSecretAvailable(
Rubin Xubb883202019-10-09 11:22:53 +01001488 credential.getType(), secret, profileId);
Annie Meng086ddc82019-03-29 17:43:35 +00001489 }
1490 }
1491
1492 /**
1493 * Send credentials for user {@code userId} to {@link RecoverableKeyStoreManager} when its
1494 * credentials are set/changed.
1495 */
1496 private void sendCredentialsOnChangeIfRequired(
Rubin Xubb883202019-10-09 11:22:53 +01001497 LockscreenCredential credential, int userId, boolean isLockTiedToParent) {
Annie Meng086ddc82019-03-29 17:43:35 +00001498 // A profile whose lock screen is being tied to its parent's will either have a randomly
1499 // generated credential (creation) or null (removal). We rely on the parent to send its
1500 // credentials for the profile in both cases as it stores the unified lock credential.
1501 if (isLockTiedToParent) {
1502 return;
1503 }
1504
Rubin Xubb883202019-10-09 11:22:53 +01001505 // RecoverableKeyStoreManager expects null for empty credential.
1506 final byte[] secret = credential.isNone() ? null : credential.getCredential();
Annie Meng086ddc82019-03-29 17:43:35 +00001507 // Send credentials for the user and any child profiles that share its lock screen.
1508 for (int profileId : getProfilesWithSameLockScreen(userId)) {
1509 mRecoverableKeyStoreManager.lockScreenSecretChanged(
Rubin Xubb883202019-10-09 11:22:53 +01001510 credential.getType(), secret, profileId);
Annie Meng086ddc82019-03-29 17:43:35 +00001511 }
1512 }
1513
1514 /**
1515 * Returns all profiles of {@code userId}, including itself, that have the same lock screen
1516 * challenge.
1517 */
1518 private Set<Integer> getProfilesWithSameLockScreen(int userId) {
1519 Set<Integer> profiles = new ArraySet<>();
1520 for (UserInfo profile : mUserManager.getProfiles(userId)) {
1521 if (profile.id == userId
1522 || (profile.profileGroupId == userId
1523 && isManagedProfileWithUnifiedLock(profile.id))) {
1524 profiles.add(profile.id);
1525 }
1526 }
1527 return profiles;
1528 }
1529
Ricky Waidc283a82016-03-24 19:55:08 +00001530 // This method should be called by LockPatternUtil only, all internal methods in this class
Rubin Xu1de89b32016-11-30 20:03:13 +00001531 // should call setLockCredentialInternal.
Amith Yamasani52c489c2012-03-28 11:42:42 -07001532 @Override
Rubin Xubb883202019-10-09 11:22:53 +01001533 public boolean setLockCredential(LockscreenCredential credential,
1534 LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange) {
Rich Canningsf64ec632019-02-21 12:40:36 -08001535
Lenka Trochtova66c492a2018-12-06 11:29:21 +01001536 if (!mLockPatternUtils.hasSecureLockScreen()) {
1537 throw new UnsupportedOperationException(
1538 "This operation requires secure lock screen feature");
1539 }
Jim Millere484eaf2016-04-13 16:35:36 -07001540 checkWritePermission(userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001541 synchronized (mSeparateChallengeLock) {
Rubin Xubb883202019-10-09 11:22:53 +01001542 if (!setLockCredentialInternal(credential, savedCredential,
Rubin Xu6a7303d2019-08-16 13:19:56 +01001543 userId, allowUntrustedChange, /* isLockTiedToParent= */ false)) {
1544 return false;
1545 }
Rubin Xubb883202019-10-09 11:22:53 +01001546 setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
Andrew Scull5daf2732016-11-14 15:02:45 +00001547 notifyPasswordChanged(userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001548 }
Pavel Grafova8da6972019-04-03 13:58:58 +01001549 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1550 // Make sure the profile doesn't get locked straight after setting work challenge.
1551 setDeviceUnlockedForUser(userId);
1552 }
Pavel Grafov28939982017-10-03 15:11:52 +01001553 notifySeparateProfileChallengeChanged(userId);
Rubin Xu6a7303d2019-08-16 13:19:56 +01001554 return true;
Ricky Waidc283a82016-03-24 19:55:08 +00001555 }
1556
Annie Meng086ddc82019-03-29 17:43:35 +00001557 /**
Rubin Xubb883202019-10-09 11:22:53 +01001558 * @param savedCredential if the user is a managed profile with unified challenge and
1559 * savedCredential is empty, LSS will try to re-derive the profile password internally.
1560 * TODO (b/80170828): Fix this so profile password is always passed in.
Annie Meng086ddc82019-03-29 17:43:35 +00001561 * @param isLockTiedToParent is {@code true} if {@code userId} is a profile and its new
1562 * credentials are being tied to its parent's credentials.
1563 */
Rubin Xubb883202019-10-09 11:22:53 +01001564 private boolean setLockCredentialInternal(LockscreenCredential credential,
1565 LockscreenCredential savedCredential, int userId,
1566 boolean allowUntrustedChange, boolean isLockTiedToParent) {
1567 Preconditions.checkNotNull(credential);
1568 Preconditions.checkNotNull(savedCredential);
Rubin Xu3bf722a2016-12-15 16:07:38 +00001569 synchronized (mSpManager) {
1570 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
Rubin Xubb883202019-10-09 11:22:53 +01001571 return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
1572 allowUntrustedChange, isLockTiedToParent);
Rubin Xu3bf722a2016-12-15 16:07:38 +00001573 }
1574 }
Adrian Roos7374d3a2017-03-31 14:14:53 -07001575
Rubin Xubb883202019-10-09 11:22:53 +01001576 if (credential.isNone()) {
Paul Crowleycc701552016-05-17 14:18:49 -07001577 clearUserKeyProtection(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01001578 gateKeeperClearSecureUserId(userId);
Rubin Xu1de89b32016-11-30 20:03:13 +00001579 mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001580 // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
1581 // since it forms part of the state that determines the credential type
1582 // @see getCredentialTypeInternal
1583 setKeyguardStoredQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
Chad Brubakera91a8502015-05-07 10:02:22 -07001584 setKeystorePassword(null, userId);
Paul Crowleycc701552016-05-17 14:18:49 -07001585 fixateNewestUserKeyAuth(userId);
Rubin Xua55b1682017-01-31 10:06:56 +00001586 synchronizeUnifiedWorkChallengeForProfiles(userId, null);
Rubin Xubb883202019-10-09 11:22:53 +01001587 setUserPasswordMetrics(LockscreenCredential.createNone(), userId);
1588 sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
Rubin Xu6a7303d2019-08-16 13:19:56 +01001589 return true;
Andres Moralesd9fc85a2015-04-09 19:14:42 -07001590 }
Rubin Xua55b1682017-01-31 10:06:56 +00001591
1592 CredentialHash currentHandle = mStorage.readCredentialHash(userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001593 if (isManagedProfileWithUnifiedLock(userId)) {
1594 // get credential from keystore when managed profile has unified lock
Rubin Xubb883202019-10-09 11:22:53 +01001595 if (savedCredential.isNone()) {
Rubin Xua55b1682017-01-31 10:06:56 +00001596 try {
1597 savedCredential = getDecryptedPasswordForTiedProfile(userId);
1598 } catch (FileNotFoundException e) {
1599 Slog.i(TAG, "Child profile key not found");
1600 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1601 | NoSuchAlgorithmException | NoSuchPaddingException
1602 | InvalidAlgorithmParameterException | IllegalBlockSizeException
1603 | BadPaddingException | CertificateException | IOException e) {
1604 Slog.e(TAG, "Failed to decrypt child profile key", e);
1605 }
Andres Morales8fa56652015-03-31 09:19:50 -07001606 }
Ricky Waidc283a82016-03-24 19:55:08 +00001607 } else {
Rubin Xua55b1682017-01-31 10:06:56 +00001608 if (currentHandle.hash == null) {
Rubin Xubb883202019-10-09 11:22:53 +01001609 if (!savedCredential.isNone()) {
Ricky Waidc283a82016-03-24 19:55:08 +00001610 Slog.w(TAG, "Saved credential provided, but none stored");
1611 }
Rubin Xubb883202019-10-09 11:22:53 +01001612 savedCredential.close();
1613 savedCredential = LockscreenCredential.createNone();
Ricky Waidc283a82016-03-24 19:55:08 +00001614 }
Andres Morales8fa56652015-03-31 09:19:50 -07001615 }
Rubin Xu3bf722a2016-12-15 16:07:38 +00001616 synchronized (mSpManager) {
1617 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
Rubin Xubb883202019-10-09 11:22:53 +01001618 initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
1619 return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
1620 allowUntrustedChange, isLockTiedToParent);
Rubin Xu3bf722a2016-12-15 16:07:38 +00001621 }
1622 }
1623 if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
Rubin Xubb883202019-10-09 11:22:53 +01001624 byte[] enrolledHandle = enrollCredential(currentHandle.hash,
1625 savedCredential.getCredential(), credential.getCredential(), userId);
Rubin Xu6a7303d2019-08-16 13:19:56 +01001626 if (enrolledHandle == null) {
1627 Slog.w(TAG, String.format("Failed to enroll %s: incorrect credential",
Rubin Xubb883202019-10-09 11:22:53 +01001628 credential.isPattern() ? "pattern" : "password"));
Rubin Xu6a7303d2019-08-16 13:19:56 +01001629 return false;
Andres Morales8fa56652015-03-31 09:19:50 -07001630 }
Rubin Xubb883202019-10-09 11:22:53 +01001631 CredentialHash willStore = CredentialHash.create(enrolledHandle, credential.getType());
Rubin Xu6a7303d2019-08-16 13:19:56 +01001632 mStorage.writeCredentialHash(willStore, userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001633 // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
1634 // since it forms part of the state that determines the credential type
1635 // @see getCredentialTypeInternal
1636 setKeyguardStoredQuality(
1637 LockPatternUtils.credentialTypeToPasswordQuality(credential.getType()), userId);
Rubin Xu6a7303d2019-08-16 13:19:56 +01001638 // push new secret and auth token to vold
1639 GateKeeperResponse gkResponse;
1640 try {
1641 gkResponse = getGateKeeperService().verifyChallenge(userId, 0, willStore.hash,
Rubin Xubb883202019-10-09 11:22:53 +01001642 credential.getCredential());
Rubin Xu6a7303d2019-08-16 13:19:56 +01001643 } catch (RemoteException e) {
1644 throw new IllegalStateException("Failed to verify current credential", e);
1645 }
1646 setUserKeyProtection(userId, credential, convertResponse(gkResponse));
1647 fixateNewestUserKeyAuth(userId);
1648 // Refresh the auth token
Rubin Xubb883202019-10-09 11:22:53 +01001649 doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId,
Rubin Xu6a7303d2019-08-16 13:19:56 +01001650 null /* progressCallback */);
1651 synchronizeUnifiedWorkChallengeForProfiles(userId, null);
Rubin Xubb883202019-10-09 11:22:53 +01001652 sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
Rubin Xu6a7303d2019-08-16 13:19:56 +01001653 return true;
Andres Morales8fa56652015-03-31 09:19:50 -07001654 }
1655
Rubin Xua55b1682017-01-31 10:06:56 +00001656 private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) {
Adrian Roos7374d3a2017-03-31 14:14:53 -07001657 return VerifyCredentialResponse.fromGateKeeperResponse(gateKeeperResponse);
Rubin Xua55b1682017-01-31 10:06:56 +00001658 }
1659
Rubin Xubb883202019-10-09 11:22:53 +01001660 @VisibleForTesting /** Note: this method is overridden in unit tests */
1661 protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
Ricky Waidc283a82016-03-24 19:55:08 +00001662 if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
Ricky Waidc283a82016-03-24 19:55:08 +00001663 byte[] encryptionResult;
1664 byte[] iv;
1665 try {
1666 KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
1667 keyGenerator.init(new SecureRandom());
1668 SecretKey secretKey = keyGenerator.generateKey();
Ricky Waidc283a82016-03-24 19:55:08 +00001669 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1670 keyStore.load(null);
Ricky Wai97c8f8d2016-07-13 17:57:45 +01001671 try {
1672 keyStore.setEntry(
1673 LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
1674 new java.security.KeyStore.SecretKeyEntry(secretKey),
1675 new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
1676 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
1677 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
1678 .build());
1679 keyStore.setEntry(
1680 LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
1681 new java.security.KeyStore.SecretKeyEntry(secretKey),
1682 new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
1683 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
1684 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
1685 .setUserAuthenticationRequired(true)
1686 .setUserAuthenticationValidityDurationSeconds(30)
Pavel Grafove053c1e2017-08-08 16:53:32 +01001687 .setCriticalToDeviceEncryption(true)
Ricky Wai97c8f8d2016-07-13 17:57:45 +01001688 .build());
1689 // Key imported, obtain a reference to it.
1690 SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
1691 LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
1692 Cipher cipher = Cipher.getInstance(
1693 KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
1694 + KeyProperties.ENCRYPTION_PADDING_NONE);
1695 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
Rubin Xubb883202019-10-09 11:22:53 +01001696 encryptionResult = cipher.doFinal(password.getCredential());
Ricky Wai97c8f8d2016-07-13 17:57:45 +01001697 iv = cipher.getIV();
1698 } finally {
1699 // The original key can now be discarded.
1700 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
1701 }
Ricky Waidc283a82016-03-24 19:55:08 +00001702 } catch (CertificateException | UnrecoverableKeyException
Zach Jange61672a2016-11-22 17:47:18 +00001703 | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
Ricky Waidc283a82016-03-24 19:55:08 +00001704 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
Rubin Xu0f9c2ff2019-08-14 16:25:57 +01001705 throw new IllegalStateException("Failed to encrypt key", e);
Ricky Waidc283a82016-03-24 19:55:08 +00001706 }
1707 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
1708 try {
1709 if (iv.length != PROFILE_KEY_IV_SIZE) {
Rubin Xu0f9c2ff2019-08-14 16:25:57 +01001710 throw new IllegalArgumentException("Invalid iv length: " + iv.length);
Ricky Waidc283a82016-03-24 19:55:08 +00001711 }
1712 outputStream.write(iv);
1713 outputStream.write(encryptionResult);
1714 } catch (IOException e) {
Rubin Xu0f9c2ff2019-08-14 16:25:57 +01001715 throw new IllegalStateException("Failed to concatenate byte arrays", e);
Ricky Waidc283a82016-03-24 19:55:08 +00001716 }
1717 mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
1718 }
1719
Andres Morales8fa56652015-03-31 09:19:50 -07001720 private byte[] enrollCredential(byte[] enrolledHandle,
Rubin Xuca6ece52019-07-31 15:02:13 +01001721 byte[] enrolledCredential, byte[] toEnroll, int userId) {
Jim Millerde1af082013-09-11 14:58:26 -07001722 checkWritePermission(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01001723 GateKeeperResponse response;
1724 try {
1725 response = getGateKeeperService().enroll(userId, enrolledHandle,
1726 enrolledCredential, toEnroll);
1727 } catch (RemoteException e) {
1728 Slog.e(TAG, "Failed to enroll credential", e);
1729 return null;
1730 }
Jim Millerde1af082013-09-11 14:58:26 -07001731
Andres Morales23974272015-05-14 22:42:26 -07001732 if (response == null) {
1733 return null;
Andres Morales8fa56652015-03-31 09:19:50 -07001734 }
Jim Millerde1af082013-09-11 14:58:26 -07001735
Andres Morales23974272015-05-14 22:42:26 -07001736 byte[] hash = response.getPayload();
1737 if (hash != null) {
1738 setKeystorePassword(toEnroll, userId);
1739 } else {
1740 // Should not happen
1741 Slog.e(TAG, "Throttled while enrolling a password");
1742 }
Andres Morales8fa56652015-03-31 09:19:50 -07001743 return hash;
Jim Millerde1af082013-09-11 14:58:26 -07001744 }
1745
Rubin Xuca6ece52019-07-31 15:02:13 +01001746 private void setAuthlessUserKeyProtection(int userId, byte[] key) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00001747 if (DEBUG) Slog.d(TAG, "setAuthlessUserKeyProtectiond: user=" + userId);
1748 addUserKeyAuth(userId, null, key);
1749 }
1750
Rubin Xubb883202019-10-09 11:22:53 +01001751 private void setUserKeyProtection(int userId, LockscreenCredential credential,
1752 VerifyCredentialResponse vcr) {
Rubin Xua55b1682017-01-31 10:06:56 +00001753 if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001754 if (vcr == null) {
Rubin Xuca6ece52019-07-31 15:02:13 +01001755 throw new IllegalArgumentException("Null response verifying a credential we just set");
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001756 }
1757 if (vcr.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
Rubin Xuca6ece52019-07-31 15:02:13 +01001758 throw new IllegalArgumentException("Non-OK response verifying a credential we just set "
Rubin Xu1de89b32016-11-30 20:03:13 +00001759 + vcr.getResponseCode());
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001760 }
1761 byte[] token = vcr.getPayload();
1762 if (token == null) {
Rubin Xuca6ece52019-07-31 15:02:13 +01001763 throw new IllegalArgumentException("Empty payload verifying a credential we just set");
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001764 }
Paul Crowleycc701552016-05-17 14:18:49 -07001765 addUserKeyAuth(userId, token, secretFromCredential(credential));
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001766 }
1767
Rubin Xuca6ece52019-07-31 15:02:13 +01001768 private void clearUserKeyProtection(int userId) {
Rubin Xua55b1682017-01-31 10:06:56 +00001769 if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
Paul Crowleycc701552016-05-17 14:18:49 -07001770 addUserKeyAuth(userId, null, null);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001771 }
1772
Rubin Xubb883202019-10-09 11:22:53 +01001773 private static byte[] secretFromCredential(LockscreenCredential credential) {
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001774 try {
1775 MessageDigest digest = MessageDigest.getInstance("SHA-512");
1776 // Personalize the hash
Rich Canningsf64ec632019-02-21 12:40:36 -08001777 byte[] personalization = "Android FBE credential hash".getBytes();
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001778 // Pad it to the block size of the hash function
1779 personalization = Arrays.copyOf(personalization, 128);
1780 digest.update(personalization);
Rubin Xubb883202019-10-09 11:22:53 +01001781 digest.update(credential.getCredential());
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001782 return digest.digest();
1783 } catch (NoSuchAlgorithmException e) {
Rubin Xu0f9c2ff2019-08-14 16:25:57 +01001784 throw new IllegalStateException("NoSuchAlgorithmException for SHA-512");
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001785 }
1786 }
1787
Rubin Xuca7007b2019-03-25 11:44:41 +00001788 private boolean isUserKeyUnlocked(int userId) {
1789 try {
1790 return mStorageManager.isUserKeyUnlocked(userId);
1791 } catch (RemoteException e) {
Rubin Xue1beaf02019-10-22 11:36:51 +01001792 Slog.e(TAG, "failed to check user key locked state", e);
Rubin Xuca7007b2019-03-25 11:44:41 +00001793 return false;
1794 }
1795 }
1796
1797 /** Unlock disk encryption */
Rubin Xuca6ece52019-07-31 15:02:13 +01001798 private void unlockUserKey(int userId, byte[] token, byte[] secret) {
Rubin Xuca7007b2019-03-25 11:44:41 +00001799 final UserInfo userInfo = mUserManager.getUserInfo(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01001800 try {
1801 mStorageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret);
1802 } catch (RemoteException e) {
1803 throw new IllegalStateException("Failed to unlock user key " + userId, e);
1804
1805 }
Rubin Xuca7007b2019-03-25 11:44:41 +00001806 }
1807
Rubin Xuca6ece52019-07-31 15:02:13 +01001808 private void addUserKeyAuth(int userId, byte[] token, byte[] secret) {
Rubin Xu0cbc19e2016-12-09 14:00:21 +00001809 final UserInfo userInfo = mUserManager.getUserInfo(userId);
Paul Crowley815036f2016-03-29 14:14:48 -07001810 final long callingId = Binder.clearCallingIdentity();
1811 try {
Rubin Xuca7007b2019-03-25 11:44:41 +00001812 mStorageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
Rubin Xuca6ece52019-07-31 15:02:13 +01001813 } catch (RemoteException e) {
1814 throw new IllegalStateException("Failed to add new key to vold " + userId, e);
Paul Crowley815036f2016-03-29 14:14:48 -07001815 } finally {
1816 Binder.restoreCallingIdentity(callingId);
1817 }
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00001818 }
1819
Rubin Xuca6ece52019-07-31 15:02:13 +01001820 private void fixateNewestUserKeyAuth(int userId) {
Rubin Xua55b1682017-01-31 10:06:56 +00001821 if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId);
Toni Barzic6c818722016-05-27 09:18:39 -07001822 final long callingId = Binder.clearCallingIdentity();
1823 try {
Rubin Xuca7007b2019-03-25 11:44:41 +00001824 mStorageManager.fixateNewestUserKeyAuth(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01001825 } catch (RemoteException e) {
1826 // OK to ignore the exception as vold would just accept both old and new
1827 // keys if this call fails, and will fix itself during the next boot
1828 Slog.w(TAG, "fixateNewestUserKeyAuth failed", e);
Toni Barzic6c818722016-05-27 09:18:39 -07001829 } finally {
1830 Binder.restoreCallingIdentity(callingId);
1831 }
Paul Crowleycc701552016-05-17 14:18:49 -07001832 }
1833
Jim Millerde1af082013-09-11 14:58:26 -07001834 @Override
Rubin Xuca6ece52019-07-31 15:02:13 +01001835 public void resetKeyStore(int userId) {
Ricky Wai7f405f12016-05-31 12:05:05 +01001836 checkWritePermission(userId);
Ricky Wai4613fe42016-05-24 11:11:42 +01001837 if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
1838 int managedUserId = -1;
Rubin Xubb883202019-10-09 11:22:53 +01001839 LockscreenCredential managedUserDecryptedPassword = null;
Ricky Wai4613fe42016-05-24 11:11:42 +01001840 final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1841 for (UserInfo pi : profiles) {
1842 // Unlock managed profile with unified lock
1843 if (pi.isManagedProfile()
1844 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
1845 && mStorage.hasChildProfileLock(pi.id)) {
1846 try {
1847 if (managedUserId == -1) {
1848 managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id);
1849 managedUserId = pi.id;
1850 } else {
1851 // Should not happen
1852 Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId
1853 + ", uid2:" + pi.id);
1854 }
1855 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1856 | NoSuchAlgorithmException | NoSuchPaddingException
1857 | InvalidAlgorithmParameterException | IllegalBlockSizeException
1858 | BadPaddingException | CertificateException | IOException e) {
1859 Slog.e(TAG, "Failed to decrypt child profile key", e);
1860 }
1861 }
1862 }
1863 try {
1864 // Clear all the users credentials could have been installed in for this user.
1865 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
1866 for (int uid : SYSTEM_CREDENTIAL_UIDS) {
1867 mKeyStore.clearUid(UserHandle.getUid(profileId, uid));
1868 }
1869 }
1870 } finally {
1871 if (managedUserId != -1 && managedUserDecryptedPassword != null) {
1872 if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
Zach Jange61672a2016-11-22 17:47:18 +00001873 tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
Ricky Wai4613fe42016-05-24 11:11:42 +01001874 }
1875 }
Rubin Xubb883202019-10-09 11:22:53 +01001876 if (managedUserDecryptedPassword != null) {
1877 managedUserDecryptedPassword.zeroize();
Rich Canningsf64ec632019-02-21 12:40:36 -08001878 }
Ricky Wai4613fe42016-05-24 11:11:42 +01001879 }
1880
1881 @Override
Rubin Xubb883202019-10-09 11:22:53 +01001882 public VerifyCredentialResponse checkCredential(LockscreenCredential credential, int userId,
Rubin Xuca6ece52019-07-31 15:02:13 +01001883 ICheckCredentialProgressCallback progressCallback) {
Rubin Xu1de89b32016-11-30 20:03:13 +00001884 checkPasswordReadPermission(userId);
Rubin Xubb883202019-10-09 11:22:53 +01001885 return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback);
Andres Moralesd9fc85a2015-04-09 19:14:42 -07001886 }
Adrian Roos261d5ab2014-10-29 14:42:38 +01001887
Andres Moralesd9fc85a2015-04-09 19:14:42 -07001888 @Override
Rubin Xubb883202019-10-09 11:22:53 +01001889 public VerifyCredentialResponse verifyCredential(LockscreenCredential credential,
1890 long challenge, int userId) {
Rubin Xu1de89b32016-11-30 20:03:13 +00001891 checkPasswordReadPermission(userId);
Rubin Xubb883202019-10-09 11:22:53 +01001892 return doVerifyCredential(credential, CHALLENGE_FROM_CALLER, challenge, userId,
Rubin Xu1de89b32016-11-30 20:03:13 +00001893 null /* progressCallback */);
Andres Moralesd9fc85a2015-04-09 19:14:42 -07001894 }
1895
Rubin Xubb883202019-10-09 11:22:53 +01001896 private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001897 @ChallengeType int challengeType, long challenge, int userId,
Rubin Xuca6ece52019-07-31 15:02:13 +01001898 ICheckCredentialProgressCallback progressCallback) {
Rubin Xubb883202019-10-09 11:22:53 +01001899 return doVerifyCredential(credential, challengeType, challenge, userId,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001900 progressCallback, null /* resetLockouts */);
1901 }
1902
Rubin Xu1de89b32016-11-30 20:03:13 +00001903 /**
1904 * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
1905 * format.
1906 */
Rubin Xubb883202019-10-09 11:22:53 +01001907 private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001908 @ChallengeType int challengeType, long challenge, int userId,
1909 ICheckCredentialProgressCallback progressCallback,
Rubin Xuca6ece52019-07-31 15:02:13 +01001910 @Nullable ArrayList<PendingResetLockout> resetLockouts) {
Rubin Xubb883202019-10-09 11:22:53 +01001911 if (credential == null || credential.isNone()) {
Rubin Xu1de89b32016-11-30 20:03:13 +00001912 throw new IllegalArgumentException("Credential can't be null or empty");
1913 }
Rubin Xu5e891bc2019-10-14 10:22:23 +01001914 if (userId == USER_FRP && mInjector.settingsGlobalGetInt(mContext.getContentResolver(),
Adrian Roos7374d3a2017-03-31 14:14:53 -07001915 Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
1916 Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
1917 return VerifyCredentialResponse.ERROR;
1918 }
Rubin Xue94a7702017-06-20 17:29:57 +01001919 VerifyCredentialResponse response = null;
Rubin Xubb883202019-10-09 11:22:53 +01001920 response = spBasedDoVerifyCredential(credential, challengeType, challenge,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001921 userId, progressCallback, resetLockouts);
Rubin Xue94a7702017-06-20 17:29:57 +01001922 // The user employs synthetic password based credential.
1923 if (response != null) {
Robert Berry40386df2018-01-22 21:16:58 +00001924 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
Rubin Xubb883202019-10-09 11:22:53 +01001925 sendCredentialsOnUnlockIfRequired(credential, userId);
Robert Berry40386df2018-01-22 21:16:58 +00001926 }
Rubin Xue94a7702017-06-20 17:29:57 +01001927 return response;
Rubin Xu3bf722a2016-12-15 16:07:38 +00001928 }
Rubin Xue94a7702017-06-20 17:29:57 +01001929
Adrian Roos7374d3a2017-03-31 14:14:53 -07001930 if (userId == USER_FRP) {
Andrew Scull971f2942017-07-12 15:09:45 +01001931 Slog.wtf(TAG, "Unexpected FRP credential type, should be SP based.");
1932 return VerifyCredentialResponse.ERROR;
Adrian Roos7374d3a2017-03-31 14:14:53 -07001933 }
1934
Andrew Scull971f2942017-07-12 15:09:45 +01001935 final CredentialHash storedHash = mStorage.readCredentialHash(userId);
Rubin Xu5e891bc2019-10-14 10:22:23 +01001936 if (!credential.checkAgainstStoredType(storedHash.type)) {
Rubin Xu1de89b32016-11-30 20:03:13 +00001937 Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
Rubin Xubb883202019-10-09 11:22:53 +01001938 + " stored: " + storedHash.type + " passed in: " + credential.getType());
Rubin Xu1de89b32016-11-30 20:03:13 +00001939 return VerifyCredentialResponse.ERROR;
1940 }
Andres Moralese40bad82015-05-28 14:21:36 -07001941
Rubin Xu7959e2a2019-07-31 11:26:53 +01001942 response = verifyCredential(userId, storedHash, credential,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001943 challengeType, challenge, progressCallback);
Andres Morales59ef1262015-06-26 13:56:39 -07001944
Michal Karpinskie71f5832017-01-13 18:18:49 +00001945 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
1946 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
Rubin Xu1de89b32016-11-30 20:03:13 +00001947 }
Andres Moralese40bad82015-05-28 14:21:36 -07001948
Rubin Xu1de89b32016-11-30 20:03:13 +00001949 return response;
Amith Yamasani52c489c2012-03-28 11:42:42 -07001950 }
1951
1952 @Override
Rubin Xubb883202019-10-09 11:22:53 +01001953 public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
Rubin Xuca6ece52019-07-31 15:02:13 +01001954 long challenge, int userId) {
Ricky Wai53940d42016-04-05 15:29:24 +01001955 checkPasswordReadPermission(userId);
1956 if (!isManagedProfileWithUnifiedLock(userId)) {
Rubin Xuca6ece52019-07-31 15:02:13 +01001957 throw new IllegalArgumentException("User id must be managed profile with unified lock");
Ricky Wai53940d42016-04-05 15:29:24 +01001958 }
1959 final int parentProfileId = mUserManager.getProfileParent(userId).id;
1960 // Unlock parent by using parent's challenge
Rubin Xu1de89b32016-11-30 20:03:13 +00001961 final VerifyCredentialResponse parentResponse = doVerifyCredential(
1962 credential,
Kevin Chynbc29dd72019-06-13 11:47:54 -07001963 CHALLENGE_FROM_CALLER,
Rubin Xu1de89b32016-11-30 20:03:13 +00001964 challenge,
1965 parentProfileId,
1966 null /* progressCallback */);
Ricky Wai53940d42016-04-05 15:29:24 +01001967 if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
1968 // Failed, just return parent's response
1969 return parentResponse;
1970 }
1971
1972 try {
1973 // Unlock work profile, and work profile with unified lock must use password only
Rubin Xu1de89b32016-11-30 20:03:13 +00001974 return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
Kevin Chynbc29dd72019-06-13 11:47:54 -07001975 CHALLENGE_FROM_CALLER,
Ricky Wai53940d42016-04-05 15:29:24 +01001976 challenge,
Jorim Jaggie8fde5d2016-06-30 23:41:37 -07001977 userId, null /* progressCallback */);
Ricky Wai53940d42016-04-05 15:29:24 +01001978 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1979 | NoSuchAlgorithmException | NoSuchPaddingException
1980 | InvalidAlgorithmParameterException | IllegalBlockSizeException
1981 | BadPaddingException | CertificateException | IOException e) {
1982 Slog.e(TAG, "Failed to decrypt child profile key", e);
Rubin Xuca6ece52019-07-31 15:02:13 +01001983 throw new IllegalStateException("Unable to get tied profile token");
Ricky Wai53940d42016-04-05 15:29:24 +01001984 }
1985 }
1986
Rubin Xu1de89b32016-11-30 20:03:13 +00001987 /**
1988 * Lowest-level credential verification routine that talks to GateKeeper. If verification
1989 * passes, unlock the corresponding user and keystore. Also handles the migration from legacy
1990 * hash to GK.
1991 */
Andres Morales23974272015-05-14 22:42:26 -07001992 private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
Rubin Xubb883202019-10-09 11:22:53 +01001993 LockscreenCredential credential, @ChallengeType int challengeType, long challenge,
Rubin Xuca6ece52019-07-31 15:02:13 +01001994 ICheckCredentialProgressCallback progressCallback) {
Rubin Xubb883202019-10-09 11:22:53 +01001995 if ((storedHash == null || storedHash.hash.length == 0) && credential.isNone()) {
Andres Morales23974272015-05-14 22:42:26 -07001996 // don't need to pass empty credentials to GateKeeper
1997 return VerifyCredentialResponse.OK;
Andres Moralesd9fc85a2015-04-09 19:14:42 -07001998 }
1999
Rubin Xubb883202019-10-09 11:22:53 +01002000 if (storedHash == null || storedHash.hash.length == 0 || credential.isNone()) {
Andres Morales23974272015-05-14 22:42:26 -07002001 return VerifyCredentialResponse.ERROR;
Amith Yamasani52c489c2012-03-28 11:42:42 -07002002 }
Adrian Roos261d5ab2014-10-29 14:42:38 +01002003
Jeff Sharkeyeddf5182016-08-09 16:36:08 -06002004 // We're potentially going to be doing a bunch of disk I/O below as part
2005 // of unlocking the user, so yell if calling from the main thread.
2006 StrictMode.noteDiskRead();
2007
Rubin Xuca6ece52019-07-31 15:02:13 +01002008 GateKeeperResponse gateKeeperResponse;
2009 try {
Rubin Xubb883202019-10-09 11:22:53 +01002010 gateKeeperResponse = getGateKeeperService().verifyChallenge(
2011 userId, challenge, storedHash.hash, credential.getCredential());
Rubin Xuca6ece52019-07-31 15:02:13 +01002012 } catch (RemoteException e) {
2013 Slog.e(TAG, "gatekeeper verify failed", e);
2014 gateKeeperResponse = GateKeeperResponse.ERROR;
2015 }
Rubin Xua55b1682017-01-31 10:06:56 +00002016 VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
2017 boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
Andres Morales8fa56652015-03-31 09:19:50 -07002018
Andres Morales23974272015-05-14 22:42:26 -07002019 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002020
Andres Morales23974272015-05-14 22:42:26 -07002021 // credential has matched
Jorim Jaggie8fde5d2016-06-30 23:41:37 -07002022
2023 if (progressCallback != null) {
Rubin Xuca6ece52019-07-31 15:02:13 +01002024 try {
2025 progressCallback.onCredentialVerified();
2026 } catch (RemoteException e) {
Rubin Xue1beaf02019-10-22 11:36:51 +01002027 Slog.w(TAG, "progressCallback throws exception", e);
Rubin Xuca6ece52019-07-31 15:02:13 +01002028 }
Jorim Jaggie8fde5d2016-06-30 23:41:37 -07002029 }
Rubin Xubb883202019-10-09 11:22:53 +01002030 setUserPasswordMetrics(credential, userId);
2031 unlockKeystore(credential.getCredential(), userId);
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002032
Rubin Xu3bf722a2016-12-15 16:07:38 +00002033 Slog.i(TAG, "Unlocking user " + userId + " with token length "
2034 + response.getPayload().length);
Paul Crowleyfaeb3eb2016-02-08 15:58:29 +00002035 unlockUser(userId, response.getPayload(), secretFromCredential(credential));
Jeff Sharkeyb9fe5372015-12-03 15:23:08 -07002036
Ricky Waidc283a82016-03-24 19:55:08 +00002037 if (isManagedProfileWithSeparatedLock(userId)) {
Pavel Grafova8da6972019-04-03 13:58:58 +01002038 setDeviceUnlockedForUser(userId);
Clara Bayarri56878a92015-10-29 15:43:55 +00002039 }
Andres Morales23974272015-05-14 22:42:26 -07002040 if (shouldReEnroll) {
Rubin Xubb883202019-10-09 11:22:53 +01002041 setLockCredentialInternal(credential, credential,
2042 userId, false, /* isLockTiedToParent= */ false);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002043 } else {
2044 // Now that we've cleared of all required GK migration, let's do the final
2045 // migration to synthetic password.
2046 synchronized (mSpManager) {
2047 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
Rubin Xu128180b2017-04-12 18:02:44 +01002048 AuthenticationToken auth = initializeSyntheticPasswordLocked(
Rubin Xubb883202019-10-09 11:22:53 +01002049 storedHash.hash, credential, userId);
Rubin Xu128180b2017-04-12 18:02:44 +01002050 activateEscrowTokens(auth, userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002051 }
2052 }
Andres Morales23974272015-05-14 22:42:26 -07002053 }
Dmitry Dementyev6a509e42017-12-19 14:47:26 -08002054 // Use credentials to create recoverable keystore snapshot.
Rubin Xubb883202019-10-09 11:22:53 +01002055 sendCredentialsOnUnlockIfRequired(credential, userId);
Dmitry Dementyev6a509e42017-12-19 14:47:26 -08002056
Adrian Roos873010d2015-08-25 15:59:00 -07002057 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
2058 if (response.getTimeout() > 0) {
2059 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
2060 }
Andres Morales23974272015-05-14 22:42:26 -07002061 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07002062
Andres Morales23974272015-05-14 22:42:26 -07002063 return response;
2064 }
Andres Moralesd9fc85a2015-04-09 19:14:42 -07002065
Rubin Xu7cf45092017-08-28 11:47:35 +01002066 /**
Rubin Xu19854862019-08-15 16:37:23 +01002067 * Keep track of the given user's latest password metric. This should be called
2068 * when the user is authenticating or when a new password is being set. In comparison,
2069 * {@link #notifyPasswordChanged} only needs to be called when the user changes the password.
Rubin Xu7cf45092017-08-28 11:47:35 +01002070 */
Rubin Xubb883202019-10-09 11:22:53 +01002071 private void setUserPasswordMetrics(LockscreenCredential password, @UserIdInt int userHandle) {
Rubin Xu19854862019-08-15 16:37:23 +01002072 synchronized (this) {
Rubin Xubb883202019-10-09 11:22:53 +01002073 mUserPasswordMetrics.put(userHandle, PasswordMetrics.computeForCredential(password));
Rubin Xu19854862019-08-15 16:37:23 +01002074 }
2075 }
Andrew Scull5daf2732016-11-14 15:02:45 +00002076
Rubin Xu19854862019-08-15 16:37:23 +01002077 @VisibleForTesting
2078 PasswordMetrics getUserPasswordMetrics(int userHandle) {
2079 if (!isUserSecure(userHandle)) {
2080 // for users without password, mUserPasswordMetrics might not be initialized
2081 // since the user never unlock the device manually. In this case, always
2082 // return a default metrics object. This is to distinguish this case from
2083 // the case where during boot user password is unknown yet (returning null here)
Pavel Grafov6f334842019-08-06 14:37:06 +01002084 return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
Rubin Xu19854862019-08-15 16:37:23 +01002085 }
2086 synchronized (this) {
2087 return mUserPasswordMetrics.get(userHandle);
2088 }
Andrew Scull5daf2732016-11-14 15:02:45 +00002089 }
2090
2091 /**
Rubin Xu19854862019-08-15 16:37:23 +01002092 * Call after {@link #setUserPasswordMetrics} so metrics are updated before
Andrew Scull5daf2732016-11-14 15:02:45 +00002093 * reporting the password changed.
2094 */
2095 private void notifyPasswordChanged(@UserIdInt int userId) {
Andrew Scull5daf2732016-11-14 15:02:45 +00002096 mHandler.post(() -> {
Rubin Xu19854862019-08-15 16:37:23 +01002097 mInjector.getDevicePolicyManager().reportPasswordChanged(userId);
Adrian Roos1c8e3c02018-11-20 20:07:55 +01002098 LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId);
Andrew Scull5daf2732016-11-14 15:02:45 +00002099 });
2100 }
2101
Rubin Xubb883202019-10-09 11:22:53 +01002102 private LockscreenCredential createPattern(String patternString) {
2103 final byte[] patternBytes = patternString.getBytes();
2104 LockscreenCredential pattern = LockscreenCredential.createPattern(
2105 LockPatternUtils.byteArrayToPattern(patternBytes));
2106 Arrays.fill(patternBytes, (byte) 0);
2107 return pattern;
2108 }
2109
Amith Yamasani52c489c2012-03-28 11:42:42 -07002110 @Override
Rubin Xuca6ece52019-07-31 15:02:13 +01002111 public boolean checkVoldPassword(int userId) {
Paul Lawrence945490c2014-03-27 16:37:28 +00002112 if (!mFirstCallToVold) {
2113 return false;
2114 }
2115 mFirstCallToVold = false;
2116
2117 checkPasswordReadPermission(userId);
2118
2119 // There's no guarantee that this will safely connect, but if it fails
2120 // we will simply show the lock screen when we shouldn't, so relatively
2121 // benign. There is an outside chance something nasty would happen if
2122 // this service restarted before vold stales out the password in this
2123 // case. The nastiness is limited to not showing the lock screen when
2124 // we should, within the first minute of decrypting the phone if this
2125 // service can't connect to vold, it restarts, and then the new instance
2126 // does successfully connect.
Rubin Xu0cbc19e2016-12-09 14:00:21 +00002127 final IStorageManager service = mInjector.getStorageManager();
Rich Canningsf64ec632019-02-21 12:40:36 -08002128 // TODO(b/120484642): Update vold to return a password as a byte array
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002129 String password;
2130 long identity = Binder.clearCallingIdentity();
2131 try {
2132 password = service.getPassword();
2133 service.clearPassword();
Rubin Xuca6ece52019-07-31 15:02:13 +01002134 } catch (RemoteException e) {
2135 Slog.w(TAG, "vold getPassword() failed", e);
2136 return false;
Paul Lawrence0bbd1082016-04-26 15:21:02 -07002137 } finally {
2138 Binder.restoreCallingIdentity(identity);
2139 }
Rubin Xu5e891bc2019-10-14 10:22:23 +01002140 if (TextUtils.isEmpty(password)) {
Paul Lawrence945490c2014-03-27 16:37:28 +00002141 return false;
2142 }
2143
2144 try {
Rubin Xu5e891bc2019-10-14 10:22:23 +01002145 final LockscreenCredential credential;
2146 switch (getCredentialTypeInternal(userId)) {
2147 case CREDENTIAL_TYPE_PATTERN:
2148 credential = createPattern(password);
2149 break;
2150 case CREDENTIAL_TYPE_PIN:
2151 credential = LockscreenCredential.createPin(password);
2152 break;
2153 case CREDENTIAL_TYPE_PASSWORD:
2154 credential = LockscreenCredential.createPassword(password);
2155 break;
2156 default:
2157 credential = null;
2158 Slog.e(TAG, "Unknown credential type");
Paul Lawrence945490c2014-03-27 16:37:28 +00002159 }
Paul Lawrence945490c2014-03-27 16:37:28 +00002160
Rubin Xu5e891bc2019-10-14 10:22:23 +01002161 if (credential != null
2162 && checkCredential(credential, userId, null /* progressCallback */)
Rubin Xu1de89b32016-11-30 20:03:13 +00002163 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
Rubin Xu5e891bc2019-10-14 10:22:23 +01002164 return true;
Paul Lawrence945490c2014-03-27 16:37:28 +00002165 }
2166 } catch (Exception e) {
Rubin Xu5e891bc2019-10-14 10:22:23 +01002167 Slog.e(TAG, "checkVoldPassword failed: ", e);
Paul Lawrence945490c2014-03-27 16:37:28 +00002168 }
2169
2170 return false;
2171 }
2172
Amith Yamasanif11a5742016-06-16 08:20:07 -07002173 private void removeUser(int userId, boolean unknownUser) {
Rubin Xu7b7424b2017-03-31 18:03:20 +01002174 mSpManager.removeUser(userId);
Adrian Roos261d5ab2014-10-29 14:42:38 +01002175 mStorage.removeUser(userId);
Adrian Roosb5e47222015-08-14 15:53:06 -07002176 mStrongAuth.removeUser(userId);
Andrew Scullede482d2018-01-30 13:54:29 +00002177 tryRemoveUserFromSpCacheLater(userId);
Robin Lee49d810c2014-09-23 13:50:22 +01002178
2179 final KeyStore ks = KeyStore.getInstance();
Chad Brubaker83ce0952015-05-12 13:00:02 -07002180 ks.onUserRemoved(userId);
Andres Morales070fe632015-06-24 10:37:10 -07002181
Rubin Xuca6ece52019-07-31 15:02:13 +01002182 gateKeeperClearSecureUserId(userId);
Irina Dumitrescud74fb7c2019-03-06 16:42:29 +00002183 if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
Ricky Waidc283a82016-03-24 19:55:08 +00002184 removeKeystoreProfileKey(userId);
2185 }
2186 }
2187
2188 private void removeKeystoreProfileKey(int targetUserId) {
Rubin Xu7b76f332019-11-08 12:10:12 +00002189 Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId);
Ricky Waidc283a82016-03-24 19:55:08 +00002190 try {
2191 java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
2192 keyStore.load(null);
Ricky Waid3982442016-05-24 19:27:08 +01002193 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
2194 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
Ricky Waidc283a82016-03-24 19:55:08 +00002195 } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
2196 | IOException e) {
2197 // We have tried our best to remove all keys
2198 Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
2199 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07002200 }
2201
Adrian Roosb5e47222015-08-14 15:53:06 -07002202 @Override
2203 public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
2204 checkPasswordReadPermission(UserHandle.USER_ALL);
2205 mStrongAuth.registerStrongAuthTracker(tracker);
2206 }
2207
2208 @Override
2209 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
2210 checkPasswordReadPermission(UserHandle.USER_ALL);
2211 mStrongAuth.unregisterStrongAuthTracker(tracker);
2212 }
2213
2214 @Override
2215 public void requireStrongAuth(int strongAuthReason, int userId) {
2216 checkWritePermission(userId);
2217 mStrongAuth.requireStrongAuth(strongAuthReason, userId);
2218 }
2219
Adrian Roos4ab7e592016-04-13 15:38:13 -07002220 @Override
2221 public void userPresent(int userId) {
2222 checkWritePermission(userId);
2223 mStrongAuth.reportUnlock(userId);
2224 }
2225
Victor Changa0940d32016-05-16 19:36:08 +01002226 @Override
2227 public int getStrongAuthForUser(int userId) {
2228 checkPasswordReadPermission(userId);
2229 return mStrongAuthTracker.getStrongAuthForUser(userId);
2230 }
2231
Jorim Jaggi2fef6f72016-11-01 19:06:25 -07002232 private boolean isCallerShell() {
2233 final int callingUid = Binder.getCallingUid();
2234 return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
2235 }
2236
2237 private void enforceShell() {
2238 if (!isCallerShell()) {
2239 throw new SecurityException("Caller must be shell");
2240 }
2241 }
2242
2243 @Override
2244 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
Rubin Xuca6ece52019-07-31 15:02:13 +01002245 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
Jorim Jaggi2fef6f72016-11-01 19:06:25 -07002246 enforceShell();
2247 final long origId = Binder.clearCallingIdentity();
2248 try {
Felipe Leme1fc9c812018-07-11 10:02:23 -07002249 (new LockSettingsShellCommand(new LockPatternUtils(mContext))).exec(
Jorim Jaggi2fef6f72016-11-01 19:06:25 -07002250 this, in, out, err, args, callback, resultReceiver);
2251 } finally {
2252 Binder.restoreCallingIdentity(origId);
2253 }
2254 }
2255
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002256 @Override
Bo Zhu7f414d92018-02-28 09:28:19 -08002257 public void initRecoveryServiceWithSigFile(@NonNull String rootCertificateAlias,
2258 @NonNull byte[] recoveryServiceCertFile, @NonNull byte[] recoveryServiceSigFile)
2259 throws RemoteException {
2260 mRecoverableKeyStoreManager.initRecoveryServiceWithSigFile(rootCertificateAlias,
2261 recoveryServiceCertFile, recoveryServiceSigFile);
2262 }
2263
2264 @Override
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002265 public @NonNull KeyChainSnapshot getKeyChainSnapshot() throws RemoteException {
Dmitry Dementyevb4fb9872018-01-26 11:49:34 -08002266 return mRecoverableKeyStoreManager.getKeyChainSnapshot();
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002267 }
2268
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002269 @Override
Dmitry Dementyev14298312018-01-04 15:19:19 -08002270 public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
Dmitry Dementyevb8b030b2017-12-19 11:02:54 -08002271 throws RemoteException {
Dmitry Dementyev14298312018-01-04 15:19:19 -08002272 mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent);
Dmitry Dementyevb8b030b2017-12-19 11:02:54 -08002273 }
2274
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002275 @Override
Dmitry Dementyev7d8c78a2018-01-12 19:14:07 -08002276 public void setServerParams(byte[] serverParams) throws RemoteException {
2277 mRecoverableKeyStoreManager.setServerParams(serverParams);
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002278 }
2279
2280 @Override
Robert Berrybbe02ae2018-02-20 19:47:43 +00002281 public void setRecoveryStatus(String alias, int status) throws RemoteException {
2282 mRecoverableKeyStoreManager.setRecoveryStatus(alias, status);
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002283 }
2284
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002285 @Override
2286 public @NonNull Map getRecoveryStatus() throws RemoteException {
Robert Berry56f06b42018-02-23 13:31:32 +00002287 return mRecoverableKeyStoreManager.getRecoveryStatus();
Dmitry Dementyevb8b030b2017-12-19 11:02:54 -08002288 }
2289
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002290 @Override
Dmitry Dementyev0916e7c2018-01-23 13:02:08 -08002291 public void setRecoverySecretTypes(@NonNull @KeyChainProtectionParams.UserSecretType
Dmitry Dementyev14298312018-01-04 15:19:19 -08002292 int[] secretTypes) throws RemoteException {
2293 mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002294 }
2295
2296 @Override
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002297 public @NonNull int[] getRecoverySecretTypes() throws RemoteException {
Dmitry Dementyev14298312018-01-04 15:19:19 -08002298 return mRecoverableKeyStoreManager.getRecoverySecretTypes();
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002299
2300 }
2301
2302 @Override
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002303 public @NonNull byte[] startRecoverySessionWithCertPath(@NonNull String sessionId,
Bo Zhub31ab672018-03-20 22:44:18 -07002304 @NonNull String rootCertificateAlias, @NonNull RecoveryCertPath verifierCertPath,
2305 @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge,
2306 @NonNull List<KeyChainProtectionParams> secrets)
Bo Zhu7c1972f2018-02-22 21:43:52 -08002307 throws RemoteException {
2308 return mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
Bo Zhub31ab672018-03-20 22:44:18 -07002309 sessionId, rootCertificateAlias, verifierCertPath, vaultParams, vaultChallenge,
2310 secrets);
Bo Zhu7c1972f2018-02-22 21:43:52 -08002311 }
2312
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002313 @Override
Robert Berry4a5c87d2018-03-19 18:00:46 +00002314 public Map<String, String> recoverKeyChainSnapshot(
2315 @NonNull String sessionId,
2316 @NonNull byte[] recoveryKeyBlob,
2317 @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
2318 return mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
2319 sessionId, recoveryKeyBlob, applicationKeys);
2320 }
2321
2322 @Override
Dmitry Dementyev745d2c92018-04-13 14:10:05 -07002323 public void closeSession(@NonNull String sessionId) throws RemoteException {
2324 mRecoverableKeyStoreManager.closeSession(sessionId);
Dmitry Dementyev1aa96132017-12-11 11:33:12 -08002325 }
2326
Robert Berrycfc990a2017-12-22 15:54:30 +00002327 @Override
Robert Berry5daccec2018-01-06 19:16:25 +00002328 public void removeKey(@NonNull String alias) throws RemoteException {
2329 mRecoverableKeyStoreManager.removeKey(alias);
2330 }
2331
2332 @Override
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002333 public @Nullable String generateKey(@NonNull String alias) throws RemoteException {
Robert Berrya3b99472018-02-23 15:59:02 +00002334 return mRecoverableKeyStoreManager.generateKey(alias);
Dmitry Dementyev29b9de52018-01-31 16:09:32 -08002335 }
2336
2337 @Override
Bo Zhuc7048342019-01-03 14:04:58 -08002338 public @Nullable String generateKeyWithMetadata(
2339 @NonNull String alias, @Nullable byte[] metadata) throws RemoteException {
2340 return mRecoverableKeyStoreManager.generateKeyWithMetadata(alias, metadata);
2341 }
2342
2343 @Override
2344 public @Nullable String importKey(@NonNull String alias, @NonNull byte[] keyBytes)
2345 throws RemoteException {
Bo Zhu2c8e5382018-02-26 15:54:25 -08002346 return mRecoverableKeyStoreManager.importKey(alias, keyBytes);
2347 }
2348
2349 @Override
Bo Zhuc7048342019-01-03 14:04:58 -08002350 public @Nullable String importKeyWithMetadata(@NonNull String alias, @NonNull byte[] keyBytes,
2351 @Nullable byte[] metadata) throws RemoteException {
2352 return mRecoverableKeyStoreManager.importKeyWithMetadata(alias, keyBytes, metadata);
2353 }
2354
2355 @Override
Dmitry Dementyev4da14e02018-03-23 15:18:33 -07002356 public @Nullable String getKey(@NonNull String alias) throws RemoteException {
Dmitry Dementyev29b9de52018-01-31 16:09:32 -08002357 return mRecoverableKeyStoreManager.getKey(alias);
2358 }
2359
Amith Yamasani52c489c2012-03-28 11:42:42 -07002360 private static final String[] VALID_SETTINGS = new String[] {
Rubin Xu1de89b32016-11-30 20:03:13 +00002361 LockPatternUtils.LOCKOUT_PERMANENT_KEY,
Rubin Xu1de89b32016-11-30 20:03:13 +00002362 LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
2363 LockPatternUtils.PASSWORD_TYPE_KEY,
2364 LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
2365 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
2366 LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
2367 LockPatternUtils.LOCKSCREEN_OPTIONS,
2368 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
2369 LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
2370 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
2371 LockPatternUtils.PASSWORD_HISTORY_KEY,
2372 Secure.LOCK_PATTERN_ENABLED,
2373 Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
2374 Secure.LOCK_PATTERN_VISIBLE,
2375 Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
Jim Miller187ec582013-04-15 18:27:54 -07002376 };
2377
Svetoslav Ganov6d2c0e52015-06-23 16:33:36 +00002378 // Reading these settings needs the contacts permission
2379 private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
Rubin Xu1de89b32016-11-30 20:03:13 +00002380 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
2381 Secure.LOCK_SCREEN_OWNER_INFO
Jim Miller187ec582013-04-15 18:27:54 -07002382 };
Paul Lawrence945490c2014-03-27 16:37:28 +00002383
Adrian Roos001b00d2015-02-24 17:08:48 +01002384 // Reading these settings needs the same permission as checking the password
2385 private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
2386 LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
2387 LockPatternUtils.PASSWORD_HISTORY_KEY,
Adrian Roos855fa302015-04-02 16:01:12 +02002388 LockPatternUtils.PASSWORD_TYPE_KEY,
Ricky Wai7f405f12016-05-31 12:05:05 +01002389 SEPARATE_PROFILE_CHALLENGE_KEY
Adrian Roos001b00d2015-02-24 17:08:48 +01002390 };
2391
Amith Yamasani072543f2015-02-13 11:09:45 -08002392 private static final String[] SETTINGS_TO_BACKUP = new String[] {
Rubin Xu1de89b32016-11-30 20:03:13 +00002393 Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
Bryan Mawhinneye483b562017-05-15 14:46:05 +01002394 Secure.LOCK_SCREEN_OWNER_INFO,
2395 Secure.LOCK_PATTERN_VISIBLE,
2396 LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
Amith Yamasani072543f2015-02-13 11:09:45 -08002397 };
2398
Andres Morales301ea442015-04-17 09:15:47 -07002399 private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
2400 @Override
2401 public void binderDied() {
2402 mGateKeeperService.asBinder().unlinkToDeath(this, 0);
2403 mGateKeeperService = null;
2404 }
2405 }
2406
Rubin Xuca6ece52019-07-31 15:02:13 +01002407 protected synchronized IGateKeeperService getGateKeeperService() {
Andres Morales8fa56652015-03-31 09:19:50 -07002408 if (mGateKeeperService != null) {
2409 return mGateKeeperService;
2410 }
2411
Rubin Xu1de89b32016-11-30 20:03:13 +00002412 final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
Andres Morales8fa56652015-03-31 09:19:50 -07002413 if (service != null) {
Rubin Xuca6ece52019-07-31 15:02:13 +01002414 try {
2415 service.linkToDeath(new GateKeeperDiedRecipient(), 0);
2416 } catch (RemoteException e) {
2417 Slog.w(TAG, " Unable to register death recipient", e);
2418 }
Andres Morales8fa56652015-03-31 09:19:50 -07002419 mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
2420 return mGateKeeperService;
2421 }
2422
2423 Slog.e(TAG, "Unable to acquire GateKeeperService");
2424 return null;
2425 }
Rubin Xu3bf722a2016-12-15 16:07:38 +00002426
Rubin Xuca6ece52019-07-31 15:02:13 +01002427 private void gateKeeperClearSecureUserId(int userId) {
2428 try {
2429 getGateKeeperService().clearSecureUserId(userId);
2430 } catch (RemoteException e) {
2431 Slog.w(TAG, "Failed to clear SID", e);
2432 }
2433 }
2434
Rubin Xu3bf722a2016-12-15 16:07:38 +00002435 /**
Andrew Scull1416bd02018-01-05 18:33:58 +00002436 * A user's synthetic password does not change so it must be cached in certain circumstances to
2437 * enable untrusted credential reset.
2438 *
2439 * Untrusted credential reset will be removed in a future version (b/68036371) at which point
2440 * this cache is no longer needed as the SP will always be known when changing the user's
2441 * credential.
2442 */
2443 @GuardedBy("mSpManager")
Rubin Xuca6ece52019-07-31 15:02:13 +01002444 private SparseArray<AuthenticationToken> mSpCache = new SparseArray<>();
Andrew Scull1416bd02018-01-05 18:33:58 +00002445
2446 private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
Andrew Scullede482d2018-01-30 13:54:29 +00002447 // Preemptively cache the SP and then try to remove it in a handler.
2448 Slog.i(TAG, "Caching SP for user " + userId);
2449 synchronized (mSpManager) {
2450 mSpCache.put(userId, auth);
2451 }
2452 tryRemoveUserFromSpCacheLater(userId);
2453
David Anderson6ebc25b2019-02-12 16:25:56 -08002454 if (mInjector.isGsiRunning()) {
2455 Slog.w(TAG, "AuthSecret disabled in GSI");
2456 return;
2457 }
2458
Andrew Sculle6527c12018-01-05 18:33:58 +00002459 // Pass the primary user's auth secret to the HAL
2460 if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
2461 try {
2462 final byte[] rawSecret = auth.deriveVendorAuthSecret();
2463 final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length);
2464 for (int i = 0; i < rawSecret.length; ++i) {
2465 secret.add(rawSecret[i]);
2466 }
2467 mAuthSecretService.primaryUserCredential(secret);
2468 } catch (RemoteException e) {
2469 Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
2470 }
2471 }
Andrew Scull1416bd02018-01-05 18:33:58 +00002472 }
2473
Andrew Scullede482d2018-01-30 13:54:29 +00002474 private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) {
2475 mHandler.post(() -> {
2476 if (!shouldCacheSpForUser(userId)) {
2477 // The transition from 'should not cache' to 'should cache' can only happen if
2478 // certain admin apps are installed after provisioning e.g. via adb. This is not
2479 // a common case and we do not seamlessly support; it may result in the SP not
2480 // being cached when it is needed. The cache can be re-populated by verifying
2481 // the credential again.
2482 Slog.i(TAG, "Removing SP from cache for user " + userId);
2483 synchronized (mSpManager) {
2484 mSpCache.remove(userId);
Andrew Scull1416bd02018-01-05 18:33:58 +00002485 }
2486 }
Andrew Scullede482d2018-01-30 13:54:29 +00002487 });
Andrew Scull1416bd02018-01-05 18:33:58 +00002488 }
2489
Andrew Scullede482d2018-01-30 13:54:29 +00002490 /** Do not hold any of the locks from this service when calling. */
Andrew Scull1416bd02018-01-05 18:33:58 +00002491 private boolean shouldCacheSpForUser(@UserIdInt int userId) {
2492 // Before the user setup has completed, an admin could be installed that requires the SP to
2493 // be cached (see below).
2494 if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
2495 Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) {
2496 return true;
2497 }
2498
2499 // If the user has an admin which can perform an untrusted credential reset, the SP needs to
2500 // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first
2501 // place so caching is not necessary.
2502 final DevicePolicyManagerInternal dpmi = LocalServices.getService(
2503 DevicePolicyManagerInternal.class);
2504 if (dpmi == null) {
2505 return false;
2506 }
2507 return dpmi.canUserHaveUntrustedCredentialReset(userId);
2508 }
2509
2510 /**
Rubin Xu3bf722a2016-12-15 16:07:38 +00002511 * Precondition: vold and keystore unlocked.
2512 *
2513 * Create new synthetic password, set up synthetic password blob protected by the supplied
2514 * user credential, and make the newly-created SP blob active.
2515 *
2516 * The invariant under a synthetic password is:
2517 * 1. If user credential exists, then both vold and keystore and protected with keys derived
2518 * from the synthetic password.
2519 * 2. If user credential does not exist, vold and keystore protection are cleared. This is to
2520 * make it consistent with current behaviour. It also allows ActivityManager to call
2521 * unlockUser() with empty secret.
2522 * 3. Once a user is migrated to have synthetic password, its value will never change, no matter
2523 * whether the user changes his lockscreen PIN or clear/reset it. When the user clears its
2524 * lockscreen PIN, we still maintain the existing synthetic password in a password blob
Andrew Scull1416bd02018-01-05 18:33:58 +00002525 * protected by a default PIN.
Rubin Xu3bf722a2016-12-15 16:07:38 +00002526 * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user
2527 * clears/re-creates his lockscreen PIN.
2528 *
2529 *
2530 * Different cases of calling this method:
2531 * 1. credentialHash != null
2532 * This implies credential != null, a new SP blob will be provisioned, and existing SID
2533 * migrated to associate with the new SP.
2534 * This happens during a normal migration case when the user currently has password.
2535 *
2536 * 2. credentialhash == null and credential == null
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002537 * A new SP blob and will be created, while the user has no credentials.
Rubin Xu3bf722a2016-12-15 16:07:38 +00002538 * This can happens when we are activating an escrow token on a unsecured device, during
2539 * which we want to create the SP structure with an empty user credential.
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002540 * This could also happen during an untrusted reset to clear password.
Rubin Xu3bf722a2016-12-15 16:07:38 +00002541 *
2542 * 3. credentialhash == null and credential != null
2543 * This is the untrusted credential reset, OR the user sets a new lockscreen password
2544 * FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
2545 */
Andrew Scull1416bd02018-01-05 18:33:58 +00002546 @GuardedBy("mSpManager")
Rubin Xu16c823e2017-06-27 14:44:58 +01002547 @VisibleForTesting
2548 protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
Rubin Xubb883202019-10-09 11:22:53 +01002549 LockscreenCredential credential, int userId) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002550 Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002551 final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
2552 getGateKeeperService(), credentialHash, credential, userId);
Andrew Scull1416bd02018-01-05 18:33:58 +00002553 onAuthTokenKnownForUser(userId, auth);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002554 if (auth == null) {
2555 Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
2556 return null;
2557 }
2558 long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
Rubin Xubb883202019-10-09 11:22:53 +01002559 credential, auth, userId);
2560 if (!credential.isNone()) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002561 if (credentialHash == null) {
2562 // Since when initializing SP, we didn't provide an existing password handle
2563 // for it to migrate SID, we need to create a new SID for the user.
2564 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
2565 }
2566 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
2567 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
2568 setKeystorePassword(auth.deriveKeyStorePassword(), userId);
2569 } else {
2570 clearUserKeyProtection(userId);
2571 setKeystorePassword(null, userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01002572 gateKeeperClearSecureUserId(userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002573 }
2574 fixateNewestUserKeyAuth(userId);
Rubin Xue2f925f2019-08-14 16:53:55 +01002575 setSyntheticPasswordHandleLocked(handle, userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002576 return auth;
2577 }
2578
2579 private long getSyntheticPasswordHandleLocked(int userId) {
Adrian Roos60dcbbf2017-08-08 16:19:33 +02002580 return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY,
2581 SyntheticPasswordManager.DEFAULT_HANDLE, userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002582 }
2583
Rubin Xue2f925f2019-08-14 16:53:55 +01002584 private void setSyntheticPasswordHandleLocked(long handle, int userId) {
2585 final long oldHandle = getSyntheticPasswordHandleLocked(userId);
2586 setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
2587 setLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, oldHandle, userId);
2588 setLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, System.currentTimeMillis(), userId);
2589
2590 }
2591
Rubin Xu5e891bc2019-10-14 10:22:23 +01002592 @VisibleForTesting
2593 boolean isSyntheticPasswordBasedCredential(int userId) {
2594 synchronized (mSpManager) {
2595 return isSyntheticPasswordBasedCredentialLocked(userId);
2596 }
2597 }
2598
Rubin Xufcd49f92017-08-24 18:21:52 +01002599 private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
Adrian Roos7374d3a2017-03-31 14:14:53 -07002600 if (userId == USER_FRP) {
2601 final int type = mStorage.readPersistentDataBlock().type;
2602 return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
2603 }
Rubin Xu3bf722a2016-12-15 16:07:38 +00002604 long handle = getSyntheticPasswordHandleLocked(userId);
2605 // This is a global setting
Paul Crowley7a0cc0a2017-05-31 22:12:57 +00002606 long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
2607 SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002608 return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
2609 }
2610
Rubin Xu16c823e2017-06-27 14:44:58 +01002611 @VisibleForTesting
Rubin Xufcd49f92017-08-24 18:21:52 +01002612 protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002613 long handle = getSyntheticPasswordHandleLocked(userId);
2614 // This is a global setting
Paul Crowley7a0cc0a2017-05-31 22:12:57 +00002615 long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
2616 SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002617 return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
2618 }
2619
Rubin Xufcd49f92017-08-24 18:21:52 +01002620 private void enableSyntheticPasswordLocked() {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002621 setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
2622 }
2623
Rubin Xubb883202019-10-09 11:22:53 +01002624 private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
2625 @ChallengeType int challengeType, long challenge,
Kevin Chynbc29dd72019-06-13 11:47:54 -07002626 int userId, ICheckCredentialProgressCallback progressCallback,
Rubin Xuca6ece52019-07-31 15:02:13 +01002627 @Nullable ArrayList<PendingResetLockout> resetLockouts) {
Kevin Chynbe67ce02019-06-10 16:14:22 -07002628
Kevin Chyn28623b62019-06-11 11:43:33 -07002629 final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
Kevin Chynbe67ce02019-06-10 16:14:22 -07002630
Kevin Chynbc29dd72019-06-13 11:47:54 -07002631 Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " challengeType=" + challengeType
Kevin Chynbe67ce02019-06-10 16:14:22 -07002632 + " hasEnrolledBiometrics=" + hasEnrolledBiometrics);
Rubin Xue94a7702017-06-20 17:29:57 +01002633
Kevin Chyna38653c2019-02-11 17:46:21 -08002634 final PackageManager pm = mContext.getPackageManager();
2635 // TODO: When lockout is handled under the HAL for all biometrics (fingerprint),
2636 // we need to generate challenge for each one, have it signed by GK and reset lockout
2637 // for each modality.
Kevin Chynbc29dd72019-06-13 11:47:54 -07002638 if (challengeType == CHALLENGE_NONE && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
Kevin Chynbe67ce02019-06-10 16:14:22 -07002639 && hasEnrolledBiometrics) {
Kevin Chynbc29dd72019-06-13 11:47:54 -07002640 // If there are multiple profiles in the same account, ensure we only generate the
2641 // challenge once.
2642 challengeType = CHALLENGE_INTERNAL;
Kevin Chyna38653c2019-02-11 17:46:21 -08002643 challenge = mContext.getSystemService(FaceManager.class).generateChallenge();
2644 }
2645
Rubin Xue94a7702017-06-20 17:29:57 +01002646 final AuthenticationResult authResult;
2647 VerifyCredentialResponse response;
2648 synchronized (mSpManager) {
2649 if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
2650 return null;
2651 }
2652 if (userId == USER_FRP) {
2653 return mSpManager.verifyFrpCredential(getGateKeeperService(),
Rubin Xubb883202019-10-09 11:22:53 +01002654 userCredential, progressCallback);
Rubin Xue94a7702017-06-20 17:29:57 +01002655 }
2656
2657 long handle = getSyntheticPasswordHandleLocked(userId);
2658 authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
Rubin Xucf326f12017-11-15 11:55:35 +00002659 getGateKeeperService(), handle, userCredential, userId, progressCallback);
Rubin Xue94a7702017-06-20 17:29:57 +01002660
2661 response = authResult.gkResponse;
2662 // credential has matched
2663 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
2664 // perform verifyChallenge with synthetic password which generates the real GK auth
2665 // token and response for the current user
2666 response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
2667 challenge, userId);
2668 if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
2669 // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't
2670 // match the recorded GK password handle.
2671 Slog.wtf(TAG, "verifyChallenge with SP failed.");
2672 return VerifyCredentialResponse.ERROR;
2673 }
2674 }
Adrian Roos7374d3a2017-03-31 14:14:53 -07002675 }
2676
Rubin Xu3bf722a2016-12-15 16:07:38 +00002677 if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
Rubin Xubb883202019-10-09 11:22:53 +01002678 setUserPasswordMetrics(userCredential, userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002679 unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
Kevin Chyna38653c2019-02-11 17:46:21 -08002680
Kevin Chynbc29dd72019-06-13 11:47:54 -07002681 // Do resetLockout / revokeChallenge when all profiles are unlocked
2682 if (hasEnrolledBiometrics) {
2683 if (resetLockouts == null) {
2684 resetLockouts = new ArrayList<>();
Kevin Chyna38653c2019-02-11 17:46:21 -08002685 }
Kevin Chynbc29dd72019-06-13 11:47:54 -07002686 resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
Kevin Chyna38653c2019-02-11 17:46:21 -08002687 }
Rubin Xu3bf722a2016-12-15 16:07:38 +00002688
2689 final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
2690 Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
Kevin Chynbc29dd72019-06-13 11:47:54 -07002691 unlockUser(userId, null, secret, challengeType, challenge, resetLockouts);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002692
Rubin Xue94a7702017-06-20 17:29:57 +01002693 activateEscrowTokens(authResult.authToken, userId);
2694
Rubin Xu3bf722a2016-12-15 16:07:38 +00002695 if (isManagedProfileWithSeparatedLock(userId)) {
Pavel Grafova8da6972019-04-03 13:58:58 +01002696 setDeviceUnlockedForUser(userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002697 }
Rubin Xue94a7702017-06-20 17:29:57 +01002698 mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
Andrew Scull1416bd02018-01-05 18:33:58 +00002699
2700 onAuthTokenKnownForUser(userId, authResult.authToken);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002701 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
2702 if (response.getTimeout() > 0) {
2703 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
2704 }
2705 }
2706
2707 return response;
2708 }
2709
Pavel Grafova8da6972019-04-03 13:58:58 +01002710 private void setDeviceUnlockedForUser(int userId) {
2711 final TrustManager trustManager = mContext.getSystemService(TrustManager.class);
2712 trustManager.setDeviceLockedForUser(userId, false);
2713 }
2714
Rubin Xu3bf722a2016-12-15 16:07:38 +00002715 /**
2716 * Change the user's lockscreen password by creating a new SP blob and update the handle, based
2717 * on an existing authentication token. Even though a new SP blob is created, the underlying
2718 * synthetic password is never changed.
2719 *
2720 * When clearing credential, we keep the SP unchanged, but clear its password handle so its
2721 * SID is gone. We also clear password from (software-based) keystore and vold, which will be
2722 * added back when new password is set in future.
2723 */
Andrew Scull1416bd02018-01-05 18:33:58 +00002724 @GuardedBy("mSpManager")
Rubin Xubb883202019-10-09 11:22:53 +01002725 private long setLockCredentialWithAuthTokenLocked(LockscreenCredential credential,
2726 AuthenticationToken auth, int userId) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002727 if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
2728 long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
Rubin Xubb883202019-10-09 11:22:53 +01002729 credential, auth, userId);
2730 final Map<Integer, LockscreenCredential> profilePasswords;
2731 if (!credential.isNone()) {
Rubin Xuca7007b2019-03-25 11:44:41 +00002732 // not needed by synchronizeUnifiedWorkChallengeForProfiles()
Rubin Xu3bf722a2016-12-15 16:07:38 +00002733 profilePasswords = null;
2734
2735 if (mSpManager.hasSidForUser(userId)) {
2736 // We are changing password of a secured device, nothing more needed as
2737 // createPasswordBasedSyntheticPassword has already taken care of maintaining
2738 // the password handle and SID unchanged.
2739
2740 //refresh auth token
2741 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
2742 } else {
2743 // A new password is set on a previously-unsecured device, we need to generate
2744 // a new SID, and re-add keys to vold and keystore.
2745 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
2746 mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
2747 setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
2748 fixateNewestUserKeyAuth(userId);
2749 setKeystorePassword(auth.deriveKeyStorePassword(), userId);
2750 }
2751 } else {
2752 // Cache all profile password if they use unified work challenge. This will later be
2753 // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
2754 profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
2755
2756 // we are clearing password of a secured device, so need to nuke SID as well.
2757 mSpManager.clearSidForUser(userId);
Rubin Xuca6ece52019-07-31 15:02:13 +01002758 gateKeeperClearSecureUserId(userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002759 // Clear key from vold so ActivityManager can just unlock the user with empty secret
Rubin Xuca7007b2019-03-25 11:44:41 +00002760 // during boot. Vold storage needs to be unlocked before manipulation of the keys can
2761 // succeed.
2762 unlockUserKey(userId, null, auth.deriveDiskEncryptionKey());
Rubin Xu3bf722a2016-12-15 16:07:38 +00002763 clearUserKeyProtection(userId);
2764 fixateNewestUserKeyAuth(userId);
Rubin Xuca7007b2019-03-25 11:44:41 +00002765 unlockKeystore(auth.deriveKeyStorePassword(), userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002766 setKeystorePassword(null, userId);
Alex Johnston6183cf92019-10-03 15:59:03 +01002767 removeBiometricsForUser(userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002768 }
Rubin Xue2f925f2019-08-14 16:53:55 +01002769 setSyntheticPasswordHandleLocked(newHandle, userId);
Rubin Xu3bf722a2016-12-15 16:07:38 +00002770 synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
Rubin Xu7cf45092017-08-28 11:47:35 +01002771
Rubin Xubb883202019-10-09 11:22:53 +01002772 setUserPasswordMetrics(credential, userId);
Rich Canningsf64ec632019-02-21 12:40:36 -08002773
2774 if (profilePasswords != null) {
Rubin Xubb883202019-10-09 11:22:53 +01002775 for (Map.Entry<Integer, LockscreenCredential> entry : profilePasswords.entrySet()) {
2776 entry.getValue().zeroize();
Rich Canningsf64ec632019-02-21 12:40:36 -08002777 }
2778 }
2779
Rubin Xu3bf722a2016-12-15 16:07:38 +00002780 return newHandle;
2781 }
2782
Alex Johnston6183cf92019-10-03 15:59:03 +01002783 private void removeBiometricsForUser(int userId) {
2784 removeAllFingerprintForUser(userId);
2785 removeAllFaceForUser(userId);
2786 }
2787
2788 private void removeAllFingerprintForUser(final int userId) {
2789 FingerprintManager mFingerprintManager = mInjector.getFingerprintManager();
2790 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
2791 if (mFingerprintManager.hasEnrolledFingerprints(userId)) {
2792 mFingerprintManager.setActiveUser(userId);
2793 CountDownLatch latch = new CountDownLatch(1);
2794 // For the purposes of M and N, groupId is the same as userId.
2795 Fingerprint finger = new Fingerprint(null, userId, 0, 0);
2796 mFingerprintManager.remove(finger, userId,
2797 fingerprintManagerRemovalCallback(latch));
2798 try {
2799 latch.await(10000, TimeUnit.MILLISECONDS);
2800 } catch (InterruptedException e) {
2801 Slog.e(TAG, "Latch interrupted when removing fingerprint", e);
2802 }
2803 }
2804 }
2805 }
2806
2807 private void removeAllFaceForUser(final int userId) {
2808 FaceManager mFaceManager = mInjector.getFaceManager();
2809 if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
2810 if (mFaceManager.hasEnrolledTemplates(userId)) {
2811 mFaceManager.setActiveUser(userId);
2812 CountDownLatch latch = new CountDownLatch(1);
2813 Face face = new Face(null, 0, 0);
2814 mFaceManager.remove(face, userId, faceManagerRemovalCallback(latch));
2815 try {
2816 latch.await(10000, TimeUnit.MILLISECONDS);
2817 } catch (InterruptedException e) {
2818 Slog.e(TAG, "Latch interrupted when removing face", e);
2819 }
2820 }
2821 }
2822 }
2823
2824 private FingerprintManager.RemovalCallback fingerprintManagerRemovalCallback(
2825 CountDownLatch latch) {
2826 return new FingerprintManager.RemovalCallback() {
2827 @Override
2828 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence err) {
2829 Slog.e(TAG, String.format(
2830 "Can't remove fingerprint %d in group %d. Reason: %s",
2831 fp.getBiometricId(), fp.getGroupId(), err));
2832 latch.countDown();
2833 }
2834
2835 @Override
2836 public void onRemovalSucceeded(Fingerprint fp, int remaining) {
2837 if (remaining == 0) {
2838 latch.countDown();
2839 }
2840 }
2841 };
2842 }
2843
2844 private FaceManager.RemovalCallback faceManagerRemovalCallback(CountDownLatch latch) {
2845 return new FaceManager.RemovalCallback() {
2846 @Override
2847 public void onRemovalError(Face face, int errMsgId, CharSequence err) {
2848 Slog.e(TAG, String.format("Can't remove face %d. Reason: %s",
2849 face.getBiometricId(), err));
2850 latch.countDown();
2851 }
2852
2853 @Override
2854 public void onRemovalSucceeded(Face face, int remaining) {
2855 if (remaining == 0) {
2856 latch.countDown();
2857 }
2858 }
2859 };
2860 }
2861
Rubin Xubb883202019-10-09 11:22:53 +01002862 /**
2863 * @param savedCredential if the user is a managed profile with unified challenge and
2864 * savedCredential is empty, LSS will try to re-derive the profile password internally.
2865 * TODO (b/80170828): Fix this so profile password is always passed in.
2866 */
Andrew Scull1416bd02018-01-05 18:33:58 +00002867 @GuardedBy("mSpManager")
Rubin Xubb883202019-10-09 11:22:53 +01002868 private boolean spBasedSetLockCredentialInternalLocked(LockscreenCredential credential,
2869 LockscreenCredential savedCredential, int userId,
Rubin Xuca6ece52019-07-31 15:02:13 +01002870 boolean allowUntrustedChange, boolean isLockTiedToParent) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002871 if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
Rubin Xubb883202019-10-09 11:22:53 +01002872 if (savedCredential.isNone() && isManagedProfileWithUnifiedLock(userId)) {
Rubin Xu3bf722a2016-12-15 16:07:38 +00002873 // get credential from keystore when managed profile has unified lock
2874 try {
2875 savedCredential = getDecryptedPasswordForTiedProfile(userId);
2876 } catch (FileNotFoundException e) {
2877 Slog.i(TAG, "Child profile key not found");
2878 } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
2879 | NoSuchAlgorithmException | NoSuchPaddingException
2880 | InvalidAlgorithmParameterException | IllegalBlockSizeException
2881 | BadPaddingException | CertificateException | IOException e) {
2882 Slog.e(TAG, "Failed to decrypt child profile key", e);
2883 }
2884 }
2885 long handle = getSyntheticPasswordHandleLocked(userId);
Rubin Xu8b30ec32017-03-05 00:47:09 +00002886 AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
Rubin Xucf326f12017-11-15 11:55:35 +00002887 getGateKeeperService(), handle, savedCredential, userId, null);
Rubin Xu8b30ec32017-03-05 00:47:09 +00002888 VerifyCredentialResponse response = authResult.gkResponse;
2889 AuthenticationToken auth = authResult.authToken;
Rubin Xu16c823e2017-06-27 14:44:58 +01002890
Irina Dumitrescuc90674d2019-02-28 17:34:19 +00002891 // If existing credential is provided, the existing credential must match.
Rubin Xubb883202019-10-09 11:22:53 +01002892 if (!savedCredential.isNone() && auth == null) {
2893 Slog.w(TAG, "Failed to enroll: incorrect credential");
Rubin Xu6a7303d2019-08-16 13:19:56 +01002894 return false;
Rubin Xu16c823e2017-06-27 14:44:58 +01002895 }
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002896 boolean untrustedReset = false;
Rubin Xu3bf722a2016-12-15 16:07:38 +00002897 if (auth != null) {
Andrew Scull1416bd02018-01-05 18:33:58 +00002898 onAuthTokenKnownForUser(userId, auth);
Irina Dumitrescuc90674d2019-02-28 17:34:19 +00002899 } else if (response == null) {
2900 throw new IllegalStateException("Password change failed.");
2901 } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002902 // We are performing an untrusted credential change, by DevicePolicyManager or other
2903 // internal callers that don't provide the existing credential
Rubin Xu3bf722a2016-12-15 16:07:38 +00002904 Slog.w(TAG, "Untrusted credential change invoked");
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002905 // Try to get a cached auth token, so we can keep SP unchanged.
2906 auth = mSpCache.get(userId);
Irina Dumitrescuc90674d2019-02-28 17:34:19 +00002907 if (!allowUntrustedChange) {
2908 throw new IllegalStateException("Untrusted credential change was invoked but it was"
2909 + " not allowed. This is likely a bug. Auth token is null: "
2910 + Boolean.toString(auth == null));
2911 }
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002912 untrustedReset = true;
Irina Dumitrescuc90674d2019-02-28 17:34:19 +00002913 } else /* responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
Rubin Xu6a7303d2019-08-16 13:19:56 +01002914 Slog.w(TAG, "Rate limit exceeded, so password was not changed.");
2915 return false;
Rubin Xu3bf722a2016-12-15 16:07:38 +00002916 }
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002917
2918 if (auth != null) {
2919 if (untrustedReset) {
2920 // Force change the current SID to mantain existing behaviour that an untrusted
2921 // reset leads to a change of SID. If the untrusted reset is for clearing the
2922 // current password, the nuking of the SID will be done in
2923 // setLockCredentialWithAuthTokenLocked next
2924 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
2925 }
Rubin Xubb883202019-10-09 11:22:53 +01002926 setLockCredentialWithAuthTokenLocked(credential, auth, userId);
Rubin Xu9a6d39a52018-02-07 08:52:34 +00002927 mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
2928 } else {
2929 throw new IllegalStateException(
2930 "Untrusted credential reset not possible without cached SP");
2931 // Could call initializeSyntheticPasswordLocked(null, credential, credentialType,
2932 // requestedQuality, userId) instead if we still allow untrusted reset that changes
2933 // synthetic password. That would invalidate existing escrow tokens though.
2934 }
Rubin Xubb883202019-10-09 11:22:53 +01002935 sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
Rubin Xu6a7303d2019-08-16 13:19:56 +01002936 return true;
Rubin Xuf095f832017-01-31 15:23:34 +00002937 }
2938
Rubin Xuf01e9072018-03-30 20:59:28 +01002939 /**
2940 * Returns a fixed pseudorandom byte string derived from the user's synthetic password.
2941 * This is used to salt the password history hash to protect the hash against offline
2942 * bruteforcing, since rederiving this value requires a successful authentication.
Rubin Xu4ed98982018-05-23 14:27:53 +01002943 * If user is a managed profile with unified challenge, currentCredential is ignored.
Rubin Xuf01e9072018-03-30 20:59:28 +01002944 */
2945 @Override
Rubin Xubb883202019-10-09 11:22:53 +01002946 public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) {
Rubin Xuf01e9072018-03-30 20:59:28 +01002947 checkPasswordReadPermission(userId);
Rubin Xu4ed98982018-05-23 14:27:53 +01002948 if (isManagedProfileWithUnifiedLock(userId)) {
2949 try {
2950 currentCredential = getDecryptedPasswordForTiedProfile(userId);
2951 } catch (Exception e) {
2952 Slog.e(TAG, "Failed to get work profile credential", e);
2953 return null;
2954 }
2955 }
Rubin Xuf01e9072018-03-30 20:59:28 +01002956 synchronized (mSpManager) {
2957 if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
2958 Slog.w(TAG, "Synthetic password not enabled");
2959 return null;
2960 }
2961 long handle = getSyntheticPasswordHandleLocked(userId);
2962 AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword(
2963 getGateKeeperService(), handle, currentCredential, userId, null);
2964 if (auth.authToken == null) {
2965 Slog.w(TAG, "Current credential is incorrect");
2966 return null;
2967 }
2968 return auth.authToken.derivePasswordHashFactor();
2969 }
2970 }
2971
Rubin Xuca6ece52019-07-31 15:02:13 +01002972 private long addEscrowToken(byte[] token, int userId, EscrowTokenStateChangeCallback callback) {
Rubin Xuf095f832017-01-31 15:23:34 +00002973 if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
2974 synchronized (mSpManager) {
2975 enableSyntheticPasswordLocked();
Rubin Xu8b30ec32017-03-05 00:47:09 +00002976 // Migrate to synthetic password based credentials if the user has no password,
Rubin Xuf095f832017-01-31 15:23:34 +00002977 // the token can then be activated immediately.
2978 AuthenticationToken auth = null;
2979 if (!isUserSecure(userId)) {
2980 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
Rubin Xubb883202019-10-09 11:22:53 +01002981 auth = initializeSyntheticPasswordLocked(
2982 /* credentialHash */ null, LockscreenCredential.createNone(), userId);
Rubin Xuf095f832017-01-31 15:23:34 +00002983 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ {
2984 long pwdHandle = getSyntheticPasswordHandleLocked(userId);
2985 auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
Rubin Xubb883202019-10-09 11:22:53 +01002986 pwdHandle, LockscreenCredential.createNone(), userId, null).authToken;
Rubin Xuf095f832017-01-31 15:23:34 +00002987 }
2988 }
Rubin Xu128180b2017-04-12 18:02:44 +01002989 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
2990 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
2991 if (!mSpManager.hasEscrowData(userId)) {
2992 throw new SecurityException("Escrow token is disabled on the current user");
2993 }
Rubin Xuf095f832017-01-31 15:23:34 +00002994 }
Ram Periathiruvadi32d53552019-02-19 13:25:46 -08002995 long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId, callback);
Rubin Xuf095f832017-01-31 15:23:34 +00002996 if (auth != null) {
2997 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
2998 }
2999 return handle;
3000 }
3001 }
3002
Rubin Xufcd49f92017-08-24 18:21:52 +01003003 private void activateEscrowTokens(AuthenticationToken auth, int userId) {
Rubin Xuf095f832017-01-31 15:23:34 +00003004 if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
3005 synchronized (mSpManager) {
Rubin Xue94a7702017-06-20 17:29:57 +01003006 disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
Rubin Xuf095f832017-01-31 15:23:34 +00003007 for (long handle : mSpManager.getPendingTokensForUser(userId)) {
3008 Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
3009 mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
3010 }
3011 }
3012 }
3013
Rubin Xufcd49f92017-08-24 18:21:52 +01003014 private boolean isEscrowTokenActive(long handle, int userId) {
Rubin Xuf095f832017-01-31 15:23:34 +00003015 synchronized (mSpManager) {
3016 return mSpManager.existsHandle(handle, userId);
3017 }
3018 }
3019
Rubin Xufc067732019-03-18 11:01:18 +00003020 @Override
3021 public boolean hasPendingEscrowToken(int userId) {
3022 checkPasswordReadPermission(userId);
3023 synchronized (mSpManager) {
3024 return !mSpManager.getPendingTokensForUser(userId).isEmpty();
3025 }
3026 }
3027
Rubin Xufcd49f92017-08-24 18:21:52 +01003028 private boolean removeEscrowToken(long handle, int userId) {
Rubin Xuf095f832017-01-31 15:23:34 +00003029 synchronized (mSpManager) {
3030 if (handle == getSyntheticPasswordHandleLocked(userId)) {
3031 Slog.w(TAG, "Cannot remove password handle");
3032 return false;
3033 }
3034 if (mSpManager.removePendingToken(handle, userId)) {
3035 return true;
3036 }
3037 if (mSpManager.existsHandle(handle, userId)) {
3038 mSpManager.destroyTokenBasedSyntheticPassword(handle, userId);
3039 return true;
3040 } else {
3041 return false;
3042 }
3043 }
3044 }
3045
Rubin Xubb883202019-10-09 11:22:53 +01003046 private boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
3047 byte[] token, int userId) {
Rubin Xuf095f832017-01-31 15:23:34 +00003048 boolean result;
3049 synchronized (mSpManager) {
3050 if (!mSpManager.hasEscrowData(userId)) {
3051 throw new SecurityException("Escrow token is disabled on the current user");
3052 }
Rubin Xubb883202019-10-09 11:22:53 +01003053 result = setLockCredentialWithTokenInternalLocked(
3054 credential, tokenHandle, token, userId);
Rubin Xuf095f832017-01-31 15:23:34 +00003055 }
3056 if (result) {
3057 synchronized (mSeparateChallengeLock) {
Rubin Xubb883202019-10-09 11:22:53 +01003058 setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
Rubin Xuf095f832017-01-31 15:23:34 +00003059 }
Rubin Xubb883202019-10-09 11:22:53 +01003060 if (credential.isNone()) {
Rubin Xuca7007b2019-03-25 11:44:41 +00003061 // If clearing credential, unlock the user manually in order to progress user start
3062 // Call unlockUser() on a handler thread so no lock is held (either by LSS or by
3063 // the caller like DPMS), otherwise it can lead to deadlock.
3064 mHandler.post(() -> unlockUser(userId, null, null));
3065 }
Rubin Xuf095f832017-01-31 15:23:34 +00003066 notifyPasswordChanged(userId);
Pavel Grafov28939982017-10-03 15:11:52 +01003067 notifySeparateProfileChallengeChanged(userId);
Rubin Xuf095f832017-01-31 15:23:34 +00003068 }
3069 return result;
3070 }
3071
Rubin Xuca7007b2019-03-25 11:44:41 +00003072 @GuardedBy("mSpManager")
Rubin Xubb883202019-10-09 11:22:53 +01003073 private boolean setLockCredentialWithTokenInternalLocked(LockscreenCredential credential,
3074 long tokenHandle, byte[] token, int userId) {
Andrew Scull1416bd02018-01-05 18:33:58 +00003075 final AuthenticationResult result;
Rubin Xuca7007b2019-03-25 11:44:41 +00003076 result = mSpManager.unwrapTokenBasedSyntheticPassword(
3077 getGateKeeperService(), tokenHandle, token, userId);
3078 if (result.authToken == null) {
3079 Slog.w(TAG, "Invalid escrow token supplied");
3080 return false;
Rubin Xuf095f832017-01-31 15:23:34 +00003081 }
Rubin Xuca7007b2019-03-25 11:44:41 +00003082 if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
3083 // Most likely, an untrusted credential reset happened in the past which
3084 // changed the synthetic password
3085 Slog.e(TAG, "Obsolete token: synthetic password derived but it fails GK "
3086 + "verification.");
3087 return false;
3088 }
Rubin Xuca7007b2019-03-25 11:44:41 +00003089 long oldHandle = getSyntheticPasswordHandleLocked(userId);
Rubin Xubb883202019-10-09 11:22:53 +01003090 setLockCredentialWithAuthTokenLocked(credential, result.authToken, userId);
Rubin Xuca7007b2019-03-25 11:44:41 +00003091 mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
3092
Andrew Scull1416bd02018-01-05 18:33:58 +00003093 onAuthTokenKnownForUser(userId, result.authToken);
3094 return true;
Rubin Xuf095f832017-01-31 15:23:34 +00003095 }
3096
Rubin Xuca6ece52019-07-31 15:02:13 +01003097 private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
Rubin Xuf095f832017-01-31 15:23:34 +00003098 AuthenticationResult authResult;
3099 synchronized (mSpManager) {
3100 if (!mSpManager.hasEscrowData(userId)) {
3101 throw new SecurityException("Escrow token is disabled on the current user");
3102 }
3103 authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(),
3104 tokenHandle, token, userId);
3105 if (authResult.authToken == null) {
3106 Slog.w(TAG, "Invalid escrow token supplied");
Rubin Xufcd49f92017-08-24 18:21:52 +01003107 return false;
Rubin Xuf095f832017-01-31 15:23:34 +00003108 }
3109 }
3110 unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
Andrew Scull1416bd02018-01-05 18:33:58 +00003111 onAuthTokenKnownForUser(userId, authResult.authToken);
Rubin Xufcd49f92017-08-24 18:21:52 +01003112 return true;
Rubin Xu3bf722a2016-12-15 16:07:38 +00003113 }
3114
Rubin Xue2f925f2019-08-14 16:53:55 +01003115 static String timestampToString(long timestamp) {
3116 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
3117 }
3118
Rubin Xu3bf722a2016-12-15 16:07:38 +00003119 @Override
Rubin Xue2f925f2019-08-14 16:53:55 +01003120 protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
3121 if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return;
3122 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
Rubin Xu3bf722a2016-12-15 16:07:38 +00003123
Rubin Xua0a0d352017-05-15 16:18:01 +00003124 pw.println("Current lock settings service state:");
Rubin Xue2f925f2019-08-14 16:53:55 +01003125
Rubin Xua0a0d352017-05-15 16:18:01 +00003126 pw.println(String.format("SP Enabled = %b",
3127 mLockPatternUtils.isSyntheticPasswordEnabled()));
Rubin Xue2f925f2019-08-14 16:53:55 +01003128 pw.println();
Rubin Xu3bf722a2016-12-15 16:07:38 +00003129
Rubin Xue2f925f2019-08-14 16:53:55 +01003130 pw.println("User State:");
3131 pw.increaseIndent();
Rubin Xua0a0d352017-05-15 16:18:01 +00003132 List<UserInfo> users = mUserManager.getUsers();
3133 for (int user = 0; user < users.size(); user++) {
3134 final int userId = users.get(user).id;
Rubin Xue2f925f2019-08-14 16:53:55 +01003135 pw.println("User " + userId);
3136 pw.increaseIndent();
Rubin Xua0a0d352017-05-15 16:18:01 +00003137 synchronized (mSpManager) {
Rubin Xue2f925f2019-08-14 16:53:55 +01003138 pw.println(String.format("SP Handle: %x",
Rubin Xu3bf722a2016-12-15 16:07:38 +00003139 getSyntheticPasswordHandleLocked(userId)));
Rubin Xue2f925f2019-08-14 16:53:55 +01003140 pw.println(String.format("Last changed: %s (%x)",
3141 timestampToString(getLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, 0, userId)),
3142 getLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId)));
Rubin Xua0a0d352017-05-15 16:18:01 +00003143 }
3144 try {
Rubin Xue2f925f2019-08-14 16:53:55 +01003145 pw.println(String.format("SID: %x",
Rubin Xua0a0d352017-05-15 16:18:01 +00003146 getGateKeeperService().getSecureUserId(userId)));
3147 } catch (RemoteException e) {
3148 // ignore.
Rubin Xu3bf722a2016-12-15 16:07:38 +00003149 }
Rubin Xue2f925f2019-08-14 16:53:55 +01003150 // It's OK to dump the password type since anyone with physical access can just
3151 // observe it from the keyguard directly.
Rubin Xu5e891bc2019-10-14 10:22:23 +01003152 pw.println("Quality: " + getKeyguardStoredQuality(userId));
3153 pw.println("CredentialType: " + getCredentialTypeInternal(userId));
Rubin Xuba6fef52019-10-25 11:10:43 +01003154 pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
Rubin Xu5e891bc2019-10-14 10:22:23 +01003155 pw.println(String.format("Metrics: %s",
Rubin Xu19854862019-08-15 16:37:23 +01003156 getUserPasswordMetrics(userId) != null ? "known" : "unknown"));
Rubin Xue2f925f2019-08-14 16:53:55 +01003157 pw.decreaseIndent();
Rubin Xu3bf722a2016-12-15 16:07:38 +00003158 }
Rubin Xue2f925f2019-08-14 16:53:55 +01003159 pw.println();
3160 pw.decreaseIndent();
3161
3162 pw.println("Storage:");
3163 pw.increaseIndent();
3164 mStorage.dump(pw);
3165 pw.println();
3166 pw.decreaseIndent();
Rubin Xu3bf722a2016-12-15 16:07:38 +00003167 }
3168
Rubin Xu0f1e56d2019-08-23 13:34:25 +01003169 /**
3170 * Cryptographically disable escrow token support for the current user, if the user is not
3171 * managed (either user has a profile owner, or if device is managed). Do not disable
3172 * if we are running an automotive build.
3173 */
Rubin Xuf095f832017-01-31 15:23:34 +00003174 private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
Rubin Xu0f1e56d2019-08-23 13:34:25 +01003175 final UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal();
Rakesh Iyercb18d562017-03-06 18:05:53 -08003176
Rubin Xu0f1e56d2019-08-23 13:34:25 +01003177 // Managed profile should have escrow enabled
3178 if (userManagerInternal.isUserManaged(userId)) {
3179 Slog.i(TAG, "Managed profile can have escrow token");
3180 return;
3181 }
Rakesh Iyercb18d562017-03-06 18:05:53 -08003182
Rubin Xu0f1e56d2019-08-23 13:34:25 +01003183 // Devices with Device Owner should have escrow enabled on all users.
3184 if (userManagerInternal.isDeviceManaged()) {
3185 Slog.i(TAG, "Corp-owned device can have escrow token");
3186 return;
3187 }
3188
3189 // If the device is yet to be provisioned (still in SUW), there is still
3190 // a chance that Device Owner will be set on the device later, so postpone
3191 // disabling escrow token for now.
3192 if (!mInjector.getDeviceStateCache().isDeviceProvisioned()) {
3193 Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
3194 return;
3195 }
3196
3197 // Escrow tokens are enabled on automotive builds.
3198 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
3199 return;
3200 }
3201
3202 // Disable escrow token permanently on all other device/user types.
3203 Slog.i(TAG, "Disabling escrow token on user " + userId);
3204 if (isSyntheticPasswordBasedCredentialLocked(userId)) {
3205 mSpManager.destroyEscrowData(userId);
Rubin Xuf095f832017-01-31 15:23:34 +00003206 }
3207 }
3208
Adrian Roos7374d3a2017-03-31 14:14:53 -07003209 private class DeviceProvisionedObserver extends ContentObserver {
3210 private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
3211 Settings.Global.DEVICE_PROVISIONED);
Andrew Scull1416bd02018-01-05 18:33:58 +00003212 private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor(
3213 Settings.Secure.USER_SETUP_COMPLETE);
Adrian Roos7374d3a2017-03-31 14:14:53 -07003214
3215 private boolean mRegistered;
3216
3217 public DeviceProvisionedObserver() {
3218 super(null);
3219 }
3220
3221 @Override
Andrew Scullede482d2018-01-30 13:54:29 +00003222 public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
Adrian Roos7374d3a2017-03-31 14:14:53 -07003223 if (mDeviceProvisionedUri.equals(uri)) {
3224 updateRegistration();
3225
3226 if (isProvisioned()) {
3227 Slog.i(TAG, "Reporting device setup complete to IGateKeeperService");
3228 reportDeviceSetupComplete();
Adrian Roos454f53f2017-08-08 14:56:42 +02003229 clearFrpCredentialIfOwnerNotSecure();
Adrian Roos7374d3a2017-03-31 14:14:53 -07003230 }
Andrew Scull1416bd02018-01-05 18:33:58 +00003231 } else if (mUserSetupCompleteUri.equals(uri)) {
Andrew Scullede482d2018-01-30 13:54:29 +00003232 tryRemoveUserFromSpCacheLater(userId);
Adrian Roos7374d3a2017-03-31 14:14:53 -07003233 }
3234 }
3235
3236 public void onSystemReady() {
Adrian Roos2adc2632017-09-05 17:01:42 +02003237 if (frpCredentialEnabled(mContext)) {
Adrian Roos7374d3a2017-03-31 14:14:53 -07003238 updateRegistration();
3239 } else {
3240 // If we don't intend to use frpCredentials and we're not provisioned yet, send
3241 // deviceSetupComplete immediately, so gatekeeper can discard any lingering
3242 // credentials immediately.
3243 if (!isProvisioned()) {
3244 Slog.i(TAG, "FRP credential disabled, reporting device setup complete "
3245 + "to Gatekeeper immediately");
3246 reportDeviceSetupComplete();
3247 }
3248 }
3249 }
3250
3251 private void reportDeviceSetupComplete() {
3252 try {
3253 getGateKeeperService().reportDeviceSetupComplete();
3254 } catch (RemoteException e) {
3255 Slog.e(TAG, "Failure reporting to IGateKeeperService", e);
3256 }
3257 }
3258
Adrian Roos454f53f2017-08-08 14:56:42 +02003259 /**
3260 * Clears the FRP credential if the user that controls it does not have a secure
3261 * lockscreen.
3262 */
3263 private void clearFrpCredentialIfOwnerNotSecure() {
3264 List<UserInfo> users = mUserManager.getUsers();
3265 for (UserInfo user : users) {
Adrian Roos2adc2632017-09-05 17:01:42 +02003266 if (userOwnsFrpCredential(mContext, user)) {
Adrian Roos454f53f2017-08-08 14:56:42 +02003267 if (!isUserSecure(user.id)) {
3268 mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id,
3269 0, null);
3270 }
3271 return;
3272 }
3273 }
3274 }
3275
Adrian Roos7374d3a2017-03-31 14:14:53 -07003276 private void updateRegistration() {
3277 boolean register = !isProvisioned();
3278 if (register == mRegistered) {
3279 return;
3280 }
3281 if (register) {
3282 mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri,
3283 false, this);
Andrew Scull1416bd02018-01-05 18:33:58 +00003284 mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri,
3285 false, this, UserHandle.USER_ALL);
Adrian Roos7374d3a2017-03-31 14:14:53 -07003286 } else {
3287 mContext.getContentResolver().unregisterContentObserver(this);
3288 }
3289 mRegistered = register;
3290 }
3291
3292 private boolean isProvisioned() {
3293 return Settings.Global.getInt(mContext.getContentResolver(),
3294 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
3295 }
3296 }
Rubin Xufcd49f92017-08-24 18:21:52 +01003297
3298 private final class LocalService extends LockSettingsInternal {
3299
3300 @Override
Ram Periathiruvadi32d53552019-02-19 13:25:46 -08003301 public long addEscrowToken(byte[] token, int userId,
3302 EscrowTokenStateChangeCallback callback) {
Rubin Xuca6ece52019-07-31 15:02:13 +01003303 return LockSettingsService.this.addEscrowToken(token, userId, callback);
Rubin Xufcd49f92017-08-24 18:21:52 +01003304 }
3305
3306 @Override
3307 public boolean removeEscrowToken(long handle, int userId) {
3308 return LockSettingsService.this.removeEscrowToken(handle, userId);
3309 }
3310
3311 @Override
3312 public boolean isEscrowTokenActive(long handle, int userId) {
3313 return LockSettingsService.this.isEscrowTokenActive(handle, userId);
3314 }
3315
3316 @Override
Rubin Xubb883202019-10-09 11:22:53 +01003317 public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
3318 byte[] token, int userId) {
Lenka Trochtova66c492a2018-12-06 11:29:21 +01003319 if (!mLockPatternUtils.hasSecureLockScreen()) {
3320 throw new UnsupportedOperationException(
3321 "This operation requires secure lock screen feature.");
3322 }
Rubin Xubb883202019-10-09 11:22:53 +01003323 return LockSettingsService.this.setLockCredentialWithToken(
3324 credential, tokenHandle, token, userId);
Rubin Xufcd49f92017-08-24 18:21:52 +01003325 }
3326
3327 @Override
3328 public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
Rubin Xuca6ece52019-07-31 15:02:13 +01003329 return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
Rubin Xufcd49f92017-08-24 18:21:52 +01003330 }
Rubin Xu19854862019-08-15 16:37:23 +01003331
3332 @Override
3333 public PasswordMetrics getUserPasswordMetrics(int userHandle) {
3334 long identity = Binder.clearCallingIdentity();
3335 try {
3336 if (isManagedProfileWithUnifiedLock(userHandle)) {
3337 // A managed profile with unified challenge is supposed to be protected by the
3338 // parent lockscreen, so asking for its password metrics is not really useful,
3339 // as this method would just return the metrics of the random profile password
3340 Slog.w(TAG, "Querying password metrics for unified challenge profile: "
3341 + userHandle);
3342 }
3343 } finally {
3344 Binder.restoreCallingIdentity(identity);
3345 }
3346 return LockSettingsService.this.getUserPasswordMetrics(userHandle);
3347 }
3348
Rubin Xufcd49f92017-08-24 18:21:52 +01003349 }
Amith Yamasani52c489c2012-03-28 11:42:42 -07003350}