summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java14
-rw-r--r--services/core/java/com/android/server/SyntheticPasswordManager.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/SyntheticPasswordTests.java20
3 files changed, 44 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index e26630bc4aee..3a24091ec1c6 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -1562,8 +1562,9 @@ public class LockSettingsService extends ILockSettings.Stub {
// migration to synthetic password.
synchronized (mSpManager) {
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
- initializeSyntheticPasswordLocked(storedHash.hash, credential,
- storedHash.type, userId);
+ AuthenticationToken auth = initializeSyntheticPasswordLocked(
+ storedHash.hash, credential, storedHash.type, userId);
+ activateEscrowTokens(auth, userId);
}
}
}
@@ -2071,9 +2072,11 @@ public class LockSettingsService extends ILockSettings.Stub {
pwdHandle, null, userId).authToken;
}
}
- disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
- if (!mSpManager.hasEscrowData(userId)) {
- throw new SecurityException("Escrow token is disabled on the current user");
+ if (isSyntheticPasswordBasedCredentialLocked(userId)) {
+ disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
+ if (!mSpManager.hasEscrowData(userId)) {
+ throw new SecurityException("Escrow token is disabled on the current user");
+ }
}
long handle = mSpManager.createTokenBasedSyntheticPassword(token, userId);
if (auth != null) {
@@ -2085,6 +2088,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
+ disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
synchronized (mSpManager) {
for (long handle : mSpManager.getPendingTokensForUser(userId)) {
Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index 2517613c03e0..d23584fab372 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -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
* handle is persisted by SyntheticPasswordManager internally.
* 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 {
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
* the synthetic password in the authentication token will produce the same SID
* (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
* 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) {
destroyState(SP_BLOB_NAME, true, handle, userId);
- destroyState(SP_E0_NAME, true, handle, userId);
- destroyState(SP_P1_NAME, true, handle, userId);
destroySPBlobKey(getHandleName(handle));
}
diff --git a/services/tests/servicestests/src/com/android/server/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/SyntheticPasswordTests.java
index 6e5ade12ce2c..3ec71e431155 100644
--- a/services/tests/servicestests/src/com/android/server/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/SyntheticPasswordTests.java
@@ -320,6 +320,26 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
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
//TODO: add non-migration work profile case, and unify/un-unify transition.
//TODO: test token after user resets password