diff options
| author | 2018-04-13 12:01:25 +0100 | |
|---|---|---|
| committer | 2018-04-17 10:34:04 +0100 | |
| commit | f49794b512745ca3b3a26221d36291440bc417e5 (patch) | |
| tree | 9190b28c330aa41aae923dc1eff6f3c317e66455 | |
| parent | 26c25f0033c73d1185b85979c2712647699ca956 (diff) | |
LSS: pass secret to AuthSecret HAL when no credential
If there was once a credential, a secret will have been enrolled. When
the credential is removed, that secret is still enrolled but still needs
to be derived. This adds that derivation in the case that the secret is
enrolled by the user doesn't have a credential.
Bug: 77942316
Test: runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests
Change-Id: I099a9537ab0739830a234b5f4f3721f4e8476571
5 files changed, 77 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 4b58d537e844..fd4bd1d50cde 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -584,10 +584,43 @@ public class LockSettingsService extends ILockSettings.Stub { if (mUserManager.getUserInfo(userId).isManagedProfile()) { tieManagedProfileLockIfNecessary(userId, null); } + + // If the user doesn't have a credential, try and derive their secret for the + // AuthSecret HAL. The secret will have been enrolled if the user previously set a + // credential and still needs to be passed to the HAL once that credential is + // removed. + if (mUserManager.getUserInfo(userId).isPrimary() && !isUserSecure(userId)) { + tryDeriveAuthTokenForUnsecuredPrimaryUser(userId); + } } }); } + private void tryDeriveAuthTokenForUnsecuredPrimaryUser(@UserIdInt int userId) { + synchronized (mSpManager) { + // Make sure the user has a synthetic password to derive + if (!isSyntheticPasswordBasedCredentialLocked(userId)) { + return; + } + + try { + final long handle = getSyntheticPasswordHandleLocked(userId); + final String noCredential = null; + AuthenticationResult result = + mSpManager.unwrapPasswordBasedSyntheticPassword( + getGateKeeperService(), handle, noCredential, userId, null); + if (result.authToken != null) { + Slog.i(TAG, "Retrieved auth token for user " + userId); + onAuthTokenKnownForUser(userId, result.authToken); + } else { + Slog.e(TAG, "Auth token not available for user " + userId); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failure retrieving auth token", e); + } + } + } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 96f81606a985..2dc3510a82e5 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.IActivityManager; +import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; @@ -102,7 +103,8 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal); mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager, - mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class)); + mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class), + mock(KeyguardManager.class)); mStorage = new LockSettingsStorageTestable(mContext, new File(getContext().getFilesDir(), "locksettings")); File storageDir = mStorage.mStorageDir; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java index 237091de2640..6e1f35784c7d 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java @@ -20,6 +20,7 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; @@ -79,7 +80,7 @@ public class LockSettingsStorageTests extends AndroidTestCase { MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager, mock(NotificationManager.class), mock(DevicePolicyManager.class), - mock(StorageManager.class), mock(TrustManager.class)); + mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class)); mStorage = new LockSettingsStorageTestable(context, new File(getContext().getFilesDir(), "locksettings")); mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java index 3ad30f38595b..b33253264317 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java @@ -16,6 +16,7 @@ package com.android.server.locksettings; +import android.app.KeyguardManager; import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; @@ -32,16 +33,19 @@ public class MockLockSettingsContext extends ContextWrapper { private DevicePolicyManager mDevicePolicyManager; private StorageManager mStorageManager; private TrustManager mTrustManager; + private KeyguardManager mKeyguardManager; public MockLockSettingsContext(Context base, UserManager userManager, NotificationManager notificationManager, DevicePolicyManager devicePolicyManager, - StorageManager storageManager, TrustManager trustManager) { + StorageManager storageManager, TrustManager trustManager, + KeyguardManager keyguardManager) { super(base); mUserManager = userManager; mNotificationManager = notificationManager; mDevicePolicyManager = devicePolicyManager; mStorageManager = storageManager; mTrustManager = trustManager; + mKeyguardManager = keyguardManager; } @Override @@ -56,6 +60,8 @@ public class MockLockSettingsContext extends ContextWrapper { return mStorageManager; } else if (TRUST_SERVICE.equals(name)) { return mTrustManager; + } else if (KEYGUARD_SERVICE.equals(name)) { + return mKeyguardManager; } else { throw new RuntimeException("System service not mocked: " + name); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index e9f9800f2198..142b950c395b 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -217,6 +217,38 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); } + public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException { + // Setting null doesn't create a synthetic password + initializeCredentialUnderSP(null, PRIMARY_USER_ID); + + reset(mAuthSecretService); + mService.onUnlockUser(PRIMARY_USER_ID); + mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); + } + + public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException { + final String PASSWORD = "passwordForASyntheticPassword"; + initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); + + reset(mAuthSecretService); + mService.onUnlockUser(PRIMARY_USER_ID); + mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class)); + } + + public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException { + final String PASSWORD = "getASyntheticPassword"; + initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID); + mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, PASSWORD, + PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID); + + reset(mAuthSecretService); + mService.onUnlockUser(PRIMARY_USER_ID); + mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler + verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class)); + } + public void testManagedProfileUnifiedChallengeMigration() throws RemoteException { final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd"; disableSyntheticPassword(); |