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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateEncodingException;
import java.util.Arrays;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 *    AndroidVerifiedBootSignature DEFINITIONS ::=
 *    BEGIN
 *        formatVersion ::= INTEGER
 *        certificate ::= Certificate
 *        algorithmIdentifier ::= SEQUENCE {
 *            algorithm OBJECT IDENTIFIER,
 *            parameters ANY DEFINED BY algorithm OPTIONAL
 *        }
 *        authenticatedAttributes ::= SEQUENCE {
 *            target CHARACTER STRING,
 *            length INTEGER
 *        }
 *        signature ::= OCTET STRING
 *     END
 */

public class BootSignature extends ASN1Object
{
    private ASN1Integer             formatVersion;
    private ASN1Encodable           certificate;
    private AlgorithmIdentifier     algorithmIdentifier;
    private DERPrintableString      target;
    private ASN1Integer             length;
    private DEROctetString          signature;
    private PublicKey               publicKey;

    private static final int FORMAT_VERSION = 1;

    /**
     * Initializes the object for signing an image file
     * @param target Target name, included in the signed data
     * @param length Length of the image, included in the signed data
     */
    public BootSignature(String target, int length) {
        this.formatVersion = new ASN1Integer(FORMAT_VERSION);
        this.target = new DERPrintableString(target);
        this.length = new ASN1Integer(length);
    }

    /**
     * Initializes the object for verifying a signed image file
     * @param signature Signature footer
     */
    public BootSignature(byte[] signature)
            throws Exception {
        ASN1InputStream stream = new ASN1InputStream(signature);
        ASN1Sequence sequence = (ASN1Sequence) stream.readObject();

        formatVersion = (ASN1Integer) sequence.getObjectAt(0);
        if (formatVersion.getValue().intValue() != FORMAT_VERSION) {
            throw new IllegalArgumentException("Unsupported format version");
        }

        certificate = sequence.getObjectAt(1);
        byte[] encoded = ((ASN1Object) certificate).getEncoded();
        ByteArrayInputStream bis = new ByteArrayInputStream(encoded);

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate c = (X509Certificate) cf.generateCertificate(bis);
        publicKey = c.getPublicKey();

        ASN1Sequence algId = (ASN1Sequence) sequence.getObjectAt(2);
        algorithmIdentifier = new AlgorithmIdentifier(
            (ASN1ObjectIdentifier) algId.getObjectAt(0));

        ASN1Sequence attrs = (ASN1Sequence) sequence.getObjectAt(3);
        target = (DERPrintableString) attrs.getObjectAt(0);
        length = (ASN1Integer) attrs.getObjectAt(1);

        this.signature = (DEROctetString) sequence.getObjectAt(4);
    }

    public ASN1Object getAuthenticatedAttributes() {
        ASN1EncodableVector attrs = new ASN1EncodableVector();
        attrs.add(target);
        attrs.add(length);
        return new DERSequence(attrs);
    }

    public byte[] getEncodedAuthenticatedAttributes() throws IOException {
        return getAuthenticatedAttributes().getEncoded();
    }

