/*
 * Copyright (C) 2020 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.internal.apk.v4;

import static com.android.apksig.internal.apk.ApkSigningBlockUtils.toHex;

import com.android.apksig.ApkVerifier;
import com.android.apksig.ApkVerifier.Issue;
import com.android.apksig.internal.apk.ApkSigningBlockUtils;
import com.android.apksig.internal.apk.ContentDigestAlgorithm;
import com.android.apksig.internal.apk.SignatureAlgorithm;
import com.android.apksig.internal.util.GuaranteedEncodedFormX509Certificate;
import com.android.apksig.internal.util.X509CertificateUtils;
import com.android.apksig.util.DataSource;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;

/**
 * APK Signature Scheme V4 verifier.
 * <p>
 * Verifies the serialized V4Signature file against an APK.
 */
public abstract class V4SchemeVerifier {
    /**
     * Hidden constructor to prevent instantiation.
     */
    private V4SchemeVerifier() {
    }

    /**
     * <p>
     * The main goals of the verifier are: 1) parse V4Signature file fields 2) verifies the PKCS7
     * signature block against the raw root hash bytes in the proto field 3) verifies that the raw
     * root hash matches with the actual hash tree root of the give APK 4) if the file contains a
     * verity tree, verifies that it matches with the actual verity tree computed from the given
     * APK.
     * </p>
     */
    public static ApkSigningBlockUtils.Result verify(DataSource apk, File v4SignatureFile)
            throws IOException, NoSuchAlgorithmException {
        final V4Signature signature;
        final byte[] tree;
        try (InputStream input = new FileInputStream(v4SignatureFile)) {
            signature = V4Signature.readFrom(input);
            tree = V4Signature.readBytes(input);
        }

        final ApkSigningBlockUtils.Result result = new ApkSigningBlockUtils.Result(
                ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V4);

        if (signature == null) {
            result.addError(Issue.V4_SIG_NO_SIGNATURES,
                    "Signature file does not contain a v4 signature.");
            return result;
        }

        if (signature.version != V4Signature.CURRENT_VERSION) {
            result.addWarning(Issue.V4_SIG_VERSION_NOT_CURRENT, signature.version,
                    V4Signature.CURRENT_VERSION);
        }

        V4Signature.HashingInfo hashingInfo = V4Signature.HashingInfo.fromByteArray(
                signature.hashingInfo);
        V4Signature.SigningInfo signingInfo = V4Signature.SigningInfo.fromByteArray(
                signature.signingInfo);

        final byte[] signedData = V4Signature.getSignedData(apk.size(), hashingInfo, signingInfo);

        // First, verify the signature over signedData.
        ApkSigningBlockUtils.Result.SignerInfo signerInfo = parseAndVerifySignatureBlock(
                signingInfo, signedData);
        result.signers.add(signerInfo);
        if (result.containsErrors()) {
            return result;
        }

        // Second, check if the root hash and the tree are correct.
        verifyRootHashAndTree(apk, signerInfo, hashingInfo.rawRootHash, tree);
        if (!result.containsErrors()) {
            result.verified = true;
        }

        return result;
    }

