/*
 * 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.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 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,
                            V3SchemeSigner.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 == V3SchemeSigner.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 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 /* padding support */);
        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[] generateV3SignerAttribute() {
        // FORMAT (little endian):
        // * length-prefixed bytes: attribute pair
        //   * uint32: ID
        //   * bytes: value - encoded V3 SigningCertificateLineage
        byte[] encodedLineage =
                V3SigningCertificateLineage.encodeSigningCertificateLineage(mSigningLineage);
        int payloadSize = 4 + 4 + encodedLineage.length;
        ByteBuffer result = ByteBuffer.allocate(payloadSize);
        result.order(ByteOrder.LITTLE_ENDIAN);
        result.putInt(4 + encodedLineage.length);
        result.putInt(V3SchemeSigner.PROOF_OF_ROTATION_ATTR_ID);
        result.put(encodedLineage);
        return result.array();
    }

    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);
        }
    }
}
