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

Commit 40dadb0e authored by Dmitry Dementyev's avatar Dmitry Dementyev
Browse files

Mark current recoverable keystore snapshot as outdated in a few events:

1) recovery service is initialized
2) Server parameters were updated
3) Recovery secrets used for end-to-end encryption were changed.

Bug: 66499222
Test: adb shell am instrument -w -e package \
com.android.server.locksettings.recoverablekeystore \
com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner

Change-Id: I1838f88268189a910573db51f290992d6147aa4a
parent ac3dbf48
Loading
Loading
Loading
Loading
+16 −4
Original line number Original line Diff line number Diff line
@@ -148,6 +148,7 @@ public class RecoverableKeyStoreManager {
            throws RemoteException {
            throws RemoteException {
        checkRecoverKeyStorePermission();
        checkRecoverKeyStorePermission();
        int userId = UserHandle.getCallingUserId();
        int userId = UserHandle.getCallingUserId();
        int uid = Binder.getCallingUid();
        // TODO: open /system/etc/security/... cert file, and check the signature on the public keys
        // TODO: open /system/etc/security/... cert file, and check the signature on the public keys
        PublicKey publicKey;
        PublicKey publicKey;
        try {
        try {
@@ -162,7 +163,10 @@ public class RecoverableKeyStoreManager {
            throw new ServiceSpecificException(
            throw new ServiceSpecificException(
                    ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 certificate.");
                    ERROR_BAD_X509_CERTIFICATE, "Not a valid X509 certificate.");
        }
        }
        mDatabase.setRecoveryServicePublicKey(userId, Binder.getCallingUid(), publicKey);
        long updatedRows = mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey);
        if (updatedRows > 0) {
            mDatabase.setShouldCreateSnapshot(userId, uid, true);
        }
    }
    }


    /**
    /**
@@ -204,7 +208,11 @@ public class RecoverableKeyStoreManager {
    public void setServerParameters(long serverParameters) throws RemoteException {
    public void setServerParameters(long serverParameters) throws RemoteException {
        checkRecoverKeyStorePermission();
        checkRecoverKeyStorePermission();
        int userId = UserHandle.getCallingUserId();
        int userId = UserHandle.getCallingUserId();
        mDatabase.setServerParameters(userId, Binder.getCallingUid(), serverParameters);
        int uid = Binder.getCallingUid();
        long updatedRows = mDatabase.setServerParameters(userId, uid, serverParameters);
        if (updatedRows > 0) {
            mDatabase.setShouldCreateSnapshot(userId, uid, true);
        }
    }
    }


    /**
    /**
@@ -256,8 +264,12 @@ public class RecoverableKeyStoreManager {
            @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] secretTypes)
            @NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] secretTypes)
            throws RemoteException {
            throws RemoteException {
        checkRecoverKeyStorePermission();
        checkRecoverKeyStorePermission();
        mDatabase.setRecoverySecretTypes(UserHandle.getCallingUserId(), Binder.getCallingUid(),
        int userId = UserHandle.getCallingUserId();
            secretTypes);
        int uid = Binder.getCallingUid();
        long updatedRows = mDatabase.setRecoverySecretTypes(userId, uid, secretTypes);
        if (updatedRows > 0) {
            mDatabase.setShouldCreateSnapshot(userId, uid, true);
        }
    }
    }


    /**
    /**
+4 −4
Original line number Original line Diff line number Diff line
@@ -349,7 +349,7 @@ public class KeySyncTaskTest {


        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
                isEqualTo(TYPE_PASSWORD);
                isEqualTo(TYPE_PASSWORD);
    }
    }


@@ -376,7 +376,7 @@ public class KeySyncTaskTest {
        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        // Password with only digits is changed to pin.
        // Password with only digits is changed to pin.
        assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
                isEqualTo(TYPE_PIN);
                isEqualTo(TYPE_PIN);
    }
    }


@@ -402,7 +402,7 @@ public class KeySyncTaskTest {


        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
        assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()).
        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
                isEqualTo(TYPE_PATTERN);
                isEqualTo(TYPE_PATTERN);
    }
    }


+39 −2
Original line number Original line Diff line number Diff line
@@ -78,6 +78,7 @@ import javax.crypto.spec.SecretKeySpec;
public class RecoverableKeyStoreManagerTest {
public class RecoverableKeyStoreManagerTest {
    private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";
    private static final String DATABASE_FILE_NAME = "recoverablekeystore.db";


    private static final String ROOT_CERTIFICATE_ALIAS = "put_default_alias_here";
    private static final String TEST_SESSION_ID = "karlin";
    private static final String TEST_SESSION_ID = "karlin";
    private static final byte[] TEST_PUBLIC_KEY = new byte[] {
    private static final byte[] TEST_PUBLIC_KEY = new byte[] {
        (byte) 0x30, (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a,
        (byte) 0x30, (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a,
@@ -206,10 +207,9 @@ public class RecoverableKeyStoreManagerTest {
    }
    }


    @Test
    @Test
    public void removeKey_UpdatesShouldCreateSnapshot() throws Exception {
    public void removeKey_updatesShouldCreateSnapshot() throws Exception {
        int uid = Binder.getCallingUid();
        int uid = Binder.getCallingUid();
        int userId = UserHandle.getCallingUserId();
        int userId = UserHandle.getCallingUserId();

        mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
        mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
        // Pretend that key was synced
        // Pretend that key was synced
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
@@ -219,6 +219,29 @@ public class RecoverableKeyStoreManagerTest {
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
    }
    }


    @Test
    public void removeKey_failureDoesNotUpdateShouldCreateSnapshot() throws Exception {
        int uid = Binder.getCallingUid();
        int userId = UserHandle.getCallingUserId();
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
        // Key did not exist
        mRecoverableKeyStoreManager.removeKey(TEST_ALIAS);

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
    }

    @Test
    public void initRecoveryService_updatesShouldCreateSnapshot() throws Exception {
        int uid = Binder.getCallingUid();
        int userId = UserHandle.getCallingUserId();
        // Sync is not needed.
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, TEST_PUBLIC_KEY);

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
    }

    @Test
    @Test
    public void startRecoverySession_checksPermissionFirst() throws Exception {
    public void startRecoverySession_checksPermissionFirst() throws Exception {
        mRecoverableKeyStoreManager.startRecoverySession(
        mRecoverableKeyStoreManager.startRecoverySession(
@@ -448,6 +471,20 @@ public class RecoverableKeyStoreManagerTest {
                types3);
                types3);
    }
    }


    @Test
    public void setRecoverySecretTypes_updatesShouldCreateSnapshot() throws Exception {
        int uid = Binder.getCallingUid();
        int userId = UserHandle.getCallingUserId();
        int[] types = new int[]{1, 2, 3};

        mRecoverableKeyStoreManager.generateAndStoreKey(TEST_ALIAS);
        // Pretend that key was synced
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
        mRecoverableKeyStoreManager.setRecoverySecretTypes(types);

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
    }

    @Test
    @Test
    public void setRecoveryStatus_forOneAlias() throws Exception {
    public void setRecoveryStatus_forOneAlias() throws Exception {
        int userId = UserHandle.getCallingUserId();
        int userId = UserHandle.getCallingUserId();