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