Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6527c12 authored by Andrew Scull's avatar Andrew Scull
Browse files

Make us of the authsecret HAL.

Derive a secret from the primary user's synthetic password and pass it
to the HAL.

Bug: 71527305
Test: runtest frameworks-services -p com.android.server.locksettings
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy

Change-Id: If3ed5d56375e9fd81fcbb16b172e908804fd568a
parent eb3442cf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ java_library_static {
    static_libs: [
        "time_zone_distro",
        "time_zone_distro_installer",
        "android.hardware.authsecret-V1.0-java",
        "android.hardware.broadcastradio-V2.0-java",
        "android.hardware.health-V1.0-java",
        "android.hardware.health-V2.0-java",
+26 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.sqlite.SQLiteDatabase;
import android.hardware.authsecret.V1_0.IAuthSecret;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -126,8 +127,10 @@ import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@@ -183,6 +186,7 @@ public class LockSettingsService extends ILockSettings.Stub {

    private boolean mFirstCallToVold;
    protected IGateKeeperService mGateKeeperService;
    protected IAuthSecret mAuthSecretService;

    /**
     * The UIDs that are used for system credential storage in keystore.
@@ -613,6 +617,14 @@ public class LockSettingsService extends ILockSettings.Stub {
        } catch (RemoteException e) {
            Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
        }
        // Find the AuthSecret HAL
        try {
            mAuthSecretService = IAuthSecret.getService();
        } catch (NoSuchElementException e) {
            Slog.i(TAG, "Device doesn't implement AuthSecret HAL");
        } catch (RemoteException e) {
            Slog.w(TAG, "Failed to get AuthSecret HAL", e);
        }
        mDeviceProvisionedObserver.onSystemReady();
        // TODO: maybe skip this for split system user mode.
        mStorage.prefetchUser(UserHandle.USER_SYSTEM);
@@ -2128,6 +2140,20 @@ public class LockSettingsService extends ILockSettings.Stub {
    private SparseArray<AuthenticationToken> mSpCache = new SparseArray();

    private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
        // Pass the primary user's auth secret to the HAL
        if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
            try {
                final byte[] rawSecret = auth.deriveVendorAuthSecret();
                final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length);
                for (int i = 0; i < rawSecret.length; ++i) {
                    secret.add(rawSecret[i]);
                }
                mAuthSecretService.primaryUserCredential(secret);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
            }
        }

        // Update the SP cache, removing the entry when allowed
        synchronized (mSpManager) {
            if (shouldCacheSpForUser(userId)) {
+6 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ public class SyntheticPasswordManager {
    private static final byte[] PERSONALIZATION_USER_GK_AUTH = "user-gk-authentication".getBytes();
    private static final byte[] PERSONALIZATION_SP_GK_AUTH = "sp-gk-authentication".getBytes();
    private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes();
    private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes();
    private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes();
    private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes();
    private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
@@ -159,6 +160,11 @@ public class SyntheticPasswordManager {
                    syntheticPassword.getBytes());
        }

        public byte[] deriveVendorAuthSecret() {
            return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_AUTHSECRET_KEY,
                    syntheticPassword.getBytes());
        }

        private void initialize(byte[] P0, byte[] P1) {
            this.P1 = P1;
            this.syntheticPassword = String.valueOf(HexEncoding.encode(
+8 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.app.trust.TrustManager;
import android.content.ComponentName;
import android.content.pm.UserInfo;
import android.hardware.authsecret.V1_0.IAuthSecret;
import android.os.FileUtils;
import android.os.IProgressListener;
import android.os.RemoteException;
@@ -80,6 +81,7 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase {
    DevicePolicyManagerInternal mDevicePolicyManagerInternal;
    KeyStore mKeyStore;
    MockSyntheticPasswordManager mSpManager;
    IAuthSecret mAuthSecretService;

    @Override
    protected void setUp() throws Exception {
@@ -115,17 +117,21 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase {
        };
        mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService,
                mUserManager);
        mAuthSecretService = mock(IAuthSecret.class);
        mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage,
                mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
                mSpManager);
                mSpManager, mAuthSecretService);
        when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
        mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
        installChildProfile(MANAGED_PROFILE_USER_ID);
        installAndTurnOffChildProfile(TURNED_OFF_PROFILE_USER_ID);
        when(mUserManager.getUsers(anyBoolean())).thenReturn(mPrimaryUserProfiles);
        when(mUserManager.getProfiles(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserProfiles);
        when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO);

        final ArrayList<UserInfo> allUsers = new ArrayList<>(mPrimaryUserProfiles);
        allUsers.add(SECONDARY_USER_INFO);
        when(mUserManager.getUsers(anyBoolean())).thenReturn(allUsers);

        when(mActivityManager.unlockUser(anyInt(), any(), any(), any())).thenAnswer(
                new Answer<Boolean>() {
            @Override
+25 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
import static com.android.server.testutils.TestUtils.assertExpectException;

import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

@@ -31,6 +32,10 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;

import java.util.ArrayList;

import org.mockito.ArgumentCaptor;

/**
 * Run the synthetic password tests with caching enabled.
 *
@@ -88,6 +93,26 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests {
                    .getResponseCode());
    }

    public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
        final String PASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-password";
        final String NEWPASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword";

        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
        // Untrusted change password
        mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);

        // Verify the password
        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
                NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
                    .getResponseCode());

        // Ensure the same secret was passed each time
        ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
        verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
        assertEquals(1, secret.getAllValues().stream().distinct().count());
    }

    public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
        final String PASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-password";
        final String NEWPASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword";
Loading