Merge "Do not check user escrow state if synthetic password is not enabled yet" into oc-dev
am: b156c3a006
Change-Id: I7453311ceb4547f18055b2856965d8f30f918f16
This commit is contained in:
@@ -1562,8 +1562,9 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
// migration to synthetic password.
|
// migration to synthetic password.
|
||||||
synchronized (mSpManager) {
|
synchronized (mSpManager) {
|
||||||
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
|
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
|
||||||
initializeSyntheticPasswordLocked(storedHash.hash, credential,
|
AuthenticationToken auth = initializeSyntheticPasswordLocked(
|
||||||
storedHash.type, userId);
|
storedHash.hash, credential, storedHash.type, userId);
|
||||||
|
activateEscrowTokens(auth, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2071,9 +2072,11 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
pwdHandle, null, userId).authToken;
|
pwdHandle, null, userId).authToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
|
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
|
||||||
if (!mSpManager.hasEscrowData(userId)) {
|
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
|
||||||
throw new SecurityException("Escrow token is disabled on the current user");
|
if (!mSpManager.hasEscrowData(userId)) {
|
||||||
|
throw new SecurityException("Escrow token is disabled on the current user");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
|
long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
@@ -2085,6 +2088,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
|||||||
|
|
||||||
private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
|
private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
|
||||||
if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
|
if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
|
||||||
|
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
|
||||||
synchronized (mSpManager) {
|
synchronized (mSpManager) {
|
||||||
for (long handle : mSpManager.getPendingTokensForUser(userId)) {
|
for (long handle : mSpManager.getPendingTokensForUser(userId)) {
|
||||||
Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
|
Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
|
||||||
|
|||||||
@@ -48,6 +48,20 @@ import java.util.Set;
|
|||||||
* The SP has an associated password handle, which binds to the SID for that user. The password
|
* The SP has an associated password handle, which binds to the SID for that user. The password
|
||||||
* handle is persisted by SyntheticPasswordManager internally.
|
* handle is persisted by SyntheticPasswordManager internally.
|
||||||
* If the user credential is null, it's treated as if the credential is DEFAULT_PASSWORD
|
* If the user credential is null, it's treated as if the credential is DEFAULT_PASSWORD
|
||||||
|
*
|
||||||
|
* Information persisted on disk:
|
||||||
|
* for each user (stored under DEFAULT_HANDLE):
|
||||||
|
* SP_HANDLE_NAME: GateKeeper password handle of synthetic password. Only available if user
|
||||||
|
* credential exists, cleared when user clears their credential.
|
||||||
|
* SP_E0_NAME, SP_P1_NAME: Secret to derive synthetic password when combined with escrow
|
||||||
|
* tokens. Destroyed when escrow support is turned off for the given user.
|
||||||
|
*
|
||||||
|
* for each SP blob under the user (stored under the corresponding handle):
|
||||||
|
* SP_BLOB_NAME: The encrypted synthetic password. Always exists.
|
||||||
|
* PASSWORD_DATA_NAME: Metadata about user credential. Only exists for password based SP.
|
||||||
|
* SECDISCARDABLE_NAME: Part of the necessary ingredient to decrypt SP_BLOB_NAME for the
|
||||||
|
* purpose of secure deletion.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class SyntheticPasswordManager {
|
public class SyntheticPasswordManager {
|
||||||
private static final String SP_BLOB_NAME = "spblob";
|
private static final String SP_BLOB_NAME = "spblob";
|
||||||
@@ -221,7 +235,7 @@ public class SyntheticPasswordManager {
|
|||||||
* If the existing credential hash is non-null, the existing SID mill be migrated so
|
* If the existing credential hash is non-null, the existing SID mill be migrated so
|
||||||
* the synthetic password in the authentication token will produce the same SID
|
* the synthetic password in the authentication token will produce the same SID
|
||||||
* (the corresponding synthetic password handle is persisted by SyntheticPasswordManager
|
* (the corresponding synthetic password handle is persisted by SyntheticPasswordManager
|
||||||
* in a per-user data storage.
|
* in a per-user data storage.)
|
||||||
*
|
*
|
||||||
* If the existing credential hash is null, it means the given user should have no SID so
|
* If the existing credential hash is null, it means the given user should have no SID so
|
||||||
* SyntheticPasswordManager will nuke any SP handle previously persisted. In this case,
|
* SyntheticPasswordManager will nuke any SP handle previously persisted. In this case,
|
||||||
@@ -578,8 +592,6 @@ public class SyntheticPasswordManager {
|
|||||||
|
|
||||||
private void destroySyntheticPassword(long handle, int userId) {
|
private void destroySyntheticPassword(long handle, int userId) {
|
||||||
destroyState(SP_BLOB_NAME, true, handle, userId);
|
destroyState(SP_BLOB_NAME, true, handle, userId);
|
||||||
destroyState(SP_E0_NAME, true, handle, userId);
|
|
||||||
destroyState(SP_P1_NAME, true, handle, userId);
|
|
||||||
destroySPBlobKey(getHandleName(handle));
|
destroySPBlobKey(getHandleName(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -320,6 +320,26 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
|||||||
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
|
assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration() throws RemoteException {
|
||||||
|
final String TOKEN = "some-high-entropy-secure-token";
|
||||||
|
final String PASSWORD = "password";
|
||||||
|
// Set up pre-SP user password
|
||||||
|
disableSyntheticPassword(PRIMARY_USER_ID);
|
||||||
|
mService.setLockCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
|
||||||
|
PRIMARY_USER_ID);
|
||||||
|
enableSyntheticPassword(PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
|
||||||
|
// Token not activated immediately since user password exists
|
||||||
|
assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||||
|
// Activate token (password gets migrated to SP at the same time)
|
||||||
|
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||||
|
mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
|
||||||
|
PRIMARY_USER_ID).getResponseCode());
|
||||||
|
// Verify token is activated
|
||||||
|
assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
// b/34600579
|
// b/34600579
|
||||||
//TODO: add non-migration work profile case, and unify/un-unify transition.
|
//TODO: add non-migration work profile case, and unify/un-unify transition.
|
||||||
//TODO: test token after user resets password
|
//TODO: test token after user resets password
|
||||||
|
|||||||
Reference in New Issue
Block a user