/*
 * 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 com.android.apksig.internal.apk.ApkSigningBlockUtils.getLengthPrefixedSlice;

import com.android.apksig.apk.ApkFormatException;
import com.android.apksig.apk.ApkUtils;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
import com.android.apksig.internal.apk.SignatureAlgorithm;
import com.android.apksig.internal.apk.SignatureInfo;
import com.android.apksig.internal.apk.v3.V3SchemeConstants;
import com.android.apksig.internal.apk.v3.V3SchemeSigner;
import com.android.apksig.internal.apk.v3.V3SigningCertificateLineage;
import com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode;
import com.android.apksig.internal.util.AndroidSdkVersion;
import com.android.apksig.internal.util.ByteBufferUtils;
import com.android.apksig.internal.util.Pair;
import com.android.apksig.internal.util.RandomAccessFileDataSink;
import com.android.apksig.util.DataSink;
import com.android.apksig.util.DataSource;
import com.android.apksig.util.DataSources;
import com.android.apksig.zip.ZipFormatException;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * APK Signer Lineage.
 *
 * <p>The signer lineage contains a history of signing certificates with each ancestor attesting to
 * the validity of its descendant.  Each additional descendant represents a new identity that can be
 * used to sign an APK, and each generation has accompanying attributes which represent how the
 * APK would like to view the older signing certificates, specifically how they should be trusted in
 * certain situations.
 *
 * <p> Its primary use is to enable APK Signing Certificate Rotation.  The Android platform verifies
 * the APK Signer Lineage, and if the current signing certificate for the APK is in the Signer
 * Lineage, and the Lineage contains the certificate the platform associates with the APK, it will
 * allow upgrades to the new certificate.
 *
 * @see <a href="https://source.android.com/security/apksigning/index.html">Application Signing</a>
 */
public class SigningCertificateLineage {

    public final static int MAGIC = 0x3eff39d1;

    private final static int FIRST_VERSION = 1;

    private static final int CURRENT_VERSION = FIRST_VERSION;

    /** accept data from already installed pkg with this cert */
    private static final int PAST_CERT_INSTALLED_DATA = 1;

    /** accept sharedUserId with pkg with this cert */
    private static final int PAST_CERT_SHARED_USER_ID = 2;

    /** grant SIGNATURE permissions to pkgs with this cert */
    private static final int PAST_CERT_PERMISSION = 4;

    /**
     * Enable updates back to this certificate.  WARNING: this effectively removes any benefit of
     * signing certificate changes, since a compromised key could retake control of an app even
     * after change, and should only be used if there is a problem encountered when trying to ditch
     * an older cert.
     */
    private static final int PAST_CERT_ROLLBACK = 8;

    /**
     * Preserve authenticator module-based access in AccountManager gated by signing certificate.
     */
    private static final int PAST_CERT_AUTH = 16;

    private final int mMinSdkVersion;

    /**
     * The signing lineage is just a list of nodes, with the first being the original signing
     * certificate and the most recent being the one with which the APK is to actually be signed.
     */
    private final List<SigningCertificateNode> mSigningLineage;

    private SigningCertificateLineage(int minSdkVersion, List<SigningCertificateNode> list) {
        mMinSdkVersion = minSdkVersion;
        mSigningLineage = list;
    }

    private static SigningCertificateLineage createSigningLineage(
            int minSdkVersion, SignerConfig parent, SignerCapabilities parentCapabilities,
            SignerConfig child, SignerCapabilities childCapabilities)
            throws CertificateEncodingException, InvalidKeyException, NoSuchAlgorithmException,
            SignatureException {
        SigningCertificateLineage signingCertificateLineage =
                new SigningCertificateLineage(minSdkVersion, new ArrayList<>());
        signingCertificateLineage =
                signingCertificateLineage.spawnFirstDescendant(parent, parentCapabilities);
        return signingCertificateLineage.spawnDescendant(parent, child, childCapabilities);
    }

    public static SigningCertificateLineage readFromBytes(byte[] lineageBytes)
            throws IOException {
        return readFromDataSource(DataSources.asDataSource(ByteBuffer.wrap(lineageBytes)));
    }

    public static SigningCertificateLineage readFromFile(File file)
            throws IOException {
        if (file == null) {
            throw new NullPointerException("file == null");
        }
        RandomAccessFile inputFile = new RandomAccessFile(file, "r");
        return readFromDataSource(DataSources.asDataSource(inputFile));
    }

    public static SigningCertificateLineage readFromDataSource(DataSource dataSource)
            throws IOException {
        if (dataSource == null) {
            throw new NullPointerException("dataSource == null");
        }
        ByteBuffer inBuff = dataSource.getByteBuffer(0, (int) dataSource.size());
        inBuff.order(ByteOrder.LITTLE_ENDIAN);
        return read(inBuff);
    }