    /**
     * Parses the provided signature block and populates the {@code result}.
     * <p>
     * This verifies {@signingInfo} over {@code signedData}, as well as parsing the certificate
     * contained in the signature block. This method adds one or more errors to the {@code result}.
     */
    private static ApkSigningBlockUtils.Result.SignerInfo parseAndVerifySignatureBlock(
            V4Signature.SigningInfo signingInfo,
            final byte[] signedData) throws NoSuchAlgorithmException {
        final ApkSigningBlockUtils.Result.SignerInfo result =
                new ApkSigningBlockUtils.Result.SignerInfo();
        result.index = 0;

        final int sigAlgorithmId = signingInfo.signatureAlgorithmId;
        final byte[] sigBytes = signingInfo.signature;
        result.signatures.add(
                new ApkSigningBlockUtils.Result.SignerInfo.Signature(sigAlgorithmId, sigBytes));

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.findById(sigAlgorithmId);
        if (signatureAlgorithm == null) {
            result.addError(Issue.V4_SIG_UNKNOWN_SIG_ALGORITHM, sigAlgorithmId);
            return result;
        }

        String jcaSignatureAlgorithm =
                signatureAlgorithm.getJcaSignatureAlgorithmAndParams().getFirst();
        AlgorithmParameterSpec jcaSignatureAlgorithmParams =
                signatureAlgorithm.getJcaSignatureAlgorithmAndParams().getSecond();

        String keyAlgorithm = signatureAlgorithm.getJcaKeyAlgorithm();

        final byte[] publicKeyBytes = signingInfo.publicKey;
        PublicKey publicKey;
        try {
            publicKey = KeyFactory.getInstance(keyAlgorithm).generatePublic(
                    new X509EncodedKeySpec(publicKeyBytes));
        } catch (Exception e) {
            result.addError(Issue.V4_SIG_MALFORMED_PUBLIC_KEY, e);
            return result;
        }

        try {
            Signature sig = Signature.getInstance(jcaSignatureAlgorithm);
            sig.initVerify(publicKey);
            if (jcaSignatureAlgorithmParams != null) {
                sig.setParameter(jcaSignatureAlgorithmParams);
            }
            sig.update(signedData);
            if (!sig.verify(sigBytes)) {
                result.addError(Issue.V4_SIG_DID_NOT_VERIFY, signatureAlgorithm);
                return result;
            }
            result.verifiedSignatures.put(signatureAlgorithm, sigBytes);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException
                | SignatureException e) {
            result.addError(Issue.V4_SIG_VERIFY_EXCEPTION, signatureAlgorithm, e);
            return result;
        }

        if (signingInfo.certificate == null) {
            result.addError(Issue.V4_SIG_NO_CERTIFICATE);
            return result;
        }

        final X509Certificate certificate;
        try {
            // Wrap the cert so that the result's getEncoded returns exactly the original encoded
            // form. Without this, getEncoded may return a different form from what was stored in
            // the signature. This is because some X509Certificate(Factory) implementations
            // re-encode certificates.
            certificate = new GuaranteedEncodedFormX509Certificate(
                    X509CertificateUtils.generateCertificate(signingInfo.certificate),
                    signingInfo.certificate);
        } catch (CertificateException e) {
            result.addError(Issue.V4_SIG_MALFORMED_CERTIFICATE, e);
            return result;
        }
        result.certs.add(certificate);

        byte[] certificatePublicKeyBytes;
        try {
            certificatePublicKeyBytes = ApkSigningBlockUtils.encodePublicKey(
                    certificate.getPublicKey());
        } catch (InvalidKeyException e) {
            System.out.println("Caught an exception encoding the public key: " + e);
            e.printStackTrace();
            certificatePublicKeyBytes = certificate.getPublicKey().getEncoded();
        }
        if (!Arrays.equals(publicKeyBytes, certificatePublicKeyBytes)) {
            result.addError(
                    Issue.V4_SIG_PUBLIC_KEY_MISMATCH_BETWEEN_CERTIFICATE_AND_SIGNATURES_RECORD,
                    ApkSigningBlockUtils.toHex(certificatePublicKeyBytes),
                    ApkSigningBlockUtils.toHex(publicKeyBytes));
            return result;
        }

        // Add apk digest from the file to the result.
        ApkSigningBlockUtils.Result.SignerInfo.ContentDigest contentDigest =
                new ApkSigningBlockUtils.Result.SignerInfo.ContentDigest(
                        0 /* signature algorithm id doesn't matter here */, signingInfo.apkDigest);
        result.contentDigests.add(contentDigest);

        return result;
    }

    private static void verifyRootHashAndTree(DataSource apkContent,
            ApkSigningBlockUtils.Result.SignerInfo signerInfo, byte[] expectedDigest,
            byte[] expectedTree) throws IOException, NoSuchAlgorithmException {
        ApkSigningBlockUtils.VerityTreeAndDigest actualContentDigestInfo =
                ApkSigningBlockUtils.computeChunkVerityTreeAndDigest(apkContent);

        ContentDigestAlgorithm algorithm = actualContentDigestInfo.contentDigestAlgorithm;
        final byte[] actualDigest = actualContentDigestInfo.rootHash;
        final byte[] actualTree = actualContentDigestInfo.tree;

        if (!Arrays.equals(expectedDigest, actualDigest)) {
            signerInfo.addError(
                    ApkVerifier.Issue.V4_SIG_APK_ROOT_DID_NOT_VERIFY,
                    algorithm,
                    toHex(expectedDigest),
                    toHex(actualDigest));
            return;
        }
        // Only check verity tree if it is not empty
        if (expectedTree != null && !Arrays.equals(expectedTree, actualTree)) {
            signerInfo.addError(
                    ApkVerifier.Issue.V4_SIG_APK_TREE_DID_NOT_VERIFY,
                    algorithm,
                    toHex(expectedDigest),
                    toHex(actualDigest));
            return;
        }

        signerInfo.verifiedContentDigests.put(algorithm, actualDigest);
    }
}
