/*
 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider;

import java.io.*;
import java.util.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;

import java.security.*;
import java.security.SecureRandom;
import java.security.interfaces.*;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;

import sun.security.util.Debug;
import sun.security.util.DerValue;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.x509.AlgIdDSA;
import sun.security.jca.JCAUtil;

/**
 * The Digital Signature Standard (using the Digital Signature
 * Algorithm), as described in fips186-3 of the National Instute of
 * Standards and Technology (NIST), using SHA digest algorithms
 * from FIPS180-3.
 *
 * This file contains both the signature implementation for the
 * commonly used SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA,
 * as well as RawDSA, used by TLS among others. RawDSA expects
 * the 20 byte SHA-1 digest as input via update rather than the
 * original data like other signature implementations.
 *
 * @author Benjamin Renaud
 *
 * @since   1.1
 *
 * @see DSAPublicKey
 * @see DSAPrivateKey
 */
abstract class DSA extends SignatureSpi {

    /* Are we debugging? */
    private static final boolean debug = false;

    /* The number of bits used in exponent blinding */
    private static final int BLINDING_BITS = 7;

    /* The constant component of the exponent blinding value */
    private static final BigInteger BLINDING_CONSTANT =
        BigInteger.valueOf(1 << BLINDING_BITS);

    /* The parameter object */
    private DSAParams params;

    /* algorithm parameters */
    private BigInteger presetP, presetQ, presetG;

    /* The public key, if any */
    private BigInteger presetY;

    /* The private key, if any */
    private BigInteger presetX;

    /* The RNG used to output a seed for generating k */
    private SecureRandom signingRandom;

    /* The message digest object used */
    private final MessageDigest md;

    /**
     * Construct a blank DSA object. It must be
     * initialized before being usable for signing or verifying.
     */
    DSA(MessageDigest md) {
        super();
        this.md = md;
    }

    private static void checkKey(DSAParams params, int digestLen, String mdAlgo)
        throws InvalidKeyException {
        // FIPS186-3 states in sec4.2 that a hash function which provides
        // a lower security strength than the (L, N) pair ordinarily should
        // not be used.
        int valueN = params.getQ().bitLength();
        if (valueN > digestLen) {
            throw new InvalidKeyException("The security strength of " +
                mdAlgo + " digest algorithm is not sufficient for this key size");
        }
    }

    /**
     * Initialize the DSA object with a DSA private key.
     *
     * @param privateKey the DSA private key
     *
     * @exception InvalidKeyException if the key is not a valid DSA private
     * key.
     */
    protected void engineInitSign(PrivateKey privateKey)
            throws InvalidKeyException {
        if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {
            throw new InvalidKeyException("not a DSA private key: " +
                                          privateKey);
        }

        java.security.interfaces.DSAPrivateKey priv =
            (java.security.interfaces.DSAPrivateKey)privateKey;

        // check for algorithm specific constraints before doing initialization
        DSAParams params = priv.getParams();
        if (params == null) {
            throw new InvalidKeyException("DSA private key lacks parameters");
        }

        // check key size against hash output size for signing
        // skip this check for verification to minimize impact on existing apps
        if (md.getAlgorithm() != "NullDigest20") {
            checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
        }

        this.params = params;
        this.presetX = priv.getX();
        this.presetY = null;
        this.presetP = params.getP();
        this.presetQ = params.getQ();
        this.presetG = params.getG();
        this.md.reset();
    }
    /**
     * Initialize the DSA object with a DSA public key.
     *
     * @param publicKey the DSA public key.
     *
     * @exception InvalidKeyException if the key is not a valid DSA public
     * key.
     */
    protected void engineInitVerify(PublicKey publicKey)
            throws InvalidKeyException {
        if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {
            throw new InvalidKeyException("not a DSA public key: " +
                                          publicKey);
        }
        java.security.interfaces.DSAPublicKey pub =
            (java.security.interfaces.DSAPublicKey)publicKey;

        // check for algorithm specific constraints before doing initialization
        DSAParams params = pub.getParams();
        if (params == null) {
            throw new InvalidKeyException("DSA public key lacks parameters");
        }
        this.params = params;
        this.presetY = pub.getY();
        this.presetX = null;
        this.presetP = params.getP();
        this.presetQ = params.getQ();
        this.presetG = params.getG();
        this.md.reset();
    }

    /**
     * Update a byte to be signed or verified.
     */
    protected void engineUpdate(byte b) {
        md.update(b);
    }

    /**
     * Update an array of bytes to be signed or verified.
     */
    protected void engineUpdate(byte[] data, int off, int len) {
        md.update(data, off, len);
    }

    protected void engineUpdate(ByteBuffer b) {
        md.update(b);
    }