    /**
     * Extracts a Signing Certificate Lineage from a v3 signer proof-of-rotation attribute.
     *
     * <note>
     *     this may not give a complete representation of an APK's signing certificate history,
     *     since the APK may have multiple signers corresponding to different platform versions.
     *     Use <code> readFromApkFile</code> to handle this case.
     * </note>
     * @param attrValue
     */
    public static SigningCertificateLineage readFromV3AttributeValue(byte[] attrValue)
            throws IOException {
        List<SigningCertificateNode> parsedLineage =
                V3SigningCertificateLineage.readSigningCertificateLineage(ByteBuffer.wrap(
                        attrValue).order(ByteOrder.LITTLE_ENDIAN));
        int minSdkVersion = calculateMinSdkVersion(parsedLineage);
        return  new SigningCertificateLineage(minSdkVersion, parsedLineage);
    }

    /**
     * Extracts a Signing Certificate Lineage from the proof-of-rotation attribute in the V3
     * signature block of the provided APK File.
     *
     * @throws IllegalArgumentException if the provided APK does not contain a V3 signature block,
     * or if the V3 signature block does not contain a valid lineage.
     */
    public static SigningCertificateLineage readFromApkFile(File apkFile)
            throws IOException, ApkFormatException {
        try (RandomAccessFile f = new RandomAccessFile(apkFile, "r")) {
            DataSource apk = DataSources.asDataSource(f, 0, f.length());
            return readFromApkDataSource(apk);
        }
    }

    /**
     * Extracts a Signing Certificate Lineage from the proof-of-rotation attribute in the V3
     * signature block of the provided APK DataSource.
     *
     * @throws IllegalArgumentException if the provided APK does not contain a V3 signature block,
     * or if the V3 signature block does not contain a valid lineage.
     */
    public static SigningCertificateLineage readFromApkDataSource(DataSource apk)
            throws IOException, ApkFormatException {
        SignatureInfo signatureInfo;
        try {
            ApkUtils.ZipSections zipSections = ApkUtils.findZipSections(apk);
            ApkSigningBlockUtils.Result result = new ApkSigningBlockUtils.Result(
                    ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V3);
            signatureInfo =
                    ApkSigningBlockUtils.findSignature(apk, zipSections,
                            V3SchemeConstants.APK_SIGNATURE_SCHEME_V3_BLOCK_ID, result);
        } catch (ZipFormatException e) {
            throw new ApkFormatException(e.getMessage());
        } catch (ApkSigningBlockUtils.SignatureNotFoundException e) {
            throw new IllegalArgumentException(
                    "The provided APK does not contain a valid V3 signature block.");
        }

        // FORMAT:
        // * length-prefixed sequence of length-prefixed signers:
        //   * length-prefixed signed data
        //   * minSDK
        //   * maxSDK
        //   * length-prefixed sequence of length-prefixed signatures
        //   * length-prefixed public key
        ByteBuffer signers = getLengthPrefixedSlice(signatureInfo.signatureBlock);
        List<SigningCertificateLineage> lineages = new ArrayList<>(1);
        while (signers.hasRemaining()) {
            ByteBuffer signer = getLengthPrefixedSlice(signers);
            ByteBuffer signedData = getLengthPrefixedSlice(signer);
            try {
                SigningCertificateLineage lineage = readFromSignedData(signedData);
                lineages.add(lineage);
            } catch (IllegalArgumentException ignored) {
                // The current signer block does not contain a valid lineage, but it is possible
                // another block will.
            }
        }
        SigningCertificateLineage result;
        if (lineages.isEmpty()) {
            throw new IllegalArgumentException(
                    "The provided APK does not contain a valid lineage.");
        } else if (lineages.size() > 1) {
            result = consolidateLineages(lineages);
        } else {
            result = lineages.get(0);
        }
        return result;
    }

    /**
     * Extracts a Signing Certificate Lineage from the proof-of-rotation attribute in the provided
     * signed data portion of a signer in a V3 signature block.
     *
     * @throws IllegalArgumentException if the provided signed data does not contain a valid
     * lineage.
     */
    public static SigningCertificateLineage readFromSignedData(ByteBuffer signedData)
            throws IOException, ApkFormatException {
        // FORMAT:
        //   * length-prefixed sequence of length-prefixed digests:
        //   * length-prefixed sequence of certificates:
        //     * length-prefixed bytes: X.509 certificate (ASN.1 DER encoded).
        //   * uint-32: minSdkVersion
        //   * uint-32: maxSdkVersion
        //   * length-prefixed sequence of length-prefixed additional attributes:
        //     * uint32: ID
        //     * (length - 4) bytes: value
        //     * uint32: Proof-of-rotation ID: 0x3ba06f8c
        //     * length-prefixed proof-of-rotation structure
        // consume the digests through the maxSdkVersion to reach the lineage in the attributes
        getLengthPrefixedSlice(signedData);
        getLengthPrefixedSlice(signedData);
        signedData.getInt();
        signedData.getInt();
        // iterate over the additional attributes adding any lineages to the List
        ByteBuffer additionalAttributes = getLengthPrefixedSlice(signedData);
        List<SigningCertificateLineage> lineages = new ArrayList<>(1);
        while (additionalAttributes.hasRemaining()) {
            ByteBuffer attribute = getLengthPrefixedSlice(additionalAttributes);
            int id = attribute.getInt();
            if (id == V3SchemeConstants.PROOF_OF_ROTATION_ATTR_ID) {
                byte[] value = ByteBufferUtils.toByteArray(attribute);
                SigningCertificateLineage lineage = readFromV3AttributeValue(value);
                lineages.add(lineage);
            }
        }
        SigningCertificateLineage result;
        // There should only be a single attribute with the lineage, but if there are multiple then
        // attempt to consolidate the lineages.
        if (lineages.isEmpty()) {
            throw new IllegalArgumentException("The signed data does not contain a valid lineage.");
        } else if (lineages.size() > 1) {
            result = consolidateLineages(lineages);
        } else {
            result = lineages.get(0);
        }
        return result;
    }