    public AlgorithmIdentifier getAlgorithmIdentifier() {
        return algorithmIdentifier;
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public byte[] getSignature() {
        return signature.getOctets();
    }

    public void setSignature(byte[] sig, AlgorithmIdentifier algId) {
        algorithmIdentifier = algId;
        signature = new DEROctetString(sig);
    }

    public void setCertificate(X509Certificate cert)
            throws Exception, IOException, CertificateEncodingException {
        ASN1InputStream s = new ASN1InputStream(cert.getEncoded());
        certificate = s.readObject();
        publicKey = cert.getPublicKey();
    }

    public byte[] generateSignableImage(byte[] image) throws IOException {
        byte[] attrs = getEncodedAuthenticatedAttributes();
        byte[] signable = Arrays.copyOf(image, image.length + attrs.length);
        for (int i=0; i < attrs.length; i++) {
            signable[i+image.length] = attrs[i];
        }
        return signable;
    }

    public byte[] sign(byte[] image, PrivateKey key) throws Exception {
        byte[] signable = generateSignableImage(image);
        return Utils.sign(key, signable);
    }

    public boolean verify(byte[] image) throws Exception {
        if (length.getValue().intValue() != image.length) {
            throw new IllegalArgumentException("Invalid image length");
        }

        byte[] signable = generateSignableImage(image);
        return Utils.verify(publicKey, signable, signature.getOctets(),
                    algorithmIdentifier);
    }

    public ASN1Primitive toASN1Primitive() {
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(formatVersion);
        v.add(certificate);
        v.add(algorithmIdentifier);
        v.add(getAuthenticatedAttributes());
        v.add(signature);
        return new DERSequence(v);
    }

    public static int getSignableImageSize(byte[] data) throws Exception {
        if (!Arrays.equals(Arrays.copyOfRange(data, 0, 8),
                "ANDROID!".getBytes("US-ASCII"))) {
            throw new IllegalArgumentException("Invalid image header: missing magic");
        }

        ByteBuffer image = ByteBuffer.wrap(data);
        image.order(ByteOrder.LITTLE_ENDIAN);

        image.getLong(); // magic
        int kernelSize = image.getInt();
        image.getInt(); // kernel_addr
        int ramdskSize = image.getInt();
        image.getInt(); // ramdisk_addr
        int secondSize = image.getInt();
        image.getLong(); // second_addr + tags_addr
        int pageSize = image.getInt();

        int length = pageSize // include the page aligned image header
                + ((kernelSize + pageSize - 1) / pageSize) * pageSize
                + ((ramdskSize + pageSize - 1) / pageSize) * pageSize
                + ((secondSize + pageSize - 1) / pageSize) * pageSize;

        length = ((length + pageSize - 1) / pageSize) * pageSize;

        if (length <= 0) {
            throw new IllegalArgumentException("Invalid image header: invalid length");
        }

        return length;
    }

    public static void doSignature( String target,
                                    String imagePath,
                                    String keyPath,
                                    String certPath,
                                    String outPath) throws Exception {

        byte[] image = Utils.read(imagePath);
        int signableSize = getSignableImageSize(image);

        if (signableSize < image.length) {
            System.err.println("NOTE: truncating file " + imagePath +
                    " from " + image.length + " to " + signableSize + " bytes");
            image = Arrays.copyOf(image, signableSize);
        } else if (signableSize > image.length) {
            throw new IllegalArgumentException("Invalid image: too short, expected " +
                    signableSize + " bytes");
        }

        BootSignature bootsig = new BootSignature(target, image.length);

        X509Certificate cert = Utils.loadPEMCertificate(certPath);
        bootsig.setCertificate(cert);

        PrivateKey key = Utils.loadDERPrivateKeyFromFile(keyPath);
        bootsig.setSignature(bootsig.sign(image, key),
            Utils.getSignatureAlgorithmIdentifier(key));

        byte[] encoded_bootsig = bootsig.getEncoded();
        byte[] image_with_metadata = Arrays.copyOf(image, image.length + encoded_bootsig.length);

        System.arraycopy(encoded_bootsig, 0, image_with_metadata,
                image.length, encoded_bootsig.length);

        Utils.write(image_with_metadata, outPath);
    }

    public static void verifySignature(String imagePath, String certPath) throws Exception {
        byte[] image = Utils.read(imagePath);
        int signableSize = getSignableImageSize(image);

        if (signableSize >= image.length) {
            throw new IllegalArgumentException("Invalid image: not signed");
        }

        byte[] signature = Arrays.copyOfRange(image, signableSize, image.length);
        BootSignature bootsig = new BootSignature(signature);

        if (!certPath.isEmpty()) {
            System.err.println("NOTE: verifying using public key from " + certPath);
            bootsig.setCertificate(Utils.loadPEMCertificate(certPath));
        }

        try {
            if (bootsig.verify(Arrays.copyOf(image, signableSize))) {
                System.err.println("Signature is VALID");
                System.exit(0);
            } else {
                System.err.println("Signature is INVALID");
            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        System.exit(1);
    }

    /* Example usage for signing a boot image using dev keys:
        java -cp \
            ../../../out/host/common/obj/JAVA_LIBRARIES/BootSignature_intermediates/ \
                classes/com.android.verity.BootSignature \
            /boot \
            ../../../out/target/product/$PRODUCT/boot.img \
            ../../../build/target/product/security/verity.pk8 \
            ../../../build/target/product/security/verity.x509.pem \
            /tmp/boot.img.signed
    */
    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        if ("-verify".equals(args[0])) {
            String certPath = "";

            if (args.length >= 4 && "-certificate".equals(args[2])) {
                /* args[3] is the path to a public key certificate */
                certPath = args[3];
            }

            /* args[1] is the path to a signed boot image */
            verifySignature(args[1], certPath);
        } else {
            /* args[0] is the target name, typically /boot
               args[1] is the path to a boot image to sign
               args[2] is the path to a private key
               args[3] is the path to the matching public key certificate
               args[4] is the path where to output the signed boot image
            */
            doSignature(args[0], args[1], args[2], args[3], args[4]);
        }
    }
}
