/*
 * Copyright (C) 2018 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.apksig;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.apksig.SigningCertificateLineage.SignerCapabilities;
import com.android.apksig.SigningCertificateLineage.SignerConfig;
import com.android.apksig.apk.ApkFormatException;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
import com.android.apksig.internal.apk.v3.V3SchemeConstants;
import com.android.apksig.internal.apk.v3.V3SchemeSigner;
import com.android.apksig.internal.util.ByteBufferUtils;
import com.android.apksig.internal.util.Resources;
import com.android.apksig.util.DataSource;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@RunWith(JUnit4.class)
public class SigningCertificateLineageTest {

    // createLineageWithSignersFromResources and updateLineageWithSignerFromResources will add the
    // SignerConfig for the signers added to the Lineage to this list.
    private List<SignerConfig> mSigners;

    // All signers with the same prefix and an _X suffix were signed with the private key of the
    // (X-1) signer.
    private static final String FIRST_RSA_1024_SIGNER_RESOURCE_NAME = "rsa-1024";
    private static final String SECOND_RSA_1024_SIGNER_RESOURCE_NAME = "rsa-1024_2";

    private static final String FIRST_RSA_2048_SIGNER_RESOURCE_NAME = "rsa-2048";
    private static final String SECOND_RSA_2048_SIGNER_RESOURCE_NAME = "rsa-2048_2";
    private static final String THIRD_RSA_2048_SIGNER_RESOURCE_NAME = "rsa-2048_3";

    @Before
    public void setUp() {
        mSigners = new ArrayList<>();
    }

    @Test
    public void testFirstRotationContainsExpectedSigners() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        assertLineageContainsExpectedSigners(lineage, mSigners);
        SignerConfig unknownSigner = Resources.toLineageSignerConfig(getClass(),
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        assertFalse("The signer " + unknownSigner.getCertificate().getSubjectDN()
                + " should not be in the lineage", lineage.isSignerInLineage(unknownSigner));
    }

    @Test
    public void testRotationWithExistingLineageContainsExpectedSigners() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        lineage = updateLineageWithSignerFromResources(lineage,
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        assertLineageContainsExpectedSigners(lineage, mSigners);
    }

    @Test
    public void testLineageFromFileContainsExpectedSigners() throws Exception {
        // This file contains the lineage with the three rsa-2048 signers
        DataSource lineageDataSource = Resources.toDataSource(getClass(),
                "rsa-2048-lineage-3-signers");
        SigningCertificateLineage lineage = SigningCertificateLineage.readFromDataSource(
                lineageDataSource);
        List<SignerConfig> signers = new ArrayList<>(3);
        signers.add(
                Resources.toLineageSignerConfig(getClass(), FIRST_RSA_2048_SIGNER_RESOURCE_NAME));
        signers.add(
                Resources.toLineageSignerConfig(getClass(), SECOND_RSA_2048_SIGNER_RESOURCE_NAME));
        signers.add(
                Resources.toLineageSignerConfig(getClass(), THIRD_RSA_2048_SIGNER_RESOURCE_NAME));
        assertLineageContainsExpectedSigners(lineage, signers);
    }

    @Test
    public void testLineageFromFileDoesNotContainUnknownSigner() throws Exception {
        // This file contains the lineage with the first two rsa-2048 signers
        SigningCertificateLineage lineage = Resources.toSigningCertificateLineage(getClass(),
                "rsa-2048-lineage-2-signers");
        SignerConfig unknownSigner = Resources.toLineageSignerConfig(getClass(),
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        assertFalse("The signer " + unknownSigner.getCertificate().getSubjectDN()
                + " should not be in the lineage", lineage.isSignerInLineage(unknownSigner));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testLineageFromFileWithInvalidMagicFails() throws Exception {
        // This file contains the lineage with two rsa-2048 signers and a modified MAGIC value
        Resources.toSigningCertificateLineage(getClass(), "rsa-2048-lineage-invalid-magic");
    }

    @Test(expected = IllegalArgumentException.class)
    public void testLineageFromFileWithInvalidVersionFails() throws Exception {
        // This file contains the lineage with two rsa-2048 signers and an invalid value of FF for
        // the version
        Resources.toSigningCertificateLineage(getClass(), "rsa-2048-lineage-invalid-version");
    }

    @Test
    public void testLineageWrittenToFileContainsExpectedSigners() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        lineage = updateLineageWithSignerFromResources(lineage,
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        File lineageFile = File.createTempFile(getClass().getSimpleName(), ".bin");
        lineageFile.deleteOnExit();
        lineage.writeToFile(lineageFile);
        lineage = SigningCertificateLineage.readFromFile(lineageFile);
        assertLineageContainsExpectedSigners(lineage, mSigners);
    }

    @Test
    public void testUpdatedCapabilitiesInLineage() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig oldSignerConfig = mSigners.get(0);
        List<Boolean> expectedCapabilityValues = Arrays.asList(false, false, false, false, false);
        SignerCapabilities newCapabilities = buildSignerCapabilities(expectedCapabilityValues);
        lineage.updateSignerCapabilities(oldSignerConfig, newCapabilities);
        SignerCapabilities updatedCapabilities = lineage.getSignerCapabilities(oldSignerConfig);
        assertExpectedCapabilityValues(updatedCapabilities, expectedCapabilityValues);
    }

    @Test
    public void testUpdatedCapabilitiesInLineageWrittenToFile() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig oldSignerConfig = mSigners.get(0);
        List<Boolean> expectedCapabilityValues = Arrays.asList(false, false, false, false, false);
        SignerCapabilities newCapabilities = buildSignerCapabilities(expectedCapabilityValues);
        lineage.updateSignerCapabilities(oldSignerConfig, newCapabilities);
        File lineageFile = File.createTempFile(getClass().getSimpleName(), ".bin");
        lineageFile.deleteOnExit();
        lineage.writeToFile(lineageFile);
        lineage = SigningCertificateLineage.readFromFile(lineageFile);
        SignerCapabilities updatedCapabilities = lineage.getSignerCapabilities(oldSignerConfig);
        assertExpectedCapabilityValues(updatedCapabilities, expectedCapabilityValues);
    }

    @Test
    public void testCapabilitiesAreNotUpdatedWithDefaultValues() throws Exception {
        // This file contains the lineage with the first two rsa-2048 signers with the first signer
        // having all of the capabilities set to false.
        SigningCertificateLineage lineage = Resources.toSigningCertificateLineage(getClass(),
                "rsa-2048-lineage-no-capabilities-first-signer");
        List<Boolean> expectedCapabilityValues = Arrays.asList(false, false, false, false, false);
        SignerConfig oldSignerConfig = Resources.toLineageSignerConfig(getClass(),
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerCapabilities oldSignerCapabilities = lineage.getSignerCapabilities(oldSignerConfig);
        assertExpectedCapabilityValues(oldSignerCapabilities, expectedCapabilityValues);
        // The builder is called directly to ensure all of the capabilities are set to the default
        // values and the caller configured flags are not modified in this SignerCapabilities.
        SignerCapabilities newCapabilities = new SignerCapabilities.Builder().build();
        lineage.updateSignerCapabilities(oldSignerConfig, newCapabilities);
        SignerCapabilities updatedCapabilities = lineage.getSignerCapabilities(oldSignerConfig);
        assertExpectedCapabilityValues(updatedCapabilities, expectedCapabilityValues);
    }

    @Test
    public void testFirstRotationWitNonDefaultCapabilitiesForSigners() throws Exception {
        SignerConfig oldSigner = Resources.toLineageSignerConfig(getClass(),
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig newSigner = Resources.toLineageSignerConfig(getClass(),
                SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        List<Boolean> oldSignerCapabilityValues = Arrays.asList(false, false, false, false, false);
        List<Boolean> newSignerCapabilityValues = Arrays.asList(false, true, false, false, false);
        SigningCertificateLineage lineage = new SigningCertificateLineage.Builder(oldSigner,
                newSigner)
                .setOriginalCapabilities(buildSignerCapabilities(oldSignerCapabilityValues))
                .setNewCapabilities(buildSignerCapabilities(newSignerCapabilityValues))
                .build();
        SignerCapabilities oldSignerCapabilities = lineage.getSignerCapabilities(oldSigner);
        assertExpectedCapabilityValues(oldSignerCapabilities, oldSignerCapabilityValues);
        SignerCapabilities newSignerCapabilities = lineage.getSignerCapabilities(newSigner);
        assertExpectedCapabilityValues(newSignerCapabilities, newSignerCapabilityValues);
    }

    @Test
    public void testRotationWithExitingLineageAndNonDefaultCapabilitiesForNewSigner()
            throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig oldSigner = mSigners.get(mSigners.size() - 1);
        SignerConfig newSigner = Resources.toLineageSignerConfig(getClass(),
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        List<Boolean> newSignerCapabilityValues = Arrays.asList(false, false, false, false, false);
        lineage = lineage.spawnDescendant(oldSigner, newSigner,
                buildSignerCapabilities(newSignerCapabilityValues));
        SignerCapabilities newSignerCapabilities = lineage.getSignerCapabilities(newSigner);
        assertExpectedCapabilityValues(newSignerCapabilities, newSignerCapabilityValues);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testRotationWithExistingLineageUsingNonParentSignerFails() throws Exception {
        // When rotating the signing certificate the most recent signer must be provided to the
        // spawnDescendant method. This test ensures that using an ancestor of the most recent
        // signer will fail as expected.
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig oldestSigner = mSigners.get(0);
        SignerConfig newSigner = Resources.toLineageSignerConfig(getClass(),
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        lineage.spawnDescendant(oldestSigner, newSigner);
    }

    @Test
    public void testLineageFromV3SignerAttribute() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        // The format of the V3 Signer Attribute is as follows (little endian):
        // * length-prefixed bytes: attribute pair
        //   * uint32: ID
        //   * bytes: value - encoded V3 SigningCertificateLineage
        ByteBuffer v3SignerAttribute = ByteBuffer.wrap(
                V3SchemeSigner.generateV3SignerAttribute(lineage));
        v3SignerAttribute.order(ByteOrder.LITTLE_ENDIAN);
        ByteBuffer attribute = ApkSigningBlockUtils.getLengthPrefixedSlice(v3SignerAttribute);
        // The generateV3SignerAttribute method should only use the PROOF_OF_ROTATION_ATTR_ID
        // value for the ID.
        int id = attribute.getInt();
        assertEquals(
                "The ID of the v3SignerAttribute ByteBuffer is not the expected "
                        + "PROOF_OF_ROTATION_ATTR_ID",
                V3SchemeConstants.PROOF_OF_ROTATION_ATTR_ID, id);
        lineage = SigningCertificateLineage.readFromV3AttributeValue(
                ByteBufferUtils.toByteArray(attribute));
        assertLineageContainsExpectedSigners(lineage, mSigners);
    }

    @Test
    public void testSortedSignerConfigsAreInSortedOrder() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        DefaultApkSignerEngine.SignerConfig oldSigner = getApkSignerEngineSignerConfigFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
        DefaultApkSignerEngine.SignerConfig newSigner = getApkSignerEngineSignerConfigFromResources(
                SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        List<DefaultApkSignerEngine.SignerConfig> signers = Arrays.asList(newSigner, oldSigner);
        List<DefaultApkSignerEngine.SignerConfig> sortedSigners = lineage.sortSignerConfigs(
                signers);
        assertEquals("The sorted signer list does not contain the expected number of elements",
                signers.size(), sortedSigners.size());
        assertEquals("The first element in the sorted list should be the first signer", oldSigner,
                sortedSigners.get(0));
        assertEquals("The second element in the sorted list should be the second signer", newSigner,
                sortedSigners.get(1));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testSortedSignerConfigsWithUnknownSignerFails() throws Exception {
        // Since this test includes a signer that is not in the lineage the sort should fail with
        // an IllegalArgumentException.
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        DefaultApkSignerEngine.SignerConfig oldSigner = getApkSignerEngineSignerConfigFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
        DefaultApkSignerEngine.SignerConfig newSigner = getApkSignerEngineSignerConfigFromResources(
                SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        DefaultApkSignerEngine.SignerConfig unknownSigner =
                getApkSignerEngineSignerConfigFromResources(THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        List<DefaultApkSignerEngine.SignerConfig> signers = Arrays.asList(newSigner, oldSigner,
                unknownSigner);
        lineage.sortSignerConfigs(signers);
    }

    @Test
    public void testAllExpectedCertificatesAreInLineage() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        lineage = updateLineageWithSignerFromResources(lineage,
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        Set<X509Certificate> expectedCertSet = new HashSet<>();
        for (int i = 0; i < mSigners.size(); i++) {
            expectedCertSet.add(mSigners.get(i).getCertificate());
        }
        List<X509Certificate> certs = lineage.getCertificatesInLineage();
        assertEquals(
                "The number of elements in the certificate list from the lineage does not equal "
                        + "the expected number",
                expectedCertSet.size(), certs.size());
        for (X509Certificate cert : certs) {
            // remove the certificate from the Set to ensure duplicate certs were not returned.
            assertTrue("An unexpected certificate, " + cert.getSubjectDN() + ", is in the lineage",
                    expectedCertSet.remove(cert));
        }
    }

    @Test
    public void testSublineageContainsExpectedSigners() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        lineage = updateLineageWithSignerFromResources(lineage,
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        List<SignerConfig> subList = mSigners.subList(0, 2);
        X509Certificate cert = subList.get(1).getCertificate();
        SigningCertificateLineage subLineage = lineage.getSubLineage(cert);
        assertLineageContainsExpectedSigners(subLineage, subList);
    }

    @Test
    public void testConsolidatedLineageContainsExpectedSigners() throws Exception {
        SigningCertificateLineage lineage = createLineageWithSignersFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME, SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SigningCertificateLineage updatedLineage = updateLineageWithSignerFromResources(lineage,
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        List<SigningCertificateLineage> lineages = Arrays.asList(lineage, updatedLineage);
        SigningCertificateLineage consolidatedLineage =
                SigningCertificateLineage.consolidateLineages(lineages);
        assertLineageContainsExpectedSigners(consolidatedLineage, mSigners);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConsolidatedLineageWithDisjointLineagesFail() throws Exception {
        List<SigningCertificateLineage> lineages = new ArrayList<>();
        lineages.add(createLineageWithSignersFromResources(FIRST_RSA_1024_SIGNER_RESOURCE_NAME,
                SECOND_RSA_1024_SIGNER_RESOURCE_NAME));
        lineages.add(createLineageWithSignersFromResources(FIRST_RSA_2048_SIGNER_RESOURCE_NAME,
                SECOND_RSA_2048_SIGNER_RESOURCE_NAME));
        SigningCertificateLineage.consolidateLineages(lineages);
    }

    @Test
    public void testLineageFromAPKContainsExpectedSigners() throws Exception {
        SignerConfig firstSigner = getSignerConfigFromResources(
                FIRST_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig secondSigner = getSignerConfigFromResources(
                SECOND_RSA_2048_SIGNER_RESOURCE_NAME);
        SignerConfig thirdSigner = getSignerConfigFromResources(
                THIRD_RSA_2048_SIGNER_RESOURCE_NAME);
        List<SignerConfig> expectedSigners = Arrays.asList(firstSigner, secondSigner, thirdSigner);
        DataSource apkDataSource = Resources.toDataSource(getClass(),
                "v1v2v3-with-rsa-2048-lineage-3-signers.apk");
        SigningCertificateLineage lineageFromApk = SigningCertificateLineage.readFromApkDataSource(
                apkDataSource);
        assertLineageContainsExpectedSigners(lineageFromApk, expectedSigners);
    }

    @Test(expected = ApkFormatException.class)
    public void testLineageFromAPKWithInvalidZipCDSizeFails() throws Exception {
        // This test verifies that attempting to read the lineage from an APK where the zip
        // sections cannot be parsed fails. This APK is based off the
        // v1v2v3-with-rsa-2048-lineage-3-signers.apk with a modified CD size in the EoCD.
        DataSource apkDataSource = Resources.toDataSource(getClass(),
                "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-zip.apk");
        SigningCertificateLineage.readFromApkDataSource(apkDataSource);
    }

    @Test
    public void testLineageFromAPKWithNoLineageFails() throws Exception {
        // This test verifies that attempting to read the lineage from an APK without a lineage
        // fails.
        // This is a valid APK that has only been signed with the V1 and V2 signature schemes;
        // since the lineage is an attribute in the V3 signature block this test should fail.
        DataSource apkDataSource = Resources.toDataSource(getClass(),
                "golden-aligned-v1v2-out.apk");
        try {
            SigningCertificateLineage.readFromApkDataSource(apkDataSource);
            fail("A failure should have been reported due to the APK not containing a V3 signing "
                    + "block");
        } catch (IllegalArgumentException expected) {}

        // This is a valid APK signed with the V1, V2, and V3 signature schemes, but there is no
        // lineage in the V3 signature block.
        apkDataSource = Resources.toDataSource(getClass(), "golden-aligned-v1v2v3-out.apk");
        try {
            SigningCertificateLineage.readFromApkDataSource(apkDataSource);
            fail("A failure should have been reported due to the APK containing a V3 signing "
                    + "block without the lineage attribute");
        } catch (IllegalArgumentException expected) {}

        // This APK is based off the v1v2v3-with-rsa-2048-lineage-3-signers.apk with a bit flip
        // in the lineage attribute ID in the V3 signature block.
        apkDataSource = Resources.toDataSource(getClass(),
                "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-lineage-attr.apk");
        try {
            SigningCertificateLineage.readFromApkDataSource(apkDataSource);
            fail("A failure should have been reported due to the APK containing a V3 signing "
                    + "block with a modified lineage attribute ID");
        } catch (IllegalArgumentException expected) {}
    }

    /**
     * Builds a new {@code SigningCertificateLinage.SignerCapabilities} object using the values in
     * the provided {@code List}. The {@code List} should contain {@code boolean} values to be
     * passed to the following methods in the
     * {@code SigningCertificateLineage.SignerCapabilities.Builder} (if a value is not provided the
     * noted default is used):
     *
     *  {@code SigningCertificateLineage.SignerCapabilities.Builder.setInstalledData} [{@code true}]
     *  {@code SigningCertificateLineage.SignerCapabilities.Builder.setSharedUid} [{@code true}]
     *  {@code SigningCertificateLineage.SignerCapabilities.Builder.setPermission} [{@code true}]
     *  {@code SigningCertificateLineage.SignerCapabilities.Builder.setRollback} [{@code false}]
     *  {@code SigningCertificateLineage.SignerCapabilities.Builder.setAuth} [{@code true}]
     *
     * This method should not be used when testing caller configured capabilities since the setXX
     * method for each capability is called.
     */
    private SignerCapabilities buildSignerCapabilities(List<Boolean> capabilityValues) {
        return new SignerCapabilities.Builder()
                .setInstalledData(capabilityValues.size() > 0 ? capabilityValues.get(0) : true)
                .setSharedUid(capabilityValues.size() > 1 ? capabilityValues.get(1) : true)
                .setPermission(capabilityValues.size() > 2 ? capabilityValues.get(2) : true)
                .setRollback(capabilityValues.size() > 3 ? capabilityValues.get(3) : false)
                .setAuth(capabilityValues.size() > 4 ? capabilityValues.get(4) : true)
                .build();
    }

    /**
     * Verifies the specified {@code SigningCertificateLinage.SignerCapabilities} contains the
     * expected values from the provided {@code List}. The {@code List} should contain
     * {@code boolean} values to be verified against the
     * {@code SigningCertificateLinage.SignerCapabilities} methods in the following order:
     *
     *  {@mcode SigningCertificateLineage.SignerCapabilities.hasInstalledData}
     *  {@mcode SigningCertificateLineage.SignerCapabilities.hasSharedUid}
     *  {@mcode SigningCertificateLineage.SignerCapabilities.hasPermission}
     *  {@mcode SigningCertificateLineage.SignerCapabilities.hasRollback}
     *  {@mcode SigningCertificateLineage.SignerCapabilities.hasAuth}
     */
    private void assertExpectedCapabilityValues(SignerCapabilities capabilities,
            List<Boolean> expectedCapabilityValues) {
        assertTrue("The expectedCapabilityValues do not contain the expected number of elements",
                expectedCapabilityValues.size() >= 5);
        assertEquals(
                "The installed data capability is not set to the expected value",
                expectedCapabilityValues.get(0), capabilities.hasInstalledData());
        assertEquals(
                "The shared UID capability is not set to the expected value",
                expectedCapabilityValues.get(1), capabilities.hasSharedUid());
        assertEquals(
                "The permission capability is not set to the expected value",
                expectedCapabilityValues.get(2), capabilities.hasPermission());
        assertEquals(
                "The rollback capability is not set to the expected value",
                expectedCapabilityValues.get(3), capabilities.hasRollback());
        assertEquals(
                "The auth capability is not set to the expected value",
                expectedCapabilityValues.get(4), capabilities.hasAuth());
    }

    /**
     * Creates a new {@code SigningCertificateLineage} with the specified signers from the
     * resources. {@code mSigners} will be updated with the
     * {@code SigningCertificateLineage.SignerConfig} for each signer added to the lineage.
     */
    private SigningCertificateLineage createLineageWithSignersFromResources(
            String oldSignerResourceName, String newSignerResourceName) throws Exception {
        SignerConfig oldSignerConfig = Resources.toLineageSignerConfig(getClass(),
                oldSignerResourceName);
        mSigners.add(oldSignerConfig);
        SignerConfig newSignerConfig = Resources.toLineageSignerConfig(getClass(),
                newSignerResourceName);
        mSigners.add(newSignerConfig);
        return new SigningCertificateLineage.Builder(oldSignerConfig, newSignerConfig).build();
    }

    /**
     * Updates the specified {@code SigningCertificateLineage} with the signer from the resources.
     * Requires that the {@code mSigners} list contains the previous signers in the lineage since
     * the most recent signer must be specified when adding a new signer to the lineage.
     */
    private SigningCertificateLineage updateLineageWithSignerFromResources(
            SigningCertificateLineage lineage, String newSignerResourceName) throws Exception {
        // To add a new Signer to an existing lineage the config of the last signer must be
        // specified. If this class was used to create the lineage then the last signer should
        // be in the mSigners list.
        assertTrue("The mSigners list did not contain the expected signers to update the lineage",
                mSigners.size() >= 2);
        SignerConfig oldSignerConfig = mSigners.get(mSigners.size() - 1);
        SignerConfig newSignerConfig = Resources.toLineageSignerConfig(getClass(),
                newSignerResourceName);
        mSigners.add(newSignerConfig);
        return lineage.spawnDescendant(oldSignerConfig, newSignerConfig);
    }

    private void assertLineageContainsExpectedSigners(SigningCertificateLineage lineage,
            List<SignerConfig> signers) {
        assertEquals("The lineage does not contain the expected number of signers",
                signers.size(), lineage.size());
        for (SignerConfig signer : signers) {
            assertTrue("The signer " + signer.getCertificate().getSubjectDN()
                    + " is expected to be in the lineage", lineage.isSignerInLineage(signer));
        }
    }

    private static SignerConfig getSignerConfigFromResources(
            String resourcePrefix) throws Exception {
        PrivateKey privateKey =
                Resources.toPrivateKey(SigningCertificateLineageTest.class,
                        resourcePrefix + ".pk8");
        X509Certificate cert = Resources.toCertificate(SigningCertificateLineageTest.class,
                resourcePrefix + ".x509.pem");
        return new SignerConfig.Builder(privateKey, cert).build();
    }

    private static DefaultApkSignerEngine.SignerConfig getApkSignerEngineSignerConfigFromResources(
            String resourcePrefix) throws Exception {
        PrivateKey privateKey =
                Resources.toPrivateKey(SigningCertificateLineageTest.class,
                        resourcePrefix + ".pk8");
        X509Certificate cert = Resources.toCertificate(SigningCertificateLineageTest.class,
                resourcePrefix + ".x509.pem");
        return new DefaultApkSignerEngine.SignerConfig.Builder(resourcePrefix, privateKey,
                Collections.singletonList(cert)).build();
    }
}