    public byte[] getBytes() {
        return write().array();
    }

    public void writeToFile(File file) throws IOException {
        if (file == null) {
            throw new NullPointerException("file == null");
        }
        RandomAccessFile outputFile = new RandomAccessFile(file, "rw");
        writeToDataSink(new RandomAccessFileDataSink(outputFile));
    }

    public void writeToDataSink(DataSink dataSink) throws IOException {
        if (dataSink == null) {
            throw new NullPointerException("dataSink == null");
        }
        dataSink.consume(write());
    }

    /**
     * Add a new signing certificate to the lineage.  This effectively creates a signing certificate
     * rotation event, forcing APKs which include this lineage to be signed by the new signer. The
     * flags associated with the new signer are set to a default value.
     *
     * @param parent current signing certificate of the containing APK
     * @param child new signing certificate which will sign the APK contents
     */
    public SigningCertificateLineage spawnDescendant(SignerConfig parent, SignerConfig child)
            throws CertificateEncodingException, InvalidKeyException, NoSuchAlgorithmException,
            SignatureException {
        if (parent == null || child == null) {
            throw new NullPointerException("can't add new descendant to lineage with null inputs");
        }
        SignerCapabilities signerCapabilities = new SignerCapabilities.Builder().build();
        return spawnDescendant(parent, child, signerCapabilities);
    }

    /**
     * Add a new signing certificate to the lineage.  This effectively creates a signing certificate
     * rotation event, forcing APKs which include this lineage to be signed by the new signer.
     *
     * @param parent current signing certificate of the containing APK
     * @param child new signing certificate which will sign the APK contents
     * @param childCapabilities flags
     */
    public SigningCertificateLineage spawnDescendant(
            SignerConfig parent, SignerConfig child, SignerCapabilities childCapabilities)
            throws CertificateEncodingException, InvalidKeyException,
            NoSuchAlgorithmException, SignatureException {
        if (parent == null) {
            throw new NullPointerException("parent == null");
        }
        if (child == null) {
            throw new NullPointerException("child == null");
        }
        if (childCapabilities == null) {
            throw new NullPointerException("childCapabilities == null");
        }
        if (mSigningLineage.isEmpty()) {
            throw new IllegalArgumentException("Cannot spawn descendant signing certificate on an"
                    + " empty SigningCertificateLineage: no parent node");
        }

        // make sure that the parent matches our newest generation (leaf node/sink)
        SigningCertificateNode currentGeneration = mSigningLineage.get(mSigningLineage.size() - 1);
        if (!Arrays.equals(currentGeneration.signingCert.getEncoded(),
                parent.getCertificate().getEncoded())) {
            throw new IllegalArgumentException("SignerConfig Certificate containing private key"
                    + " to sign the new SigningCertificateLineage record does not match the"
                    + " existing most recent record");
        }

        // create data to be signed, including the algorithm we're going to use
        SignatureAlgorithm signatureAlgorithm = getSignatureAlgorithm(parent);
        ByteBuffer prefixedSignedData = ByteBuffer.wrap(
                V3SigningCertificateLineage.encodeSignedData(
                        child.getCertificate(), signatureAlgorithm.getId()));
        prefixedSignedData.position(4);
        ByteBuffer signedDataBuffer = ByteBuffer.allocate(prefixedSignedData.remaining());
        signedDataBuffer.put(prefixedSignedData);
        byte[] signedData = signedDataBuffer.array();

        // create SignerConfig to do the signing
        List<X509Certificate> certificates = new ArrayList<>(1);
        certificates.add(parent.getCertificate());
        ApkSigningBlockUtils.SignerConfig newSignerConfig =
                new ApkSigningBlockUtils.SignerConfig();
        newSignerConfig.privateKey = parent.getPrivateKey();
        newSignerConfig.certificates = certificates;
        newSignerConfig.signatureAlgorithms = Collections.singletonList(signatureAlgorithm);

        // sign it
        List<Pair<Integer, byte[]>> signatures =
                ApkSigningBlockUtils.generateSignaturesOverData(newSignerConfig, signedData);

        // finally, add it to our lineage
        SignatureAlgorithm sigAlgorithm = SignatureAlgorithm.findById(signatures.get(0).getFirst());
        byte[] signature = signatures.get(0).getSecond();
        currentGeneration.sigAlgorithm = sigAlgorithm;
        SigningCertificateNode childNode =
                new SigningCertificateNode(
                        child.getCertificate(), sigAlgorithm, null,
                        signature, childCapabilities.getFlags());
        List<SigningCertificateNode> lineageCopy = new ArrayList<>(mSigningLineage);
        lineageCopy.add(childNode);
        return new SigningCertificateLineage(mMinSdkVersion, lineageCopy);
    }

