1 /* 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 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_SOMETHING; 21 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 22 23 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; 24 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; 25 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; 26 import static org.mockito.Mockito.verify; 27 28 import android.app.admin.PasswordMetrics; 29 import android.os.RemoteException; 30 import android.os.UserHandle; 31 32 import com.android.internal.widget.LockPatternUtils; 33 import com.android.internal.widget.VerifyCredentialResponse; 34 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult; 35 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; 36 import com.android.server.locksettings.SyntheticPasswordManager.PasswordData; 37 38 39 /** 40 * runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests 41 */ 42 public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { 43 44 public static final byte[] PAYLOAD = new byte[] {1, 2, -1, -2, 55}; 45 public static final byte[] PAYLOAD2 = new byte[] {2, 3, -2, -3, 44, 1}; 46 47 @Override 48 protected void setUp() throws Exception { 49 super.setUp(); 50 } 51 52 @Override 53 protected void tearDown() throws Exception { 54 super.tearDown(); 55 } 56 57 public void testPasswordBasedSyntheticPassword() throws RemoteException { 58 final int USER_ID = 10; 59 final String PASSWORD = "user-password"; 60 final String BADPASSWORD = "bad-password"; 61 MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage, 62 mGateKeeperService, mUserManager); 63 AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null, 64 null, USER_ID); 65 long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService, PASSWORD, 66 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken, PASSWORD_QUALITY_ALPHABETIC, 67 USER_ID); 68 69 AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle, PASSWORD, USER_ID); 70 assertEquals(result.authToken.deriveKeyStorePassword(), authToken.deriveKeyStorePassword()); 71 72 result = manager.unwrapPasswordBasedSyntheticPassword(mGateKeeperService, handle, BADPASSWORD, USER_ID); 73 assertNull(result.authToken); 74 } 75 76 private void disableSyntheticPassword() throws RemoteException { 77 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM); 78 } 79 80 private void enableSyntheticPassword() throws RemoteException { 81 mService.setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM); 82 } 83 84 private boolean hasSyntheticPassword(int userId) throws RemoteException { 85 return mService.getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId) != 0; 86 } 87 88 public void testPasswordMigration() throws RemoteException { 89 final String PASSWORD = "testPasswordMigration-password"; 90 91 disableSyntheticPassword(); 92 mService.setLockCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 93 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 94 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 95 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 96 enableSyntheticPassword(); 97 // Performs migration 98 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 99 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 100 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 101 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); 102 103 // SP-based verification 104 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 105 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 106 assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 107 } 108 109 private void initializeCredentialUnderSP(String password, int userId) throws RemoteException { 110 enableSyntheticPassword(); 111 int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC 112 : PASSWORD_QUALITY_UNSPECIFIED; 113 int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD 114 : LockPatternUtils.CREDENTIAL_TYPE_NONE; 115 mService.setLockCredential(password, type, null, quality, userId); 116 } 117 118 public void testSyntheticPasswordChangeCredential() throws RemoteException { 119 final String PASSWORD = "testSyntheticPasswordChangeCredential-password"; 120 final String NEWPASSWORD = "testSyntheticPasswordChangeCredential-newpassword"; 121 122 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 123 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 124 mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD, 125 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 126 mGateKeeperService.clearSecureUserId(PRIMARY_USER_ID); 127 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 128 mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 129 assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 130 } 131 132 public void testSyntheticPasswordVerifyCredential() throws RemoteException { 133 final String PASSWORD = "testSyntheticPasswordVerifyCredential-password"; 134 final String BADPASSWORD = "testSyntheticPasswordVerifyCredential-badpassword"; 135 136 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 137 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 138 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 139 140 assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, 141 mService.verifyCredential(BADPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 142 } 143 144 public void testSyntheticPasswordClearCredential() throws RemoteException { 145 final String PASSWORD = "testSyntheticPasswordClearCredential-password"; 146 final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword"; 147 148 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 149 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 150 // clear password 151 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, PASSWORD, 152 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); 153 assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 154 155 // set a new password 156 mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 157 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 158 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 159 mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 160 assertNotSame(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 161 } 162 163 public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException { 164 final String PASSWORD = "testSyntheticPasswordClearCredential-password"; 165 final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword"; 166 167 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 168 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 169 // clear password 170 mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null, 171 PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); 172 assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 173 174 // set a new password 175 mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 176 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 177 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 178 mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 179 assertNotSame(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 180 } 181 182 public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException { 183 final String PASSWORD = "testSyntheticPasswordClearCredential-password"; 184 final String NEWPASSWORD = "testSyntheticPasswordClearCredential-newpassword"; 185 186 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 187 long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 188 // Untrusted change password 189 mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 190 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 191 assertNotSame(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 192 assertNotSame(sid ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 193 194 // Verify the password 195 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 196 mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 197 } 198 199 200 public void testManagedProfileUnifiedChallengeMigration() throws RemoteException { 201 final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd"; 202 disableSyntheticPassword(); 203 mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 204 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 205 mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null); 206 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 207 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); 208 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 209 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID); 210 assertTrue(primarySid != 0); 211 assertTrue(profileSid != 0); 212 assertTrue(profileSid != primarySid); 213 214 // do migration 215 enableSyntheticPassword(); 216 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 217 mService.verifyCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 218 219 // verify 220 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 221 mService.verifyCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 222 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 223 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 224 assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 225 assertArrayNotSame(profileStorageKey, mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID)); 226 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); 227 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID)); 228 } 229 230 public void testManagedProfileSeparateChallengeMigration() throws RemoteException { 231 final String primaryPassword = "testManagedProfileSeparateChallengeMigration-primary"; 232 final String profilePassword = "testManagedProfileSeparateChallengeMigration-profile"; 233 disableSyntheticPassword(); 234 mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 235 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 236 mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 237 PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID); 238 final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID); 239 final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID); 240 final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 241 final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID); 242 assertTrue(primarySid != 0); 243 assertTrue(profileSid != 0); 244 assertTrue(profileSid != primarySid); 245 246 // do migration 247 enableSyntheticPassword(); 248 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 249 mService.verifyCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 250 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 251 mService.verifyCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, MANAGED_PROFILE_USER_ID).getResponseCode()); 252 253 // verify 254 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 255 mService.verifyCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 256 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 257 mService.verifyCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, MANAGED_PROFILE_USER_ID).getResponseCode()); 258 assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 259 assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID)); 260 assertArrayNotSame(primaryStorageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 261 assertArrayNotSame(profileStorageKey, mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID)); 262 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); 263 assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID)); 264 } 265 266 public void testTokenBasedResetPassword() throws RemoteException { 267 final String PASSWORD = "password"; 268 final String PATTERN = "123654"; 269 final String TOKEN = "some-high-entropy-secure-token"; 270 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 271 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 272 273 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 274 assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 275 276 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 277 PRIMARY_USER_ID).getResponseCode(); 278 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 279 280 mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 281 handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); 282 283 // Verify DPM gets notified about new device lock 284 mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler 285 PasswordMetrics metric = PasswordMetrics.computeForPassword(PATTERN); 286 metric.quality = PASSWORD_QUALITY_SOMETHING; 287 verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID); 288 289 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 290 mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, 291 PRIMARY_USER_ID).getResponseCode()); 292 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 293 } 294 295 public void testTokenBasedClearPassword() throws RemoteException { 296 final String PASSWORD = "password"; 297 final String PATTERN = "123654"; 298 final String TOKEN = "some-high-entropy-secure-token"; 299 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 300 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 301 302 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 303 assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 304 305 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode(); 306 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 307 308 mService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, handle, 309 TOKEN.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); 310 mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 311 handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); 312 313 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 314 mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID).getResponseCode()); 315 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 316 } 317 318 public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException { 319 final String PASSWORD = "password"; 320 final String PATTERN = "123654"; 321 final String NEWPASSWORD = "password"; 322 final String TOKEN = "some-high-entropy-secure-token"; 323 initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); 324 final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); 325 326 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 327 assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 328 329 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode(); 330 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 331 332 mService.setLockCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, PASSWORD, 333 PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID); 334 335 mService.setLockCredentialWithToken(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 336 handle, TOKEN.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 337 338 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 339 mService.verifyCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode()); 340 assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID)); 341 } 342 343 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration() throws RemoteException { 344 final String TOKEN = "some-high-entropy-secure-token"; 345 enableSyntheticPassword(); 346 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 347 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 348 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 349 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); 350 } 351 352 public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration() throws RemoteException { 353 final String TOKEN = "some-high-entropy-secure-token"; 354 initializeCredentialUnderSP(null, PRIMARY_USER_ID); 355 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 356 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 357 assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID)); 358 assertTrue(hasSyntheticPassword(PRIMARY_USER_ID)); 359 } 360 361 public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration() throws RemoteException { 362 final String TOKEN = "some-high-entropy-secure-token"; 363 final String PASSWORD = "password"; 364 // Set up pre-SP user password 365 disableSyntheticPassword(); 366 mService.setLockCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null, 367 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID); 368 enableSyntheticPassword(); 369 370 long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID); 371 // Token not activated immediately since user password exists 372 assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 373 // Activate token (password gets migrated to SP at the same time) 374 assertEquals(VerifyCredentialResponse.RESPONSE_OK, 375 mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, 376 PRIMARY_USER_ID).getResponseCode()); 377 // Verify token is activated 378 assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID)); 379 } 380 381 public void testPasswordData_serializeDeserialize() { 382 PasswordData data = new PasswordData(); 383 data.scryptN = 11; 384 data.scryptR = 22; 385 data.scryptP = 33; 386 data.passwordType = CREDENTIAL_TYPE_PASSWORD; 387 data.salt = PAYLOAD; 388 data.passwordHandle = PAYLOAD2; 389 390 PasswordData deserialized = PasswordData.fromBytes(data.toBytes()); 391 392 assertEquals(11, deserialized.scryptN); 393 assertEquals(22, deserialized.scryptR); 394 assertEquals(33, deserialized.scryptP); 395 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType); 396 assertArrayEquals(PAYLOAD, deserialized.salt); 397 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle); 398 } 399 400 public void testPasswordData_deserialize() { 401 // Test that we can deserialize existing PasswordData and don't inadvertently change the 402 // wire format. 403 byte[] serialized = new byte[] { 404 0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD */ 405 11, /* scryptN */ 406 22, /* scryptR */ 407 33, /* scryptP */ 408 0, 0, 0, 5, /* salt.length */ 409 1, 2, -1, -2, 55, /* salt */ 410 0, 0, 0, 6, /* passwordHandle.length */ 411 2, 3, -2, -3, 44, 1, /* passwordHandle */ 412 }; 413 PasswordData deserialized = PasswordData.fromBytes(serialized); 414 415 assertEquals(11, deserialized.scryptN); 416 assertEquals(22, deserialized.scryptR); 417 assertEquals(33, deserialized.scryptP); 418 assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType); 419 assertArrayEquals(PAYLOAD, deserialized.salt); 420 assertArrayEquals(PAYLOAD2, deserialized.passwordHandle); 421 } 422 423 // b/34600579 424 //TODO: add non-migration work profile case, and unify/un-unify transition. 425 //TODO: test token after user resets password 426 //TODO: test token based reset after unified work challenge 427 //TODO: test clear password after unified work challenge 428 } 429