152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/*
252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Copyright (C) 2012 The Android Open Source Project
352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani *
452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * you may not use this file except in compliance with the License.
652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * You may obtain a copy of the License at
752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani *
852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani *
1052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Unless required by applicable law or agreed to in writing, software
1152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
1252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * See the License for the specific language governing permissions and
1452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * limitations under the License.
1552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */
1652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
17507d11c9353666a75fee014565f900825a907691Andrew Scullpackage com.android.server.locksettings;
1852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
191de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
201de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport static android.Manifest.permission.READ_CONTACTS;
211de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport static android.content.Context.KEYGUARD_SERVICE;
22b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roosimport static android.content.pm.PackageManager.PERMISSION_GRANTED;
237374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
240da8983bc5e58714675b8cd01dcae82b0b9baa16Rubin Xuimport static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
251de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
263bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
273bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
287374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roosimport static com.android.internal.widget.LockPatternUtils.USER_FRP;
297374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roosimport static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
30454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roosimport static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
311de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu
321aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyevimport android.annotation.NonNull;
331aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyevimport android.annotation.Nullable;
345daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scullimport android.annotation.UserIdInt;
35dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shankaimport android.app.ActivityManager;
360cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xuimport android.app.IActivityManager;
37b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guyimport android.app.KeyguardManager;
384f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Millerimport android.app.Notification;
394f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Millerimport android.app.NotificationManager;
404f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Millerimport android.app.PendingIntent;
41230635efe7ffb09d6dc56bfd9193aa1d89c8a898Adrian Roosimport android.app.admin.DevicePolicyManager;
4228939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafovimport android.app.admin.DevicePolicyManagerInternal;
435daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scullimport android.app.admin.PasswordMetrics;
44072543f58037697772663ed34ee26317e9d662c5Amith Yamasaniimport android.app.backup.BackupManager;
45b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roosimport android.app.trust.IStrongAuthTracker;
4656878a93989a49538fabccfb7218face645030bfClara Bayarriimport android.app.trust.TrustManager;
47f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.BroadcastReceiver;
4852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentResolver;
4952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.Context;
50f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.Intent;
51f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.IntentFilter;
52158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport android.content.pm.PackageManager;
53187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.content.pm.UserInfo;
544f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Millerimport android.content.res.Resources;
557374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roosimport android.database.ContentObserver;
5652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteDatabase;
57e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scullimport android.hardware.authsecret.V1_0.IAuthSecret;
587374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roosimport android.net.Uri;
5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.Binder;
60bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.os.Bundle;
61b0cdf3845fd33cc40a929a2b9b882bf0a3a994d3Ricky Waiimport android.os.Handler;
62945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.IBinder;
63bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.os.IProgressListener;
644613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Waiimport android.os.Process;
6552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.RemoteException;
662fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggiimport android.os.ResultReceiver;
67945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.ServiceManager;
681de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport android.os.ShellCallback;
69eddf518763261536f31b777b0e262f85676d6967Jeff Sharkeyimport android.os.StrictMode;
70d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasaniimport android.os.SystemProperties;
71f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
72187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.os.UserManager;
731de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport android.os.storage.IStorageManager;
741de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xuimport android.os.storage.StorageManager;
7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings;
7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings.Secure;
77187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.provider.Settings.SettingNotFoundException;
78de1af08dd3a073f007ae4b8a114352cae3775028Jim Millerimport android.security.KeyStore;
79dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport android.security.keystore.AndroidKeyStoreProvider;
80dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport android.security.keystore.KeyProperties;
81dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport android.security.keystore.KeyProtection;
820acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafovimport android.security.keystore.UserNotAuthenticatedException;
830916e7ca44aba5e6c89d75007da805697fdace9eDmitry Dementyevimport android.security.keystore.recovery.KeyChainProtectionParams;
847c1972ff71080568b7288197e96e163d5a469e5fBo Zhuimport android.security.keystore.recovery.RecoveryCertPath;
8581ee34bf957dffe020442e3f0c6c06817397ebf0Robert Berryimport android.security.keystore.recovery.WrappedApplicationKey;
860916e7ca44aba5e6c89d75007da805697fdace9eDmitry Dementyevimport android.security.keystore.recovery.KeyChainSnapshot;
872397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Moralesimport android.service.gatekeeper.GateKeeperResponse;
888fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Moralesimport android.service.gatekeeper.IGateKeeperService;
8952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.text.TextUtils;
90a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xuimport android.util.ArrayMap;
91b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roosimport android.util.EventLog;
92bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport android.util.Log;
9352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.util.Slog;
941416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scullimport android.util.SparseArray;
9552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
9628939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafovimport com.android.internal.annotations.GuardedBy;
970cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xuimport com.android.internal.annotations.VisibleForTesting;
98282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wrenimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
99af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitschimport com.android.internal.notification.SystemNotificationChannels;
100072543f58037697772663ed34ee26317e9d662c5Amith Yamasaniimport com.android.internal.util.ArrayUtils;
101fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
1027374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roosimport com.android.internal.util.Preconditions;
103e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggiimport com.android.internal.widget.ICheckCredentialProgressCallback;
1047a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.ILockSettings;
1057a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.LockPatternUtils;
106fcd49f993ede363d0b17900565dfe37066362480Rubin Xuimport com.android.internal.widget.LockSettingsInternal;
1072397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Moralesimport com.android.internal.widget.VerifyCredentialResponse;
10828939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafovimport com.android.server.LocalServices;
109507d11c9353666a75fee014565f900825a907691Andrew Scullimport com.android.server.SystemService;
110507d11c9353666a75fee014565f900825a907691Andrew Scullimport com.android.server.locksettings.LockSettingsStorage.CredentialHash;
1111aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyevimport com.android.server.locksettings.LockSettingsStorage.PersistentData;
1121aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyevimport com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
113507d11c9353666a75fee014565f900825a907691Andrew Scullimport com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
114507d11c9353666a75fee014565f900825a907691Andrew Scullimport com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
1157a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey
116dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport libcore.util.HexEncoding;
117dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
118dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.io.ByteArrayOutputStream;
1192fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggiimport java.io.FileDescriptor;
120dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.io.FileNotFoundException;
121dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.io.IOException;
1223bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport java.io.PrintWriter;
123faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowleyimport java.nio.charset.StandardCharsets;
124dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.InvalidAlgorithmParameterException;
125dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.InvalidKeyException;
126dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.KeyStoreException;
127faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowleyimport java.security.MessageDigest;
128faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowleyimport java.security.NoSuchAlgorithmException;
129dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.SecureRandom;
130dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.UnrecoverableKeyException;
131dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport java.security.cert.CertificateException;
13252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.util.Arrays;
133e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scullimport java.util.ArrayList;
134187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport java.util.List;
135a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xuimport java.util.Map;
136e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scullimport java.util.NoSuchElementException;
137bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport java.util.concurrent.CountDownLatch;
138bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkeyimport java.util.concurrent.TimeUnit;
13952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
140dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.BadPaddingException;
141dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.Cipher;
142dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.IllegalBlockSizeException;
143dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.KeyGenerator;
144dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.NoSuchPaddingException;
145dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.SecretKey;
146dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Waiimport javax.crypto.spec.GCMParameterSpec;
147dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
14852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/**
1491de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu * Keeps the lock pattern/password data and related settings for each user. Used by
1501de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu * LockPatternUtils. Needs to be a service because Settings app also needs to be able to save
1511de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu * lockscreen information for secondary users.
1521de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu *
15352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * @hide
15452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */
15552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipublic class LockSettingsService extends ILockSettings.Stub {
156261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos    private static final String TAG = "LockSettingsService";
1574f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
1584f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    private static final boolean DEBUG = false;
15952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
160dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private static final int PROFILE_KEY_IV_SIZE = 12;
161dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
1627a0cc0a7fbfaae2843dd333ab8e62731bc04e2b2Paul Crowley    private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
1631de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu
16404a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu    // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
165e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu    // Do not call into ActivityManager while holding mSpManager lock.
166dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private final Object mSeparateChallengeLock = new Object();
167dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1687374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    private final DeviceProvisionedObserver mDeviceProvisionedObserver =
1697374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            new DeviceProvisionedObserver();
1707374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
1710cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final Injector mInjector;
172261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos    private final Context mContext;
1737cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu    @VisibleForTesting
1747cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu    protected final Handler mHandler;
1750cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    @VisibleForTesting
1760cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected final LockSettingsStorage mStorage;
177a7aa4d6f0b91e050c083c19459b0c8b265c92617Rakesh Iyer    private final LockSettingsStrongAuth mStrongAuth;
178a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang    private final SynchronizedStrongAuthTracker mStrongAuthTracker;
17952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
1800cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final LockPatternUtils mLockPatternUtils;
1810cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final NotificationManager mNotificationManager;
1820cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final UserManager mUserManager;
1830cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final IActivityManager mActivityManager;
1848fc2ec832f765a51c8fcd04cc89428a3ced4b605Andrew Scull    private final SyntheticPasswordManager mSpManager;
1854f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
1860cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private final KeyStore mKeyStore;
1874613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai
1881aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
1891aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
1900cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    private boolean mFirstCallToVold;
1910cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected IGateKeeperService mGateKeeperService;
192e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull    protected IAuthSecret mAuthSecretService;
1933bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
1944613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai    /**
1954613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai     * The UIDs that are used for system credential storage in keystore.
1964613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai     */
1971de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    private static final int[] SYSTEM_CREDENTIAL_UIDS = {
1981de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Process.WIFI_UID, Process.VPN_UID,
19924b89b1a4295f9c2c33fa00a4a9ea7f94d26a938Rubin Xu            Process.ROOT_UID, Process.SYSTEM_UID };
2002397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales
2014f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
2024f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    // devices. The most basic of these is to show/hide notifications about missing features until
2034f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    // the user unlocks the account and credential-encrypted storage is available.
2044f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    public static final class Lifecycle extends SystemService {
2054f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        private LockSettingsService mLockSettingsService;
2064f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2074f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        public Lifecycle(Context context) {
2084f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            super(context);
2094f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
2104f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2114f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        @Override
2124f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        public void onStart() {
213dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            AndroidKeyStoreProvider.install();
2144f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            mLockSettingsService = new LockSettingsService(getContext());
2154f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            publishBinderService("lock_settings", mLockSettingsService);
2164f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
2174f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2184f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        @Override
21960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        public void onBootPhase(int phase) {
22060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            super.onBootPhase(phase);
22160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            if (phase == PHASE_ACTIVITY_MANAGER_READY) {
22260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                mLockSettingsService.migrateOldDataAfterSystemReady();
22360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            }
22460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        }
22560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos
22660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        @Override
22785a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        public void onStartUser(int userHandle) {
22885a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            mLockSettingsService.onStartUser(userHandle);
2294f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
2304f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2314f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        @Override
2324f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        public void onUnlockUser(int userHandle) {
2334f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            mLockSettingsService.onUnlockUser(userHandle);
2344f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
2354f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2364f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        @Override
2374f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        public void onCleanupUser(int userHandle) {
2384f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            mLockSettingsService.onCleanupUser(userHandle);
2394f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
2404f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
2414f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
2420cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    @VisibleForTesting
2430cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected static class SynchronizedStrongAuthTracker
2440cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            extends LockPatternUtils.StrongAuthTracker {
245a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        public SynchronizedStrongAuthTracker(Context context) {
246a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang            super(context);
247a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        }
248a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
249a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        @Override
250a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        protected void handleStrongAuthRequiredChanged(int strongAuthFlags, int userId) {
251a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang            synchronized (this) {
252a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang                super.handleStrongAuthRequiredChanged(strongAuthFlags, userId);
253a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang            }
254a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        }
255a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
256a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        @Override
257a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        public int getStrongAuthForUser(int userId) {
258a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang            synchronized (this) {
259a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang                return super.getStrongAuthForUser(userId);
260a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang            }
261a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        }
262a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
2630cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        void register(LockSettingsStrongAuth strongAuth) {
2640cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            strongAuth.registerStrongAuthTracker(this.mStub);
265a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        }
266a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang    }
267a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
268dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    /**
269dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     * Tie managed profile to primary profile if it is in unified mode and not tied before.
270dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     *
271dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     * @param managedUserId Managed profile user Id
272dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     * @param managedUserPassword Managed profile original password (when it has separated lock).
273dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     *            NULL when it does not have a separated lock before.
274dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai     */
275dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
276dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
277dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        // Only for managed profile
2780cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
279dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return;
280dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
281dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        // Do not tie managed profile when work challenge is enabled
282dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
283dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return;
284dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
285dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        // Do not tie managed profile to parent when it's done already
286dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (mStorage.hasChildProfileLock(managedUserId)) {
287dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return;
288dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
289dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        // Do not tie it to parent when parent does not have a screen lock
290dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        final int parentId = mUserManager.getProfileParent(managedUserId).id;
291a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        if (!isUserSecure(parentId)) {
292dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
293dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return;
294dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
295bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        // Do not tie when the parent has no SID (but does have a screen lock).
296bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        // This can only happen during an upgrade path where SID is yet to be
297bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        // generated when the user unlocks for the first time.
298bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        try {
299bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu            if (getGateKeeperService().getSecureUserId(parentId) == 0) {
300bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu                return;
301bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu            }
302bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        } catch (RemoteException e) {
303bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu            Slog.e(TAG, "Failed to talk to GateKeeper service", e);
304bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu            return;
305bfc7faaf353ea75ab04e986edbc79478679d40f6Rubin Xu        }
306dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
307dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] randomLockSeed = new byte[] {};
308dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
309dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
310dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
3117374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
3121de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            setLockCredentialInternal(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
3137374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    managedUserPassword, quality, managedUserId);
3147b9eb419e35f12963eeea119b51a241146029b74Ricky Wai            // We store a private credential for the managed user that's unlocked by the primary
3157b9eb419e35f12963eeea119b51a241146029b74Ricky Wai            // account holder's credential. As such, the user will never be prompted to enter this
3167b9eb419e35f12963eeea119b51a241146029b74Ricky Wai            // password directly, so we always store a password.
3177374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, managedUserId);
318e61672ab087df4857a4f0923258b945800046589Zach Jang            tieProfileLockToParent(managedUserId, newPassword);
319dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (NoSuchAlgorithmException | RemoteException e) {
320dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            Slog.e(TAG, "Fail to tie managed profile", e);
321dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            // Nothing client can do to fix this issue, so we do not throw exception out
322dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
323dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
324dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
3250cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    static class Injector {
3260cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3270cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        protected Context mContext;
3280cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3290cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public Injector(Context context) {
3300cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            mContext = context;
3310cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3320cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3330cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public Context getContext() {
3340cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return mContext;
3350cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3360cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3370cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public Handler getHandler() {
3380cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return new Handler();
3390cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3400cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3410cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public LockSettingsStorage getStorage() {
3420cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            final LockSettingsStorage storage = new LockSettingsStorage(mContext);
3430cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            storage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
3440cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                @Override
3450cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                public void initialize(SQLiteDatabase db) {
3460cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                    // Get the lockscreen default from a system property, if available
3470cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                    boolean lockScreenDisable = SystemProperties.getBoolean(
3480cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                            "ro.lockscreen.disable.default", false);
3490cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                    if (lockScreenDisable) {
3500cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                        storage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
3510cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                    }
3520cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                }
3530cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            });
3540cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return storage;
3550cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3560cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3570cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public LockSettingsStrongAuth getStrongAuth() {
3580cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return new LockSettingsStrongAuth(mContext);
3590cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3600cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3610cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public SynchronizedStrongAuthTracker getStrongAuthTracker() {
3620cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return new SynchronizedStrongAuthTracker(mContext);
3630cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3640cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3650cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public IActivityManager getActivityManager() {
3660cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return ActivityManager.getService();
3670cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3680cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3690cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public LockPatternUtils getLockPatternUtils() {
3700cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return new LockPatternUtils(mContext);
3710cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3720cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3730cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public NotificationManager getNotificationManager() {
3740cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
3750cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3760cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3770cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public UserManager getUserManager() {
3780cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
3790cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3800cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
3818b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        public DevicePolicyManager getDevicePolicyManager() {
3828b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu            return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
3838b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        }
3848b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu
3850cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public KeyStore getKeyStore() {
3860cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return KeyStore.getInstance();
3870cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
3880cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
38929b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev        public RecoverableKeyStoreManager getRecoverableKeyStoreManager(KeyStore keyStore) {
39029b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev            return RecoverableKeyStoreManager.getInstance(mContext, keyStore);
3911aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev        }
3921aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
3930cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        public IStorageManager getStorageManager() {
3940cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            final IBinder service = ServiceManager.getService("mount");
3950cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            if (service != null) {
3960cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                return IStorageManager.Stub.asInterface(service);
3970cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            }
3980cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            return null;
3990cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        }
4003bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
4013bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
4022adc263ce97ae6c8291653490868879841d31a63Adrian Roos            return new SyntheticPasswordManager(getContext(), storage, getUserManager());
4033bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
4043bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
4053bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        public int binderGetCallingUid() {
4063bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            return Binder.getCallingUid();
4073bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
4080cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    }
4090cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
41052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public LockSettingsService(Context context) {
4110cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        this(new Injector(context));
4120cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    }
413de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
4140cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    @VisibleForTesting
4150cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected LockSettingsService(Injector injector) {
4160cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mInjector = injector;
4170cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mContext = injector.getContext();
4180cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mKeyStore = injector.getKeyStore();
41929b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev        mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager(mKeyStore);
4200cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mHandler = injector.getHandler();
4210cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mStrongAuth = injector.getStrongAuth();
4220cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mActivityManager = injector.getActivityManager();
4230cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu
4240cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mLockPatternUtils = injector.getLockPatternUtils();
425945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        mFirstCallToVold = true;
426f0246a8a14d69680d1776620e75a485cf963e574Robin Lee
427f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        IntentFilter filter = new IntentFilter();
428f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        filter.addAction(Intent.ACTION_USER_ADDED);
4293dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos        filter.addAction(Intent.ACTION_USER_STARTING);
430db0f76e1d85f8cb878a9540ac1b692636f9fd89eAdrian Roos        filter.addAction(Intent.ACTION_USER_REMOVED);
4310cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
4320cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu                null, null);
433a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
4340cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mStorage = injector.getStorage();
4350cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mNotificationManager = injector.getNotificationManager();
4360cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mUserManager = injector.getUserManager();
4370cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mStrongAuthTracker = injector.getStrongAuthTracker();
4380cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        mStrongAuthTracker.register(mStrongAuth);
4393bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
4403bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        mSpManager = injector.getSyntheticPasswordManager(mStorage);
441fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
442fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        LocalServices.addService(LockSettingsInternal.class, new LocalService());
4434f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
4444f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
4454f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    /**
4461de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * If the account is credential-encrypted, show notification requesting the user to unlock the
4471de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * device.
4484f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller     */
44985a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull    private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
45085a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        final UserInfo user = mUserManager.getUserInfo(userId);
45185a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        if (!user.isManagedProfile()) {
45285a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            // When the user is locked, we communicate it loud-and-clear
45385a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            // on the lockscreen; we only show a notification below for
45485a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            // locked managed profiles.
45585a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            return;
45685a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        }
45785a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull
45885a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        final UserHandle userHandle = user.getUserHandle();
459a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        final boolean isSecure = isUserSecure(userId);
46085a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
46185a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            UserInfo parent = mUserManager.getProfileParent(userId);
46285a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull            if (parent != null &&
46385a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull                    mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
46485a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull                    !mUserManager.isQuietModeEnabled(userHandle)) {
46585a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull                // Only show notifications for managed profiles once their parent
46685a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull                // user is unlocked.
46785a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull                showEncryptionNotificationForProfile(userHandle);
4684f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller            }
4694f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        }
4704f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
4714f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
472b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy    private void showEncryptionNotificationForProfile(UserHandle user) {
473b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        Resources r = mContext.getResources();
474b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        CharSequence title = r.getText(
475b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy                com.android.internal.R.string.user_encrypted_title);
476b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        CharSequence message = r.getText(
477b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy                com.android.internal.R.string.profile_encrypted_message);
478b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        CharSequence detail = r.getText(
479b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy                com.android.internal.R.string.profile_encrypted_detail);
480b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy
481b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
4821de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
4831de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                user.getIdentifier());
484b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        if (unlockIntent == null) {
485b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy            return;
486b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        }
4871de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        unlockIntent.setFlags(
4881de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
489b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
490b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy                PendingIntent.FLAG_UPDATE_CURRENT);
4914f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
492b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        showEncryptionNotification(user, title, message, detail, intent);
493b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy    }
494b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy
4951de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    private void showEncryptionNotification(UserHandle user, CharSequence title,
4961de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            CharSequence message, CharSequence detail, PendingIntent intent) {
497b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy        if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
4984a39936d3669696dc6a25a4023daf7a7e4b158efJeff Sharkey
4994a39936d3669696dc6a25a4023daf7a7e4b158efJeff Sharkey        // Suppress all notifications on non-FBE devices for now
5004a39936d3669696dc6a25a4023daf7a7e4b158efJeff Sharkey        if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
5014a39936d3669696dc6a25a4023daf7a7e4b158efJeff Sharkey
502af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch        Notification notification =
503af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                new Notification.Builder(mContext, SystemNotificationChannels.SECURITY)
504af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
505af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setWhen(0)
506af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setOngoing(true)
507af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setTicker(title)
508af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setColor(mContext.getColor(
509af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                                com.android.internal.R.color.system_notification_accent_color))
510af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setContentTitle(title)
511af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setContentText(message)
512af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setSubText(detail)
513af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setVisibility(Notification.VISIBILITY_PUBLIC)
514af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .setContentIntent(intent)
515af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                        .build();
516282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren        mNotificationManager.notifyAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
517282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren            notification, user);
5184f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
5194f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
52085a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull    private void hideEncryptionNotification(UserHandle userHandle) {
5211de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
522282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren        mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
523282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren            userHandle);
5244f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
5254f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
5264f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    public void onCleanupUser(int userId) {
5274f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller        hideEncryptionNotification(new UserHandle(userId));
5280da8983bc5e58714675b8cd01dcae82b0b9baa16Rubin Xu        // User is stopped with its CE key evicted. Require strong auth next time to be able to
5290da8983bc5e58714675b8cd01dcae82b0b9baa16Rubin Xu        // unlock the user's storage. Use STRONG_AUTH_REQUIRED_AFTER_BOOT since stopping and
5300da8983bc5e58714675b8cd01dcae82b0b9baa16Rubin Xu        // restarting a user later is equivalent to rebooting the device.
5310da8983bc5e58714675b8cd01dcae82b0b9baa16Rubin Xu        requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_BOOT, userId);
5324f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    }
5334f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller
53485a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull    public void onStartUser(final int userId) {
53585a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull        maybeShowEncryptionNotificationForUser(userId);
53685a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull    }
53785a63bc1a06870b5a86926b0bce94a2bf559e3f0Andrew Scull
5380acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    /**
5390acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov     * Check if profile got unlocked but the keystore is still locked. This happens on full disk
5400acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov     * encryption devices since the profile may not yet be running when we consider unlocking it
5410acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov     * during the normal flow. In this case unlock the keystore for the profile.
5420acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov     */
5430acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    private void ensureProfileKeystoreUnlocked(int userId) {
5440acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov        final KeyStore ks = KeyStore.getInstance();
5450acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov        if (ks.state(userId) == KeyStore.State.LOCKED
5460acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                && tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) {
5470acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore");
5480acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            try {
5490acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                // If boot took too long and the password in vold got expired, parent keystore will
5500acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                // be still locked, we ignore this case since the user will be prompted to unlock
5510acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                // the device after boot.
5520acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */);
5530acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            } catch (RemoteException e) {
5540acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                Slog.e(TAG, "Failed to unlock child profile");
5550acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            }
5560acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov        }
5570acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    }
5580acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov
559b0cdf3845fd33cc40a929a2b9b882bf0a3a994d3Ricky Wai    public void onUnlockUser(final int userId) {
560a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        // Perform tasks which require locks in LSS on a handler, as we are callbacks from
561a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        // ActivityManager.unlockUser()
562a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        mHandler.post(new Runnable() {
563a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            @Override
564a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            public void run() {
5650acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                ensureProfileKeystoreUnlocked(userId);
566a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                // Hide notification first, as tie managed profile lock takes time
567a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                hideEncryptionNotification(new UserHandle(userId));
568a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu
569a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                // Now we have unlocked the parent user we should show notifications
570a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                // about any profiles that exist.
571a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                List<UserInfo> profiles = mUserManager.getProfiles(userId);
572a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                for (int i = 0; i < profiles.size(); i++) {
573a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    UserInfo profile = profiles.get(i);
574a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    final boolean isSecure = isUserSecure(profile.id);
575a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    if (isSecure && profile.isManagedProfile()) {
576a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        UserHandle userHandle = profile.getUserHandle();
577a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
578a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                                !mUserManager.isQuietModeEnabled(userHandle)) {
579a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                            showEncryptionNotificationForProfile(userHandle);
580a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        }
581a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    }
582b0cdf3845fd33cc40a929a2b9b882bf0a3a994d3Ricky Wai                }
583b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy
584a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                if (mUserManager.getUserInfo(userId).isManagedProfile()) {
585a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    tieManagedProfileLockIfNecessary(userId, null);
586b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy                }
587f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull
588f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                // If the user doesn't have a credential, try and derive their secret for the
589f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                // AuthSecret HAL. The secret will have been enrolled if the user previously set a
590f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                // credential and still needs to be passed to the HAL once that credential is
591f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                // removed.
592f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                if (mUserManager.getUserInfo(userId).isPrimary() && !isUserSecure(userId)) {
593f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                    tryDeriveAuthTokenForUnsecuredPrimaryUser(userId);
594f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                }
595b1b302660cf5b1b1c5b342cc90eca93b8f66890cKenny Guy            }
596a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        });
59752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
59852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
599f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull    private void tryDeriveAuthTokenForUnsecuredPrimaryUser(@UserIdInt int userId) {
600f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull        synchronized (mSpManager) {
601f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            // Make sure the user has a synthetic password to derive
602f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
603f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                return;
604f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            }
605f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull
606f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            try {
607f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                final long handle = getSyntheticPasswordHandleLocked(userId);
608f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                final String noCredential = null;
609f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                AuthenticationResult result =
610f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                        mSpManager.unwrapPasswordBasedSyntheticPassword(
611f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                                getGateKeeperService(), handle, noCredential, userId, null);
612f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                if (result.authToken != null) {
613f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                    Slog.i(TAG, "Retrieved auth token for user " + userId);
614f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                    onAuthTokenKnownForUser(userId, result.authToken);
615f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                } else {
616f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                    Slog.e(TAG, "Auth token not available for user " + userId);
617f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                }
618f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            } catch (RemoteException e) {
619f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull                Slog.e(TAG, "Failure retrieving auth token", e);
620f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull            }
621f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull        }
622f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull    }
623f49794b512745ca3b3a26221d36291440bc417e5Andrew Scull
624f0246a8a14d69680d1776620e75a485cf963e574Robin Lee    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
625f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        @Override
626f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        public void onReceive(Context context, Intent intent) {
6271096cf8664963a136a325b2bc511c8f381b9ba77Robin Lee            if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
62883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker                // Notify keystore that a new user was added.
629f0246a8a14d69680d1776620e75a485cf963e574Robin Lee                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
630f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani                if (userHandle > UserHandle.USER_SYSTEM) {
631f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani                    removeUser(userHandle, /* unknownUser= */ true);
632f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani                }
63349d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee                final KeyStore ks = KeyStore.getInstance();
634dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
63583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker                final int parentHandle = parentInfo != null ? parentInfo.id : -1;
63683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker                ks.onUserAdded(userHandle, parentHandle);
6373dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos            } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
6383dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
6393dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos                mStorage.prefetchUser(userHandle);
640db0f76e1d85f8cb878a9540ac1b692636f9fd89eAdrian Roos            } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
641db0f76e1d85f8cb878a9540ac1b692636f9fd89eAdrian Roos                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
642db0f76e1d85f8cb878a9540ac1b692636f9fd89eAdrian Roos                if (userHandle > 0) {
643f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani                    removeUser(userHandle, /* unknownUser= */ false);
644db0f76e1d85f8cb878a9540ac1b692636f9fd89eAdrian Roos                }
645f0246a8a14d69680d1776620e75a485cf963e574Robin Lee            }
646f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        }
647f0246a8a14d69680d1776620e75a485cf963e574Robin Lee    };
648f0246a8a14d69680d1776620e75a485cf963e574Robin Lee
6494f93c58b393bad5d0bcc4237fa66f14fb9c9ee28Jim Miller    @Override // binder interface
65052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public void systemReady() {
651b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
652b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos            EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), "");  // SafetyNet
653b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        }
654b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        checkWritePermission(UserHandle.USER_SYSTEM);
65552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        migrateOldData();
656301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        try {
657301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            getGateKeeperService();
6587b7424b0b7c5b6be09ed6fb0ec70272574dfe718Rubin Xu            mSpManager.initWeaverService();
659301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        } catch (RemoteException e) {
660301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
661301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        }
662e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        // Find the AuthSecret HAL
663e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        try {
664e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            mAuthSecretService = IAuthSecret.getService();
665e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        } catch (NoSuchElementException e) {
666e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            Slog.i(TAG, "Device doesn't implement AuthSecret HAL");
667e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        } catch (RemoteException e) {
668e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            Slog.w(TAG, "Failed to get AuthSecret HAL", e);
669e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        }
6707374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        mDeviceProvisionedObserver.onSystemReady();
6717c69636c9a406265e1da368f3edfd8fb9651132cXiaohui Chen        // TODO: maybe skip this for split system user mode.
6727c69636c9a406265e1da368f3edfd8fb9651132cXiaohui Chen        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
6734dc098aed14cf42a343932d2074025e8caf16febKevin Chyn        mStrongAuth.systemReady();
67452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
67552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
67652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private void migrateOldData() {
677fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // These Settings moved before multi-user was enabled, so we only have to do it for the
678fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // root user.
679fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        if (getString("migrated", null, 0) == null) {
680fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final ContentResolver cr = mContext.getContentResolver();
681fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            for (String validSetting : VALID_SETTINGS) {
682fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                String value = Settings.Secure.getString(cr, validSetting);
683fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (value != null) {
684fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    setString(validSetting, value, 0);
685187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller                }
68652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
687fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            // No need to move the password / pattern files. They're already in the right place.
688fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            setString("migrated", "true", 0);
689fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            Slog.i(TAG, "Migrated lock settings to new location");
690fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        }
691fe354477c186090165d79357d07b7047ef86cba4Rubin Xu
692fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // These Settings changed after multi-user was enabled, hence need to be moved per user.
693fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        if (getString("migrated_user_specific", null, 0) == null) {
694fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final ContentResolver cr = mContext.getContentResolver();
695fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            List<UserInfo> users = mUserManager.getUsers();
696fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            for (int user = 0; user < users.size(); user++) {
697fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // Migrate owner info
698fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                final int userId = users.get(user).id;
699fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
700fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
701fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (!TextUtils.isEmpty(ownerInfo)) {
702fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    setString(OWNER_INFO, ownerInfo, userId);
703fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
704fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                }
70552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
706fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // Migrate owner info enabled. Note there was a bug where older platforms only
707fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // stored this value if the checkbox was toggled at least once. The code detects
708fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // this case by handling the exception.
709fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
710fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                boolean enabled;
711fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                try {
712fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
713fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    enabled = ivalue != 0;
714fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
715fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                } catch (SettingNotFoundException e) {
716fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    // Setting was never stored. Store it if the string is not empty.
717325c56741a4896741f3e3c5894c20ee55090a31bJim Miller                    if (!TextUtils.isEmpty(ownerInfo)) {
718fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        setLong(OWNER_INFO_ENABLED, 1, userId);
7192d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller                    }
72052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                }
721fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
72252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani            }
723fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            // No need to move the password / pattern files. They're already in the right place.
724fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            setString("migrated_user_specific", "true", 0);
725fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            Slog.i(TAG, "Migrated per-user lock settings to new location");
726fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        }
727230635efe7ffb09d6dc56bfd9193aa1d89c8a898Adrian Roos
728fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // Migrates biometric weak such that the fallback mechanism becomes the primary.
729fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        if (getString("migrated_biometric_weak", null, 0) == null) {
730fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            List<UserInfo> users = mUserManager.getUsers();
731fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            for (int i = 0; i < users.size(); i++) {
732fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                int userId = users.get(i).id;
733fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
734fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
735fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        userId);
736fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
737fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
738fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        userId);
739fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
740fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
741fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                            alternateType,
742230635efe7ffb09d6dc56bfd9193aa1d89c8a898Adrian Roos                            userId);
743230635efe7ffb09d6dc56bfd9193aa1d89c8a898Adrian Roos                }
744fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
745fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
746fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        userId);
747230635efe7ffb09d6dc56bfd9193aa1d89c8a898Adrian Roos            }
748fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            setString("migrated_biometric_weak", "true", 0);
749fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
750fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        }
7514383058bf4956f3a3132a58f0904087fdd569526Adrian Roos
752fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // Migrates lockscreen.disabled. Prior to M, the flag was ignored when more than one
753fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // user was present on the system, so if we're upgrading to M and there is more than one
754fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // user we disable the flag to remain consistent.
755fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        if (getString("migrated_lockscreen_disabled", null, 0) == null) {
756fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final List<UserInfo> users = mUserManager.getUsers();
757fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final int userCount = users.size();
758fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            int switchableUsers = 0;
759fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            for (int i = 0; i < userCount; i++) {
760fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (users.get(i).supportsSwitchTo()) {
761fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    switchableUsers++;
7624383058bf4956f3a3132a58f0904087fdd569526Adrian Roos                }
763fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            }
7644383058bf4956f3a3132a58f0904087fdd569526Adrian Roos
765fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            if (switchableUsers > 1) {
766fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                for (int i = 0; i < userCount; i++) {
767fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    int id = users.get(i).id;
7684383058bf4956f3a3132a58f0904087fdd569526Adrian Roos
769fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
770fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
7714383058bf4956f3a3132a58f0904087fdd569526Adrian Roos                    }
7724383058bf4956f3a3132a58f0904087fdd569526Adrian Roos                }
7734383058bf4956f3a3132a58f0904087fdd569526Adrian Roos            }
7747b9eb419e35f12963eeea119b51a241146029b74Ricky Wai
775fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            setString("migrated_lockscreen_disabled", "true", 0);
776fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            Slog.i(TAG, "Migrated lockscreen disabled flag");
777fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        }
778fe354477c186090165d79357d07b7047ef86cba4Rubin Xu
779fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        final List<UserInfo> users = mUserManager.getUsers();
780fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        for (int i = 0; i < users.size(); i++) {
781fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final UserInfo userInfo = users.get(i);
782fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
783fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // When managed profile has a unified lock, the password quality stored has 2
784fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // possibilities only.
785fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
786fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
787fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
788fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                // unified lock.
789fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
790fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
791fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
792fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    // Only possible when it's upgraded from nyc dp3
793fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    Slog.i(TAG, "Migrated tied profile lock type");
794fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
795fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                            DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
796fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
797fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    // It should not happen
798fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    Slog.e(TAG, "Invalid tied profile lock type: " + quality);
7997b9eb419e35f12963eeea119b51a241146029b74Ricky Wai                }
800fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            }
801fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            try {
802fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
803fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                java.security.KeyStore keyStore =
804fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                        java.security.KeyStore.getInstance("AndroidKeyStore");
805fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                keyStore.load(null);
806fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                if (keyStore.containsAlias(alias)) {
807fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    keyStore.deleteEntry(alias);
80897c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                }
809fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            } catch (KeyStoreException | NoSuchAlgorithmException |
810fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                    CertificateException | IOException e) {
811fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                Slog.e(TAG, "Unable to remove tied profile key", e);
8127b9eb419e35f12963eeea119b51a241146029b74Ricky Wai            }
813fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        }
814eb2e45369a92548e34b664d466d0578f966f7cefGreg Plesur
815fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        boolean isWatch = mContext.getPackageManager().hasSystemFeature(
816fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                PackageManager.FEATURE_WATCH);
817fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts
818fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        // and device management the lockscreen must be re-enabled now for users that upgrade.
819fe354477c186090165d79357d07b7047ef86cba4Rubin Xu        if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
820fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            final int userCount = users.size();
821fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            for (int i = 0; i < userCount; i++) {
822fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                int id = users.get(i).id;
823fe354477c186090165d79357d07b7047ef86cba4Rubin Xu                setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
824eb2e45369a92548e34b664d466d0578f966f7cefGreg Plesur            }
825fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            setString("migrated_wear_lockscreen_disabled", "true", 0);
826fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
82752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
82852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
82952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
83060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    private void migrateOldDataAfterSystemReady() {
83160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        try {
83260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            // Migrate the FRP credential to the persistent data block
8332adc263ce97ae6c8291653490868879841d31a63Adrian Roos            if (LockPatternUtils.frpCredentialEnabled(mContext)
8342adc263ce97ae6c8291653490868879841d31a63Adrian Roos                    && !getBoolean("migrated_frp", false, 0)) {
83560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                migrateFrpCredential();
83660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                setBoolean("migrated_frp", true, 0);
83760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                Slog.i(TAG, "Migrated migrated_frp.");
83860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            }
83960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        } catch (RemoteException e) {
84060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            Slog.e(TAG, "Unable to migrateOldDataAfterSystemReady", e);
84160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        }
84260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    }
84360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos
84460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    /**
84560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * Migrate the credential for the FRP credential owner user if the following are satisfied:
84660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * - the user has a secure credential
84760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * - the FRP credential is not set up
84860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * - the credential is based on a synthetic password.
84960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     */
85060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    private void migrateFrpCredential() throws RemoteException {
85160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        if (mStorage.readPersistentDataBlock() != PersistentData.NONE) {
85260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            return;
85360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        }
85460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        for (UserInfo userInfo : mUserManager.getUsers()) {
8552adc263ce97ae6c8291653490868879841d31a63Adrian Roos            if (userOwnsFrpCredential(mContext, userInfo) && isUserSecure(userInfo.id)) {
85660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                synchronized (mSpManager) {
85760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                    if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) {
85860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                        int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
85960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
86060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos
86160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                        mSpManager.migrateFrpPasswordLocked(
86260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                                getSyntheticPasswordHandleLocked(userInfo.id),
86360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                                userInfo,
86460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                                redactActualQualityToMostLenientEquivalentQuality(actualQuality));
86560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                    }
86660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                }
86760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                return;
86860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            }
86960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        }
87060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    }
87160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos
87260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    /**
87360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * Returns the lowest password quality that still presents the same UI for entering it.
87460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     *
87560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * For the FRP credential, we do not want to leak the actual quality of the password, only what
87660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * kind of UI it requires. However, when migrating, we only know the actual quality, not the
87760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * originally requested quality; since this is only used to determine what input variant to
87860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     * present to the user, we just assume the lowest possible quality was requested.
87960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos     */
88060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    private int redactActualQualityToMostLenientEquivalentQuality(int quality) {
88160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        switch (quality) {
88260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
88360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
88460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
88560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                return DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
88660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
88760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
88860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
88960dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
89060dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
89160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
89260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
89360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos            default:
89460dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                return quality;
89560dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        }
89660dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    }
89760dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos
8985ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller    private final void checkWritePermission(int userId) {
899505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
90052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
90152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
9025ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller    private final void checkPasswordReadPermission(int userId) {
903505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead");
90452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
90552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
906b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos    private final void checkPasswordHavePermission(int userId) {
907b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
908b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos            EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), "");  // SafetyNet
909b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        }
910b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
911b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos    }
912b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos
913158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller    private final void checkReadPermission(String requestedKey, int userId) {
91452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        final int callingUid = Binder.getCallingUid();
915001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos
9166d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov        for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
9176d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov            String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
9186d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
919158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                    != PackageManager.PERMISSION_GRANTED) {
920158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                throw new SecurityException("uid=" + callingUid
9216d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov                        + " needs permission " + READ_CONTACTS + " to read "
922158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller                        + requestedKey + " for user " + userId);
923158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller            }
92452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        }
925001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos
926001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos        for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
927001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos            String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
928001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
929001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos                    != PackageManager.PERMISSION_GRANTED) {
930001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos                throw new SecurityException("uid=" + callingUid
931001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos                        + " needs permission " + PERMISSION + " to read "
932001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos                        + requestedKey + " for user " + userId);
933001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos            }
934001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos        }
93552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
93652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
93752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
938fe354477c186090165d79357d07b7047ef86cba4Rubin Xu    public boolean getSeparateProfileChallengeEnabled(int userId) {
9397f405f170f66d201f893a2f29866f528f0ec7fc8Ricky Wai        checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
940dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        synchronized (mSeparateChallengeLock) {
941dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
942dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
943dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
944dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
945dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    @Override
946dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
947fe354477c186090165d79357d07b7047ef86cba4Rubin Xu            String managedUserPassword) {
9487f405f170f66d201f893a2f29866f528f0ec7fc8Ricky Wai        checkWritePermission(userId);
949dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        synchronized (mSeparateChallengeLock) {
95028939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword);
95128939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        }
95228939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        notifySeparateProfileChallengeChanged(userId);
95328939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov    }
95428939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov
95528939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov    @GuardedBy("mSeparateChallengeLock")
95628939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov    private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId, boolean enabled,
95728939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            String managedUserPassword) {
95828939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
95928939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        if (enabled) {
96028939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            mStorage.removeChildProfileLock(userId);
96128939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            removeKeystoreProfileKey(userId);
96228939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        } else {
96328939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            tieManagedProfileLockIfNecessary(userId, managedUserPassword);
964dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
965dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
966dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
96728939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov    private void notifySeparateProfileChallengeChanged(int userId) {
9687f4ff4c17f3668080dcefa1f8acbbff5df184f0bAndrew Scull        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
9697f4ff4c17f3668080dcefa1f8acbbff5df184f0bAndrew Scull                DevicePolicyManagerInternal.class);
9707f4ff4c17f3668080dcefa1f8acbbff5df184f0bAndrew Scull        if (dpmi != null) {
9717f4ff4c17f3668080dcefa1f8acbbff5df184f0bAndrew Scull            dpmi.reportSeparateProfileChallengeChanged(userId);
9727f4ff4c17f3668080dcefa1f8acbbff5df184f0bAndrew Scull        }
97328939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov    }
97428939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov
975dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    @Override
976fe354477c186090165d79357d07b7047ef86cba4Rubin Xu    public void setBoolean(String key, boolean value, int userId) {
97752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
978261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        setStringUnchecked(key, userId, value ? "1" : "0");
97952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
98052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
98152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
982fe354477c186090165d79357d07b7047ef86cba4Rubin Xu    public void setLong(String key, long value, int userId) {
98352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
984261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        setStringUnchecked(key, userId, Long.toString(value));
98552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
98652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
98752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
988fe354477c186090165d79357d07b7047ef86cba4Rubin Xu    public void setString(String key, String value, int userId) {
98952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        checkWritePermission(userId);
990261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        setStringUnchecked(key, userId, value);
991261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos    }
99252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
993261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos    private void setStringUnchecked(String key, int userId, String value) {
9947374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        Preconditions.checkArgument(userId != USER_FRP, "cannot store lock settings for FRP user");
9957374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
996261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        mStorage.writeKeyValue(key, value, userId);
997072543f58037697772663ed34ee26317e9d662c5Amith Yamasani        if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
998072543f58037697772663ed34ee26317e9d662c5Amith Yamasani            BackupManager.dataChanged("com.android.providers.settings");
999072543f58037697772663ed34ee26317e9d662c5Amith Yamasani        }
100052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
100152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
100252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
100360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    public boolean getBoolean(String key, boolean defaultValue, int userId) {
1004158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
10059dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos        String value = getStringUnchecked(key, null, userId);
100652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return TextUtils.isEmpty(value) ?
100752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani                defaultValue : (value.equals("1") || value.equals("true"));
100852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
100952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
101052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
101160dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    public long getLong(String key, long defaultValue, int userId) {
1012158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
10139dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos        String value = getStringUnchecked(key, null, userId);
101452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
101552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
101652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
101752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
101860dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos    public String getString(String key, String defaultValue, int userId) {
1019158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller        checkReadPermission(key, userId);
10209dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos        return getStringUnchecked(key, defaultValue, userId);
10219dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos    }
10229dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos
10239dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos    public String getStringUnchecked(String key, String defaultValue, int userId) {
10249dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos        if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
10257811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos            long ident = Binder.clearCallingIdentity();
10267811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos            try {
10277811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos                return mLockPatternUtils.isLockPatternEnabled(userId) ? "1" : "0";
10287811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos            } finally {
10297811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos                Binder.restoreCallingIdentity(ident);
10307811d9f5095a343acd218f4bb0a0e9e8f480b401Adrian Roos            }
10319dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos        }
10329dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos
10337374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        if (userId == USER_FRP) {
10347374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            return getFrpStringUnchecked(key);
10357374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
10367374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
10374614596a395b6c86fff3f35a07edda2e848d743cBryce Lee        if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
10384614596a395b6c86fff3f35a07edda2e848d743cBryce Lee            key = Settings.Secure.LOCK_PATTERN_ENABLED;
10394614596a395b6c86fff3f35a07edda2e848d743cBryce Lee        }
10404614596a395b6c86fff3f35a07edda2e848d743cBryce Lee
1041261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        return mStorage.readKeyValue(key, defaultValue, userId);
104252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
104352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
10447374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    private String getFrpStringUnchecked(String key) {
10457374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        if (LockPatternUtils.PASSWORD_TYPE_KEY.equals(key)) {
10467374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            return String.valueOf(readFrpPasswordQuality());
10477374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
10487374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        return null;
10497374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    }
10507374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
10517374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    private int readFrpPasswordQuality() {
10527374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        return mStorage.readPersistentDataBlock().qualityForUi;
10537374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    }
10547374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
10554f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roos    @Override
105652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public boolean havePassword(int userId) throws RemoteException {
1057b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        checkPasswordHavePermission(userId);
10583bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronized (mSpManager) {
10593bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
10603bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                long handle = getSyntheticPasswordHandleLocked(userId);
10613bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                return mSpManager.getCredentialType(handle, userId) ==
10623bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                        LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
10633bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
10643bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
106552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        // Do we need a permissions check here?
1066261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        return mStorage.hasPassword(userId);
106752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
106852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
106952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
107052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    public boolean havePattern(int userId) throws RemoteException {
1071b953e188d005a8bce937577d8b7fe16eec9d7a99Adrian Roos        checkPasswordHavePermission(userId);
10723bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronized (mSpManager) {
10733bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
10743bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                long handle = getSyntheticPasswordHandleLocked(userId);
10753bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                return mSpManager.getCredentialType(handle, userId) ==
10763bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                        LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
10773bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
10783bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
107952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani        // Do we need a permissions check here?
1080261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        return mStorage.hasPattern(userId);
108152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
108252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
1083a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    private boolean isUserSecure(int userId) {
10843bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronized (mSpManager) {
1085fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
1086fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                long handle = getSyntheticPasswordHandleLocked(userId);
1087fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                return mSpManager.getCredentialType(handle, userId) !=
1088fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                        LockPatternUtils.CREDENTIAL_TYPE_NONE;
10893bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
10903bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
1091a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        return mStorage.hasCredential(userId);
1092a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    }
1093a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu
1094a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    private void setKeystorePassword(String password, int userHandle) {
1095f0246a8a14d69680d1776620e75a485cf963e574Robin Lee        final KeyStore ks = KeyStore.getInstance();
1096dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        ks.onUserPasswordChanged(userHandle, password);
1097a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
1098a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
1099a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    private void unlockKeystore(String password, int userHandle) {
1100dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
1101a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        final KeyStore ks = KeyStore.getInstance();
1102dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        ks.unlock(userHandle, password);
1103dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1104dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
11050cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    @VisibleForTesting
11060cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected String getDecryptedPasswordForTiedProfile(int userId)
1107dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            throws KeyStoreException, UnrecoverableKeyException,
1108dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
1109dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
1110dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            CertificateException, IOException {
11114613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        if (DEBUG) Slog.v(TAG, "Get child profile decrytped key");
1112dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] storedData = mStorage.readChildProfileLock(userId);
1113dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (storedData == null) {
1114dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            throw new FileNotFoundException("Child profile lock file not found");
1115dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1116dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
1117dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
1118dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                storedData.length);
1119dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] decryptionResult;
1120dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1121dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        keyStore.load(null);
1122dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        SecretKey decryptionKey = (SecretKey) keyStore.getKey(
1123d398244513c62c9ea14a0f1c6ffef832e803c16fRicky Wai                LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId, null);
1124dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1125dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
1126dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
1127dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1128dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
1129dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        decryptionResult = cipher.doFinal(encryptedPassword);
1130dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        return new String(decryptionResult, StandardCharsets.UTF_8);
1131dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1132f0246a8a14d69680d1776620e75a485cf963e574Robin Lee
11330acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated)
11340acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            throws RemoteException {
1135dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
11361de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
11371de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
11381de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    false, 0 /* no challenge */, profileHandle, null /* progressCallback */);
1139dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1140dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                | NoSuchAlgorithmException | NoSuchPaddingException
1141dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                | InvalidAlgorithmParameterException | IllegalBlockSizeException
1142dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                | BadPaddingException | CertificateException | IOException e) {
1143dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (e instanceof FileNotFoundException) {
1144dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                Slog.i(TAG, "Child profile key not found");
11450acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov            } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) {
11460acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                Slog.i(TAG, "Parent keystore seems locked, ignoring");
11470a587d2840ca105746a9e14d018dc8ec2b3442beClara Bayarri            } else {
1148dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                Slog.e(TAG, "Failed to decrypt child profile key", e);
11490a587d2840ca105746a9e14d018dc8ec2b3442beClara Bayarri            }
1150de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller        }
1151de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    }
1152de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
1153faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    private void unlockUser(int userId, byte[] token, byte[] secret) {
1154bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        // TODO: make this method fully async so we can update UI with progress strings
1155bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        final CountDownLatch latch = new CountDownLatch(1);
1156bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        final IProgressListener listener = new IProgressListener.Stub() {
1157bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            @Override
1158bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            public void onStarted(int id, Bundle extras) throws RemoteException {
1159fd24108ca9876ac4f3598cf06464b78b61f32a96Jeff Sharkey                Log.d(TAG, "unlockUser started");
1160bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            }
1161bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
1162bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            @Override
1163bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
1164fd24108ca9876ac4f3598cf06464b78b61f32a96Jeff Sharkey                Log.d(TAG, "unlockUser progress " + progress);
1165bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            }
1166bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
1167bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            @Override
1168bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            public void onFinished(int id, Bundle extras) throws RemoteException {
1169fd24108ca9876ac4f3598cf06464b78b61f32a96Jeff Sharkey                Log.d(TAG, "unlockUser finished");
1170bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey                latch.countDown();
1171bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            }
1172bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        };
1173bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
11748924e8759f9a8cffb5ad538ca40a7826793aac07Jeff Sharkey        try {
11750cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu            mActivityManager.unlockUser(userId, token, secret, listener);
11768924e8759f9a8cffb5ad538ca40a7826793aac07Jeff Sharkey        } catch (RemoteException e) {
11778924e8759f9a8cffb5ad538ca40a7826793aac07Jeff Sharkey            throw e.rethrowAsRuntimeException();
11788924e8759f9a8cffb5ad538ca40a7826793aac07Jeff Sharkey        }
1179bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey
1180bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        try {
1181bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            latch.await(15, TimeUnit.SECONDS);
1182bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        } catch (InterruptedException e) {
1183bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey            Thread.currentThread().interrupt();
1184bd91e2f3f6aca512a02be645b2515b5e3331e177Jeff Sharkey        }
1185dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
1186dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
1187dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1188dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                for (UserInfo pi : profiles) {
1189dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    // Unlock managed profile with unified lock
11900acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                    if (tiedManagedProfileReadyToUnlock(pi)) {
11910acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                        unlockChildProfile(pi.id, false /* ignoreUserNotAuthenticated */);
1192dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    }
1193dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                }
1194dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            }
1195dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (RemoteException e) {
1196dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            Log.d(TAG, "Failed to unlock child profile", e);
1197dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
11988924e8759f9a8cffb5ad538ca40a7826793aac07Jeff Sharkey    }
11998fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
12000acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) {
12010acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov        return userInfo.isManagedProfile()
12020acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id)
12030acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                && mStorage.hasChildProfileLock(userInfo.id)
12040acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov                && mUserManager.isUserRunning(userInfo.id);
12050acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov    }
12060acc4bf545b0bea215407f72a2c855f5bd15711cPavel Grafov
1207a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) {
1208a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1209a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            return null;
12108fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
1211a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        Map<Integer, String> result = new ArrayMap<Integer, String>();
1212a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1213a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        final int size = profiles.size();
1214a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        for (int i = 0; i < size; i++) {
1215a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            final UserInfo profile = profiles.get(i);
1216a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            if (!profile.isManagedProfile()) {
1217a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                continue;
1218a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            }
1219a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            final int managedUserId = profile.id;
1220a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
1221a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                continue;
1222a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            }
1223a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            try {
12244f988c98bf3ea4069d33c538ec3467a86b6d5f6cRubin Xu                result.put(managedUserId, getDecryptedPasswordForTiedProfile(managedUserId));
1225a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException
1226a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    | NoSuchPaddingException | InvalidKeyException
1227a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    | InvalidAlgorithmParameterException | IllegalBlockSizeException
1228a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    | BadPaddingException | CertificateException | IOException e) {
12294f988c98bf3ea4069d33c538ec3467a86b6d5f6cRubin Xu                Slog.e(TAG, "getDecryptedPasswordsForAllTiedProfiles failed for user " +
12304f988c98bf3ea4069d33c538ec3467a86b6d5f6cRubin Xu                    managedUserId, e);
1231a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            }
1232a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        }
1233a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        return result;
12348fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales    }
12358fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
1236a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    /**
1237a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
1238a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * depending on the parent user's secure state.
1239a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     *
1240a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * When clearing tied work challenges, a pre-computed password table for profiles are required,
1241a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * since changing password for profiles requires existing password, and existing passwords can
1242a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * only be computed before the parent user's password is cleared.
1243a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     *
1244a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
1245a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * method again on profiles. However the recursion is guaranteed to terminate as this method
1246a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     * terminates when the user is a managed profile.
1247a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu     */
1248a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
1249a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            Map<Integer, String> profilePasswordMap) throws RemoteException {
1250dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
1251dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            return;
1252dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1253a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        final boolean isSecure = isUserSecure(userId);
1254dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        final List<UserInfo> profiles = mUserManager.getProfiles(userId);
1255dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        final int size = profiles.size();
1256dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        for (int i = 0; i < size; i++) {
1257dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            final UserInfo profile = profiles.get(i);
1258dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (profile.isManagedProfile()) {
1259dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                final int managedUserId = profile.id;
1260dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
1261dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    continue;
1262dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                }
1263dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                if (isSecure) {
1264dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    tieManagedProfileLockIfNecessary(managedUserId, null);
1265dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                } else {
1266a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    // We use cached work profile password computed before clearing the parent's
1267a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    // credential, otherwise they get lost
1268a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) {
1269a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
12707374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                profilePasswordMap.get(managedUserId),
12717374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId);
1272a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    } else {
1273a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
1274a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        // Supplying null here would lead to untrusted credential change
1275a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        setLockCredentialInternal(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
12767374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId);
1277a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    }
1278dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    mStorage.removeChildProfileLock(managedUserId);
1279dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    removeKeystoreProfileKey(managedUserId);
1280dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                }
1281dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            }
1282dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1283dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1284dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1285dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private boolean isManagedProfileWithUnifiedLock(int userId) {
1286dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        return mUserManager.getUserInfo(userId).isManagedProfile()
1287dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
1288dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
12898fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
1290dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private boolean isManagedProfileWithSeparatedLock(int userId) {
1291dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        return mUserManager.getUserInfo(userId).isManagedProfile()
1292dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
1293dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1294dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1295dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    // This method should be called by LockPatternUtil only, all internal methods in this class
12961de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    // should call setLockCredentialInternal.
129752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
12987374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    public void setLockCredential(String credential, int type, String savedCredential,
12997374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            int requestedQuality, int userId)
13008fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            throws RemoteException {
1301e484eaff00096f3819c5002b66487b8c1d16ef57Jim Miller        checkWritePermission(userId);
1302dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        synchronized (mSeparateChallengeLock) {
13037374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            setLockCredentialInternal(credential, type, savedCredential, requestedQuality, userId);
130428939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            setSeparateProfileChallengeEnabledLocked(userId, true, null);
13055daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            notifyPasswordChanged(userId);
1306dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
130728939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov        notifySeparateProfileChallengeChanged(userId);
1308dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1309dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
13101de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    private void setLockCredentialInternal(String credential, int credentialType,
13117374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            String savedCredential, int requestedQuality, int userId) throws RemoteException {
1312df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        // Normalize savedCredential and credential such that empty string is always represented
1313df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        // as null.
1314df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        if (TextUtils.isEmpty(savedCredential)) {
1315df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu            savedCredential = null;
1316df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        }
1317df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        if (TextUtils.isEmpty(credential)) {
1318df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu            credential = null;
1319df406d802e9f6348f307ebbe1809c5cdc6c0b64eRubin Xu        }
13203bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronized (mSpManager) {
13213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
13223bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential,
13237374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        requestedQuality, userId);
13243bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                return;
13253bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
13263bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
13277374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
13281de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
13291de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            if (credential != null) {
13301de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
1331dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            }
1332cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley            clearUserKeyProtection(userId);
1333cfb61601fa4e92445655de7b82d2bc0ea9000824Andres Morales            getGateKeeperService().clearSecureUserId(userId);
13341de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
1335a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            setKeystorePassword(null, userId);
1336cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley            fixateNewestUserKeyAuth(userId);
1337a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
13385daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            notifyActivePasswordMetricsAvailable(null, userId);
133977183effbf21cbaa9dd81b31ba5c0e1a580619a3Dmitry Dementyev            mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
1340d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales            return;
1341d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales        }
13421de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (credential == null) {
13431de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            throw new RemoteException("Null credential with mismatched credential type");
13441de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        }
1345a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu
1346a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        CredentialHash currentHandle = mStorage.readCredentialHash(userId);
1347dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (isManagedProfileWithUnifiedLock(userId)) {
1348dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            // get credential from keystore when managed profile has unified lock
1349a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            if (savedCredential == null) {
1350a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                try {
1351a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    savedCredential = getDecryptedPasswordForTiedProfile(userId);
1352a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                } catch (FileNotFoundException e) {
1353a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    Slog.i(TAG, "Child profile key not found");
1354a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
1355a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        | NoSuchAlgorithmException | NoSuchPaddingException
1356a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        | InvalidAlgorithmParameterException | IllegalBlockSizeException
1357a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                        | BadPaddingException | CertificateException | IOException e) {
1358a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    Slog.e(TAG, "Failed to decrypt child profile key", e);
1359a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                }
1360dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            }
1361dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } else {
1362a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            if (currentHandle.hash == null) {
1363dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                if (savedCredential != null) {
1364dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                    Slog.w(TAG, "Saved credential provided, but none stored");
1365dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                }
1366dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                savedCredential = null;
13678fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            }
13688fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
13693bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronized (mSpManager) {
13703bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (shouldMigrateToSyntheticPasswordLocked(userId)) {
13713bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential,
13727374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        currentHandle.type, requestedQuality, userId);
13733bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential,
13747374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        requestedQuality, userId);
13753bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                return;
13763bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
13773bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
13783bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
1379a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        byte[] enrolledHandle = enrollCredential(currentHandle.hash, savedCredential, credential,
13801de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                userId);
13818fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        if (enrolledHandle != null) {
13821de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType);
13831de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            mStorage.writeCredentialHash(willStore, userId);
1384a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            // push new secret and auth token to vold
1385a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            GateKeeperResponse gkResponse = getGateKeeperService()
1386a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu                    .verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
1387a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            setUserKeyProtection(userId, credential, convertResponse(gkResponse));
1388cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley            fixateNewestUserKeyAuth(userId);
1389a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            // Refresh the auth token
1390a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
1391a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu            synchronizeUnifiedWorkChallengeForProfiles(userId, null);
13926e16724fb66e4bd14274768174379aa88c34464fDmitry Dementyev            mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
13936e16724fb66e4bd14274768174379aa88c34464fDmitry Dementyev                userId);
13948fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        } else {
13951de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            throw new RemoteException("Failed to enroll " +
13961de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
13971de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                            : "pattern"));
13988fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
13998fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales    }
14008fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
1401a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    private VerifyCredentialResponse convertResponse(GateKeeperResponse gateKeeperResponse) {
14027374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        return VerifyCredentialResponse.fromGateKeeperResponse(gateKeeperResponse);
1403a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu    }
1404a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu
14050cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    @VisibleForTesting
14060cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu    protected void tieProfileLockToParent(int userId, String password) {
1407dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
1408dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
1409dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] encryptionResult;
1410dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        byte[] iv;
1411dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
1412dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
1413dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            keyGenerator.init(new SecureRandom());
1414dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            SecretKey secretKey = keyGenerator.generateKey();
1415dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1416dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            keyStore.load(null);
141797c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai            try {
141897c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                keyStore.setEntry(
141997c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
142097c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        new java.security.KeyStore.SecretKeyEntry(secretKey),
142197c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
142297c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
142397c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
142497c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .build());
142597c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                keyStore.setEntry(
142697c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
142797c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        new java.security.KeyStore.SecretKeyEntry(secretKey),
142897c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
142997c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
143097c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
143197c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setUserAuthenticationRequired(true)
143297c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .setUserAuthenticationValidityDurationSeconds(30)
1433e053c1e5fb69fa87c534f2ba489f10bdcac3120cPavel Grafov                                .setCriticalToDeviceEncryption(true)
143497c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                .build());
143597c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                // Key imported, obtain a reference to it.
143697c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
143797c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
143897c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                Cipher cipher = Cipher.getInstance(
143997c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                        KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
144097c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                                + KeyProperties.ENCRYPTION_PADDING_NONE);
144197c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
144297c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                encryptionResult = cipher.doFinal(randomLockSeed);
144397c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                iv = cipher.getIV();
144497c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai            } finally {
144597c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                // The original key can now be discarded.
144697c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai                keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
144797c8f8d16132747f3fe98f076a215f850b4f7c05Ricky Wai            }
1448dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (CertificateException | UnrecoverableKeyException
1449e61672ab087df4857a4f0923258b945800046589Zach Jang                | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
1450dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
1451dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            throw new RuntimeException("Failed to encrypt key", e);
1452dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1453dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
1454dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
1455dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (iv.length != PROFILE_KEY_IV_SIZE) {
1456dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                throw new RuntimeException("Invalid iv length: " + iv.length);
1457dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            }
1458dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            outputStream.write(iv);
1459dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            outputStream.write(encryptionResult);
1460dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (IOException e) {
1461dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            throw new RuntimeException("Failed to concatenate byte arrays", e);
1462dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1463dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
1464dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1465dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
14668fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales    private byte[] enrollCredential(byte[] enrolledHandle,
14678fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            String enrolledCredential, String toEnroll, int userId)
14688fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            throws RemoteException {
14698fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        checkWritePermission(userId);
14708fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        byte[] enrolledCredentialBytes = enrolledCredential == null
14718fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales                ? null
14728fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales                : enrolledCredential.getBytes();
14738fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        byte[] toEnrollBytes = toEnroll == null
14748fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales                ? null
14758fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales                : toEnroll.getBytes();
14762397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
14772397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales                enrolledCredentialBytes, toEnrollBytes);
14788fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
14792397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        if (response == null) {
14802397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            return null;
14812397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        }
14822397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales
14832397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        byte[] hash = response.getPayload();
14848fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        if (hash != null) {
1485a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            setKeystorePassword(toEnroll, userId);
14862397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        } else {
14872397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            // Should not happen
14882397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            Slog.e(TAG, "Throttled while enrolling a password");
14898fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
14908fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        return hash;
1491de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    }
1492de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller
14933bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private void setAuthlessUserKeyProtection(int userId, byte[] key) throws RemoteException {
14943bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (DEBUG) Slog.d(TAG, "setAuthlessUserKeyProtectiond: user=" + userId);
14953bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        addUserKeyAuth(userId, null, key);
14963bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
14973bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
1498faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    private void setUserKeyProtection(int userId, String credential, VerifyCredentialResponse vcr)
1499faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throws RemoteException {
1500a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
1501faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        if (vcr == null) {
1502faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throw new RemoteException("Null response verifying a credential we just set");
1503faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        }
1504faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        if (vcr.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
1505faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throw new RemoteException("Non-OK response verifying a credential we just set: "
15061de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    + vcr.getResponseCode());
1507faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        }
1508faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        byte[] token = vcr.getPayload();
1509faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        if (token == null) {
1510faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throw new RemoteException("Empty payload verifying a credential we just set");
1511faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        }
1512cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley        addUserKeyAuth(userId, token, secretFromCredential(credential));
1513faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    }
1514faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley
1515faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    private void clearUserKeyProtection(int userId) throws RemoteException {
1516a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
1517cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley        addUserKeyAuth(userId, null, null);
1518faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    }
1519faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley
1520faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    private static byte[] secretFromCredential(String credential) throws RemoteException {
1521faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        try {
1522faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            MessageDigest digest = MessageDigest.getInstance("SHA-512");
1523faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            // Personalize the hash
1524faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            byte[] personalization = "Android FBE credential hash"
1525faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                    .getBytes(StandardCharsets.UTF_8);
1526faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            // Pad it to the block size of the hash function
1527faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            personalization = Arrays.copyOf(personalization, 128);
1528faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            digest.update(personalization);
1529faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            digest.update(credential.getBytes(StandardCharsets.UTF_8));
1530faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            return digest.digest();
1531faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        } catch (NoSuchAlgorithmException e) {
1532faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throw new RuntimeException("NoSuchAlgorithmException for SHA-512");
1533faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley        }
1534faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    }
1535faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley
1536cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley    private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
1537faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            throws RemoteException {
15380cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        final UserInfo userInfo = mUserManager.getUserInfo(userId);
15390cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        final IStorageManager storageManager = mInjector.getStorageManager();
1540815036f055173d4dfcddd03a4e6c03d24bff00c7Paul Crowley        final long callingId = Binder.clearCallingIdentity();
1541815036f055173d4dfcddd03a4e6c03d24bff00c7Paul Crowley        try {
15422250d56a0b47b93016018340c8f4040325aa5611Sudheer Shanka            storageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
1543815036f055173d4dfcddd03a4e6c03d24bff00c7Paul Crowley        } finally {
1544815036f055173d4dfcddd03a4e6c03d24bff00c7Paul Crowley            Binder.restoreCallingIdentity(callingId);
1545815036f055173d4dfcddd03a4e6c03d24bff00c7Paul Crowley        }
1546faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley    }
1547faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley
1548cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley    private void fixateNewestUserKeyAuth(int userId)
1549cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley            throws RemoteException {
1550a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId);
15510cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        final IStorageManager storageManager = mInjector.getStorageManager();
15526c8187282ecc20419a5a70371bc6a21af6d364e0Toni Barzic        final long callingId = Binder.clearCallingIdentity();
15536c8187282ecc20419a5a70371bc6a21af6d364e0Toni Barzic        try {
15542250d56a0b47b93016018340c8f4040325aa5611Sudheer Shanka            storageManager.fixateNewestUserKeyAuth(userId);
15556c8187282ecc20419a5a70371bc6a21af6d364e0Toni Barzic        } finally {
15566c8187282ecc20419a5a70371bc6a21af6d364e0Toni Barzic            Binder.restoreCallingIdentity(callingId);
15576c8187282ecc20419a5a70371bc6a21af6d364e0Toni Barzic        }
1558cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley    }
1559cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley
1560de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller    @Override
15614613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai    public void resetKeyStore(int userId) throws RemoteException {
15627f405f170f66d201f893a2f29866f528f0ec7fc8Ricky Wai        checkWritePermission(userId);
15634613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
15644613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        int managedUserId = -1;
15654613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        String managedUserDecryptedPassword = null;
15664613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        final List<UserInfo> profiles = mUserManager.getProfiles(userId);
15674613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        for (UserInfo pi : profiles) {
15684613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            // Unlock managed profile with unified lock
15694613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            if (pi.isManagedProfile()
15704613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
15714613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    && mStorage.hasChildProfileLock(pi.id)) {
15724613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                try {
15734613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    if (managedUserId == -1) {
15744613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        managedUserDecryptedPassword = getDecryptedPasswordForTiedProfile(pi.id);
15754613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        managedUserId = pi.id;
15764613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    } else {
15774613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        // Should not happen
15784613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        Slog.e(TAG, "More than one managed profile, uid1:" + managedUserId
15794613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                                + ", uid2:" + pi.id);
15804613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    }
15814613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
15824613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        | NoSuchAlgorithmException | NoSuchPaddingException
15834613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        | InvalidAlgorithmParameterException | IllegalBlockSizeException
15844613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                        | BadPaddingException | CertificateException | IOException e) {
15854613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    Slog.e(TAG, "Failed to decrypt child profile key", e);
15864613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                }
15874613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            }
15884613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        }
15894613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        try {
15904613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            // Clear all the users credentials could have been installed in for this user.
15914613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
15924613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                for (int uid : SYSTEM_CREDENTIAL_UIDS) {
15934613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                    mKeyStore.clearUid(UserHandle.getUid(profileId, uid));
15944613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                }
15954613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            }
15964613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        } finally {
15974613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            if (managedUserId != -1 && managedUserDecryptedPassword != null) {
15984613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai                if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
1599e61672ab087df4857a4f0923258b945800046589Zach Jang                tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
16004613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai            }
16014613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai        }
16024613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai    }
16034613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai
16044613fe41ac9e817e76d7087de45bf01f4a6584d6Ricky Wai    @Override
16051de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    public VerifyCredentialResponse checkCredential(String credential, int type, int userId,
1606e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi            ICheckCredentialProgressCallback progressCallback) throws RemoteException {
16071de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        checkPasswordReadPermission(userId);
16081de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        return doVerifyCredential(credential, type, false, 0, userId, progressCallback);
1609d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales    }
16108fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
1611d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales    @Override
16121de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    public VerifyCredentialResponse verifyCredential(String credential, int type, long challenge,
16131de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            int userId) throws RemoteException {
16141de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        checkPasswordReadPermission(userId);
16151de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        return doVerifyCredential(credential, type, true, challenge, userId,
16161de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                null /* progressCallback */);
1617cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley    }
1618cc70155f3bf18341296aaa2163bd2e7df6997b11Paul Crowley
16191de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    /**
16201de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
16211de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * format.
16221de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     */
16231de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    private VerifyCredentialResponse doVerifyCredential(String credential, int credentialType,
1624e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi            boolean hasChallenge, long challenge, int userId,
1625e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi            ICheckCredentialProgressCallback progressCallback) throws RemoteException {
16261de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (TextUtils.isEmpty(credential)) {
16271de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            throw new IllegalArgumentException("Credential can't be null or empty");
16281de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        }
16297374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(),
16307374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
16317374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
16327374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            return VerifyCredentialResponse.ERROR;
16337374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
1634e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        VerifyCredentialResponse response = null;
1635e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge,
1636e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                userId, progressCallback);
1637e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        // The user employs synthetic password based credential.
1638e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        if (response != null) {
163940386dfddcf607332c949c1f5bc4466eaba58422Robert Berry            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
164040386dfddcf607332c949c1f5bc4466eaba58422Robert Berry                mRecoverableKeyStoreManager.lockScreenSecretAvailable(credentialType, credential,
164140386dfddcf607332c949c1f5bc4466eaba58422Robert Berry                        userId);
164240386dfddcf607332c949c1f5bc4466eaba58422Robert Berry            }
1643e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            return response;
16443bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
1645e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu
16467374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        if (userId == USER_FRP) {
1647971f2948fbee3766ec01907f5a6e23f4c9bb4872Andrew Scull            Slog.wtf(TAG, "Unexpected FRP credential type, should be SP based.");
1648971f2948fbee3766ec01907f5a6e23f4c9bb4872Andrew Scull            return VerifyCredentialResponse.ERROR;
16497374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
16507374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
1651971f2948fbee3766ec01907f5a6e23f4c9bb4872Andrew Scull        final CredentialHash storedHash = mStorage.readCredentialHash(userId);
16521de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (storedHash.type != credentialType) {
16531de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
16541de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    + " stored: " + storedHash.type + " passed in: " + credentialType);
16551de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            return VerifyCredentialResponse.ERROR;
16561de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        }
165752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
16581de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        boolean shouldReEnrollBaseZero = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
16591de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                && storedHash.isBaseZeroPattern;
1660d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales
16611de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        String credentialToVerify;
16621de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        if (shouldReEnrollBaseZero) {
16631de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            credentialToVerify = LockPatternUtils.patternStringToBaseZero(credential);
16641de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        } else {
16651de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            credentialToVerify = credential;
16661de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        }
16671de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu
1668e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        response = verifyCredential(userId, storedHash, credentialToVerify,
16691de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                hasChallenge, challenge, progressCallback);
16701de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu
1671e71f583c782a98e977d6a5c450dff856b132e5c6Michal Karpinski        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
1672e71f583c782a98e977d6a5c450dff856b132e5c6Michal Karpinski            mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
1673e71f583c782a98e977d6a5c450dff856b132e5c6Michal Karpinski            if (shouldReEnrollBaseZero) {
16747374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                setLockCredentialInternal(credential, storedHash.type, credentialToVerify,
16757374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, userId);
1676e71f583c782a98e977d6a5c450dff856b132e5c6Michal Karpinski            }
16771de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        }
16781de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu
16791de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        return response;
1680d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales    }
1681d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales
168253940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai    @Override
16831de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    public VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type,
168453940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            long challenge, int userId) throws RemoteException {
168553940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        checkPasswordReadPermission(userId);
168653940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        if (!isManagedProfileWithUnifiedLock(userId)) {
168753940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            throw new RemoteException("User id must be managed profile with unified lock");
168853940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        }
168953940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        final int parentProfileId = mUserManager.getProfileParent(userId).id;
169053940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        // Unlock parent by using parent's challenge
16911de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        final VerifyCredentialResponse parentResponse = doVerifyCredential(
16921de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                credential,
16931de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                type,
16941de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                true /* hasChallenge */,
16951de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                challenge,
16961de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                parentProfileId,
16971de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                null /* progressCallback */);
169853940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
169953940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            // Failed, just return parent's response
170053940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            return parentResponse;
170153940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        }
170253940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai
170353940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        try {
170453940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            // Unlock work profile, and work profile with unified lock must use password only
17051de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
17061de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
17071de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    true,
170853940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai                    challenge,
1709e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi                    userId, null /* progressCallback */);
171053940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
171153940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai                | NoSuchAlgorithmException | NoSuchPaddingException
171253940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai                | InvalidAlgorithmParameterException | IllegalBlockSizeException
171353940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai                | BadPaddingException | CertificateException | IOException e) {
171453940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            Slog.e(TAG, "Failed to decrypt child profile key", e);
171553940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai            throw new RemoteException("Unable to get tied profile token");
171653940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai        }
171753940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai    }
171853940d4c7f45a26d8b571982a1f8f4b8094aa5e0Ricky Wai
17191de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu    /**
17201de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * Lowest-level credential verification routine that talks to GateKeeper. If verification
17211de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * passes, unlock the corresponding user and keystore. Also handles the migration from legacy
17221de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     * hash to GK.
17231de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu     */
17242397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales    private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
17251de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            String credential, boolean hasChallenge, long challenge,
17261de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            ICheckCredentialProgressCallback progressCallback) throws RemoteException {
17272397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
17282397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            // don't need to pass empty credentials to GateKeeper
17292397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            return VerifyCredentialResponse.OK;
1730d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales        }
1731d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales
1732750563ee508e3ad9af6a70ccc669c070f892cfcbAndrew Zeng        if (storedHash == null || TextUtils.isEmpty(credential)) {
17332397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            return VerifyCredentialResponse.ERROR;
1734261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        }
1735261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos
1736eddf518763261536f31b777b0e262f85676d6967Jeff Sharkey        // We're potentially going to be doing a bunch of disk I/O below as part
1737eddf518763261536f31b777b0e262f85676d6967Jeff Sharkey        // of unlocking the user, so yell if calling from the main thread.
1738eddf518763261536f31b777b0e262f85676d6967Jeff Sharkey        StrictMode.noteDiskRead();
1739eddf518763261536f31b777b0e262f85676d6967Jeff Sharkey
17408fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        if (storedHash.version == CredentialHash.VERSION_LEGACY) {
17411de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            final byte[] hash;
17421de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
17431de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(credential));
17441de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            } else {
1745f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                hash = mLockPatternUtils.legacyPasswordToHash(credential, userId)
1746f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                        .getBytes(StandardCharsets.UTF_8);
17471de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            }
1748d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales            if (Arrays.equals(hash, storedHash.hash)) {
17491de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                if (storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
17501de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    unlockKeystore(LockPatternUtils.patternStringToBaseZero(credential), userId);
17511de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                } else {
17521de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                    unlockKeystore(credential, userId);
17531de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                }
1754faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                // Users with legacy credentials don't have credential-backed
1755faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                // FBE keys, so just pass through a fake token/secret
1756faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                Slog.i(TAG, "Unlocking user with fake token: " + userId);
1757faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                final byte[] fakeToken = String.valueOf(userId).getBytes();
1758faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley                unlockUser(userId, fakeToken, fakeToken);
1759b9fe53705ca851c39abe44e980219fd6733bf821Jeff Sharkey
17602397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales                // migrate credential to GateKeeper
17617374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                setLockCredentialInternal(credential, storedHash.type, null,
17627374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
17637374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
17647374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
17657374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                /* TODO(roosa): keep the same password quality */, userId);
1766d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales                if (!hasChallenge) {
17675daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull                    notifyActivePasswordMetricsAvailable(credential, userId);
1768f899bff7a0fa2f8a5969d063d731b623a71f249fRobert Berry                    // Use credentials to create recoverable keystore snapshot.
1769f899bff7a0fa2f8a5969d063d731b623a71f249fRobert Berry                    mRecoverableKeyStoreManager.lockScreenSecretAvailable(
1770f899bff7a0fa2f8a5969d063d731b623a71f249fRobert Berry                            storedHash.type, credential, userId);
17712397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales                    return VerifyCredentialResponse.OK;
1772d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales                }
1773d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales                // Fall through to get the auth token. Technically this should never happen,
17742397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales                // as a user that had a legacy credential would have to unlock their device
1775d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales                // before getting to a flow with a challenge, but supporting for consistency.
1776d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales            } else {
17772397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales                return VerifyCredentialResponse.ERROR;
17788fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            }
17798fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
178098e0a266ea27e8dcd4d5e4380921f40f00e7b685Paul Crowley        GateKeeperResponse gateKeeperResponse = getGateKeeperService()
178198e0a266ea27e8dcd4d5e4380921f40f00e7b685Paul Crowley                .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
1782a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
1783a55b168b5d5a0584b2411793f870a7849c5014f1Rubin Xu        boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
17848fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
17852397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
1786e31f6b8024d1a0cfa71894e9a8ce1b39a9f85b2fJorim Jaggi
17872397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            // credential has matched
1788e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi
1789e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi            if (progressCallback != null) {
1790e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi                progressCallback.onCredentialVerified();
1791e8fde5d9666eea10307cbc27f4b1a94d3cbb4ec9Jorim Jaggi            }
17925daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            notifyActivePasswordMetricsAvailable(credential, userId);
17932397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            unlockKeystore(credential, userId);
1794b9fe53705ca851c39abe44e980219fd6733bf821Jeff Sharkey
17953bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            Slog.i(TAG, "Unlocking user " + userId + " with token length "
17963bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    + response.getPayload().length);
1797faeb3eb0ba190e6d6cfe2b82ce20af587848de57Paul Crowley            unlockUser(userId, response.getPayload(), secretFromCredential(credential));
1798b9fe53705ca851c39abe44e980219fd6733bf821Jeff Sharkey
1799dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            if (isManagedProfileWithSeparatedLock(userId)) {
180056878a93989a49538fabccfb7218face645030bfClara Bayarri                TrustManager trustManager =
180156878a93989a49538fabccfb7218face645030bfClara Bayarri                        (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
180256878a93989a49538fabccfb7218face645030bfClara Bayarri                trustManager.setDeviceLockedForUser(userId, false);
180356878a93989a49538fabccfb7218face645030bfClara Bayarri            }
18047374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            int reEnrollQuality = storedHash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
18057374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
18067374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
18077374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    /* TODO(roosa): keep the same password quality */;
18082397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            if (shouldReEnroll) {
18097374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                setLockCredentialInternal(credential, storedHash.type, credential,
18107374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        reEnrollQuality, userId);
18113bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            } else {
18123bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // Now that we've cleared of all required GK migration, let's do the final
18133bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // migration to synthetic password.
18143bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                synchronized (mSpManager) {
18153bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    if (shouldMigrateToSyntheticPasswordLocked(userId)) {
1816128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                        AuthenticationToken auth = initializeSyntheticPasswordLocked(
18177374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                storedHash.hash, credential, storedHash.type, reEnrollQuality,
18187374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                                userId);
1819128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                        activateEscrowTokens(auth, userId);
18203bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    }
18213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                }
18222397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales            }
18236a509e4a84c57d1a18eeabac9a78d6843ad0f91bDmitry Dementyev            // Use credentials to create recoverable keystore snapshot.
18246a509e4a84c57d1a18eeabac9a78d6843ad0f91bDmitry Dementyev            mRecoverableKeyStoreManager.lockScreenSecretAvailable(storedHash.type, credential,
18256a509e4a84c57d1a18eeabac9a78d6843ad0f91bDmitry Dementyev                userId);
18266a509e4a84c57d1a18eeabac9a78d6843ad0f91bDmitry Dementyev
1827873010dfeea11e0f9982c66ad9bdc990d055b129Adrian Roos        } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
1828873010dfeea11e0f9982c66ad9bdc990d055b129Adrian Roos            if (response.getTimeout() > 0) {
1829873010dfeea11e0f9982c66ad9bdc990d055b129Adrian Roos                requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
1830873010dfeea11e0f9982c66ad9bdc990d055b129Adrian Roos            }
18312397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        }
183252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
18332397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales        return response;
18342397427cb1a0bad8a42e6a342dcf29b31e40a234Andres Morales    }
1835d9fc85ac27742adbe89e54fd35f3cb2469e94b91Andres Morales
18367cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu    /**
18377cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu     * Call this method to notify DPMS regarding the latest password metric. This should be called
18387cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu     * when the user is authenticating or when a new password is being set.
18397cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu     */
18405daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull    private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
18415daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        final PasswordMetrics metrics;
18425daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        if (password == null) {
18435daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            metrics = new PasswordMetrics();
18445daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        } else {
18455daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            metrics = PasswordMetrics.computeForPassword(password);
18465daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            metrics.quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
18475daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        }
18485daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull
18495daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        // Asynchronous to avoid dead lock
18505daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        mHandler.post(() -> {
18515daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            DevicePolicyManager dpm = (DevicePolicyManager)
18525daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull                    mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
18535daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            dpm.setActivePasswordState(metrics, userId);
18545daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        });
18555daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull    }
18565daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull
18575daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull    /**
18585daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull     * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before
18595daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull     * reporting the password changed.
18605daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull     */
18615daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull    private void notifyPasswordChanged(@UserIdInt int userId) {
18625daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering
18635daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        mHandler.post(() -> {
18645daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            DevicePolicyManager dpm = (DevicePolicyManager)
18655daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull                    mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
18665daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull            dpm.reportPasswordChanged(userId);
18675daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull        });
18685daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull    }
18695daf273b7e3272269c53eda20ce494d0e7a365b5Andrew Scull
187052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    @Override
1871261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos    public boolean checkVoldPassword(int userId) throws RemoteException {
1872945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        if (!mFirstCallToVold) {
1873945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            return false;
1874945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
1875945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        mFirstCallToVold = false;
1876945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1877945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        checkPasswordReadPermission(userId);
1878945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1879945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // There's no guarantee that this will safely connect, but if it fails
1880945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // we will simply show the lock screen when we shouldn't, so relatively
1881945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // benign. There is an outside chance something nasty would happen if
1882945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // this service restarted before vold stales out the password in this
1883945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // case. The nastiness is limited to not showing the lock screen when
1884945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // we should, within the first minute of decrypting the phone if this
1885945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // service can't connect to vold, it restarts, and then the new instance
1886945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        // does successfully connect.
18870cbc19e4a66f7db51596b57ca91afc6f5b27f3b4Rubin Xu        final IStorageManager service = mInjector.getStorageManager();
18880bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence        String password;
18890bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence        long identity = Binder.clearCallingIdentity();
18900bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence        try {
18910bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence            password = service.getPassword();
18920bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence            service.clearPassword();
18930bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence        } finally {
18940bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence            Binder.restoreCallingIdentity(identity);
18950bbd108aa1fee8c69bbaf41990d3f3d8a99d54cbPaul Lawrence        }
1896945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        if (password == null) {
1897945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            return false;
1898945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
1899945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1900945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        try {
19019dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos            if (mLockPatternUtils.isLockPatternEnabled(userId)) {
19021de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, userId,
19031de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                        null /* progressCallback */)
19041de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                                .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
1905945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                    return true;
1906945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                }
1907945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            }
1908945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        } catch (Exception e) {
1909945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
1910945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1911945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        try {
19129dd16ebcf2a25c189a39b72847d3db2b1189cb4dAdrian Roos            if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
19131de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                if (checkCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, userId,
19141de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                        null /* progressCallback */)
19151de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                                .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
1916945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                    return true;
1917945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence                }
1918945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence            }
1919945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        } catch (Exception e) {
1920945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        }
1921945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1922945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence        return false;
1923945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence    }
1924945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
1925f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani    private void removeUser(int userId, boolean unknownUser) {
19267b7424b0b7c5b6be09ed6fb0ec70272574dfe718Rubin Xu        mSpManager.removeUser(userId);
1927261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos        mStorage.removeUser(userId);
1928b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        mStrongAuth.removeUser(userId);
1929ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        tryRemoveUserFromSpCacheLater(userId);
193049d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee
193149d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee        final KeyStore ks = KeyStore.getInstance();
193283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        ks.onUserRemoved(userId);
1933070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales
1934070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales        try {
1935070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales            final IGateKeeperService gk = getGateKeeperService();
1936070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales            if (gk != null) {
19371de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu                gk.clearSecureUserId(userId);
1938070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales            }
1939070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales        } catch (RemoteException ex) {
1940070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales            Slog.w(TAG, "unable to clear GK secure user id");
1941070fe63962baf30a648f7f85a7d00c177fc8b7c5Andres Morales        }
1942f11a574027a8dbe18d79ce467984d63d07fea9e1Amith Yamasani        if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
1943dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            removeKeystoreProfileKey(userId);
1944dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
1945dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    }
1946dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai
1947dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai    private void removeKeystoreProfileKey(int targetUserId) {
1948dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
1949dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        try {
1950dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
1951dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            keyStore.load(null);
1952d398244513c62c9ea14a0f1c6ffef832e803c16fRicky Wai            keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + targetUserId);
1953d398244513c62c9ea14a0f1c6ffef832e803c16fRicky Wai            keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + targetUserId);
1954dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
1955dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai                | IOException e) {
1956dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            // We have tried our best to remove all keys
1957dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai            Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
1958dc283a897680ffd33c4d15535ebe778ba5b42c43Ricky Wai        }
195952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    }
196052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani
1961b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    @Override
1962b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
1963b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        checkPasswordReadPermission(UserHandle.USER_ALL);
1964b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        mStrongAuth.registerStrongAuthTracker(tracker);
1965b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    }
1966b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos
1967b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    @Override
1968b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
1969b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        checkPasswordReadPermission(UserHandle.USER_ALL);
1970b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        mStrongAuth.unregisterStrongAuthTracker(tracker);
1971b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    }
1972b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos
1973b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    @Override
1974b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    public void requireStrongAuth(int strongAuthReason, int userId) {
1975b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        checkWritePermission(userId);
1976b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos        mStrongAuth.requireStrongAuth(strongAuthReason, userId);
1977b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos    }
1978b5e4722891e7bbf2fffcd995af02838667a3ababAdrian Roos
19794ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos    @Override
19804ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos    public void userPresent(int userId) {
19814ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos        checkWritePermission(userId);
19824ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos        mStrongAuth.reportUnlock(userId);
19834ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos    }
19844ab7e595a5deef72448da950f2f973bc0c90fe18Adrian Roos
1985a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang    @Override
1986a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang    public int getStrongAuthForUser(int userId) {
1987a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        checkPasswordReadPermission(userId);
1988a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang        return mStrongAuthTracker.getStrongAuthForUser(userId);
1989a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang    }
1990a0940d33dcbac0245ad5467d9c302f8eaee615dcVictor Chang
19912fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    private boolean isCallerShell() {
19922fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        final int callingUid = Binder.getCallingUid();
19932fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
19942fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    }
19952fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi
19962fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    private void enforceShell() {
19972fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        if (!isCallerShell()) {
19982fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi            throw new SecurityException("Caller must be shell");
19992fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        }
20002fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    }
20012fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi
20022fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    @Override
20032fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
20042fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
20052fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi            throws RemoteException {
20062fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        enforceShell();
20072fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        final long origId = Binder.clearCallingIdentity();
20082fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        try {
20092fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi            (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
20102fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi                    this, in, out, err, args, callback, resultReceiver);
20112fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        } finally {
20122fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi            Binder.restoreCallingIdentity(origId);
20132fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi        }
20142fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi    }
20152fef6f7b155f2ff0d3531fe63b8e1c745bb3dc9dJorim Jaggi
20161aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
20177f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu    public void initRecoveryServiceWithSigFile(@NonNull String rootCertificateAlias,
20187f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu            @NonNull byte[] recoveryServiceCertFile, @NonNull byte[] recoveryServiceSigFile)
20197f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu            throws RemoteException {
20207f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu        mRecoverableKeyStoreManager.initRecoveryServiceWithSigFile(rootCertificateAlias,
20217f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu                recoveryServiceCertFile, recoveryServiceSigFile);
20227f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu    }
20237f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu
20247f414d94fc4f6bd34325f3865b51e8d11acb52adBo Zhu    @Override
20254da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @NonNull KeyChainSnapshot getKeyChainSnapshot() throws RemoteException {
2026b4fb98777006bc3c2bb038d50473663fbc92932cDmitry Dementyev        return mRecoverableKeyStoreManager.getKeyChainSnapshot();
20271aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20281aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20294da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    @Override
20301429831ac86ad48b3ea7cb39f7c1234d9272dc0bDmitry Dementyev    public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
2031b8b030bdbb1aa20d74bedce3ca6f302be5421a86Dmitry Dementyev            throws RemoteException {
20321429831ac86ad48b3ea7cb39f7c1234d9272dc0bDmitry Dementyev        mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent);
2033b8b030bdbb1aa20d74bedce3ca6f302be5421a86Dmitry Dementyev    }
2034b8b030bdbb1aa20d74bedce3ca6f302be5421a86Dmitry Dementyev
20351aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
20367d8c78a2c88a4898a63b918ab8b974aecd7b165bDmitry Dementyev    public void setServerParams(byte[] serverParams) throws RemoteException {
20377d8c78a2c88a4898a63b918ab8b974aecd7b165bDmitry Dementyev        mRecoverableKeyStoreManager.setServerParams(serverParams);
20381aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20391aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20401aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
2041bbe02ae8a3dd07989d61bbb739bfd863123c5489Robert Berry    public void setRecoveryStatus(String alias, int status) throws RemoteException {
2042bbe02ae8a3dd07989d61bbb739bfd863123c5489Robert Berry        mRecoverableKeyStoreManager.setRecoveryStatus(alias, status);
20431aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20441aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20454da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    @Override
20464da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @NonNull Map getRecoveryStatus() throws RemoteException {
204756f06b4d111f99f72d4232b43037fea2f6246e7dRobert Berry        return mRecoverableKeyStoreManager.getRecoveryStatus();
2048b8b030bdbb1aa20d74bedce3ca6f302be5421a86Dmitry Dementyev    }
2049b8b030bdbb1aa20d74bedce3ca6f302be5421a86Dmitry Dementyev
20501aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
20510916e7ca44aba5e6c89d75007da805697fdace9eDmitry Dementyev    public void setRecoverySecretTypes(@NonNull @KeyChainProtectionParams.UserSecretType
20521429831ac86ad48b3ea7cb39f7c1234d9272dc0bDmitry Dementyev            int[] secretTypes) throws RemoteException {
20531429831ac86ad48b3ea7cb39f7c1234d9272dc0bDmitry Dementyev        mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
20541aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20551aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20561aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
20574da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @NonNull int[] getRecoverySecretTypes() throws RemoteException {
20581429831ac86ad48b3ea7cb39f7c1234d9272dc0bDmitry Dementyev        return mRecoverableKeyStoreManager.getRecoverySecretTypes();
20591aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20601aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20611aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
20621aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    @Override
20634da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @NonNull byte[] startRecoverySessionWithCertPath(@NonNull String sessionId,
2064b31ab6740d66b21a74ffa77b753ea3364288254eBo Zhu            @NonNull String rootCertificateAlias, @NonNull RecoveryCertPath verifierCertPath,
2065b31ab6740d66b21a74ffa77b753ea3364288254eBo Zhu            @NonNull byte[] vaultParams, @NonNull byte[] vaultChallenge,
2066b31ab6740d66b21a74ffa77b753ea3364288254eBo Zhu            @NonNull List<KeyChainProtectionParams> secrets)
20677c1972ff71080568b7288197e96e163d5a469e5fBo Zhu            throws RemoteException {
20687c1972ff71080568b7288197e96e163d5a469e5fBo Zhu        return mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
2069b31ab6740d66b21a74ffa77b753ea3364288254eBo Zhu                sessionId, rootCertificateAlias, verifierCertPath, vaultParams, vaultChallenge,
2070b31ab6740d66b21a74ffa77b753ea3364288254eBo Zhu                secrets);
20717c1972ff71080568b7288197e96e163d5a469e5fBo Zhu    }
20727c1972ff71080568b7288197e96e163d5a469e5fBo Zhu
20734da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    @Override
20744a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry    public Map<String, String> recoverKeyChainSnapshot(
20754a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry            @NonNull String sessionId,
20764a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry            @NonNull byte[] recoveryKeyBlob,
20774a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry            @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
20784a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry        return mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
20794a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry                sessionId, recoveryKeyBlob, applicationKeys);
20804a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry    }
20814a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry
20824a5c87def075c805d4fcae7ff01dd2e78ec27b1aRobert Berry    @Override
2083745d2c98f9467f1befb7ec3a6c485333d4f1b437Dmitry Dementyev    public void closeSession(@NonNull String sessionId) throws RemoteException {
2084745d2c98f9467f1befb7ec3a6c485333d4f1b437Dmitry Dementyev        mRecoverableKeyStoreManager.closeSession(sessionId);
20851aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev    }
20861aa96132bdcbaf89f7a69d6c3664790f08f87cc9Dmitry Dementyev
2087cfc990a49ddc00f3ca972b463c6475d7d5ac7b41Robert Berry    @Override
20885daccec818ffc26fafb795b17d5b1f76fbce3a60Robert Berry    public void removeKey(@NonNull String alias) throws RemoteException {
20895daccec818ffc26fafb795b17d5b1f76fbce3a60Robert Berry        mRecoverableKeyStoreManager.removeKey(alias);
20905daccec818ffc26fafb795b17d5b1f76fbce3a60Robert Berry    }
20915daccec818ffc26fafb795b17d5b1f76fbce3a60Robert Berry
20925daccec818ffc26fafb795b17d5b1f76fbce3a60Robert Berry    @Override
20934da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @Nullable String generateKey(@NonNull String alias) throws RemoteException {
2094a3b994798d870244f11b56ae0bdfb870924402a8Robert Berry        return mRecoverableKeyStoreManager.generateKey(alias);
209529b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev    }
209629b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev
209729b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev    @Override
20984da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @Nullable String importKey(@NonNull String alias, byte[] keyBytes) throws RemoteException {
20992c8e5383c836d2dfa39b0be6bfa281285667a880Bo Zhu        return mRecoverableKeyStoreManager.importKey(alias, keyBytes);
21002c8e5383c836d2dfa39b0be6bfa281285667a880Bo Zhu    }
21012c8e5383c836d2dfa39b0be6bfa281285667a880Bo Zhu
21022c8e5383c836d2dfa39b0be6bfa281285667a880Bo Zhu    @Override
21034da14e00fc5919a7e36fe6d7d7e63512eb23bb4aDmitry Dementyev    public @Nullable String getKey(@NonNull String alias) throws RemoteException {
210429b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev        return mRecoverableKeyStoreManager.getKey(alias);
210529b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev    }
210629b9de5b8a9b38290c2855890ae1f7a93c0b8421Dmitry Dementyev
210752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani    private static final String[] VALID_SETTINGS = new String[] {
21081de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.LOCKOUT_PERMANENT_KEY,
21091de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
21101de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.PASSWORD_TYPE_KEY,
21111de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
21121de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
21131de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
21141de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.LOCKSCREEN_OPTIONS,
21151de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
21161de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
21171de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
21181de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            LockPatternUtils.PASSWORD_HISTORY_KEY,
21191de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_PATTERN_ENABLED,
21201de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
21211de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_PATTERN_VISIBLE,
21221de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
2123187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller    };
2124187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller
21256d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov    // Reading these settings needs the contacts permission
21266d2c0e5ee2f717d4a5c00df08aca21c76eea8278Svetoslav Ganov    private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
21271de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
21281de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_SCREEN_OWNER_INFO
2129187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller    };
2130945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence
2131001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos    // Reading these settings needs the same permission as checking the password
2132001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos    private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
2133001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos            LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
2134001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos            LockPatternUtils.PASSWORD_HISTORY_KEY,
2135855fa30b74c99410869a7cdfa4cf07b37937c238Adrian Roos            LockPatternUtils.PASSWORD_TYPE_KEY,
21367f405f170f66d201f893a2f29866f528f0ec7fc8Ricky Wai            SEPARATE_PROFILE_CHALLENGE_KEY
2137001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos    };
2138001b00d3bd8c20c7e73cb8101cbe98291bd5e68fAdrian Roos
2139072543f58037697772663ed34ee26317e9d662c5Amith Yamasani    private static final String[] SETTINGS_TO_BACKUP = new String[] {
21401de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu            Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
2141e483b56ea8454886a892a6840d3f71ce9fd5becfBryan Mawhinney            Secure.LOCK_SCREEN_OWNER_INFO,
2142e483b56ea8454886a892a6840d3f71ce9fd5becfBryan Mawhinney            Secure.LOCK_PATTERN_VISIBLE,
2143e483b56ea8454886a892a6840d3f71ce9fd5becfBryan Mawhinney            LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
2144072543f58037697772663ed34ee26317e9d662c5Amith Yamasani    };
2145072543f58037697772663ed34ee26317e9d662c5Amith Yamasani
2146301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales    private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
2147301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        @Override
2148301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        public void binderDied() {
2149301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            mGateKeeperService.asBinder().unlinkToDeath(this, 0);
2150301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            mGateKeeperService = null;
2151301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales        }
2152301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales    }
2153301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales
21543bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected synchronized IGateKeeperService getGateKeeperService()
2155301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            throws RemoteException {
21568fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        if (mGateKeeperService != null) {
21578fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            return mGateKeeperService;
21588fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
21598fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
21601de89b3bec2f296763f3ecde9a36ecbca2110f3dRubin Xu        final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
21618fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        if (service != null) {
2162301ea449921663ffe5673fb5751a7185a40bd5eaAndres Morales            service.linkToDeath(new GateKeeperDiedRecipient(), 0);
21638fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
21648fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales            return mGateKeeperService;
21658fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        }
21668fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales
21678fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        Slog.e(TAG, "Unable to acquire GateKeeperService");
21688fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales        return null;
21698fa5665f0e757cec0063fb4cf1354f1596f93a91Andres Morales    }
21703bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
21713bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    /**
21721416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     * A user's synthetic password does not change so it must be cached in certain circumstances to
21731416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     * enable untrusted credential reset.
21741416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     *
21751416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     * Untrusted credential reset will be removed in a future version (b/68036371) at which point
21761416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     * this cache is no longer needed as the SP will always be known when changing the user's
21771416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     * credential.
21781416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     */
21791416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    @GuardedBy("mSpManager")
21801416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    private SparseArray<AuthenticationToken> mSpCache = new SparseArray();
21811416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
21821416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
2183ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        // Preemptively cache the SP and then try to remove it in a handler.
2184ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        Slog.i(TAG, "Caching SP for user " + userId);
2185ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        synchronized (mSpManager) {
2186ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull            mSpCache.put(userId, auth);
2187ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        }
2188ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        tryRemoveUserFromSpCacheLater(userId);
2189ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull
2190e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        // Pass the primary user's auth secret to the HAL
2191e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
2192e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            try {
2193e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                final byte[] rawSecret = auth.deriveVendorAuthSecret();
2194e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length);
2195e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                for (int i = 0; i < rawSecret.length; ++i) {
2196e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                    secret.add(rawSecret[i]);
2197e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                }
2198e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                mAuthSecretService.primaryUserCredential(secret);
2199e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            } catch (RemoteException e) {
2200e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull                Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
2201e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull            }
2202e6527c1285cf38057d95c33f5fac4f4ea124e003Andrew Scull        }
22031416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    }
22041416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
2205ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull    private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) {
2206ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        mHandler.post(() -> {
2207ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull            if (!shouldCacheSpForUser(userId)) {
2208ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                // The transition from 'should not cache' to 'should cache' can only happen if
2209ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                // certain admin apps are installed after provisioning e.g. via adb. This is not
2210ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                // a common case and we do not seamlessly support; it may result in the SP not
2211ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                // being cached when it is needed. The cache can be re-populated by verifying
2212ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                // the credential again.
2213ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                Slog.i(TAG, "Removing SP from cache for user " + userId);
2214ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                synchronized (mSpManager) {
2215ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                    mSpCache.remove(userId);
22161416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                }
22171416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            }
2218ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        });
22191416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    }
22201416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
2221ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull    /** Do not hold any of the locks from this service when calling. */
22221416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    private boolean shouldCacheSpForUser(@UserIdInt int userId) {
22231416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        // Before the user setup has completed, an admin could be installed that requires the SP to
22241416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        // be cached (see below).
22251416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
22261416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                    Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) {
22271416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            return true;
22281416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        }
22291416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
22301416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        // If the user has an admin which can perform an untrusted credential reset, the SP needs to
22311416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first
22321416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        // place so caching is not necessary.
22331416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
22341416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                DevicePolicyManagerInternal.class);
22351416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        if (dpmi == null) {
22361416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            return false;
22371416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        }
22381416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        return dpmi.canUserHaveUntrustedCredentialReset(userId);
22391416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    }
22401416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
22411416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    /**
22423bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * Precondition: vold and keystore unlocked.
22433bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22443bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * Create new synthetic password, set up synthetic password blob protected by the supplied
22453bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * user credential, and make the newly-created SP blob active.
22463bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22473bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * The invariant under a synthetic password is:
22483bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 1. If user credential exists, then both vold and keystore and protected with keys derived
22493bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     from the synthetic password.
22503bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 2. If user credential does not exist, vold and keystore protection are cleared. This is to
22513bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     make it consistent with current behaviour. It also allows ActivityManager to call
22523bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     unlockUser() with empty secret.
22533bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 3. Once a user is migrated to have synthetic password, its value will never change, no matter
22543bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     whether the user changes his lockscreen PIN or clear/reset it. When the user clears its
22553bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     lockscreen PIN, we still maintain the existing synthetic password in a password blob
22561416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull     *     protected by a default PIN.
22573bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 4. The user SID is linked with synthetic password, but its cleared/re-created when the user
22583bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     clears/re-creates his lockscreen PIN.
22593bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22603bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22613bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * Different cases of calling this method:
22623bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 1. credentialHash != null
22633bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     This implies credential != null, a new SP blob will be provisioned, and existing SID
22643bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     migrated to associate with the new SP.
22653bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     This happens during a normal migration case when the user currently has password.
22663bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22673bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 2. credentialhash == null and credential == null
22689a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu     *     A new SP blob and will be created, while the user has no credentials.
22693bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     This can happens when we are activating an escrow token on a unsecured device, during
22703bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     which we want to create the SP structure with an empty user credential.
22719a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu     *     This could also happen during an untrusted reset to clear password.
22723bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
22733bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * 3. credentialhash == null and credential != null
22743bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     This is the untrusted credential reset, OR the user sets a new lockscreen password
22753bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *     FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
22763bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     */
22771416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    @GuardedBy("mSpManager")
227816c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu    @VisibleForTesting
227916c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu    protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
22807374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            String credential, int credentialType, int requestedQuality,
22817374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            int userId) throws RemoteException {
22823bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
22839a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu        final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
22849a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                getGateKeeperService(), credentialHash, credential, userId);
22851416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        onAuthTokenKnownForUser(userId, auth);
22863bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (auth == null) {
22873bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token");
22883bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            return null;
22893bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
22903bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
22917374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                credential, credentialType, auth, requestedQuality, userId);
22923bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (credential != null) {
22933bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (credentialHash == null) {
22943bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // Since when initializing SP, we didn't provide an existing password handle
22953bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // for it to migrate SID, we need to create a new SID for the user.
22963bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
22973bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
22983bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
22993bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
23003bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            setKeystorePassword(auth.deriveKeyStorePassword(), userId);
23013bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        } else {
23023bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            clearUserKeyProtection(userId);
23033bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            setKeystorePassword(null, userId);
23043bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            getGateKeeperService().clearSecureUserId(userId);
23053bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
23063bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        fixateNewestUserKeyAuth(userId);
23073bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
23083bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return auth;
23093bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
23103bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
23113bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private long getSyntheticPasswordHandleLocked(int userId) {
231260dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos        return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY,
231360dcbbf9232dc4b19c39c0a131b9819ea86dbda2Adrian Roos                SyntheticPasswordManager.DEFAULT_HANDLE, userId);
23143bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
23153bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2316fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
23177374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        if (userId == USER_FRP) {
23187374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            final int type = mStorage.readPersistentDataBlock().type;
23197374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
23207374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
23213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long handle = getSyntheticPasswordHandleLocked(userId);
23223bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        // This is a global setting
23237a0cc0a7fbfaae2843dd333ab8e62731bc04e2b2Paul Crowley        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
23247a0cc0a7fbfaae2843dd333ab8e62731bc04e2b2Paul Crowley                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
23253bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu      return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
23263bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
23273bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
232816c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu    @VisibleForTesting
2329fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
23303bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long handle = getSyntheticPasswordHandleLocked(userId);
23313bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        // This is a global setting
23327a0cc0a7fbfaae2843dd333ab8e62731bc04e2b2Paul Crowley        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
23337a0cc0a7fbfaae2843dd333ab8e62731bc04e2b2Paul Crowley                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
23343bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
23353bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
23363bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2337fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private void enableSyntheticPasswordLocked() {
23383bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
23393bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
23403bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2341e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu    private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int
23423bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            credentialType, boolean hasChallenge, long challenge, int userId,
23433bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            ICheckCredentialProgressCallback progressCallback) throws RemoteException {
2344e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId);
23453bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
23463bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            userCredential = null;
23473bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
23487374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
2349e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        final AuthenticationResult authResult;
2350e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        VerifyCredentialResponse response;
2351e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        synchronized (mSpManager) {
2352e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
2353e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                return null;
2354e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            }
2355e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            if (userId == USER_FRP) {
2356e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                return mSpManager.verifyFrpCredential(getGateKeeperService(),
2357e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                        userCredential, credentialType, progressCallback);
2358e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            }
23593bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2360e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            long handle = getSyntheticPasswordHandleLocked(userId);
2361e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
2362cf326f1882476d76a63f5b700a397088c312e050Rubin Xu                    getGateKeeperService(), handle, userCredential, userId, progressCallback);
2363e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu
236416c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu            if (authResult.credentialType != credentialType) {
236516c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu                Slog.e(TAG, "Credential type mismatch.");
236616c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu                return VerifyCredentialResponse.ERROR;
236716c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu            }
2368e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            response = authResult.gkResponse;
23693bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // credential has matched
2370e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
2371e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                // perform verifyChallenge with synthetic password which generates the real GK auth
2372e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                // token and response for the current user
2373e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
2374e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                        challenge, userId);
2375e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
2376e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                    // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't
2377e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                    // match the recorded GK password handle.
2378e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                    Slog.wtf(TAG, "verifyChallenge with SP failed.");
2379e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                    return VerifyCredentialResponse.ERROR;
2380e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu                }
23813bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
2382e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        }
2383e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu
2384e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
23853bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            notifyActivePasswordMetricsAvailable(userCredential, userId);
23863bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
23873bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
23883bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
23893bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
23903bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            unlockUser(userId, null, secret);
23913bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2392e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            activateEscrowTokens(authResult.authToken, userId);
2393e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu
23943bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (isManagedProfileWithSeparatedLock(userId)) {
23953bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                TrustManager trustManager =
23963bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                        (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
23973bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                trustManager.setDeviceLockedForUser(userId, false);
23983bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
2399e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
24001416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull
24011416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            onAuthTokenKnownForUser(userId, authResult.authToken);
24023bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
24033bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (response.getTimeout() > 0) {
24043bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
24053bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
24063bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
24073bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24083bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return response;
24093bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
24103bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24113bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    /**
24123bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * Change the user's lockscreen password by creating a new SP blob and update the handle, based
24133bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * on an existing authentication token. Even though a new SP blob is created, the underlying
24143bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * synthetic password is never changed.
24153bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     *
24163bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * When clearing credential, we keep the SP unchanged, but clear its password handle so its
24173bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * SID is gone. We also clear password from (software-based) keystore and vold, which will be
24183bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     * added back when new password is set in future.
24193bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu     */
24201416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    @GuardedBy("mSpManager")
24213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private long setLockCredentialWithAuthTokenLocked(String credential, int credentialType,
24227374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            AuthenticationToken auth, int requestedQuality, int userId) throws RemoteException {
24233bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
24243bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
24257374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                credential, credentialType, auth, requestedQuality, userId);
24263bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        final Map<Integer, String> profilePasswords;
24273bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (credential != null) {
24283bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // // not needed by synchronizeUnifiedWorkChallengeForProfiles()
24293bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            profilePasswords = null;
24303bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24313bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            if (mSpManager.hasSidForUser(userId)) {
24323bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // We are changing password of a secured device, nothing more needed as
24333bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // createPasswordBasedSyntheticPassword has already taken care of maintaining
24343bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // the password handle and SID unchanged.
24353bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24363bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                //refresh auth token
24373bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
24383bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            } else {
24393bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // A new password is set on a previously-unsecured device, we need to generate
24403bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                // a new SID, and re-add keys to vold and keystore.
24413bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
24423bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                mSpManager.verifyChallenge(getGateKeeperService(), auth, 0L, userId);
24433bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
24443bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                fixateNewestUserKeyAuth(userId);
24453bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                setKeystorePassword(auth.deriveKeyStorePassword(), userId);
24463bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
24473bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        } else {
24483bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // Cache all profile password if they use unified work challenge. This will later be
24493bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
24503bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
24513bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24523bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // we are clearing password of a secured device, so need to nuke SID as well.
24533bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            mSpManager.clearSidForUser(userId);
24543bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            getGateKeeperService().clearSecureUserId(userId);
24553bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // Clear key from vold so ActivityManager can just unlock the user with empty secret
24563bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // during boot.
24573bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            clearUserKeyProtection(userId);
24583bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            fixateNewestUserKeyAuth(userId);
24593bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            setKeystorePassword(null, userId);
24603bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
24613bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
24623bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
24637cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu
24647cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu        notifyActivePasswordMetricsAvailable(credential, userId);
24653bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return newHandle;
24663bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
24673bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
24681416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull    @GuardedBy("mSpManager")
24693bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private void spBasedSetLockCredentialInternalLocked(String credential, int credentialType,
24707374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            String savedCredential, int requestedQuality, int userId) throws RemoteException {
24713bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
24723bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (isManagedProfileWithUnifiedLock(userId)) {
24733bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            // get credential from keystore when managed profile has unified lock
24743bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            try {
24753bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                savedCredential = getDecryptedPasswordForTiedProfile(userId);
24763bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            } catch (FileNotFoundException e) {
24773bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                Slog.i(TAG, "Child profile key not found");
24783bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
24793bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    | NoSuchAlgorithmException | NoSuchPaddingException
24803bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    | InvalidAlgorithmParameterException | IllegalBlockSizeException
24813bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                    | BadPaddingException | CertificateException | IOException e) {
24823bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                Slog.e(TAG, "Failed to decrypt child profile key", e);
24833bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
24843bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
24853bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long handle = getSyntheticPasswordHandleLocked(userId);
24868b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
2487cf326f1882476d76a63f5b700a397088c312e050Rubin Xu                getGateKeeperService(), handle, savedCredential, userId, null);
24888b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        VerifyCredentialResponse response = authResult.gkResponse;
24898b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        AuthenticationToken auth = authResult.authToken;
249016c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu
249116c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu        // If existing credential is provided, then it must match.
249216c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu        if (savedCredential != null && auth == null) {
249316c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu            throw new RemoteException("Failed to enroll " +
249416c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu                    (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
249516c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu                            : "pattern"));
249616c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu        }
249716c823ebf398138add71ad8ff82053e3676f85c3Rubin Xu
24989a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu        boolean untrustedReset = false;
24993bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (auth != null) {
25001416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            onAuthTokenKnownForUser(userId, auth);
25018b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        } else if (response != null
25021416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
25039a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // We are performing an untrusted credential change, by DevicePolicyManager or other
25049a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // internal callers that don't provide the existing credential
25053bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            Slog.w(TAG, "Untrusted credential change invoked");
25069a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // Try to get a cached auth token, so we can keep SP unchanged.
25079a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            auth = mSpCache.get(userId);
25089a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            untrustedReset = true;
25098b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu        } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
25108b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu            Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
25118b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu                    (response != null ? "rate limit exceeded" : "failed"));
25128b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu            return;
25133bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
25149a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu
25159a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu        if (auth != null) {
25169a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            if (untrustedReset) {
25179a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                // Force change the current SID to mantain existing behaviour that an untrusted
25189a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                // reset leads to a change of SID. If the untrusted reset is for clearing the
25199a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                // current password, the nuking of the SID will be done in
25209a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                // setLockCredentialWithAuthTokenLocked next
25219a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
25229a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            }
25239a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality,
25249a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                    userId);
25259a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
25269a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu        } else {
25279a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            throw new IllegalStateException(
25289a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu                    "Untrusted credential reset not possible without cached SP");
25299a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // Could call initializeSyntheticPasswordLocked(null, credential, credentialType,
25309a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // requestedQuality, userId) instead if we still allow untrusted reset that changes
25319a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu            // synthetic password. That would invalidate existing escrow tokens though.
25329a6d39a5d79687bbdc80c554bc524d7dfc2c5f20Rubin Xu        }
25336e16724fb66e4bd14274768174379aa88c34464fDmitry Dementyev        mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
2534f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2535f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2536f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu    /**
2537f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu     * Returns a fixed pseudorandom byte string derived from the user's synthetic password.
2538f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu     * This is used to salt the password history hash to protect the hash against offline
2539f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu     * bruteforcing, since rederiving this value requires a successful authentication.
25404ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu     * If user is a managed profile with unified challenge, currentCredential is ignored.
2541f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu     */
2542f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu    @Override
2543f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu    public byte[] getHashFactor(String currentCredential, int userId) throws RemoteException {
2544f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu        checkPasswordReadPermission(userId);
2545f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu        if (TextUtils.isEmpty(currentCredential)) {
2546f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            currentCredential = null;
2547f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu        }
25484ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu        if (isManagedProfileWithUnifiedLock(userId)) {
25494ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu            try {
25504ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu                currentCredential = getDecryptedPasswordForTiedProfile(userId);
25514ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu            } catch (Exception e) {
25524ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu                Slog.e(TAG, "Failed to get work profile credential", e);
25534ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu                return null;
25544ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu            }
25554ed98986ff33d8b0831951dd1f42cac2aae556adRubin Xu        }
2556f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu        synchronized (mSpManager) {
2557f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
2558f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                Slog.w(TAG, "Synthetic password not enabled");
2559f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                return null;
2560f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            }
2561f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            long handle = getSyntheticPasswordHandleLocked(userId);
2562f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            AuthenticationResult auth = mSpManager.unwrapPasswordBasedSyntheticPassword(
2563f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                    getGateKeeperService(), handle, currentCredential, userId, null);
2564f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            if (auth.authToken == null) {
2565f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                Slog.w(TAG, "Current credential is incorrect");
2566f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu                return null;
2567f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            }
2568f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu            return auth.authToken.derivePasswordHashFactor();
2569f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu        }
2570f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu    }
2571f01e90789eb27bc538df13374b6e67991c0ea829Rubin Xu
2572fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private long addEscrowToken(byte[] token, int userId) throws RemoteException {
2573f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
2574f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2575f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            enableSyntheticPasswordLocked();
25768b30ec3f49d4c8037bc6aa03ed6dd91aff3968adRubin Xu            // Migrate to synthetic password based credentials if the user has no password,
2577f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // the token can then be activated immediately.
2578f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            AuthenticationToken auth = null;
2579f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (!isUserSecure(userId)) {
2580f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                if (shouldMigrateToSyntheticPasswordLocked(userId)) {
2581f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                    auth = initializeSyntheticPasswordLocked(null, null,
25827374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                            LockPatternUtils.CREDENTIAL_TYPE_NONE,
25837374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                            DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
2584f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ {
2585f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                    long pwdHandle = getSyntheticPasswordHandleLocked(userId);
2586f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                    auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
2587cf326f1882476d76a63f5b700a397088c312e050Rubin Xu                            pwdHandle, null, userId, null).authToken;
2588f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                }
2589f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2590128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
2591128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
2592128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                if (!mSpManager.hasEscrowData(userId)) {
2593128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                    throw new SecurityException("Escrow token is disabled on the current user");
2594128180b2d38d2ae4ba1f440ef10534777d643f00Rubin Xu                }
2595f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2596f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
2597f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (auth != null) {
2598f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
2599f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2600f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            return handle;
2601f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2602f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2603f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2604fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private void activateEscrowTokens(AuthenticationToken auth, int userId) {
2605f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
2606f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2607e94a7703cc927c4bf4c4791ea342a57c9217101fRubin Xu            disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
2608f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            for (long handle : mSpManager.getPendingTokensForUser(userId)) {
2609f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
2610f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
2611f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2612f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2613f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2614f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2615fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private boolean isEscrowTokenActive(long handle, int userId) {
2616f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2617f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            return mSpManager.existsHandle(handle, userId);
2618f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2619f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2620f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2621fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private boolean removeEscrowToken(long handle, int userId) {
2622f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2623f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (handle == getSyntheticPasswordHandleLocked(userId)) {
2624f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                Slog.w(TAG, "Cannot remove password handle");
2625f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return false;
2626f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2627f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (mSpManager.removePendingToken(handle, userId)) {
2628f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return true;
2629f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2630f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (mSpManager.existsHandle(handle, userId)) {
2631f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                mSpManager.destroyTokenBasedSyntheticPassword(handle, userId);
2632f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return true;
2633f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            } else {
2634f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return false;
2635f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2636f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2637f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2638f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2639fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
26407374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            byte[] token, int requestedQuality, int userId) throws RemoteException {
2641f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        boolean result;
2642f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2643f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (!mSpManager.hasEscrowData(userId)) {
2644f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                throw new SecurityException("Escrow token is disabled on the current user");
2645f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2646f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            result = setLockCredentialWithTokenInternal(credential, type, tokenHandle, token,
26477374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    requestedQuality, userId);
2648f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2649f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        if (result) {
2650f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            synchronized (mSeparateChallengeLock) {
265128939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov                setSeparateProfileChallengeEnabledLocked(userId, true, null);
2652f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2653f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            notifyPasswordChanged(userId);
265428939988f0da2f37bac87a6929a1584ad18fdebaPavel Grafov            notifySeparateProfileChallengeChanged(userId);
2655f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2656f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        return result;
2657f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2658f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2659f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    private boolean setLockCredentialWithTokenInternal(String credential, int type,
26607374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            long tokenHandle, byte[] token, int requestedQuality, int userId) throws RemoteException {
26611416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        final AuthenticationResult result;
2662f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
26631416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            result = mSpManager.unwrapTokenBasedSyntheticPassword(
2664f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                    getGateKeeperService(), tokenHandle, token, userId);
2665f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (result.authToken == null) {
2666f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                Slog.w(TAG, "Invalid escrow token supplied");
2667f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return false;
2668f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
266924570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu            if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
267024570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu                // Most likely, an untrusted credential reset happened in the past which
267124570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu                // changed the synthetic password
267224570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu                Slog.e(TAG, "Obsolete token: synthetic password derived but it fails GK "
267324570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu                        + "verification.");
267424570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu                return false;
267524570e49f3f56ee9439493cbdc039894eb9af850Rubin Xu            }
26767cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu            // Update PASSWORD_TYPE_KEY since it's needed by notifyActivePasswordMetricsAvailable()
26777cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu            // called by setLockCredentialWithAuthTokenLocked().
26787cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu            // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740
26797cf4509c31f3dc1c32f89c26867a50c4ed0d5618Rubin Xu            setLong(LockPatternUtils.PASSWORD_TYPE_KEY, requestedQuality, userId);
2680f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            long oldHandle = getSyntheticPasswordHandleLocked(userId);
26817374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
26827374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    requestedQuality, userId);
2683f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
2684f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
26851416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        onAuthTokenKnownForUser(userId, result.authToken);
26861416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        return true;
2687f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2688f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
2689fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId)
2690f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            throws RemoteException {
2691f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        AuthenticationResult authResult;
2692f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        synchronized (mSpManager) {
2693f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (!mSpManager.hasEscrowData(userId)) {
2694f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                throw new SecurityException("Escrow token is disabled on the current user");
2695f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2696f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            authResult = mSpManager.unwrapTokenBasedSyntheticPassword(getGateKeeperService(),
2697f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                    tokenHandle, token, userId);
2698f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (authResult.authToken == null) {
2699f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                Slog.w(TAG, "Invalid escrow token supplied");
2700fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                return false;
2701f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2702f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2703f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        unlockUser(userId, null, authResult.authToken.deriveDiskEncryptionKey());
27041416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        onAuthTokenKnownForUser(userId, authResult.authToken);
2705fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        return true;
27063bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
27073bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
27083bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
27093bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
2710fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
27113bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
271204a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu        pw.println("Current lock settings service state:");
271304a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu        pw.println(String.format("SP Enabled = %b",
271404a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu                mLockPatternUtils.isSyntheticPasswordEnabled()));
27153bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
271604a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu        List<UserInfo> users = mUserManager.getUsers();
271704a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu        for (int user = 0; user < users.size(); user++) {
271804a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            final int userId = users.get(user).id;
271904a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            pw.println("    User " + userId);
272004a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            synchronized (mSpManager) {
27213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                pw.println(String.format("        SP Handle = %x",
27223bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                        getSyntheticPasswordHandleLocked(userId)));
272304a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            }
272404a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            try {
272504a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu                pw.println(String.format("        SID = %x",
272604a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu                        getGateKeeperService().getSecureUserId(userId)));
272704a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu            } catch (RemoteException e) {
272804a4e1de71189c6ead8cb363f393ea7e0e4db0c7Rubin Xu                // ignore.
27293bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            }
27303bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
27313bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
27323bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
2733f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
2734f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        long ident = Binder.clearCallingIdentity();
2735f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        try {
2736f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // Managed profile should have escrow enabled
2737f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (mUserManager.getUserInfo(userId).isManagedProfile()) {
2738bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu                Slog.i(TAG, "Managed profile can have escrow token");
2739f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return;
2740f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2741f34d2f607f6dc4f7345c3fd7bacb580ac98c31c5Rubin Xu            DevicePolicyManager dpm = mInjector.getDevicePolicyManager();
2742f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // Devices with Device Owner should have escrow enabled on all users.
2743f34d2f607f6dc4f7345c3fd7bacb580ac98c31c5Rubin Xu            if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
2744bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu                Slog.i(TAG, "Corp-owned device can have escrow token");
2745bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu                return;
2746bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu            }
2747bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu            // We could also have a profile owner on the given (non-managed) user for unicorn cases
2748f34d2f607f6dc4f7345c3fd7bacb580ac98c31c5Rubin Xu            if (dpm.getProfileOwnerAsUser(userId) != null) {
2749bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu                Slog.i(TAG, "User with profile owner can have escrow token");
2750f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return;
2751f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2752f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // If the device is yet to be provisioned (still in SUW), there is still
2753f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // a chance that Device Owner will be set on the device later, so postpone
2754f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // disabling escrow token for now.
2755f34d2f607f6dc4f7345c3fd7bacb580ac98c31c5Rubin Xu            if (!dpm.isDeviceProvisioned()) {
2756bc7a47c6d30943be512f9f982ae4803ff3cdc52aRubin Xu                Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
2757f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                return;
2758f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2759cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer
2760cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer            // Escrow tokens are enabled on automotive builds.
2761cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
2762cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer                return;
2763cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer            }
2764cb18d56eec278b0eeea82c9f309004cb179e79caRakesh Iyer
2765f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            // Disable escrow token permanently on all other device/user types.
2766f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            Slog.i(TAG, "Disabling escrow token on user " + userId);
2767f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
2768f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu                mSpManager.destroyEscrowData(userId);
2769f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            }
2770f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        } finally {
2771f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu            Binder.restoreCallingIdentity(ident);
2772f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu        }
2773f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu    }
2774f095f8366bac52ac1eeb2b3eb1a403294ceeb541Rubin Xu
27757374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    private class DeviceProvisionedObserver extends ContentObserver {
27767374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
27777374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                Settings.Global.DEVICE_PROVISIONED);
27781416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull        private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor(
27791416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                Settings.Secure.USER_SETUP_COMPLETE);
27807374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
27817374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        private boolean mRegistered;
27827374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
27837374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        public DeviceProvisionedObserver() {
27847374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            super(null);
27857374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
27867374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
27877374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        @Override
2788ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
27897374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            if (mDeviceProvisionedUri.equals(uri)) {
27907374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                updateRegistration();
27917374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
27927374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                if (isProvisioned()) {
27937374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    Slog.i(TAG, "Reporting device setup complete to IGateKeeperService");
27947374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    reportDeviceSetupComplete();
2795454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                    clearFrpCredentialIfOwnerNotSecure();
27967374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                }
27971416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull            } else if (mUserSetupCompleteUri.equals(uri)) {
2798ede482d4af5155a79f2f1eceecc333aa94d8c11bAndrew Scull                tryRemoveUserFromSpCacheLater(userId);
27997374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            }
28007374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
28017374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
28027374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        public void onSystemReady() {
28032adc263ce97ae6c8291653490868879841d31a63Adrian Roos            if (frpCredentialEnabled(mContext)) {
28047374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                updateRegistration();
28057374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            } else {
28067374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                // If we don't intend to use frpCredentials and we're not provisioned yet, send
28077374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                // deviceSetupComplete immediately, so gatekeeper can discard any lingering
28087374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                // credentials immediately.
28097374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                if (!isProvisioned()) {
28107374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    Slog.i(TAG, "FRP credential disabled, reporting device setup complete "
28117374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                            + "to Gatekeeper immediately");
28127374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    reportDeviceSetupComplete();
28137374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                }
28147374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            }
28157374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
28167374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
28177374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        private void reportDeviceSetupComplete() {
28187374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            try {
28197374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                getGateKeeperService().reportDeviceSetupComplete();
28207374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            } catch (RemoteException e) {
28217374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                Slog.e(TAG, "Failure reporting to IGateKeeperService", e);
28227374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            }
28237374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
28247374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
2825454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos        /**
2826454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos         * Clears the FRP credential if the user that controls it does not have a secure
2827454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos         * lockscreen.
2828454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos         */
2829454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos        private void clearFrpCredentialIfOwnerNotSecure() {
2830454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos            List<UserInfo> users = mUserManager.getUsers();
2831454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos            for (UserInfo user : users) {
28322adc263ce97ae6c8291653490868879841d31a63Adrian Roos                if (userOwnsFrpCredential(mContext, user)) {
2833454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                    if (!isUserSecure(user.id)) {
2834454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                        mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id,
2835454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                                0, null);
2836454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                    }
2837454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                    return;
2838454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos                }
2839454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos            }
2840454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos        }
2841454f53f7fd7084d6d9cda4376cb8ff7c4dca7983Adrian Roos
28427374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        private void updateRegistration() {
28437374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            boolean register = !isProvisioned();
28447374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            if (register == mRegistered) {
28457374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                return;
28467374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            }
28477374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            if (register) {
28487374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri,
28497374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                        false, this);
28501416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri,
28511416bd022f344b4fdeadcbdbf2f87e19f0fac7e7Andrew Scull                        false, this, UserHandle.USER_ALL);
28527374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            } else {
28537374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                mContext.getContentResolver().unregisterContentObserver(this);
28547374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            }
28557374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            mRegistered = register;
28567374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
28577374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos
28587374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        private boolean isProvisioned() {
28597374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos            return Settings.Global.getInt(mContext.getContentResolver(),
28607374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
28617374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos        }
28627374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315Adrian Roos    }
2863fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2864fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    private final class LocalService extends LockSettingsInternal {
2865fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2866fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        @Override
2867fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        public long addEscrowToken(byte[] token, int userId) {
2868fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            try {
2869fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                return LockSettingsService.this.addEscrowToken(token, userId);
2870fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            } catch (RemoteException re) {
2871fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                throw re.rethrowFromSystemServer();
2872fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            }
2873fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        }
2874fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2875fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        @Override
2876fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        public boolean removeEscrowToken(long handle, int userId) {
2877fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            return LockSettingsService.this.removeEscrowToken(handle, userId);
2878fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        }
2879fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2880fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        @Override
2881fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        public boolean isEscrowTokenActive(long handle, int userId) {
2882fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            return LockSettingsService.this.isEscrowTokenActive(handle, userId);
2883fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        }
2884fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2885fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        @Override
2886fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
2887fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                byte[] token, int requestedQuality, int userId) {
2888fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            try {
2889fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                return LockSettingsService.this.setLockCredentialWithToken(credential, type,
2890fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                        tokenHandle, token, requestedQuality, userId);
2891fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            } catch (RemoteException re) {
2892fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                throw re.rethrowFromSystemServer();
2893fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            }
2894fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        }
2895fcd49f993ede363d0b17900565dfe37066362480Rubin Xu
2896fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        @Override
2897fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
2898fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            try {
2899fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
2900fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            } catch (RemoteException re) {
2901fcd49f993ede363d0b17900565dfe37066362480Rubin Xu                throw re.rethrowFromSystemServer();
2902fcd49f993ede363d0b17900565dfe37066362480Rubin Xu            }
2903fcd49f993ede363d0b17900565dfe37066362480Rubin Xu        }
2904fcd49f993ede363d0b17900565dfe37066362480Rubin Xu    }
290552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani}
2906