    /**
     * The number of signing certificates in the lineage, including the current signer, which means
     * this value can also be used to V2determine the number of signing certificate rotations by
     * subtracting 1.
     */
    public int size() {
        return mSigningLineage.size();
    }

    private SignatureAlgorithm getSignatureAlgorithm(SignerConfig parent)
            throws InvalidKeyException {
        PublicKey publicKey = parent.getCertificate().getPublicKey();

        // TODO switch to one signature algorithm selection, or add support for multiple algorithms
        List<SignatureAlgorithm> algorithms = V3SchemeSigner.getSuggestedSignatureAlgorithms(
                publicKey, mMinSdkVersion, false /* verityEnabled */,
                false /* deterministicDsaSigning */);
        return algorithms.get(0);
    }

    private SigningCertificateLineage spawnFirstDescendant(
            SignerConfig parent, SignerCapabilities signerCapabilities) {
        if (!mSigningLineage.isEmpty()) {
            throw new IllegalStateException("SigningCertificateLineage already has its first node");
        }

        // check to make sure that the public key for the first node is acceptable for our minSdk
        try {
            getSignatureAlgorithm(parent);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("Algorithm associated with first signing certificate"
                    + " invalid on desired platform versions", e);
        }

        // create "fake" signed data (there will be no signature over it, since there is no parent
        SigningCertificateNode firstNode = new SigningCertificateNode(
                parent.getCertificate(), null, null, new byte[0], signerCapabilities.getFlags());
        return new SigningCertificateLineage(mMinSdkVersion, Collections.singletonList(firstNode));
    }

    private static SigningCertificateLineage read(ByteBuffer inputByteBuffer)
            throws IOException {
        ApkSigningBlockUtils.checkByteOrderLittleEndian(inputByteBuffer);
        if (inputByteBuffer.remaining() < 8) {
            throw new IllegalArgumentException(
                    "Improper SigningCertificateLineage format: insufficient data for header.");
        }

        if (inputByteBuffer.getInt() != MAGIC) {
            throw new IllegalArgumentException(
                    "Improper SigningCertificateLineage format: MAGIC header mismatch.");
        }
        return read(inputByteBuffer, inputByteBuffer.getInt());
    }

    private static SigningCertificateLineage read(ByteBuffer inputByteBuffer, int version)
            throws IOException {
        switch (version) {
            case FIRST_VERSION:
                try {
                    List<SigningCertificateNode> nodes =
                            V3SigningCertificateLineage.readSigningCertificateLineage(
                                    getLengthPrefixedSlice(inputByteBuffer));
                    int minSdkVersion = calculateMinSdkVersion(nodes);
                    return new SigningCertificateLineage(minSdkVersion, nodes);
                } catch (ApkFormatException e) {
                    // unable to get a proper length-prefixed lineage slice
                    throw new IOException("Unable to read list of signing certificate nodes in "
                            + "SigningCertificateLineage", e);
                }
            default:
                throw new IllegalArgumentException(
                        "Improper SigningCertificateLineage format: unrecognized version.");
        }
    }

    private static int calculateMinSdkVersion(List<SigningCertificateNode> nodes) {
        if (nodes == null) {
            throw new IllegalArgumentException("Can't calculate minimum SDK version of null nodes");
        }
        int minSdkVersion = AndroidSdkVersion.P; // lineage introduced in P
        for (SigningCertificateNode node : nodes) {
            if (node.sigAlgorithm != null) {
                int nodeMinSdkVersion = node.sigAlgorithm.getMinSdkVersion();
                if (nodeMinSdkVersion > minSdkVersion) {
                    minSdkVersion = nodeMinSdkVersion;
                }
            }
        }
        return minSdkVersion;
    }

    private ByteBuffer write() {
        byte[] encodedLineage =
                V3SigningCertificateLineage.encodeSigningCertificateLineage(mSigningLineage);
        int payloadSize = 4 + 4 + 4 + encodedLineage.length;
        ByteBuffer result = ByteBuffer.allocate(payloadSize);
        result.order(ByteOrder.LITTLE_ENDIAN);
        result.putInt(MAGIC);
        result.putInt(CURRENT_VERSION);
        result.putInt(encodedLineage.length);
        result.put(encodedLineage);
        result.flip();
        return result;
    }

    public byte[] encodeSigningCertificateLineage() {
        return V3SigningCertificateLineage.encodeSigningCertificateLineage(mSigningLineage);
    }

