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

Commit 95f2965a authored by Dmitry Dementyev's avatar Dmitry Dementyev Committed by Android (Google) Code Review
Browse files

Merge "Prepare KeyChainSnapshot to removing deprecated...

Merge "Prepare KeyChainSnapshot to removing deprecated getTrustedHardwarePublicKey method." into pi-dev
parents 7ed5fb3e 3b67e06d
Loading
Loading
Loading
Loading
+13 −21
Original line number Diff line number Diff line
@@ -127,11 +127,7 @@ public final class KeyChainSnapshot implements Parcelable {
    /**
     * CertPath containing the public key used to encrypt {@code encryptedRecoveryKeyBlob}.
     */
    // TODO: Change to @NonNull
    public CertPath getTrustedHardwareCertPath() {
        if (mCertPath == null) {
            return null;
        } else {
    public @NonNull CertPath getTrustedHardwareCertPath() {
        try {
            return mCertPath.getCertPath();
        } catch (CertificateException e) {
@@ -140,7 +136,6 @@ public final class KeyChainSnapshot implements Parcelable {
            throw new BadParcelableException(e);
        }
    }
    }

    /**
     * UI and key derivation parameters. Note that combination of secrets may be used.
@@ -248,13 +243,9 @@ public final class KeyChainSnapshot implements Parcelable {
         * @throws CertificateException if the given certificate path cannot be encoded properly
         * @return This builder.
         */
        public Builder setTrustedHardwareCertPath(CertPath certPath) throws CertificateException {
            // TODO: Make it NonNull when the caller code is all updated
            if (certPath == null) {
                mInstance.mCertPath = null;
            } else {
        public Builder setTrustedHardwareCertPath(@NonNull CertPath certPath)
                throws CertificateException {
            mInstance.mCertPath = RecoveryCertPath.createRecoveryCertPath(certPath);
            }
            return this;
        }

@@ -282,7 +273,7 @@ public final class KeyChainSnapshot implements Parcelable {
        }

        /**
         * Sets recovery key blob
         * Sets recovery key blob.
         *
         * @param encryptedRecoveryKeyBlob The recovery key blob.
         * @return This builder.
@@ -297,7 +288,7 @@ public final class KeyChainSnapshot implements Parcelable {
         * Creates a new {@link KeyChainSnapshot} instance.
         *
         * @return new instance
         * @throws NullPointerException if some required fields were not set.
         * @throws NullPointerException if some of the required fields were not set.
         */
        @NonNull public KeyChainSnapshot build() {
            Preconditions.checkCollectionElementsNotNull(mInstance.mKeyChainProtectionParams,
@@ -306,6 +297,7 @@ public final class KeyChainSnapshot implements Parcelable {
                    "entryRecoveryData");
            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
            Preconditions.checkNotNull(mInstance.mServerParams);
            Preconditions.checkNotNull(mInstance.mCertPath);
            return mInstance;
        }
    }
+0 −298
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.locksettings.recoverablekeystore.storage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.security.keystore.recovery.KeyChainProtectionParams;
import android.security.keystore.recovery.KeyChainSnapshot;
import android.security.keystore.recovery.KeyDerivationParams;
import android.security.keystore.recovery.WrappedApplicationKey;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * This class provides helper methods serialize and deserialize {@link KeyChainSnapshot}.
 *
 * <p> It is necessary since {@link android.os.Parcelable} is not designed for persistent storage.
 *
 * <p> For every list, length is stored before the elements.
 *
 */
public class PersistentKeyChainSnapshot {
    private static final int VERSION = 1;
    private static final int NULL_LIST_LENGTH = -1;

    private DataInputStream mInput;
    private DataOutputStream mOut;
    private ByteArrayOutputStream mOutStream;

    @VisibleForTesting
    PersistentKeyChainSnapshot() {
    }

    @VisibleForTesting
    void initReader(byte[] input) {
        mInput = new DataInputStream(new ByteArrayInputStream(input));
    }

    @VisibleForTesting
    void initWriter() {
        mOutStream = new ByteArrayOutputStream();
        mOut = new DataOutputStream(mOutStream);
    }

    @VisibleForTesting
    byte[] getOutput() {
        return mOutStream.toByteArray();
    }

    /**
     * Converts {@link KeyChainSnapshot} to its binary representation.
     *
     * @param snapshot The snapshot.
     *
     * @throws IOException if serialization failed.
     */
    public static byte[] serialize(@NonNull KeyChainSnapshot snapshot) throws IOException {
        PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
        writer.initWriter();
        writer.writeInt(VERSION);
        writer.writeKeyChainSnapshot(snapshot);
        return writer.getOutput();
    }

    /**
     * deserializes {@link KeyChainSnapshot}.
     *
     * @input input - byte array produced by {@link serialize} method.
     * @throws IOException if parsing failed.
     */
    public static @NonNull KeyChainSnapshot deserialize(@NonNull byte[] input)
            throws IOException {
        PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
        reader.initReader(input);
        try {
            int version = reader.readInt();
            if (version != VERSION) {
                throw new IOException("Unsupported version " + version);
            }
            return reader.readKeyChainSnapshot();
        } catch (IOException e) {
            throw new IOException("Malformed KeyChainSnapshot", e);
        }
    }

    /**
     * Must be in sync with {@link KeyChainSnapshot.writeToParcel}
     */
    @VisibleForTesting
    void writeKeyChainSnapshot(KeyChainSnapshot snapshot) throws IOException {
        writeInt(snapshot.getSnapshotVersion());
        writeProtectionParamsList(snapshot.getKeyChainProtectionParams());
        writeBytes(snapshot.getEncryptedRecoveryKeyBlob());
        writeKeysList(snapshot.getWrappedApplicationKeys());

        writeInt(snapshot.getMaxAttempts());
        writeLong(snapshot.getCounterId());
        writeBytes(snapshot.getServerParams());
        writeBytes(snapshot.getTrustedHardwarePublicKey());
    }

    @VisibleForTesting
    KeyChainSnapshot readKeyChainSnapshot() throws IOException {
        int snapshotVersion = readInt();
        List<KeyChainProtectionParams> protectionParams = readProtectionParamsList();
        byte[] encryptedRecoveryKey = readBytes();
        List<WrappedApplicationKey> keysList = readKeysList();

        int maxAttempts = readInt();
        long conterId = readLong();
        byte[] serverParams = readBytes();
        byte[] trustedHardwarePublicKey = readBytes();

        return new KeyChainSnapshot.Builder()
                .setSnapshotVersion(snapshotVersion)
                .setKeyChainProtectionParams(protectionParams)
                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
                .setWrappedApplicationKeys(keysList)
                .setMaxAttempts(maxAttempts)
                .setCounterId(conterId)
                .setServerParams(serverParams)
                .setTrustedHardwarePublicKey(trustedHardwarePublicKey)
                .build();
    }

    @VisibleForTesting
    void writeProtectionParamsList(
            @NonNull List<KeyChainProtectionParams> ProtectionParamsList) throws IOException {
        writeInt(ProtectionParamsList.size());
        for (KeyChainProtectionParams protectionParams : ProtectionParamsList) {
            writeProtectionParams(protectionParams);
        }
    }

    @VisibleForTesting
    List<KeyChainProtectionParams> readProtectionParamsList() throws IOException {
        int length = readInt();
        List<KeyChainProtectionParams> result = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            result.add(readProtectionParams());
        }
        return result;
    }

    /**
     * Must be in sync with {@link KeyChainProtectionParams.writeToParcel}
     */
    @VisibleForTesting
    void writeProtectionParams(@NonNull KeyChainProtectionParams protectionParams)
            throws IOException {
        if (!ArrayUtils.isEmpty(protectionParams.getSecret())) {
            // Extra security check.
            throw new RuntimeException("User generated secret should not be stored");
        }
        writeInt(protectionParams.getUserSecretType());
        writeInt(protectionParams.getLockScreenUiFormat());
        writeKeyDerivationParams(protectionParams.getKeyDerivationParams());
        writeBytes(protectionParams.getSecret());
    }

    @VisibleForTesting
    KeyChainProtectionParams readProtectionParams() throws IOException {
        int userSecretType = readInt();
        int lockScreenUiFormat = readInt();
        KeyDerivationParams derivationParams = readKeyDerivationParams();
        byte[] secret = readBytes();
        return new KeyChainProtectionParams.Builder()
                .setUserSecretType(userSecretType)
                .setLockScreenUiFormat(lockScreenUiFormat)
                .setKeyDerivationParams(derivationParams)
                .setSecret(secret)
                .build();
    }

    /**
     * Must be in sync with {@link KeyDerivationParams.writeToParcel}
     */
    @VisibleForTesting
    void writeKeyDerivationParams(@NonNull KeyDerivationParams Params) throws IOException {
        writeInt(Params.getAlgorithm());
        writeBytes(Params.getSalt());
    }

    @VisibleForTesting
    KeyDerivationParams readKeyDerivationParams() throws IOException {
        int algorithm = readInt();
        byte[] salt = readBytes();
        return KeyDerivationParams.createSha256Params(salt);
    }

    @VisibleForTesting
    void writeKeysList(@NonNull List<WrappedApplicationKey> applicationKeys) throws IOException {
        writeInt(applicationKeys.size());
        for (WrappedApplicationKey keyEntry : applicationKeys) {
            writeKeyEntry(keyEntry);
        }
    }

    @VisibleForTesting
    List<WrappedApplicationKey> readKeysList() throws IOException {
        int length = readInt();
        List<WrappedApplicationKey> result = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            result.add(readKeyEntry());
        }
        return result;
    }

    /**
     * Must be in sync with {@link WrappedApplicationKey.writeToParcel}
     */
    @VisibleForTesting
    void writeKeyEntry(@NonNull WrappedApplicationKey keyEntry) throws IOException {
        mOut.writeUTF(keyEntry.getAlias());
        writeBytes(keyEntry.getEncryptedKeyMaterial());
        writeBytes(keyEntry.getAccount());
    }

    @VisibleForTesting
    WrappedApplicationKey readKeyEntry() throws IOException {
        String alias = mInput.readUTF();
        byte[] keyMaterial = readBytes();
        byte[] account = readBytes();
        return new WrappedApplicationKey.Builder()
                .setAlias(alias)
                .setEncryptedKeyMaterial(keyMaterial)
                .setAccount(account)
                .build();
    }

    @VisibleForTesting
    void writeInt(int value) throws IOException {
        mOut.writeInt(value);
    }

    @VisibleForTesting
    int readInt() throws IOException {
        return mInput.readInt();
    }

    @VisibleForTesting
    void writeLong(long value) throws IOException {
        mOut.writeLong(value);
    }

    @VisibleForTesting
    long readLong() throws IOException {
        return mInput.readLong();
    }

    @VisibleForTesting
    void writeBytes(@Nullable byte[] value) throws IOException {
        if (value == null) {
            writeInt(NULL_LIST_LENGTH);
            return;
        }
        writeInt(value.length);
        mOut.write(value, 0, value.length);
    }

    /**
     * Reads @code{byte[]} from current position. Converts {@code null} to an empty array.
     */
    @VisibleForTesting
    @NonNull byte[] readBytes() throws IOException {
        int length = readInt();
        if (length == NULL_LIST_LENGTH) {
            return new byte[]{};
        }
        byte[] result = new byte[length];
        mInput.read(result, 0, result.length);
        return result;
    }
}
+34 −38
Original line number Diff line number Diff line
@@ -62,7 +62,6 @@ import org.mockito.MockitoAnnotations;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
@@ -95,7 +94,6 @@ public class KeySyncTaskTest {
    private RecoverySnapshotStorage mRecoverySnapshotStorage;
    private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
    private File mDatabaseFile;
    private KeyPair mKeyPair;
    private AndroidKeyStoreSecretKey mWrappingKey;
    private PlatformEncryptionKey mEncryptKey;

@@ -108,7 +106,6 @@ public class KeySyncTaskTest {
        Context context = InstrumentationRegistry.getTargetContext();
        mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME);
        mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
        mKeyPair = SecureBox.genKeyPair();

        mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
                new int[] {TYPE_LOCKSCREEN});
@@ -249,8 +246,8 @@ public class KeySyncTaskTest {
                TEST_RECOVERY_AGENT_UID,
                TEST_APP_KEY_ALIAS,
                WrappedKey.fromSecretKey(mEncryptKey, applicationKey));
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);

        mKeySyncTask.run();
@@ -265,8 +262,8 @@ public class KeySyncTaskTest {
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);

        mKeySyncTask.run();

@@ -275,8 +272,8 @@ public class KeySyncTaskTest {

    @Test
    public void run_sendsEncryptedKeysIfAvailableToSync_withRawPublicKey() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);

        mRecoverableKeyStoreDb.setServerParams(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
@@ -301,7 +298,7 @@ public class KeySyncTaskTest {
                lockScreenHash,
                keyChainSnapshot.getEncryptedRecoveryKeyBlob(),
                /*vaultParams=*/ KeySyncUtils.packVaultParams(
                        mKeyPair.getPublic(),
                        TestData.CERT_1_PUBLIC_KEY,
                        counterId,
                        /*maxAttempts=*/ 10,
                        TEST_VAULT_HANDLE));
@@ -309,8 +306,8 @@ public class KeySyncTaskTest {
        assertThat(applicationKeys).hasSize(1);
        assertThat(keyChainSnapshot.getCounterId()).isEqualTo(counterId);
        assertThat(keyChainSnapshot.getMaxAttempts()).isEqualTo(10);
        assertThat(keyChainSnapshot.getTrustedHardwarePublicKey())
                .isEqualTo(SecureBox.encodePublicKey(mKeyPair.getPublic()));
        assertThat(keyChainSnapshot.getTrustedHardwareCertPath())
                .isEqualTo(TestData.CERT_PATH_1);
        assertThat(keyChainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
        WrappedApplicationKey keyData = applicationKeys.get(0);
        assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
@@ -335,15 +332,14 @@ public class KeySyncTaskTest {
        verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
        List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys();
        assertThat(applicationKeys).hasSize(1);
        assertThat(keyChainSnapshot.getTrustedHardwarePublicKey())
                .isEqualTo(SecureBox.encodePublicKey(
                        TestData.CERT_PATH_1.getCertificates().get(0).getPublicKey()));
        assertThat(keyChainSnapshot.getTrustedHardwareCertPath())
                .isEqualTo(TestData.CERT_PATH_1);
    }

    @Test
    public void run_setsCorrectSnapshotVersion() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);

@@ -361,8 +357,8 @@ public class KeySyncTaskTest {

    @Test
    public void run_recreatesMissingSnapshot() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);

@@ -391,8 +387,8 @@ public class KeySyncTaskTest {
                /*credentialUpdated=*/ false,
                mPlatformKeyManager);

        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        SecretKey applicationKey =
                addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -417,8 +413,8 @@ public class KeySyncTaskTest {
                /*credentialUpdated=*/ false,
                mPlatformKeyManager);

        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        SecretKey applicationKey =
                addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -444,8 +440,8 @@ public class KeySyncTaskTest {
                /*credentialUpdated=*/ false,
                mPlatformKeyManager);

        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        SecretKey applicationKey =
                addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -460,10 +456,10 @@ public class KeySyncTaskTest {

    @Test
    public void run_sendsEncryptedKeysWithTwoRegisteredAgents() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -482,10 +478,10 @@ public class KeySyncTaskTest {
        mRecoverableKeyStoreDb.setRecoverySecretTypes(TEST_USER_ID, TEST_RECOVERY_AGENT_UID2,
                new int[] {1000});

        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(true);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -499,10 +495,10 @@ public class KeySyncTaskTest {

    @Test
    public void run_notifiesNonregisteredAgent() throws Exception {
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, mKeyPair.getPublic());
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1);
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID2, TestData.CERT_PATH_1);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
        when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID2)).thenReturn(false);
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
@@ -562,7 +558,7 @@ public class KeySyncTaskTest {
    private byte[] decryptThmEncryptedKey(
            byte[] lockScreenHash, byte[] encryptedKey, byte[] vaultParams) throws Exception {
        byte[] locallyEncryptedKey = SecureBox.decrypt(
                mKeyPair.getPrivate(),
                TestData.CERT_1_PRIVATE_KEY,
                /*sharedSecret=*/ KeySyncUtils.calculateThmKfHash(lockScreenHash),
                /*header=*/ KeySyncUtils.concat(THM_ENCRYPTED_RECOVERY_KEY_HEADER, vaultParams),
                encryptedKey
+53 −1

File changed.

Preview size limit exceeded, changes collapsed.

+0 −331

File deleted.

Preview size limit exceeded, changes collapsed.