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

Commit d5ba9f60 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add 4 new fields to KeychainSnapshot"

parents 84dec420 add1bad0
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
@@ -43,7 +43,14 @@ import java.util.List;
 * @hide
 */
public final class KeychainSnapshot implements Parcelable {
    private static final int DEFAULT_MAX_ATTEMPTS = 10;
    private static final long DEFAULT_COUNTER_ID = 1L;

    private int mSnapshotVersion;
    private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
    private long mCounterId = DEFAULT_COUNTER_ID;
    private byte[] mServerParams;
    private byte[] mPublicKey;
    private List<KeychainProtectionParams> mKeychainProtectionParams;
    private List<WrappedApplicationKey> mEntryRecoveryData;
    private byte[] mEncryptedRecoveryKeyBlob;
@@ -78,6 +85,37 @@ public final class KeychainSnapshot implements Parcelable {
        return mSnapshotVersion;
    }

    /**
     * Number of user secret guesses allowed during Keychain recovery.
     */
    public int getMaxAttempts() {
        return mMaxAttempts;
    }

    /**
     * CounterId which is rotated together with user secret.
     */
    public long getCounterId() {
        return mCounterId;
    }

    /**
     * Server parameters.
     */
    public @NonNull byte[] getServerParams() {
        return mServerParams;
    }

    /**
     * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
     *
     * See implementation for binary key format
     */
    // TODO: document key format.
    public @NonNull byte[] getTrustedHardwarePublicKey() {
        return mPublicKey;
    }

    /**
     * UI and key derivation parameters. Note that combination of secrets may be used.
     */
@@ -128,6 +166,50 @@ public final class KeychainSnapshot implements Parcelable {
            return this;
        }

        /**
         * Sets the number of user secret guesses allowed during Keychain recovery.
         *
         * @param maxAttempts The maximum number of guesses.
         * @return This builder.
         */
        public Builder setMaxAttempts(int maxAttempts) {
            mInstance.mMaxAttempts = maxAttempts;
            return this;
        }

        /**
         * Sets counter id.
         *
         * @param counterId The counter id.
         * @return This builder.
         */
        public Builder setCounterId(long counterId) {
            mInstance.mCounterId = counterId;
            return this;
        }

        /**
         * Sets server parameters.
         *
         * @param serverParams The server parameters
         * @return This builder.
         */
        public Builder setServerParams(byte[] serverParams) {
            mInstance.mServerParams = serverParams;
            return this;
        }

        /**
         * Sets public key used to encrypt recovery blob.
         *
         * @param publicKey The public key
         * @return This builder.
         */
        public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
            mInstance.mPublicKey = publicKey;
            return this;
        }

        /**
         * Sets UI and key derivation parameters
         *
@@ -175,6 +257,8 @@ public final class KeychainSnapshot implements Parcelable {
            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
                    "entryRecoveryData");
            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
            Preconditions.checkNotNull(mInstance.mServerParams);
            Preconditions.checkNotNull(mInstance.mPublicKey);
            return mInstance;
        }
    }
+10 −6
Original line number Diff line number Diff line
@@ -267,12 +267,16 @@ public class KeySyncTask implements Runnable {
        // If application keys are not updated, snapshot will not be created on next unlock.
        mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);

        // TODO: use Builder.
        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot(
                snapshotVersion,
                /*recoveryMetadata=*/ metadataList,
                /*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
                /*encryptedRecoveryKeyblob=*/ encryptedRecoveryKey));
        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot.Builder()
                .setSnapshotVersion(snapshotVersion)
                .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
                .setCounterId(counterId)
                .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
                .setServerParams(vaultHandle)
                .setKeychainProtectionParams(metadataList)
                .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
                .build());

        mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid);
    }
+9 −0
Original line number Diff line number Diff line
@@ -278,9 +278,13 @@ public class KeySyncTaskTest {
    public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());

        mRecoverableKeyStoreDb.setServerParams(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        SecretKey applicationKey =
                addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);

        mKeySyncTask.run();

        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
@@ -305,6 +309,11 @@ public class KeySyncTaskTest {
                        TEST_VAULT_HANDLE));
        List<WrappedApplicationKey> applicationKeys = keychainSnapshot.getWrappedApplicationKeys();
        assertThat(applicationKeys).hasSize(1);
        assertThat(keychainSnapshot.getCounterId()).isEqualTo(counterId);
        assertThat(keychainSnapshot.getMaxAttempts()).isEqualTo(10);
        assertThat(keychainSnapshot.getTrustedHardwarePublicKey())
                .isEqualTo(SecureBox.encodePublicKey(mKeyPair.getPublic()));
        assertThat(keychainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
        WrappedApplicationKey keyData = applicationKeys.get(0);
        assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
        assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());