    public List<DefaultApkSignerEngine.SignerConfig> sortSignerConfigs(
            List<DefaultApkSignerEngine.SignerConfig> signerConfigs) {
        if (signerConfigs == null) {
            throw new NullPointerException("signerConfigs == null");
        }

        // not the most elegant sort, but we expect signerConfigs to be quite small (1 or 2 signers
        // in most cases) and likely already sorted, so not worth the overhead of doing anything
        // fancier
        List<DefaultApkSignerEngine.SignerConfig> sortedSignerConfigs =
                new ArrayList<>(signerConfigs.size());
        for (int i = 0; i < mSigningLineage.size(); i++) {
            for (int j = 0; j < signerConfigs.size(); j++) {
                DefaultApkSignerEngine.SignerConfig config = signerConfigs.get(j);
                if (mSigningLineage.get(i).signingCert.equals(config.getCertificates().get(0))) {
                    sortedSignerConfigs.add(config);
                    break;
                }
            }
        }
        if (sortedSignerConfigs.size() != signerConfigs.size()) {
            throw new IllegalArgumentException("SignerConfigs supplied which are not present in the"
                    + " SigningCertificateLineage");
        }
        return sortedSignerConfigs;
    }

    /**
     * Returns the SignerCapabilities for the signer in the lineage that matches the provided
     * config.
     */
    public SignerCapabilities getSignerCapabilities(SignerConfig config) {
        if (config == null) {
            throw new NullPointerException("config == null");
        }

        X509Certificate cert = config.getCertificate();
        return getSignerCapabilities(cert);
    }

    /**
     * Returns the SignerCapabilities for the signer in the lineage that matches the provided
     * certificate.
     */
    public SignerCapabilities getSignerCapabilities(X509Certificate cert) {
        if (cert == null) {
            throw new NullPointerException("cert == null");
        }

        for (int i = 0; i < mSigningLineage.size(); i++) {
            SigningCertificateNode lineageNode = mSigningLineage.get(i);
            if (lineageNode.signingCert.equals(cert)) {
                int flags = lineageNode.flags;
                return new SignerCapabilities.Builder(flags).build();
            }
        }

        // the provided signer certificate was not found in the lineage
        throw new IllegalArgumentException("Certificate (" + cert.getSubjectDN()
                + ") not found in the SigningCertificateLineage");
    }

    /**
     * Updates the SignerCapabilities for the signer in the lineage that matches the provided
     * config. Only those capabilities that have been modified through the setXX methods will be
     * updated for the signer to prevent unset default values from being applied.
     */
    public void updateSignerCapabilities(SignerConfig config, SignerCapabilities capabilities) {
        if (config == null) {
            throw new NullPointerException("config == null");
        }

        X509Certificate cert = config.getCertificate();
        for (int i = 0; i < mSigningLineage.size(); i++) {
            SigningCertificateNode lineageNode = mSigningLineage.get(i);
            if (lineageNode.signingCert.equals(cert)) {
                int flags = lineageNode.flags;
                SignerCapabilities newCapabilities = new SignerCapabilities.Builder(
                        flags).setCallerConfiguredCapabilities(capabilities).build();
                lineageNode.flags = newCapabilities.getFlags();
                return;
            }
        }

        // the provided signer config was not found in the lineage
        throw new IllegalArgumentException("Certificate (" + cert.getSubjectDN()
                + ") not found in the SigningCertificateLineage");
    }

    /**
     * Returns a list containing all of the certificates in the lineage.
     */
    public List<X509Certificate> getCertificatesInLineage() {
        List<X509Certificate> certs = new ArrayList<>();
        for (int i = 0; i < mSigningLineage.size(); i++) {
            X509Certificate cert = mSigningLineage.get(i).signingCert;
            certs.add(cert);
        }
        return certs;
    }

    /**
     * Returns {@code true} if the specified config is in the lineage.
     */
    public boolean isSignerInLineage(SignerConfig config) {
        if (config == null) {
            throw new NullPointerException("config == null");
        }

        X509Certificate cert = config.getCertificate();
        return isCertificateInLineage(cert);
    }

    /**
     * Returns {@code true} if the specified certificate is in the lineage.
     */
    public boolean isCertificateInLineage(X509Certificate cert) {
        if (cert == null) {
            throw new NullPointerException("cert == null");
        }

        for (int i = 0; i < mSigningLineage.size(); i++) {
            if (mSigningLineage.get(i).signingCert.equals(cert)) {
                return true;
            }
        }
        return false;
    }

    private static int calculateDefaultFlags() {
        return PAST_CERT_INSTALLED_DATA | PAST_CERT_PERMISSION
                | PAST_CERT_SHARED_USER_ID | PAST_CERT_AUTH;
    }

