blob: d9b13209d28c2bd9a2da308ea1fa1e24ba425649 [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
Kenny Rootd01bb412019-11-22 09:34:03 -080027import static org.junit.Assert.assertEquals;
28import static org.junit.Assert.assertFalse;
29import static org.junit.Assert.assertNotNull;
30import static org.junit.Assert.assertNull;
31import static org.junit.Assert.assertTrue;
32import static org.junit.Assert.fail;
Andrew Sculle6527c12018-01-05 18:33:58 +000033import static org.mockito.Mockito.any;
34import static org.mockito.Mockito.atLeastOnce;
35import static org.mockito.Mockito.never;
36import static org.mockito.Mockito.reset;
Rubin Xu7cf45092017-08-28 11:47:35 +010037import static org.mockito.Mockito.verify;
Rubin Xu3bf722a2016-12-15 16:07:38 +000038
Rubin Xu7cf45092017-08-28 11:47:35 +010039import android.app.admin.PasswordMetrics;
Rubin Xu3bf722a2016-12-15 16:07:38 +000040import android.os.RemoteException;
41import android.os.UserHandle;
Pavel Grafov57f1b662019-03-27 14:55:38 +000042import android.platform.test.annotations.Presubmit;
43
44import androidx.test.filters.SmallTest;
Kenny Rootd01bb412019-11-22 09:34:03 -080045import androidx.test.runner.AndroidJUnit4;
Rubin Xu3bf722a2016-12-15 16:07:38 +000046
47import com.android.internal.widget.LockPatternUtils;
48import com.android.internal.widget.VerifyCredentialResponse;
Andrew Scull507d11c2017-05-03 17:19:01 +010049import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
50import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
Adrian Roos7374d3a2017-03-31 14:14:53 -070051import com.android.server.locksettings.SyntheticPasswordManager.PasswordData;
Rubin Xu3bf722a2016-12-15 16:07:38 +000052
Kenny Rootd01bb412019-11-22 09:34:03 -080053import org.junit.Test;
54import org.junit.runner.RunWith;
Andrew Sculle6527c12018-01-05 18:33:58 +000055import org.mockito.ArgumentCaptor;
56
Lenka Trochtova66c492a2018-12-06 11:29:21 +010057import java.util.ArrayList;
58
Rubin Xu3bf722a2016-12-15 16:07:38 +000059
60/**
Kenny Rootd01bb412019-11-22 09:34:03 -080061 * atest FrameworksServicesTests:SyntheticPasswordTests
Rubin Xu3bf722a2016-12-15 16:07:38 +000062 */
Pavel Grafov57f1b662019-03-27 14:55:38 +000063@SmallTest
64@Presubmit
Kenny Rootd01bb412019-11-22 09:34:03 -080065@RunWith(AndroidJUnit4.class)
Rubin Xu3bf722a2016-12-15 16:07:38 +000066public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
67
Adrian Roos7374d3a2017-03-31 14:14:53 -070068 public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55};
69 public static final byte[] PAYLOAD2 = new byte[] {2, 3, -2, -3, 44, 1};
70
Kenny Rootd01bb412019-11-22 09:34:03 -080071 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +000072 public void testPasswordBasedSyntheticPassword() throws RemoteException {
73 final int USER_ID = 10;
Rich Canningsf64ec632019-02-21 12:40:36 -080074 final byte[] password = "user-password".getBytes();
75 final byte[] badPassword = "bad-password".getBytes();
Adrian Roos2adc2632017-09-05 17:01:42 +020076 MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
David Anderson28dea682019-02-20 13:37:51 -080077 mGateKeeperService, mUserManager, mPasswordSlotManager);
Rubin Xu3bf722a2016-12-15 16:07:38 +000078 AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null,
79 null, USER_ID);
Rich Canningsf64ec632019-02-21 12:40:36 -080080 long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService,
81 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken,
82 PASSWORD_QUALITY_ALPHABETIC, USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +000083
Rubin Xucf326f12017-11-15 11:55:35 +000084 AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(
Rich Canningsf64ec632019-02-21 12:40:36 -080085 mGateKeeperService, handle, password, USER_ID, null);
86 assertArrayEquals(result.authToken.deriveKeyStorePassword(),
87 authToken.deriveKeyStorePassword());
Rubin Xu3bf722a2016-12-15 16:07:38 +000088
Rubin Xucf326f12017-11-15 11:55:35 +000089 result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle,
Rich Canningsf64ec632019-02-21 12:40:36 -080090 badPassword, USER_ID, null);
Rubin Xu3bf722a2016-12-15 16:07:38 +000091 assertNull(result.authToken);
92 }
93
Rubin Xu16c823e2017-06-27 14:44:58 +010094 private void disableSyntheticPassword() throws RemoteException {
Rubin Xu3bf722a2016-12-15 16:07:38 +000095 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM);
96 }
97
Rubin Xu16c823e2017-06-27 14:44:58 +010098 private void enableSyntheticPassword() throws RemoteException {
Rubin Xu3bf722a2016-12-15 16:07:38 +000099 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
100 }
101
102 private boolean hasSyntheticPassword(int userId) throws RemoteException {
103 return mService.getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId) != 0;
104 }
105
Kenny Rootd01bb412019-11-22 09:34:03 -0800106 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000107 public void testPasswordMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800108 final byte[] password = "testPasswordMigration-password".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000109
Rubin Xu16c823e2017-06-27 14:44:58 +0100110 disableSyntheticPassword();
Rich Canningsf64ec632019-02-21 12:40:36 -0800111 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000112 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000113 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
114 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
Rubin Xu16c823e2017-06-27 14:44:58 +0100115 enableSyntheticPassword();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000116 // Performs migration
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000117 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800118 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000119 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000120 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
121 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
122
123 // SP-based verification
Rich Canningsf64ec632019-02-21 12:40:36 -0800124 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
125 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000126 .getResponseCode());
127 assertArrayNotEquals(primaryStorageKey,
128 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000129 }
130
Rich Canningsf64ec632019-02-21 12:40:36 -0800131 protected void initializeCredentialUnderSP(byte[] password, int userId) throws RemoteException {
Rubin Xu16c823e2017-06-27 14:44:58 +0100132 enableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700133 int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
134 : PASSWORD_QUALITY_UNSPECIFIED;
135 int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
136 : LockPatternUtils.CREDENTIAL_TYPE_NONE;
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000137 mService.setLockCredential(password, type, null, quality, userId, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000138 }
139
Kenny Rootd01bb412019-11-22 09:34:03 -0800140 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000141 public void testSyntheticPasswordChangeCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800142 final byte[] password = "testSyntheticPasswordChangeCredential-password".getBytes();
143 final byte[] newPassword = "testSyntheticPasswordChangeCredential-newpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000144
Rich Canningsf64ec632019-02-21 12:40:36 -0800145 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000146 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
Rich Canningsf64ec632019-02-21 12:40:36 -0800147 mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000148 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000149 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800150 newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000151 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000152 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
153 }
154
Kenny Rootd01bb412019-11-22 09:34:03 -0800155 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000156 public void testSyntheticPasswordVerifyCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800157 final byte[] password = "testSyntheticPasswordVerifyCredential-password".getBytes();
158 final byte[] badPassword = "testSyntheticPasswordVerifyCredential-badpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000159
Rich Canningsf64ec632019-02-21 12:40:36 -0800160 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000161 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800162 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000163 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000164
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000165 assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800166 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
167 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000168 }
169
Kenny Rootd01bb412019-11-22 09:34:03 -0800170 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000171 public void testSyntheticPasswordClearCredential() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800172 final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
173 final byte[] badPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
Rubin Xu3bf722a2016-12-15 16:07:38 +0000174
Rich Canningsf64ec632019-02-21 12:40:36 -0800175 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000176 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
177 // clear password
Rich Canningsf64ec632019-02-21 12:40:36 -0800178 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000179 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000180 assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
181
182 // set a new password
Rich Canningsf64ec632019-02-21 12:40:36 -0800183 mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000184 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000185 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800186 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
187 .getResponseCode());
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000188 assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000189 }
190
Kenny Rootd01bb412019-11-22 09:34:03 -0800191 @Test
Andrew Sculle6527c12018-01-05 18:33:58 +0000192 public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800193 final byte[] password =
194 "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password".getBytes();
195 final byte[] badPassword =
196 "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000197
Rich Canningsf64ec632019-02-21 12:40:36 -0800198 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
199 mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000200 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Andrew Sculle6527c12018-01-05 18:33:58 +0000201 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800202 badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000203 .getResponseCode());
204
205 // Check the same secret was passed each time
206 ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
207 verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
208 assertEquals(1, secret.getAllValues().stream().distinct().count());
209 }
210
Kenny Rootd01bb412019-11-22 09:34:03 -0800211 @Test
Andrew Sculle6527c12018-01-05 18:33:58 +0000212 public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800213 final byte[] password =
214 "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password".getBytes();
215 final byte[] newPassword =
216 "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000217
Rich Canningsf64ec632019-02-21 12:40:36 -0800218 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Sculle6527c12018-01-05 18:33:58 +0000219 reset(mAuthSecretService);
Rich Canningsf64ec632019-02-21 12:40:36 -0800220 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
221 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000222 .getResponseCode());
223 verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
224 }
225
Kenny Rootd01bb412019-11-22 09:34:03 -0800226 @Test
Andrew Sculle6527c12018-01-05 18:33:58 +0000227 public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800228 final byte[] password = "testSecondaryUserDoesNotPassAuthSecret-password".getBytes();
Andrew Sculle6527c12018-01-05 18:33:58 +0000229
Rich Canningsf64ec632019-02-21 12:40:36 -0800230 initializeCredentialUnderSP(password, SECONDARY_USER_ID);
Andrew Sculle6527c12018-01-05 18:33:58 +0000231 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800232 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
Andrew Sculle6527c12018-01-05 18:33:58 +0000233 .getResponseCode());
234 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
235 }
236
Kenny Rootd01bb412019-11-22 09:34:03 -0800237 @Test
Andrew Scullf49794b2018-04-13 12:01:25 +0100238 public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException {
239 // Setting null doesn't create a synthetic password
240 initializeCredentialUnderSP(null, PRIMARY_USER_ID);
241
242 reset(mAuthSecretService);
243 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100244 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100245 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
246 }
247
Kenny Rootd01bb412019-11-22 09:34:03 -0800248 @Test
Andrew Scullf49794b2018-04-13 12:01:25 +0100249 public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800250 final byte[] password = "passwordForASyntheticPassword".getBytes();
251 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Andrew Scullf49794b2018-04-13 12:01:25 +0100252
253 reset(mAuthSecretService);
254 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100255 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100256 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
257 }
258
Kenny Rootd01bb412019-11-22 09:34:03 -0800259 @Test
Andrew Scullf49794b2018-04-13 12:01:25 +0100260 public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800261 final byte[] password = "getASyntheticPassword".getBytes();
262 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
263 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000264 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Andrew Scullf49794b2018-04-13 12:01:25 +0100265
266 reset(mAuthSecretService);
267 mService.onUnlockUser(PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100268 flushHandlerTasks();
Andrew Scullf49794b2018-04-13 12:01:25 +0100269 verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
270 }
271
Kenny Rootd01bb412019-11-22 09:34:03 -0800272 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000273 public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800274 final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes();
Rubin Xu16c823e2017-06-27 14:44:58 +0100275 disableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700276 mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000277 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000278 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
279 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
280 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
281 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
282 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
283 assertTrue(primarySid != 0);
284 assertTrue(profileSid != 0);
285 assertTrue(profileSid != primarySid);
286
287 // do migration
Rubin Xu16c823e2017-06-27 14:44:58 +0100288 enableSyntheticPassword();
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000289 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
290 UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
291 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000292
293 // verify
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000294 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
295 UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
296 .getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000297 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
298 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000299 assertArrayNotEquals(primaryStorageKey,
300 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
301 assertArrayNotEquals(profileStorageKey,
302 mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000303 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
304 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
305 }
306
Kenny Rootd01bb412019-11-22 09:34:03 -0800307 @Test
Rubin Xu3bf722a2016-12-15 16:07:38 +0000308 public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800309 final byte[] primaryPassword =
310 "testManagedProfileSeparateChallengeMigration-primary".getBytes();
311 final byte[] profilePassword =
312 "testManagedProfileSeparateChallengeMigration-profile".getBytes();
Rubin Xu16c823e2017-06-27 14:44:58 +0100313 disableSyntheticPassword();
Adrian Roos7374d3a2017-03-31 14:14:53 -0700314 mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000315 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Adrian Roos7374d3a2017-03-31 14:14:53 -0700316 mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000317 PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
Rubin Xu3bf722a2016-12-15 16:07:38 +0000318 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
319 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
320 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
321 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
322 assertTrue(primarySid != 0);
323 assertTrue(profileSid != 0);
324 assertTrue(profileSid != primarySid);
325
326 // do migration
Rubin Xu16c823e2017-06-27 14:44:58 +0100327 enableSyntheticPassword();
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000328 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
329 primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
330 .getResponseCode());
331 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
332 profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
333 0, MANAGED_PROFILE_USER_ID).getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000334
335 // verify
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000336 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
337 primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
338 .getResponseCode());
339 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
340 profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
341 0, MANAGED_PROFILE_USER_ID).getResponseCode());
Rubin Xu3bf722a2016-12-15 16:07:38 +0000342 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
343 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000344 assertArrayNotEquals(primaryStorageKey,
345 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
346 assertArrayNotEquals(profileStorageKey,
347 mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
Rubin Xu3bf722a2016-12-15 16:07:38 +0000348 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
349 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
350 }
Rubin Xuf095f832017-01-31 15:23:34 +0000351
Kenny Rootd01bb412019-11-22 09:34:03 -0800352 @Test
Rubin Xuf095f832017-01-31 15:23:34 +0000353 public void testTokenBasedResetPassword() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800354 final byte[] password = "password".getBytes();
355 final byte[] pattern = "123654".getBytes();
356 final byte[] token = "some-high-entropy-secure-token".getBytes();
357 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000358 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
359
Rubin Xufc067732019-03-18 11:01:18 +0000360 assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800361 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100362 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xufc067732019-03-18 11:01:18 +0000363 assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000364
Rich Canningsf64ec632019-02-21 12:40:36 -0800365 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
Rubin Xu7cf45092017-08-28 11:47:35 +0100366 PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100367 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xufc067732019-03-18 11:01:18 +0000368 assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000369
Rich Canningsf64ec632019-02-21 12:40:36 -0800370 mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
371 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000372
Rubin Xu7cf45092017-08-28 11:47:35 +0100373 // Verify DPM gets notified about new device lock
Rubin Xu340e5ba2019-05-14 16:10:03 +0100374 flushHandlerTasks();
Pavel Grafov42904c12019-03-25 15:32:41 +0000375 final PasswordMetrics metric = PasswordMetrics.computeForCredential(
376 LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern);
Rubin Xu7cf45092017-08-28 11:47:35 +0100377 verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
378
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000379 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800380 pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000381 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000382 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
383 }
384
Kenny Rootd01bb412019-11-22 09:34:03 -0800385 @Test
Rubin Xuf095f832017-01-31 15:23:34 +0000386 public void testTokenBasedClearPassword() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800387 final byte[] password = "password".getBytes();
388 final byte[] pattern = "123654".getBytes();
389 final byte[] token = "some-high-entropy-secure-token".getBytes();
390 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000391 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
392
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800393 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100394 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000395
Rich Canningsf64ec632019-02-21 12:40:36 -0800396 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000397 0, PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100398 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000399
Rubin Xufcd49f92017-08-24 18:21:52 +0100400 mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
Rich Canningsf64ec632019-02-21 12:40:36 -0800401 handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
Rubin Xu340e5ba2019-05-14 16:10:03 +0100402 flushHandlerTasks(); // flush the unlockUser() call before changing password again
Rich Canningsf64ec632019-02-21 12:40:36 -0800403 mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
404 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000405
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000406 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800407 pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000408 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000409 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
410 }
411
Kenny Rootd01bb412019-11-22 09:34:03 -0800412 @Test
Rubin Xuf095f832017-01-31 15:23:34 +0000413 public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800414 final byte[] password = "password".getBytes();
415 final byte[] pattern = "123654".getBytes();
416 final byte[] newPassword = "password".getBytes();
417 final byte[] token = "some-high-entropy-secure-token".getBytes();
418 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000419 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
420
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800421 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100422 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000423
Rich Canningsf64ec632019-02-21 12:40:36 -0800424 mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000425 0, PRIMARY_USER_ID).getResponseCode();
Rubin Xufcd49f92017-08-24 18:21:52 +0100426 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000427
Rich Canningsf64ec632019-02-21 12:40:36 -0800428 mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000429 PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
Rubin Xuf095f832017-01-31 15:23:34 +0000430
Rich Canningsf64ec632019-02-21 12:40:36 -0800431 mLocalService.setLockCredentialWithToken(newPassword,
432 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
Rubin Xufcd49f92017-08-24 18:21:52 +0100433 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
Rubin Xuf095f832017-01-31 15:23:34 +0000434
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000435 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800436 newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000437 .getResponseCode());
Rubin Xuf095f832017-01-31 15:23:34 +0000438 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
439 }
440
Kenny Rootd01bb412019-11-22 09:34:03 -0800441 @Test
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000442 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
443 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800444 final String token = "some-high-entropy-secure-token";
Rubin Xu16c823e2017-06-27 14:44:58 +0100445 enableSyntheticPassword();
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800446 long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100447 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000448 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
449 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
450 }
451
Kenny Rootd01bb412019-11-22 09:34:03 -0800452 @Test
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000453 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
454 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800455 final String token = "some-high-entropy-secure-token";
Rubin Xuf095f832017-01-31 15:23:34 +0000456 initializeCredentialUnderSP(null, PRIMARY_USER_ID);
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800457 long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
Rubin Xufcd49f92017-08-24 18:21:52 +0100458 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xuf095f832017-01-31 15:23:34 +0000459 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
460 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
461 }
462
Kenny Rootd01bb412019-11-22 09:34:03 -0800463 @Test
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000464 public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
465 throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800466 final byte[] token = "some-high-entropy-secure-token".getBytes();
467 final byte[] password = "password".getBytes();
Rubin Xu128180b2017-04-12 18:02:44 +0100468 // Set up pre-SP user password
Rubin Xu16c823e2017-06-27 14:44:58 +0100469 disableSyntheticPassword();
Rich Canningsf64ec632019-02-21 12:40:36 -0800470 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000471 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu16c823e2017-06-27 14:44:58 +0100472 enableSyntheticPassword();
Rubin Xu128180b2017-04-12 18:02:44 +0100473
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800474 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Rubin Xu128180b2017-04-12 18:02:44 +0100475 // Token not activated immediately since user password exists
Rubin Xufcd49f92017-08-24 18:21:52 +0100476 assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xu128180b2017-04-12 18:02:44 +0100477 // Activate token (password gets migrated to SP at the same time)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000478 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
Rich Canningsf64ec632019-02-21 12:40:36 -0800479 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000480 .getResponseCode());
Rubin Xu128180b2017-04-12 18:02:44 +0100481 // Verify token is activated
Rubin Xufcd49f92017-08-24 18:21:52 +0100482 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
Rubin Xu128180b2017-04-12 18:02:44 +0100483 }
484
Kenny Rootd01bb412019-11-22 09:34:03 -0800485 @Test
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100486 public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception {
Rich Canningsf64ec632019-02-21 12:40:36 -0800487 final byte[] password = "password".getBytes();
488 final byte[] pattern = "123654".getBytes();
489 final byte[] token = "some-high-entropy-secure-token".getBytes();
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100490
491 mHasSecureLockScreen = false;
492 enableSyntheticPassword();
Ram Periathiruvadi32d53552019-02-19 13:25:46 -0800493 long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100494 assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
495
496 try {
497 mLocalService.setLockCredentialWithToken(password,
Rich Canningsf64ec632019-02-21 12:40:36 -0800498 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100499 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
500 fail("An exception should have been thrown.");
501 } catch (UnsupportedOperationException e) {
502 // Success - the exception was expected.
503 }
504 assertFalse(mService.havePassword(PRIMARY_USER_ID));
505
506 try {
507 mLocalService.setLockCredentialWithToken(pattern,
Rich Canningsf64ec632019-02-21 12:40:36 -0800508 LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token,
Lenka Trochtova66c492a2018-12-06 11:29:21 +0100509 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
510 fail("An exception should have been thrown.");
511 } catch (UnsupportedOperationException e) {
512 // Success - the exception was expected.
513 }
514 assertFalse(mService.havePattern(PRIMARY_USER_ID));
515 }
516
Kenny Rootd01bb412019-11-22 09:34:03 -0800517 @Test
Rubin Xu4ed98982018-05-23 14:27:53 +0100518 public void testgetHashFactorPrimaryUser() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800519 final byte[] password = "password".getBytes();
Rubin Xu4ed98982018-05-23 14:27:53 +0100520 mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000521 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100522 final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
523 assertNotNull(hashFactor);
524
Rich Canningsf64ec632019-02-21 12:40:36 -0800525 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000526 password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100527 final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID);
528 assertNotNull(newHashFactor);
529 // Hash factor should never change after password change/removal
530 assertArrayEquals(hashFactor, newHashFactor);
531 }
532
Kenny Rootd01bb412019-11-22 09:34:03 -0800533 @Test
Rubin Xu4ed98982018-05-23 14:27:53 +0100534 public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800535 final byte[] pattern = "1236".getBytes();
536 mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000537 null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100538 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
539 assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
540 }
541
Kenny Rootd01bb412019-11-22 09:34:03 -0800542 @Test
Rubin Xu4ed98982018-05-23 14:27:53 +0100543 public void testgetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
Rich Canningsf64ec632019-02-21 12:40:36 -0800544 final byte[] primaryPassword = "primary".getBytes();
545 final byte[] profilePassword = "profile".getBytes();
Rubin Xu4ed98982018-05-23 14:27:53 +0100546 mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000547 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100548 mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
Irina Dumitrescuc90674d2019-02-28 17:34:19 +0000549 PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
Rubin Xu4ed98982018-05-23 14:27:53 +0100550 assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
551 }
552
Kenny Rootd01bb412019-11-22 09:34:03 -0800553 @Test
Adrian Roos7374d3a2017-03-31 14:14:53 -0700554 public void testPasswordData_serializeDeserialize() {
555 PasswordData data = new PasswordData();
556 data.scryptN = 11;
557 data.scryptR = 22;
558 data.scryptP = 33;
559 data.passwordType = CREDENTIAL_TYPE_PASSWORD;
560 data.salt = PAYLOAD;
561 data.passwordHandle = PAYLOAD2;
562
563 PasswordData deserialized = PasswordData.fromBytes(data.toBytes());
564
565 assertEquals(11, deserialized.scryptN);
566 assertEquals(22, deserialized.scryptR);
567 assertEquals(33, deserialized.scryptP);
568 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
569 assertArrayEquals(PAYLOAD, deserialized.salt);
570 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
571 }
572
Kenny Rootd01bb412019-11-22 09:34:03 -0800573 @Test
Adrian Roos7374d3a2017-03-31 14:14:53 -0700574 public void testPasswordData_deserialize() {
575 // Test that we can deserialize existing PasswordData and don't inadvertently change the
576 // wire format.
577 byte[] serialized = new byte[] {
578 0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD */
579 11, /* scryptN */
580 22, /* scryptR */
581 33, /* scryptP */
582 0, 0, 0, 5, /* salt.length */
583 1, 2, -1, -2, 55, /* salt */
584 0, 0, 0, 6, /* passwordHandle.length */
585 2, 3, -2, -3, 44, 1, /* passwordHandle */
586 };
587 PasswordData deserialized = PasswordData.fromBytes(serialized);
588
589 assertEquals(11, deserialized.scryptN);
590 assertEquals(22, deserialized.scryptR);
591 assertEquals(33, deserialized.scryptP);
592 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
593 assertArrayEquals(PAYLOAD, deserialized.salt);
594 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
595 }
596
Kenny Rootd01bb412019-11-22 09:34:03 -0800597 @Test
David Anderson6ebc25b2019-02-12 16:25:56 -0800598 public void testGsiDisablesAuthSecret() throws RemoteException {
599 mGsiService.setIsGsiRunning(true);
600
Rich Canningsf64ec632019-02-21 12:40:36 -0800601 final byte[] password = "testGsiDisablesAuthSecret-password".getBytes();
David Anderson6ebc25b2019-02-12 16:25:56 -0800602
603 initializeCredentialUnderSP(password, PRIMARY_USER_ID);
604 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
605 password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
606 .getResponseCode());
607 verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
608 }
609
Andrew Scull7f4ff4c2018-01-05 18:33:58 +0000610 // b/62213311
Rubin Xu3bf722a2016-12-15 16:07:38 +0000611 //TODO: add non-migration work profile case, and unify/un-unify transition.
612 //TODO: test token after user resets password
613 //TODO: test token based reset after unified work challenge
614 //TODO: test clear password after unified work challenge
615}