    /**
     * Sign all the data thus far updated. The signature is formatted
     * according to the Canonical Encoding Rules, returned as a DER
     * sequence of Integer, r and s.
     *
     * @return a signature block formatted according to the Canonical
     * Encoding Rules.
     *
     * @exception SignatureException if the signature object was not
     * properly initialized, or if another exception occurs.
     *
     * @see sun.security.DSA#engineUpdate
     * @see sun.security.DSA#engineVerify
     */
    protected byte[] engineSign() throws SignatureException {
        BigInteger k = generateK(presetQ);
        BigInteger r = generateR(presetP, presetQ, presetG, k);
        BigInteger s = generateS(presetX, presetQ, r, k);

        try {
            DerOutputStream outseq = new DerOutputStream(100);
            outseq.putInteger(r);
            outseq.putInteger(s);
            DerValue result = new DerValue(DerValue.tag_Sequence,
                                           outseq.toByteArray());

            return result.toByteArray();

        } catch (IOException e) {
            throw new SignatureException("error encoding signature");
        }
    }

    /**
     * Verify all the data thus far updated.
     *
     * @param signature the alledged signature, encoded using the
     * Canonical Encoding Rules, as a sequence of integers, r and s.
     *
     * @exception SignatureException if the signature object was not
     * properly initialized, or if another exception occurs.
     *
     * @see sun.security.DSA#engineUpdate
     * @see sun.security.DSA#engineSign
     */
    protected boolean engineVerify(byte[] signature)
            throws SignatureException {
        return engineVerify(signature, 0, signature.length);
    }