    /**
     * Returns a new SigingCertificateLineage which terminates at the node corresponding to the
     * given certificate.  This is useful in the event of rotating to a new signing algorithm that
     * is only supported on some platform versions.  It enables a v3 signature to be generated using
     * this signing certificate and the shortened proof-of-rotation record from this sub lineage in
     * conjunction with the appropriate SDK version values.
     *
     * @param x509Certificate the signing certificate for which to search
     * @return A new SigningCertificateLineage if the given certificate is present.
     *
     * @throws IllegalArgumentException if the provided certificate is not in the lineage.
     */
    public SigningCertificateLineage getSubLineage(X509Certificate x509Certificate) {
        if (x509Certificate == null) {
            throw new NullPointerException("x509Certificate == null");
        }
        for (int i = 0; i < mSigningLineage.size(); i++) {
            if (mSigningLineage.get(i).signingCert.equals(x509Certificate)) {
                return new SigningCertificateLineage(
                        mMinSdkVersion, new ArrayList<>(mSigningLineage.subList(0, i + 1)));
            }
        }

        // looks like we didn't find the cert,
        throw new IllegalArgumentException("Certificate not found in SigningCertificateLineage");
    }

    /**
     * Consolidates all of the lineages found in an APK into one lineage, which is the longest one.
     * In so doing, it also checks that all of the smaller lineages are contained in the largest,
     * and that they properly cover the desired platform ranges.
     *
     * An APK may contain multiple lineages, one for each signer, which correspond to different
     * supported platform versions.  In this event, the lineage(s) from the earlier platform
     * version(s) need to be present in the most recent (longest) one to make sure that when a
     * platform version changes.
     *
     * <note> This does not verify that the largest lineage corresponds to the most recent supported
     * platform version.  That check requires is performed during v3 verification. </note>
     */
    public static SigningCertificateLineage consolidateLineages(
            List<SigningCertificateLineage> lineages) {
        if (lineages == null || lineages.isEmpty()) {
            return null;
        }
        int largestIndex = 0;
        int maxSize = 0;

        // determine the longest chain
        for (int i = 0; i < lineages.size(); i++) {
            int curSize = lineages.get(i).size();
            if (curSize > maxSize) {
                largestIndex = i;
                maxSize = curSize;
            }
        }

        List<SigningCertificateNode> largestList = lineages.get(largestIndex).mSigningLineage;
        // make sure all other lineages fit into this one, with the same capabilities
        for (int i = 0; i < lineages.size(); i++) {
            if (i == largestIndex) {
                continue;
            }
            List<SigningCertificateNode> underTest = lineages.get(i).mSigningLineage;
            if (!underTest.equals(largestList.subList(0, underTest.size()))) {
                throw new IllegalArgumentException("Inconsistent SigningCertificateLineages. "
                        + "Not all lineages are subsets of each other.");
            }
        }

        // if we've made it this far, they all check out, so just return the largest
        return lineages.get(largestIndex);
    }

    /**
     * Representation of the capabilities the APK would like to grant to its old signing
     * certificates.  The {@code SigningCertificateLineage} provides two conceptual data structures.
     *   1) proof of rotation - Evidence that other parties can trust an APK's current signing
     *      certificate if they trust an older one in this lineage
     *   2) self-trust - certain capabilities may have been granted by an APK to other parties based
     *      on its own signing certificate.  When it changes its signing certificate it may want to
     *      allow the other parties to retain those capabilities.
     * {@code SignerCapabilties} provides a representation of the second structure.
     *
     * <p>Use {@link Builder} to obtain configuration instances.
     */
    public static class SignerCapabilities {
        private final int mFlags;

        private final int mCallerConfiguredFlags;

        private SignerCapabilities(int flags) {
            this(flags, 0);
        }

        private SignerCapabilities(int flags, int callerConfiguredFlags) {
            mFlags = flags;
            mCallerConfiguredFlags = callerConfiguredFlags;
        }

        private int getFlags() {
            return mFlags;
        }

        /**
         * Returns {@code true} if the capabilities of this object match those of the provided
         * object.
         */
        public boolean equals(SignerCapabilities other) {
            return this.mFlags == other.mFlags;
        }

        /**
         * Returns {@code true} if this object has the installed data capability.
         */
        public boolean hasInstalledData() {
            return (mFlags & PAST_CERT_INSTALLED_DATA) != 0;
        }

        /**
         * Returns {@code true} if this object has the shared UID capability.
         */
        public boolean hasSharedUid() {
            return (mFlags & PAST_CERT_SHARED_USER_ID) != 0;
        }

        /**
         * Returns {@code true} if this object has the permission capability.
         */
        public boolean hasPermission() {
            return (mFlags & PAST_CERT_PERMISSION) != 0;
        }

        /**
         * Returns {@code true} if this object has the rollback capability.
         */
        public boolean hasRollback() {
            return (mFlags & PAST_CERT_ROLLBACK) != 0;
        }

        /**
         * Returns {@code true} if this object has the auth capability.
         */
        public boolean hasAuth() {
            return (mFlags & PAST_CERT_AUTH) != 0;
        }

        /**
         * Builder of {@link SignerCapabilities} instances.
         */
        public static class Builder {
            private int mFlags;

            private int mCallerConfiguredFlags;

