1 /* 2 * Copyright (C) 2016 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 17 package com.android.server.locksettings; 18 19 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 22 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 23 24 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; 25 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 26 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; 27 28 import static org.mockito.ArgumentMatchers.any; 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.ArgumentMatchers.eq; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.reset; 33 import static org.mockito.Mockito.verify; 34 35 import android.os.RemoteException; 36 import android.platform.test.annotations.Presubmit; 37 import android.service.gatekeeper.GateKeeperResponse; 38 39 import androidx.test.filters.SmallTest; 40 41 import com.android.internal.widget.LockPatternUtils; 42 import com.android.internal.widget.VerifyCredentialResponse; 43 import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle; 44 import com.android.server.locksettings.LockSettingsStorage.CredentialHash; 45 46 /** 47 * runtest frameworks-services -c com.android.server.locksettings.LockSettingsServiceTests 48 */ 49 @SmallTest 50 @Presubmit 51 public class LockSettingsServiceTests extends BaseLockSettingsServiceTests { 52 53 @Override setUp()54 protected void setUp() throws Exception { 55 super.setUp(); 56 } 57 58 @Override tearDown()59 protected void tearDown() throws Exception { 60 super.tearDown(); 61 } 62 testCreatePasswordPrimaryUser()63 public void testCreatePasswordPrimaryUser() throws RemoteException { 64 testCreateCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, 65 PASSWORD_QUALITY_ALPHABETIC); 66 } 67 testCreatePasswordFailsWithoutLockScreen()68 public void testCreatePasswordFailsWithoutLockScreen() throws RemoteException { 69 testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "password", 70 CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC); 71 } 72 testCreatePatternPrimaryUser()73 public void testCreatePatternPrimaryUser() throws RemoteException { 74 testCreateCredential(PRIMARY_USER_ID, "123456789", CREDENTIAL_TYPE_PATTERN, 75 PASSWORD_QUALITY_SOMETHING); 76 } 77 testCreatePatternFailsWithoutLockScreen()78 public void testCreatePatternFailsWithoutLockScreen() throws RemoteException { 79 testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "123456789", 80 CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING); 81 } 82 testChangePasswordPrimaryUser()83 public void testChangePasswordPrimaryUser() throws RemoteException { 84 testChangeCredentials(PRIMARY_USER_ID, "78963214", CREDENTIAL_TYPE_PATTERN, 85 "asdfghjk", CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC); 86 } 87 testChangePatternPrimaryUser()88 public void testChangePatternPrimaryUser() throws RemoteException { 89 testChangeCredentials(PRIMARY_USER_ID, "!£$%^&*(())", CREDENTIAL_TYPE_PASSWORD, 90 "1596321", CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING); 91 } 92 testChangePasswordFailPrimaryUser()93 public void testChangePasswordFailPrimaryUser() throws RemoteException { 94 final long sid = 1234; 95 final String FAILED_MESSAGE = "Failed to enroll password"; 96 initializeStorageWithCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid); 97 98 try { 99 mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD, 100 "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); 101 fail("Did not fail when enrolling using incorrect credential"); 102 } catch (IllegalStateException expected) { 103 assertTrue(expected.getMessage().equals(FAILED_MESSAGE)); 104 } 105 assertVerifyCredentials(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid); 106 } 107 testClearPasswordPrimaryUser()108 public void testClearPasswordPrimaryUser() throws RemoteException { 109 final String PASSWORD = "password"; 110 initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234); 111 mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(), 112 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false); 113 assertFalse(mService.havePassword(PRIMARY_USER_ID)); 114 assertFalse(mService.havePattern(PRIMARY_USER_ID)); 115 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 116 } 117 testManagedProfileUnifiedChallenge()118 public void testManagedProfileUnifiedChallenge() throws RemoteException { 119 final String firstUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-1"; 120 final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2"; 121 mService.setLockCredential(firstUnifiedPassword.getBytes(), 122 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 123 null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); 124 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 125 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 126 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); 127 final long turnedOffProfileSid = 128 mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID); 129 assertTrue(primarySid != 0); 130 assertTrue(profileSid != 0); 131 assertTrue(profileSid != primarySid); 132 assertTrue(turnedOffProfileSid != 0); 133 assertTrue(turnedOffProfileSid != primarySid); 134 assertTrue(turnedOffProfileSid != profileSid); 135 136 // clear auth token and wait for verify challenge from primary user to re-generate it. 137 mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID); 138 mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID); 139 // verify credential 140 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( 141 firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 142 PRIMARY_USER_ID).getResponseCode()); 143 144 // Verify that we have a new auth token for the profile 145 assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID)); 146 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 147 148 // Verify that profile which aren't running (e.g. turn off work) don't get unlocked 149 assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID)); 150 151 /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new 152 * credential as part of verifyCredential() before the new credential is committed in 153 * StorageManager. So we relax the check in our mock StorageManager to allow that. 154 */ 155 mStorageManager.setIgnoreBadUnlock(true); 156 // Change primary password and verify that profile SID remains 157 mService.setLockCredential(secondUnifiedPassword.getBytes(), 158 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, firstUnifiedPassword.getBytes(), 159 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); 160 mStorageManager.setIgnoreBadUnlock(false); 161 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 162 assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID)); 163 164 // Clear unified challenge 165 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, 166 secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, 167 false); 168 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 169 assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 170 assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID)); 171 } 172 testManagedProfileSeparateChallenge()173 public void testManagedProfileSeparateChallenge() throws RemoteException { 174 final String primaryPassword = "testManagedProfileSeparateChallenge-primary"; 175 final String profilePassword = "testManagedProfileSeparateChallenge-profile"; 176 mService.setLockCredential(primaryPassword.getBytes(), 177 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 178 PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false); 179 /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new 180 * credential as part of verifyCredential() before the new credential is committed in 181 * StorageManager. So we relax the check in our mock StorageManager to allow that. 182 */ 183 mStorageManager.setIgnoreBadUnlock(true); 184 mService.setLockCredential(profilePassword.getBytes(), 185 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 186 PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID, false); 187 mStorageManager.setIgnoreBadUnlock(false); 188 189 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 190 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); 191 assertTrue(primarySid != 0); 192 assertTrue(profileSid != 0); 193 assertTrue(profileSid != primarySid); 194 195 // clear auth token and make sure verify challenge from primary user does not regenerate it. 196 mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID); 197 // verify primary credential 198 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( 199 primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 200 PRIMARY_USER_ID).getResponseCode()); 201 assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID)); 202 203 // verify profile credential 204 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( 205 profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 206 MANAGED_PROFILE_USER_ID).getResponseCode()); 207 assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID)); 208 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 209 210 // Change primary credential and make sure we don't affect profile 211 mStorageManager.setIgnoreBadUnlock(true); 212 mService.setLockCredential("pwd".getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 213 primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false); 214 mStorageManager.setIgnoreBadUnlock(false); 215 assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( 216 profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 217 MANAGED_PROFILE_USER_ID).getResponseCode()); 218 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 219 } 220 testSetLockCredential_forPrimaryUser_sendsCredentials()221 public void testSetLockCredential_forPrimaryUser_sendsCredentials() throws Exception { 222 final byte[] password = "password".getBytes(); 223 224 mService.setLockCredential( 225 password, 226 CREDENTIAL_TYPE_PASSWORD, 227 null, 228 PASSWORD_QUALITY_ALPHABETIC, 229 PRIMARY_USER_ID, 230 false); 231 232 verify(mRecoverableKeyStoreManager) 233 .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, password, PRIMARY_USER_ID); 234 } 235 testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()236 public void testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials() 237 throws Exception { 238 final byte[] pattern = "12345".getBytes(); 239 240 mService.setLockCredential( 241 pattern, 242 CREDENTIAL_TYPE_PATTERN, 243 null, 244 PASSWORD_QUALITY_SOMETHING, 245 MANAGED_PROFILE_USER_ID, 246 false); 247 248 verify(mRecoverableKeyStoreManager) 249 .lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID); 250 } 251 testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials()252 public void testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials() 253 throws Exception { 254 final String oldCredential = "12345"; 255 final byte[] newCredential = "newPassword".getBytes(); 256 initializeStorageWithCredential( 257 MANAGED_PROFILE_USER_ID, 258 oldCredential, 259 CREDENTIAL_TYPE_PATTERN, 260 PASSWORD_QUALITY_SOMETHING); 261 262 mService.setLockCredential( 263 newCredential, 264 CREDENTIAL_TYPE_PASSWORD, 265 oldCredential.getBytes(), 266 PASSWORD_QUALITY_ALPHABETIC, 267 MANAGED_PROFILE_USER_ID, 268 false); 269 270 verify(mRecoverableKeyStoreManager) 271 .lockScreenSecretChanged( 272 CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID); 273 } 274 testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()275 public void testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential() 276 throws Exception { 277 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 278 279 mService.setLockCredential( 280 "12345".getBytes(), 281 CREDENTIAL_TYPE_PATTERN, 282 null, 283 PASSWORD_QUALITY_SOMETHING, 284 PRIMARY_USER_ID, 285 false); 286 287 verify(mRecoverableKeyStoreManager, never()) 288 .lockScreenSecretChanged( 289 eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID)); 290 } 291 292 public void testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_updatesBothCredentials()293 testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_updatesBothCredentials() 294 throws Exception { 295 final String oldCredential = "oldPassword"; 296 final byte[] newCredential = "newPassword".getBytes(); 297 initializeStorageWithCredential( 298 PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234); 299 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 300 301 mService.setLockCredential( 302 newCredential, 303 CREDENTIAL_TYPE_PASSWORD, 304 oldCredential.getBytes(), 305 PASSWORD_QUALITY_ALPHABETIC, 306 PRIMARY_USER_ID, 307 false); 308 309 verify(mRecoverableKeyStoreManager) 310 .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential, PRIMARY_USER_ID); 311 verify(mRecoverableKeyStoreManager) 312 .lockScreenSecretChanged( 313 CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID); 314 } 315 316 public void testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()317 testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials() 318 throws Exception { 319 final String oldCredential = "oldPassword"; 320 initializeStorageWithCredential( 321 PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234); 322 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 323 324 mService.setLockCredential( 325 null, 326 CREDENTIAL_TYPE_NONE, 327 oldCredential.getBytes(), 328 PASSWORD_QUALITY_UNSPECIFIED, 329 PRIMARY_USER_ID, 330 false); 331 332 verify(mRecoverableKeyStoreManager) 333 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, PRIMARY_USER_ID); 334 verify(mRecoverableKeyStoreManager) 335 .lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, MANAGED_PROFILE_USER_ID); 336 } 337 testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()338 public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials() 339 throws Exception { 340 final String parentPassword = "parentPassword"; 341 final byte[] profilePassword = "profilePassword".getBytes(); 342 initializeStorageWithCredential( 343 PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234); 344 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 345 346 mService.setLockCredential( 347 profilePassword, 348 CREDENTIAL_TYPE_PASSWORD, 349 null, 350 PASSWORD_QUALITY_ALPHABETIC, 351 MANAGED_PROFILE_USER_ID, 352 false); 353 354 verify(mRecoverableKeyStoreManager) 355 .lockScreenSecretChanged( 356 CREDENTIAL_TYPE_PASSWORD, profilePassword, MANAGED_PROFILE_USER_ID); 357 } 358 359 public void testSetLockCredential_forSeparateToUnifiedChallengeProfile_doesNotSendRandomCredential()360 testSetLockCredential_forSeparateToUnifiedChallengeProfile_doesNotSendRandomCredential() 361 throws Exception { 362 final String parentPassword = "parentPassword"; 363 final String profilePassword = "12345"; 364 initializeStorageWithCredential( 365 PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234); 366 // Create and verify separate profile credentials. 367 testCreateCredential( 368 MANAGED_PROFILE_USER_ID, 369 profilePassword, 370 CREDENTIAL_TYPE_PATTERN, 371 PASSWORD_QUALITY_SOMETHING); 372 373 mService.setSeparateProfileChallengeEnabled( 374 MANAGED_PROFILE_USER_ID, false, profilePassword.getBytes()); 375 376 // Called once for setting the initial separate profile credentials and not again during 377 // unification. 378 verify(mRecoverableKeyStoreManager) 379 .lockScreenSecretChanged(anyInt(), any(), eq(MANAGED_PROFILE_USER_ID)); 380 } 381 testVerifyCredential_forPrimaryUser_sendsCredentials()382 public void testVerifyCredential_forPrimaryUser_sendsCredentials() throws Exception { 383 final String password = "password"; 384 initializeStorageWithCredential(PRIMARY_USER_ID, password, CREDENTIAL_TYPE_PASSWORD, 1234); 385 reset(mRecoverableKeyStoreManager); 386 387 mService.verifyCredential( 388 password.getBytes(), CREDENTIAL_TYPE_PASSWORD, 1, PRIMARY_USER_ID); 389 390 verify(mRecoverableKeyStoreManager) 391 .lockScreenSecretAvailable( 392 CREDENTIAL_TYPE_PASSWORD, password.getBytes(), PRIMARY_USER_ID); 393 } 394 testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials()395 public void testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials() 396 throws Exception { 397 final byte[] pattern = "12345".getBytes(); 398 mService.setLockCredential( 399 pattern, 400 CREDENTIAL_TYPE_PATTERN, 401 null, 402 PASSWORD_QUALITY_SOMETHING, 403 MANAGED_PROFILE_USER_ID, 404 false); 405 reset(mRecoverableKeyStoreManager); 406 407 mService.verifyCredential(pattern, CREDENTIAL_TYPE_PATTERN, 1, MANAGED_PROFILE_USER_ID); 408 409 verify(mRecoverableKeyStoreManager) 410 .lockScreenSecretAvailable( 411 CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID); 412 } 413 414 public void testVerifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()415 testVerifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth() 416 throws Exception { 417 final String pattern = "12345"; 418 initializeStorageWithCredential(PRIMARY_USER_ID, pattern, CREDENTIAL_TYPE_PATTERN, 1234); 419 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 420 reset(mRecoverableKeyStoreManager); 421 422 mService.verifyCredential(pattern.getBytes(), CREDENTIAL_TYPE_PATTERN, 1, PRIMARY_USER_ID); 423 424 // Parent sends its credentials for both the parent and profile. 425 verify(mRecoverableKeyStoreManager) 426 .lockScreenSecretAvailable( 427 CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), PRIMARY_USER_ID); 428 verify(mRecoverableKeyStoreManager) 429 .lockScreenSecretAvailable( 430 CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), MANAGED_PROFILE_USER_ID); 431 // Profile doesn't send its own random credentials. 432 verify(mRecoverableKeyStoreManager, never()) 433 .lockScreenSecretAvailable( 434 eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID)); 435 } 436 testCreateCredential(int userId, String credential, int type, int quality)437 private void testCreateCredential(int userId, String credential, int type, int quality) 438 throws RemoteException { 439 mService.setLockCredential(credential.getBytes(), type, null, quality, 440 userId, false); 441 assertVerifyCredentials(userId, credential, type, -1); 442 } 443 testCreateCredentialFailsWithoutLockScreen( int userId, String credential, int type, int quality)444 private void testCreateCredentialFailsWithoutLockScreen( 445 int userId, String credential, int type, int quality) throws RemoteException { 446 mHasSecureLockScreen = false; 447 448 try { 449 mService.setLockCredential(credential.getBytes(), type, null, quality, 450 userId, false); 451 fail("An exception should have been thrown."); 452 } catch (UnsupportedOperationException e) { 453 // Success - the exception was expected. 454 } 455 456 assertFalse(mService.havePassword(userId)); 457 assertFalse(mService.havePattern(userId)); 458 } 459 testChangeCredentials(int userId, String newCredential, int newType, String oldCredential, int oldType, int quality)460 private void testChangeCredentials(int userId, String newCredential, int newType, 461 String oldCredential, int oldType, int quality) throws RemoteException { 462 final long sid = 1234; 463 initializeStorageWithCredential(userId, oldCredential, oldType, sid); 464 mService.setLockCredential(newCredential.getBytes(), newType, oldCredential.getBytes(), 465 quality, userId, false); 466 assertVerifyCredentials(userId, newCredential, newType, sid); 467 } 468 assertVerifyCredentials(int userId, String credential, int type, long sid)469 private void assertVerifyCredentials(int userId, String credential, int type, long sid) 470 throws RemoteException{ 471 final long challenge = 54321; 472 VerifyCredentialResponse response = mService.verifyCredential(credential.getBytes(), 473 type, challenge, userId); 474 475 assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode()); 476 if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId)); 477 final int incorrectType; 478 if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) { 479 assertTrue(mService.havePassword(userId)); 480 assertFalse(mService.havePattern(userId)); 481 incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PATTERN; 482 } else if (type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN){ 483 assertFalse(mService.havePassword(userId)); 484 assertTrue(mService.havePattern(userId)); 485 incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 486 } else { 487 assertFalse(mService.havePassword(userId)); 488 assertFalse(mService.havePassword(userId)); 489 incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 490 } 491 // check for bad type 492 assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential( 493 credential.getBytes(), incorrectType, challenge, userId).getResponseCode()); 494 // check for bad credential 495 assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential( 496 ("0" + credential).getBytes(), type, challenge, userId).getResponseCode()); 497 } 498 initializeStorageWithCredential(int userId, String credential, int type, long sid)499 private void initializeStorageWithCredential(int userId, String credential, int type, long sid) 500 throws RemoteException { 501 byte[] credentialBytes = credential == null ? null : credential.getBytes(); 502 byte[] oldHash = new VerifyHandle(credential.getBytes(), sid).toBytes(); 503 if (mService.shouldMigrateToSyntheticPasswordLocked(userId)) { 504 mService.initializeSyntheticPasswordLocked(oldHash, credentialBytes, type, 505 type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? PASSWORD_QUALITY_ALPHABETIC 506 : PASSWORD_QUALITY_SOMETHING, userId); 507 } else { 508 if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) { 509 mStorage.writeCredentialHash(CredentialHash.create(oldHash, 510 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), userId); 511 } else { 512 mStorage.writeCredentialHash(CredentialHash.create(oldHash, 513 LockPatternUtils.CREDENTIAL_TYPE_PATTERN), userId); 514 } 515 } 516 } 517 } 518