    /**
     * Verify all the data thus far updated.
     *
     * @param signature the alledged signature, encoded using the
     * Canonical Encoding Rules, as a sequence of integers, r and s.
     *
     * @param offset the offset to start from in the array of bytes.
     *
     * @param length the number of bytes to use, starting at offset.
     *
     * @exception SignatureException if the signature object was not
     * properly initialized, or if another exception occurs.
     *
     * @see sun.security.DSA#engineUpdate
     * @see sun.security.DSA#engineSign
     */
    protected boolean engineVerify(byte[] signature, int offset, int length)
            throws SignatureException {

        BigInteger r = null;
        BigInteger s = null;
        // first decode the signature.
        try {
            // Enforce strict DER checking for signatures
            DerInputStream in =
                new DerInputStream(signature, offset, length, false);
            DerValue[] values = in.getSequence(2);

            // check number of components in the read sequence
            // and trailing data
            if ((values.length != 2) || (in.available() != 0)) {
                throw new IOException("Invalid encoding for signature");
            }
            r = values[0].getBigInteger();
            s = values[1].getBigInteger();
        } catch (IOException e) {
            throw new SignatureException("Invalid encoding for signature", e);
        }

        // some implementations do not correctly encode values in the ASN.1
        // 2's complement format. force r and s to be positive in order to
        // to validate those signatures
        if (r.signum() < 0) {
            r = new BigInteger(1, r.toByteArray());
        }
        if (s.signum() < 0) {
            s = new BigInteger(1, s.toByteArray());
        }

        if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) {
            BigInteger w = generateW(presetP, presetQ, presetG, s);
            BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);
            return v.equals(r);
        } else {
            throw new SignatureException("invalid signature: out of range values");
        }
    }

    @Deprecated
    protected void engineSetParameter(String key, Object param) {
        throw new InvalidParameterException("No parameter accepted");
    }

    @Deprecated
    protected Object engineGetParameter(String key) {
        return null;
    }


    private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,
                         BigInteger k) {

        // exponent blinding to hide information from timing channel
        SecureRandom random = getSigningRandom();
        // start with a random blinding component
        BigInteger blindingValue = new BigInteger(BLINDING_BITS, random);
        // add the fixed blinding component
        blindingValue = blindingValue.add(BLINDING_CONSTANT);
        // replace k with a blinded value that is congruent (mod q)
        k = k.add(q.multiply(blindingValue));

        BigInteger temp = g.modPow(k, p);
        return temp.mod(q);
    }

    private BigInteger generateS(BigInteger x, BigInteger q,
            BigInteger r, BigInteger k) throws SignatureException {

        byte[] s2;
        try {
            s2 = md.digest();
        } catch (RuntimeException re) {
            // Only for RawDSA due to its 20-byte length restriction
            throw new SignatureException(re.getMessage());
        }
        // get the leftmost min(N, outLen) bits of the digest value
        int nBytes = q.bitLength()/8;
        if (nBytes < s2.length) {
            s2 = Arrays.copyOfRange(s2, 0, nBytes);
        }
        BigInteger z = new BigInteger(1, s2);
        BigInteger k1 = k.modInverse(q);

        return x.multiply(r).add(z).multiply(k1).mod(q);
    }

    private BigInteger generateW(BigInteger p, BigInteger q,
                         BigInteger g, BigInteger s) {
        return s.modInverse(q);
    }

    private BigInteger generateV(BigInteger y, BigInteger p,
             BigInteger q, BigInteger g, BigInteger w, BigInteger r)
             throws SignatureException {

        byte[] s2;
        try {
            s2 = md.digest();
        } catch (RuntimeException re) {
            // Only for RawDSA due to its 20-byte length restriction
            throw new SignatureException(re.getMessage());
        }
        // get the leftmost min(N, outLen) bits of the digest value
        int nBytes = q.bitLength()/8;
        if (nBytes < s2.length) {
            s2 = Arrays.copyOfRange(s2, 0, nBytes);
        }
        BigInteger z = new BigInteger(1, s2);

        BigInteger u1 = z.multiply(w).mod(q);
        BigInteger u2 = (r.multiply(w)).mod(q);

        BigInteger t1 = g.modPow(u1,p);
        BigInteger t2 = y.modPow(u2,p);
        BigInteger t3 = t1.multiply(t2);
        BigInteger t5 = t3.mod(p);
        return t5.mod(q);
    }

    protected BigInteger generateK(BigInteger q) {
        // Implementation defined in FIPS 186-4 AppendixB.2.1.
        SecureRandom random = getSigningRandom();
        byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];

        random.nextBytes(kValue);
        return new BigInteger(1, kValue).mod(
                q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
    }

    // Use the application-specified SecureRandom Object if provided.
    // Otherwise, use our default SecureRandom Object.
    protected SecureRandom getSigningRandom() {
        if (signingRandom == null) {
            if (appRandom != null) {
                signingRandom = appRandom;
            } else {
                signingRandom = JCAUtil.getSecureRandom();
            }
        }
        return signingRandom;
    }

    /**
     * Return a human readable rendition of the engine.
     */
    public String toString() {
        String printable = "DSA Signature";
        if (presetP != null && presetQ != null && presetG != null) {
            printable += "\n\tp: " + Debug.toHexString(presetP);
            printable += "\n\tq: " + Debug.toHexString(presetQ);
            printable += "\n\tg: " + Debug.toHexString(presetG);
        } else {
            printable += "\n\t P, Q or G not initialized.";
        }
        if (presetY != null) {
            printable += "\n\ty: " + Debug.toHexString(presetY);
        }
        if (presetY == null && presetX == null) {
            printable += "\n\tUNINIIALIZED";
        }
        return printable;
    }

    /**
     * Standard SHA224withDSA implementation as defined in FIPS186-3.
     */
    public static final class SHA224withDSA extends DSA {
        public SHA224withDSA() throws NoSuchAlgorithmException {
            super(MessageDigest.getInstance("SHA-224"));
        }
    }

    /**
     * Standard SHA256withDSA implementation as defined in FIPS186-3.
     */
    public static final class SHA256withDSA extends DSA {
        public SHA256withDSA() throws NoSuchAlgorithmException {
            super(MessageDigest.getInstance("SHA-256"));
        }
    }

    /**
     * Standard SHA1withDSA implementation.
     */
    public static final class SHA1withDSA extends DSA {
        public SHA1withDSA() throws NoSuchAlgorithmException {
            super(MessageDigest.getInstance("SHA-1"));
        }
    }

    /**
     * RawDSA implementation.
     *
     * RawDSA requires the data to be exactly 20 bytes long. If it is
     * not, a SignatureException is thrown when sign()/verify() is called
     * per JCA spec.
     */
    public static final class RawDSA extends DSA {
        // Internal special-purpose MessageDigest impl for RawDSA
        // Only override whatever methods used
        // NOTE: no clone support
        public static final class NullDigest20 extends MessageDigest {
            // 20 byte digest buffer
            private final byte[] digestBuffer = new byte[20];

            // offset into the buffer; use Integer.MAX_VALUE to indicate
            // out-of-bound condition
            private int ofs = 0;

            protected NullDigest20() {
                super("NullDigest20");
            }
            protected void engineUpdate(byte input) {
                if (ofs == digestBuffer.length) {
                    ofs = Integer.MAX_VALUE;
                } else {
                    digestBuffer[ofs++] = input;
                }
            }
            protected void engineUpdate(byte[] input, int offset, int len) {
                if (len > (digestBuffer.length - ofs)) {
                    ofs = Integer.MAX_VALUE;
                } else {
                    System.arraycopy(input, offset, digestBuffer, ofs, len);
                    ofs += len;
                }
            }
            protected final void engineUpdate(ByteBuffer input) {
                int inputLen = input.remaining();
                if (inputLen > (digestBuffer.length - ofs)) {
                    ofs = Integer.MAX_VALUE;
                } else {
                    input.get(digestBuffer, ofs, inputLen);
                    ofs += inputLen;
                }
            }
            protected byte[] engineDigest() throws RuntimeException {
                if (ofs != digestBuffer.length) {
                    throw new RuntimeException
                        ("Data for RawDSA must be exactly 20 bytes long");
                }
                reset();
                return digestBuffer;
            }
            protected int engineDigest(byte[] buf, int offset, int len)
                throws DigestException {
                if (ofs != digestBuffer.length) {
                    throw new DigestException
                        ("Data for RawDSA must be exactly 20 bytes long");
                }
                if (len < digestBuffer.length) {
                    throw new DigestException
                        ("Output buffer too small; must be at least 20 bytes");
                }
                System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);
                reset();
                return digestBuffer.length;
            }

            protected void engineReset() {
                ofs = 0;
            }
            protected final int engineGetDigestLength() {
                return digestBuffer.length;
            }
        }

        public RawDSA() throws NoSuchAlgorithmException {
            super(new NullDigest20());
        }
    }
}