            /**
             * Constructs a new {@code Builder}.
             */
            public Builder() {
                mFlags = calculateDefaultFlags();
            }

            /**
             * Constructs a new {@code Builder} with the initial capabilities set to the provided
             * flags.
             */
            public Builder(int flags) {
                mFlags = flags;
            }

            /**
             * Set the {@code PAST_CERT_INSTALLED_DATA} flag in this capabilities object.  This flag
             * is used by the platform to determine if installed data associated with previous
             * signing certificate should be trusted.  In particular, this capability is required to
             * perform signing certificate rotation during an upgrade on-device.  Without it, the
             * platform will not permit the app data from the old signing certificate to
             * propagate to the new version.  Typically, this flag should be set to enable signing
             * certificate rotation, and may be unset later when the app developer is satisfied that
             * their install base is as migrated as it will be.
             */
            public Builder setInstalledData(boolean enabled) {
                mCallerConfiguredFlags |= PAST_CERT_INSTALLED_DATA;
                if (enabled) {
                    mFlags |= PAST_CERT_INSTALLED_DATA;
                } else {
                    mFlags &= ~PAST_CERT_INSTALLED_DATA;
                }
                return this;
            }

            /**
             * Set the {@code PAST_CERT_SHARED_USER_ID} flag in this capabilities object.  This flag
             * is used by the platform to determine if this app is willing to be sharedUid with
             * other apps which are still signed with the associated signing certificate.  This is
             * useful in situations where sharedUserId apps would like to change their signing
             * certificate, but can't guarantee the order of updates to those apps.
             */
            public Builder setSharedUid(boolean enabled) {
                mCallerConfiguredFlags |= PAST_CERT_SHARED_USER_ID;
                if (enabled) {
                    mFlags |= PAST_CERT_SHARED_USER_ID;
                } else {
                    mFlags &= ~PAST_CERT_SHARED_USER_ID;
                }
                return this;
            }

            /**
             * Set the {@code PAST_CERT_PERMISSION} flag in this capabilities object.  This flag
             * is used by the platform to determine if this app is willing to grant SIGNATURE
             * permissions to apps signed with the associated signing certificate.  Without this
             * capability, an application signed with the older certificate will not be granted the
             * SIGNATURE permissions defined by this app.  In addition, if multiple apps define the
             * same SIGNATURE permission, the second one the platform sees will not be installable
             * if this capability is not set and the signing certificates differ.
             */
            public Builder setPermission(boolean enabled) {
                mCallerConfiguredFlags |= PAST_CERT_PERMISSION;
                if (enabled) {
                    mFlags |= PAST_CERT_PERMISSION;
                } else {
                    mFlags &= ~PAST_CERT_PERMISSION;
                }
                return this;
            }

            /**
             * Set the {@code PAST_CERT_ROLLBACK} flag in this capabilities object.  This flag
             * is used by the platform to determine if this app is willing to upgrade to a new
             * version that is signed by one of its past signing certificates.
             *
             * <note> WARNING: this effectively removes any benefit of signing certificate changes,
             * since a compromised key could retake control of an app even after change, and should
             * only be used if there is a problem encountered when trying to ditch an older cert
             * </note>
             */
            public Builder setRollback(boolean enabled) {
                mCallerConfiguredFlags |= PAST_CERT_ROLLBACK;
                if (enabled) {
                    mFlags |= PAST_CERT_ROLLBACK;
                } else {
                    mFlags &= ~PAST_CERT_ROLLBACK;
                }
                return this;
            }

            /**
             * Set the {@code PAST_CERT_AUTH} flag in this capabilities object.  This flag
             * is used by the platform to determine whether or not privileged access based on
             * authenticator module signing certificates should be granted.
             */
            public Builder setAuth(boolean enabled) {
                mCallerConfiguredFlags |= PAST_CERT_AUTH;
                if (enabled) {
                    mFlags |= PAST_CERT_AUTH;
                } else {
                    mFlags &= ~PAST_CERT_AUTH;
                }
                return this;
            }

            /**
             * Applies the capabilities that were explicitly set in the provided capabilities object
             * to this builder. Any values that were not set will not be applied to this builder
             * to prevent unintentinoally setting a capability back to a default value.
             */
            public Builder setCallerConfiguredCapabilities(SignerCapabilities capabilities) {
                // The mCallerConfiguredFlags should have a bit set for each capability that was
                // set by a caller. If a capability was explicitly set then the corresponding bit
                // in mCallerConfiguredFlags should be set. This allows the provided capabilities
                // to take effect for those set by the caller while those that were not set will
                // be cleared by the bitwise and and the initial value for the builder will remain.
                mFlags = (mFlags & ~capabilities.mCallerConfiguredFlags) |
                        (capabilities.mFlags & capabilities.mCallerConfiguredFlags);
                return this;
            }

            /**
             * Returns a new {@code SignerConfig} instance configured based on the configuration of
             * this builder.
             */
            public SignerCapabilities build() {
                return new SignerCapabilities(mFlags, mCallerConfiguredFlags);
            }
        }
    }

