blob: 1cd590c39f49713af411ea5d9b5a653328fe1795 [file] [log] [blame]
Rubin Xu3bf722a2016-12-15 16:07:38 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
Andrew Scull507d11c2017-05-03 17:19:01 +010017package com.android.server.locksettings;
Rubin Xu3bf722a2016-12-15 16:07:38 +000018
Adrian Roos7374d3a2017-03-31 14:14:53 -070019import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
20import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
21import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
22
23import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
Rubin Xu3bf722a2016-12-15 16:07:38 +000024import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
25import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
Andrew Scull7f4ff4c2018-01-05 18:33:58 +000026
Andrew Sculle6527c12018-01-05 18:33:58 +000027import static org.mockito.Mockito.any;
28import static org.mockito.Mockito.atLeastOnce;
29import static org.mockito.Mockito.never;
30import static org.mockito.Mockito.reset;
Rubin Xu7cf45092017-08-28 11:47:35 +010031import static org.mockito.Mockito.verify;
Rubin Xu3bf722a2016-12-15 16:07:38 +000032
Rubin Xu7cf45092017-08-28 11:47:35 +010033import android.app.admin.PasswordMetrics;
Rubin Xu3bf722a2016-12-15 16:07:38 +000034import android.os.RemoteException;
35import android.os.UserHandle;
Pavel Grafov57f1b662019-03-27 14:55:38 +000036import android.platform.test.annotations.Presubmit;
37
38import androidx.test.filters.SmallTest;
Rubin Xu3bf722a2016-12-15 16:07:38 +000039
40import com.android.internal.widget.LockPatternUtils;
41import com.android.internal.widget.VerifyCredentialResponse;
Andrew Scull507d11c2017-05-03 17:19:01 +010042import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
43import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
Adrian Roos7374d3a2017-03-31 14:14:53 -070044import com.android.server.locksettings.SyntheticPasswordManager.PasswordData;
Rubin Xu3bf722a2016-12-15 16:07:38 +000045
Andrew Sculle6527c12018-01-05 18:33:58 +000046import org.mockito.ArgumentCaptor;
47
Lenka Trochtova66c492a2018-12-06 11:29:21 +010048import java.util.ArrayList;
49
Rubin Xu3bf722a2016-12-15 16:07:38 +000050
51/**
Andrew Scull507d11c2017-05-03 17:19:01 +010052 * runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests
Rubin Xu3bf722a2016-12-15 16:07:38 +000053 */
Pavel Grafov57f1b662019-03-27 14:55:38 +000054@SmallTest
55@Presubmit
Rubin Xu3bf722a2016-12-15 16:07:38 +000056public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
57
Adrian Roos7374d3a2017-03-31 14:14:53 -070058 public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55};
59 public static final byte[] PAYLOAD2 = new byte[] {2, 3, -2, -3, 44, 1};
60
Rubin Xu3bf722a2016-12-15 16:07:38 +000061 @Override
62 protected void setUp() throws Exception {
63 super.setUp();
64 }
65
66 @Override
67 protected void tearDown() throws Exception {
68 super.tearDown();
69 }
70
71 public void testPasswordBasedSyntheticPassword() throws RemoteException {
72 final int USER_ID = 10;
Rich Canningsf64ec632019-02-21 12:40:36 -080073 final byte[] password = "user-password".getBytes();
74 final byte[] badPassword = "bad-password".getBytes();
Adrian Roos2adc2632017-09-05 17:01:42 +020075 MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
David Anderson28dea682019-02-20 13:37:51 -080076 mGateKeeperService, mUserManager, mPasswordSlotManager);
Rubin Xu3bf722a2016-12-15 16:07:38 +000077 AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null,
78 null, USER_ID);
Rich Canningsf64ec632019-02-21 12:40:36 -080079 long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService,
80 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken,
81 PASSWORD_QUALITY_ALPHABETIC, USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +000082
Rubin Xucf326f12017-11-15 11:55:35 +000083 AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(
Rich Canningsf64ec632019-02-21 12:40:36 -080084 mGateKeeperService, handle, password, USER_ID, null);
85 assertArrayEquals(result.authToken.deriveKeyStorePassword(),
86 authToken.deriveKeyStorePassword());
Rubin Xu3bf722a2016-12-15 16:07:38 +000087
Rubin Xucf326f12017-11-15 11:55:35 +000088 result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle,
Rich Canningsf64ec632019-02-21 12:40:36 -080089 badPassword, USER_ID, null);
Rubin Xu3bf722a2016-12-15 16:07:38 +000090 assertNull(result.authToken);
91 }
92
Rubin Xu16c823e2017-06-27 14:44:58 +010093 private void disableSyntheticPassword() throws RemoteException {
Rubin Xu3bf722a2016-12-15 16:07:38 +000094 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
95 }
96
Rubin Xu16c823e2017-06-27 14:44:58 +010097 private void enableSyntheticPassword() throws RemoteException {
Rubin Xu3bf722a2016-12-15 16:07:38 +000098 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
99 }
100
101 private boolean hasSyntheticPassword(int userId) throws RemoteException {
102 return mService.getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId) != 0;
103 }
104
105 public void testPasswordMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800106 final byte[] password = "testPasswordMigration-password".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000107
Rubin Xu16c823e2017-06-27 14:44:58 +0100108 disableSyntheticPassword();
Rich Canningsf64ec632019-02-21 12:40:36 -0800109 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000110 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000111 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
112 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
Rubin Xu16c823e2017-06-27 14:44:58 +0100113 enableSyntheticPassword();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000114 // Performs migration
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000115 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800116 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000117 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000118 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
119 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
120
121 // SP-based verification
Rich Canningsf64ec632019-02-21 12:40:36 -0800122 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
123 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000124 .getResponseCode());
125 assertArrayNotEquals(primaryStorageKey,
126 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000127 }
128
Rich Canningsf64ec632019-02-21 12:40:36 -0800129 protected void initializeCredentialUnderSP(byte[] password, int userId) throws RemoteException {
Rubin Xu16c823e2017-06-27 14:44:58 +0100130 enableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700131 int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
132 : PASSWORD_QUALITY_UNSPECIFIED;
133 int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
134 : LockPatternUtils.CREDENTIAL_TYPE_NONE;
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000135 mService.setLockCredential(password, type, null, quality, userId, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000136 }
137
138 public void testSyntheticPasswordChangeCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800139 final byte[] password = "testSyntheticPasswordChangeCredential-password".getBytes();
140 final byte[] newPassword = "testSyntheticPasswordChangeCredential-newpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000141
Rich Canningsf64ec632019-02-21 12:40:36 -0800142 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000143 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
Rich Canningsf64ec632019-02-21 12:40:36 -0800144 mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000145 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000146 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800147 newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000148 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000149 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
150 }
151
152 public void testSyntheticPasswordVerifyCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800153 final byte[] password = "testSyntheticPasswordVerifyCredential-password".getBytes();
154 final byte[] badPassword = "testSyntheticPasswordVerifyCredential-badpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000155
Rich Canningsf64ec632019-02-21 12:40:36 -0800156 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000157 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800158 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000159 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000160
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000161 assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800162 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
163 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000164 }
165
166 public void testSyntheticPasswordClearCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800167 final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
168 final byte[] badPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000169
Rich Canningsf64ec632019-02-21 12:40:36 -0800170 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000171 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
172 // clear password
Rich Canningsf64ec632019-02-21 12:40:36 -0800173 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000174 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000175 assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
176
177 // set a new password
Rich Canningsf64ec632019-02-21 12:40:36 -0800178 mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000179 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000180 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800181 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
182 .getResponseCode());
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000183 assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000184 }
185
Andrew Sculle6527c12018-01-05 18:33:58 +0000186 public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800187 final byte[] password =
188 "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password".getBytes();
189 final byte[] badPassword =
190 "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000191
Rich Canningsf64ec632019-02-21 12:40:36 -0800192 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
193 mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000194 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Sculle6527c12018-01-05 18:33:58 +0000195 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800196 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000197 .getResponseCode());
198
199 // Check the same secret was passed each time
200 ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
201 verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
202 assertEquals(1, secret.getAllValues().stream().distinct().count());
203 }
204
205 public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800206 final byte[] password =
207 "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password".getBytes();
208 final byte[] newPassword =
209 "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000210
Rich Canningsf64ec632019-02-21 12:40:36 -0800211 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Sculle6527c12018-01-05 18:33:58 +0000212 reset(mAuthSecretService);
Rich Canningsf64ec632019-02-21 12:40:36 -0800213 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
214 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000215 .getResponseCode());
216 verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
217 }
218
219 public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800220 final byte[] password = "testSecondaryUserDoesNotPassAuthSecret-password".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000221
Rich Canningsf64ec632019-02-21 12:40:36 -0800222 initializeCredentialUnderSP(password, SECONDARY_USER_ID);
Andrew Sculle6527c12018-01-05 18:33:58 +0000223 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800224 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000225 .getResponseCode());
226 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
227 }
228
Andrew Scullf49794b2018-04-13 12:01:25 +0100229 public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException {
230 // Setting null doesn't create a synthetic password
231 initializeCredentialUnderSP(null, PRIMARY_USER_ID);
232
233 reset(mAuthSecretService);
234 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100235 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100236 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
237 }
238
239 public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800240 final byte[] password = "passwordForASyntheticPassword".getBytes();
241 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Scullf49794b2018-04-13 12:01:25 +0100242
243 reset(mAuthSecretService);
244 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100245 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100246 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
247 }
248
249 public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800250 final byte[] password = "getASyntheticPassword".getBytes();
251 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
252 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000253 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Andrew Scullf49794b2018-04-13 12:01:25 +0100254
255 reset(mAuthSecretService);
256 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100257 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100258 verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
259 }
260
Rubin Xu3bf722a2016-12-15 16:07:38 +0000261 public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800262 final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes();
Rubin Xu16c823e2017-06-27 14:44:58 +0100263 disableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700264 mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000265 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000266 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
267 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
268 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
269 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
270 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
271 assertTrue(primarySid != 0);
272 assertTrue(profileSid != 0);
273 assertTrue(profileSid != primarySid);
274
275 // do migration
Rubin Xu16c823e2017-06-27 14:44:58 +0100276 enableSyntheticPassword();
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000277 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
278 UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
279 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000280
281 // verify
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000282 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
283 UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
284 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000285 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
286 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000287 assertArrayNotEquals(primaryStorageKey,
288 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
289 assertArrayNotEquals(profileStorageKey,
290 mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000291 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
292 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
293 }
294
295 public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800296 final byte[] primaryPassword =
297 "testManagedProfileSeparateChallengeMigration-primary".getBytes();
298 final byte[] profilePassword =
299 "testManagedProfileSeparateChallengeMigration-profile".getBytes();
Rubin Xu16c823e2017-06-27 14:44:58 +0100300 disableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700301 mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000302 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Adrian Roos7374d3a2017-03-31 14:14:53 -0700303 mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000304 PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000305 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
306 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
307 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
308 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
309 assertTrue(primarySid != 0);
310 assertTrue(profileSid != 0);
311 assertTrue(profileSid != primarySid);
312
313 // do migration
Rubin Xu16c823e2017-06-27 14:44:58 +0100314 enableSyntheticPassword();
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000315 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
316 primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
317 .getResponseCode());
318 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
319 profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
320 0, MANAGED_PROFILE_USER_ID).getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000321
322 // verify
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000323 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
324 primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
325 .getResponseCode());
326 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
327 profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
328 0, MANAGED_PROFILE_USER_ID).getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000329 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
330 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000331 assertArrayNotEquals(primaryStorageKey,
332 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
333 assertArrayNotEquals(profileStorageKey,
334 mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000335 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
336 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
337 }
Rubin Xuf095f832017-01-31 15:23:34 +0000338
339 public void testTokenBasedResetPassword() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800340 final byte[] password = "password".getBytes();
341 final byte[] pattern = "123654".getBytes();
342 final byte[] token = "some-high-entropy-secure-token".getBytes();
343 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000344 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
345
Rubin Xufc067732019-03-18 11:01:18 +0000346 assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800347 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100348 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xufc067732019-03-18 11:01:18 +0000349 assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000350
Rich Canningsf64ec632019-02-21 12:40:36 -0800351 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
Rubin Xu7cf45092017-08-28 11:47:35 +0100352 PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100353 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xufc067732019-03-18 11:01:18 +0000354 assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000355
Rich Canningsf64ec632019-02-21 12:40:36 -0800356 mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
357 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000358
Rubin Xu7cf45092017-08-28 11:47:35 +0100359 // Verify DPM gets notified about new device lock
Rubin Xu340e5ba2019-05-14 16:10:03 +0100360 flushHandlerTasks();
Pavel Grafov42904c12019-03-25 15:32:41 +0000361 final PasswordMetrics metric = PasswordMetrics.computeForCredential(
362 LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern);
Rubin Xu7cf45092017-08-28 11:47:35 +0100363 verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
364
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000365 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800366 pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000367 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000368 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
369 }
370
371 public void testTokenBasedClearPassword() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800372 final byte[] password = "password".getBytes();
373 final byte[] pattern = "123654".getBytes();
374 final byte[] token = "some-high-entropy-secure-token".getBytes();
375 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000376 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
377
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800378 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100379 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000380
Rich Canningsf64ec632019-02-21 12:40:36 -0800381 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000382 0, PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100383 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000384
Rubin Xufcd49f92017-08-24 18:21:52 +0100385 mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
Rich Canningsf64ec632019-02-21 12:40:36 -0800386 handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100387 flushHandlerTasks(); // flush the unlockUser() call before changing password again
Rich Canningsf64ec632019-02-21 12:40:36 -0800388 mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
389 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000390
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000391 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800392 pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000393 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000394 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
395 }
396
397 public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800398 final byte[] password = "password".getBytes();
399 final byte[] pattern = "123654".getBytes();
400 final byte[] newPassword = "password".getBytes();
401 final byte[] token = "some-high-entropy-secure-token".getBytes();
402 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000403 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
404
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800405 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100406 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000407
Rich Canningsf64ec632019-02-21 12:40:36 -0800408 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000409 0, PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100410 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000411
Rich Canningsf64ec632019-02-21 12:40:36 -0800412 mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000413 PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
Rubin Xuf095f832017-01-31 15:23:34 +0000414
Rich Canningsf64ec632019-02-21 12:40:36 -0800415 mLocalService.setLockCredentialWithToken(newPassword,
416 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
Rubin Xufcd49f92017-08-24 18:21:52 +0100417 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000418
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000419 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800420 newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000421 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000422 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
423 }
424
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000425 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
426 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800427 final String token = "some-high-entropy-secure-token";
Rubin Xu16c823e2017-06-27 14:44:58 +0100428 enableSyntheticPassword();
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800429 long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100430 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000431 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
432 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
433 }
434
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000435 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
436 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800437 final String token = "some-high-entropy-secure-token";
Rubin Xuf095f832017-01-31 15:23:34 +0000438 initializeCredentialUnderSP(null, PRIMARY_USER_ID);
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800439 long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100440 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000441 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
442 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
443 }
444
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000445 public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
446 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800447 final byte[] token = "some-high-entropy-secure-token".getBytes();
448 final byte[] password = "password".getBytes();
Rubin Xu128180b2017-04-12 18:02:44 +0100449 // Set up pre-SP user password
Rubin Xu16c823e2017-06-27 14:44:58 +0100450 disableSyntheticPassword();
Rich Canningsf64ec632019-02-21 12:40:36 -0800451 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000452 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu16c823e2017-06-27 14:44:58 +0100453 enableSyntheticPassword();
Rubin Xu128180b2017-04-12 18:02:44 +0100454
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800455 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xu128180b2017-04-12 18:02:44 +0100456 // Token not activated immediately since user password exists
Rubin Xufcd49f92017-08-24 18:21:52 +0100457 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xu128180b2017-04-12 18:02:44 +0100458 // Activate token (password gets migrated to SP at the same time)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000459 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800460 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000461 .getResponseCode());
Rubin Xu128180b2017-04-12 18:02:44 +0100462 // Verify token is activated
Rubin Xufcd49f92017-08-24 18:21:52 +0100463 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xu128180b2017-04-12 18:02:44 +0100464 }
465
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100466 public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception {
Rich Canningsf64ec632019-02-21 12:40:36 -0800467 final byte[] password = "password".getBytes();
468 final byte[] pattern = "123654".getBytes();
469 final byte[] token = "some-high-entropy-secure-token".getBytes();
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100470
471 mHasSecureLockScreen = false;
472 enableSyntheticPassword();
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800473 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100474 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
475
476 try {
477 mLocalService.setLockCredentialWithToken(password,
Rich Canningsf64ec632019-02-21 12:40:36 -0800478 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100479 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
480 fail("An exception should have been thrown.");
481 } catch (UnsupportedOperationException e) {
482 // Success - the exception was expected.
483 }
484 assertFalse(mService.havePassword(PRIMARY_USER_ID));
485
486 try {
487 mLocalService.setLockCredentialWithToken(pattern,
Rich Canningsf64ec632019-02-21 12:40:36 -0800488 LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token,
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100489 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
490 fail("An exception should have been thrown.");
491 } catch (UnsupportedOperationException e) {
492 // Success - the exception was expected.
493 }
494 assertFalse(mService.havePattern(PRIMARY_USER_ID));
495 }
496
Rubin Xu4ed98982018-05-23 14:27:53 +0100497 public void testgetHashFactorPrimaryUser() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800498 final byte[] password = "password".getBytes();
Rubin Xu4ed98982018-05-23 14:27:53 +0100499 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000500 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100501 final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
502 assertNotNull(hashFactor);
503
Rich Canningsf64ec632019-02-21 12:40:36 -0800504 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000505 password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100506 final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID);
507 assertNotNull(newHashFactor);
508 // Hash factor should never change after password change/removal
509 assertArrayEquals(hashFactor, newHashFactor);
510 }
511
512 public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800513 final byte[] pattern = "1236".getBytes();
514 mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000515 null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100516 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
517 assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
518 }
519
520 public void testgetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800521 final byte[] primaryPassword = "primary".getBytes();
522 final byte[] profilePassword = "profile".getBytes();
Rubin Xu4ed98982018-05-23 14:27:53 +0100523 mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000524 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100525 mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000526 PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100527 assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
528 }
529
Adrian Roos7374d3a2017-03-31 14:14:53 -0700530 public void testPasswordData_serializeDeserialize() {
531 PasswordData data = new PasswordData();
532 data.scryptN = 11;
533 data.scryptR = 22;
534 data.scryptP = 33;
535 data.passwordType = CREDENTIAL_TYPE_PASSWORD;
536 data.salt = PAYLOAD;
537 data.passwordHandle = PAYLOAD2;
538
539 PasswordData deserialized = PasswordData.fromBytes(data.toBytes());
540
541 assertEquals(11, deserialized.scryptN);
542 assertEquals(22, deserialized.scryptR);
543 assertEquals(33, deserialized.scryptP);
544 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
545 assertArrayEquals(PAYLOAD, deserialized.salt);
546 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
547 }
548
549 public void testPasswordData_deserialize() {
550 // Test that we can deserialize existing PasswordData and don't inadvertently change the
551 // wire format.
552 byte[] serialized = new byte[] {
553 0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD */
554 11, /* scryptN */
555 22, /* scryptR */
556 33, /* scryptP */
557 0, 0, 0, 5, /* salt.length */
558 1, 2, -1, -2, 55, /* salt */
559 0, 0, 0, 6, /* passwordHandle.length */
560 2, 3, -2, -3, 44, 1, /* passwordHandle */
561 };
562 PasswordData deserialized = PasswordData.fromBytes(serialized);
563
564 assertEquals(11, deserialized.scryptN);
565 assertEquals(22, deserialized.scryptR);
566 assertEquals(33, deserialized.scryptP);
567 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
568 assertArrayEquals(PAYLOAD, deserialized.salt);
569 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
570 }
571
David Anderson6ebc25b2019-02-12 16:25:56 -0800572 public void testGsiDisablesAuthSecret() throws RemoteException {
573 mGsiService.setIsGsiRunning(true);
574
Rich Canningsf64ec632019-02-21 12:40:36 -0800575 final byte[] password = "testGsiDisablesAuthSecret-password".getBytes();
David Anderson6ebc25b2019-02-12 16:25:56 -0800576
577 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
578 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
579 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
580 .getResponseCode());
581 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
582 }
583
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000584 // b/62213311
Rubin Xu3bf722a2016-12-15 16:07:38 +0000585 //TODO: add non-migration work profile case, and unify/un-unify transition.
586 //TODO: test token after user resets password
587 //TODO: test token based reset after unified work challenge
588 //TODO: test clear password after unified work challenge
589}