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

Commit 925f026c authored by Dmitry Dementyev's avatar Dmitry Dementyev
Browse files

Don't create recovery snapshot until it contains at least one key.

Bug: 77931409
Test: atest RecoveryControllerHostTest
Change-Id: Ibd239cbd21a756a00c33e3cd0100b389b88d38b0
parent 6ce84086
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -232,9 +232,6 @@ public class RecoverableKeyStoreManager {
            throw new ServiceSpecificException(ERROR_INVALID_CERTIFICATE, e.getMessage());
        }

        boolean wasInitialized = mDatabase.getRecoveryServiceCertPath(userId, uid,
                rootCertificateAlias) != null;

        // Save the chosen and validated certificate into database
        try {
            Log.d(TAG, "Saving the randomly chosen endpoint certificate to database");
@@ -242,9 +239,11 @@ public class RecoverableKeyStoreManager {
                    certPath) > 0) {
                mDatabase.setRecoveryServiceCertSerial(userId, uid, rootCertificateAlias,
                        newSerial);
                if (wasInitialized) {
                    Log.i(TAG, "This is a certificate change. Snapshot pending.");
                if (mDatabase.getSnapshotVersion(userId, uid) != null) {
                    mDatabase.setShouldCreateSnapshot(userId, uid, true);
                    Log.i(TAG, "This is a certificate change. Snapshot must be updated");
                } else {
                    Log.i(TAG, "This is a certificate change. Snapshot didn't exist");
                }
                mDatabase.setCounterId(userId, uid, new SecureRandom().nextLong());
            }
@@ -350,8 +349,12 @@ public class RecoverableKeyStoreManager {
            return;
        }

        Log.i(TAG, "Updated server params. Snapshot pending.");
        if (mDatabase.getSnapshotVersion(userId, uid) != null) {
            mDatabase.setShouldCreateSnapshot(userId, uid, true);
            Log.i(TAG, "Updated server params. Snapshot must be updated");
        } else {
            Log.i(TAG, "Updated server params. Snapshot didn't exist");
        }
    }

    /**
@@ -407,7 +410,12 @@ public class RecoverableKeyStoreManager {
        }

        Log.i(TAG, "Updated secret types. Snapshot pending.");
        if (mDatabase.getSnapshotVersion(userId, uid) != null) {
            mDatabase.setShouldCreateSnapshot(userId, uid, true);
            Log.i(TAG, "Updated secret types. Snapshot must be updated");
        } else {
            Log.i(TAG, "Updated secret types. Snapshot didn't exist");
        }
    }

    /**
+12 −3
Original line number Diff line number Diff line
@@ -789,11 +789,20 @@ public class RecoverableKeyStoreDb {
    }

    /**
     * Updates the snapshot version.
     * Updates a flag indicating that a new snapshot should be created.
     * It will be {@code false} until the first application key is added.
     * After that, the flag will be set to true, if one of the following values is updated:
     * <ul>
     *     <li> List of application keys
     *     <li> Server params.
     *     <li> Lock-screen secret.
     *     <li> Lock-screen secret type.
     *     <li> Trusted hardware certificate.
     * </ul>
     *
     * @param userId The userId of the profile the application is running under.
     * @param uid The uid of the application.
     * @param pending The server parameters.
     * @param pending Should create snapshot flag.
     * @return The primary key of the inserted row, or -1 if failed.
     *
     * @hide
@@ -809,7 +818,7 @@ public class RecoverableKeyStoreDb {
     *
     * @param userId The userId of the profile the application is running under.
     * @param uid The uid of the application who initialized the local recovery components.
     * @return snapshot outdated flag.
     * @return should create snapshot flag
     *
     * @hide
     */
+57 −7
Original line number Diff line number Diff line
@@ -301,6 +301,33 @@ public class RecoverableKeyStoreManagerTest {
        assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
    }

    @Test
    public void initRecoveryService_updatesShouldCreatesnapshotOnCertUpdate() throws Exception {
        int uid = Binder.getCallingUid();
        int userId = UserHandle.getCallingUserId();
        long certSerial = 1000L;
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
                TestData.getCertXmlWithSerial(certSerial));

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

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
                TestData.getCertXmlWithSerial(certSerial + 1));

        // Since there were no recoverable keys, new snapshot will not be created.
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
                TestData.getCertXmlWithSerial(certSerial + 2));

        // Since there were a recoverable key, new serial number triggers snapshot creation
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
    }

    @Test
    public void initRecoveryService_triesToFilterRootAlias() throws Exception {
        int uid = Binder.getCallingUid();
@@ -405,7 +432,8 @@ public class RecoverableKeyStoreManagerTest {

        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
                DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(certSerial + 1);
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
        // There were no keys.
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
    }

    @Test
@@ -479,10 +507,12 @@ public class RecoverableKeyStoreManagerTest {

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
                TestData.getCertXmlWithSerial(certSerial));

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
                TestData.getCertXmlWithSerial(certSerial));

        // If the second update succeeds, getShouldCreateSnapshot() will return true.
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
    }

@@ -935,7 +965,6 @@ public class RecoverableKeyStoreManagerTest {

        assertThat(recoveredKeys).hasSize(1);
        assertThat(recoveredKeys).containsKey(TEST_ALIAS);
        // TODO(76083050) Test the grant mechanism for the keys.
    }

    @Test
@@ -974,7 +1003,6 @@ public class RecoverableKeyStoreManagerTest {

        assertThat(recoveredKeys).hasSize(1);
        assertThat(recoveredKeys).containsKey(TEST_ALIAS2);
        // TODO(76083050) Test the grant mechanism for the keys.
    }

    @Test
@@ -1016,6 +1044,9 @@ public class RecoverableKeyStoreManagerTest {
        byte[] serverParams = new byte[] { 1 };

        mRecoverableKeyStoreManager.setServerParams(serverParams);

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.setServerParams(serverParams);

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
@@ -1027,6 +1058,9 @@ public class RecoverableKeyStoreManagerTest {
        int userId = UserHandle.getCallingUserId();

        mRecoverableKeyStoreManager.setServerParams(new byte[] { 1 });

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.setServerParams(new byte[] { 2 });

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1059,6 +1093,7 @@ public class RecoverableKeyStoreManagerTest {

        mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);

        // There were no keys.
        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
    }

@@ -1070,6 +1105,9 @@ public class RecoverableKeyStoreManagerTest {
        int[] secretTypes = new int[] { 101 };

        mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
@@ -1081,6 +1119,11 @@ public class RecoverableKeyStoreManagerTest {
        int userId = UserHandle.getCallingUserId();

        mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 101 });

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

        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 102 });

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1102,9 +1145,8 @@ public class RecoverableKeyStoreManagerTest {
        int userId = UserHandle.getCallingUserId();
        mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 1 });

        mRecoverableKeyStoreManager.generateKey(TEST_ALIAS);
        // Pretend that key was synced
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
        generateKeyAndSimulateSync(userId, uid, 10);

        mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 2 });

        assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1175,6 +1217,14 @@ public class RecoverableKeyStoreManagerTest {
        return bytes;
    }

    private void generateKeyAndSimulateSync(int userId, int uid, int snapshotVersion)
            throws Exception{
        mRecoverableKeyStoreManager.generateKey(TEST_ALIAS);
        // Simulate key sync.
        mRecoverableKeyStoreDb.setSnapshotVersion(userId, uid, snapshotVersion);
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
    }

    private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(
                KEY_ALGORITHM,