    /**
     * Configuration of a signer.  Used to add a new entry to the {@link SigningCertificateLineage}
     *
     * <p>Use {@link Builder} to obtain configuration instances.
     */
    public static class SignerConfig {
        private final PrivateKey mPrivateKey;
        private final X509Certificate mCertificate;

        private SignerConfig(
                PrivateKey privateKey,
                X509Certificate certificate) {
            mPrivateKey = privateKey;
            mCertificate = certificate;
        }

        /**
         * Returns the signing key of this signer.
         */
        public PrivateKey getPrivateKey() {
            return mPrivateKey;
        }

        /**
         * Returns the certificate(s) of this signer. The first certificate's public key corresponds
         * to this signer's private key.
         */
        public X509Certificate getCertificate() {
            return mCertificate;
        }

        /**
         * Builder of {@link SignerConfig} instances.
         */
        public static class Builder {
            private final PrivateKey mPrivateKey;
            private final X509Certificate mCertificate;

            /**
             * Constructs a new {@code Builder}.
             *
             * @param privateKey signing key
             * @param certificate the X.509 certificate with a subject public key of the
             * {@code privateKey}.
             */
            public Builder(
                    PrivateKey privateKey,
                    X509Certificate certificate) {
                mPrivateKey = privateKey;
                mCertificate = certificate;
            }

            /**
             * Returns a new {@code SignerConfig} instance configured based on the configuration of
             * this builder.
             */
            public SignerConfig build() {
                return new SignerConfig(
                        mPrivateKey,
                        mCertificate);
            }
        }
    }

    /**
     * Builder of {@link SigningCertificateLineage} instances.
     */
    public static class Builder {
        private final SignerConfig mOriginalSignerConfig;
        private final SignerConfig mNewSignerConfig;
        private SignerCapabilities mOriginalCapabilities;
        private SignerCapabilities mNewCapabilities;
        private int mMinSdkVersion;
        /**
         * Constructs a new {@code Builder}.
         *
         * @param originalSignerConfig first signer in this lineage, parent of the next
         * @param newSignerConfig new signer in the lineage; the new signing key that the APK will
         *                        use
         */
        public Builder(
                SignerConfig originalSignerConfig,
                SignerConfig newSignerConfig) {
            if (originalSignerConfig == null || newSignerConfig == null) {
                throw new NullPointerException("Can't pass null SignerConfigs when constructing a "
                        + "new SigningCertificateLineage");
            }
            mOriginalSignerConfig = originalSignerConfig;
            mNewSignerConfig = newSignerConfig;
        }

        /**
         * Sets the minimum Android platform version (API Level) on which this lineage is expected
         * to validate.  It is possible that newer signers in the lineage may not be recognized on
         * the given platform, but as long as an older signer is, the lineage can still be used to
         * sign an APK for the given platform.
         *
         * <note> By default, this value is set to the value for the
         * P release, since this structure was created for that release, and will also be set to
         * that value if a smaller one is specified. </note>
         */
        public Builder setMinSdkVersion(int minSdkVersion) {
            mMinSdkVersion = minSdkVersion;
            return this;
        }

        /**
         * Sets capabilities to give {@code mOriginalSignerConfig}. These capabilities allow an
         * older signing certificate to still be used in some situations on the platform even though
         * the APK is now being signed by a newer signing certificate.
         */
        public Builder setOriginalCapabilities(SignerCapabilities signerCapabilities) {
            if (signerCapabilities == null) {
                throw new NullPointerException("signerCapabilities == null");
            }
            mOriginalCapabilities = signerCapabilities;
            return this;
        }

        /**
         * Sets capabilities to give {@code mNewSignerConfig}. These capabilities allow an
         * older signing certificate to still be used in some situations on the platform even though
         * the APK is now being signed by a newer signing certificate.  By default, the new signer
         * will have all capabilities, so when first switching to a new signing certificate, these
         * capabilities have no effect, but they will act as the default level of trust when moving
         * to a new signing certificate.
         */
        public Builder setNewCapabilities(SignerCapabilities signerCapabilities) {
            if (signerCapabilities == null) {
                throw new NullPointerException("signerCapabilities == null");
            }
            mNewCapabilities = signerCapabilities;
            return this;
        }

        public SigningCertificateLineage build()
                throws CertificateEncodingException, InvalidKeyException, NoSuchAlgorithmException,
                SignatureException {
            if (mMinSdkVersion < AndroidSdkVersion.P) {
                mMinSdkVersion = AndroidSdkVersion.P;
            }

            if (mOriginalCapabilities == null) {
                mOriginalCapabilities = new SignerCapabilities.Builder().build();
            }

            if (mNewCapabilities == null) {
                mNewCapabilities = new SignerCapabilities.Builder().build();
            }

            return createSigningLineage(
                    mMinSdkVersion, mOriginalSignerConfig, mOriginalCapabilities,
                    mNewSignerConfig, mNewCapabilities);
        }
    }
}
