/*
 * Copyright (c) 1996, 2009, 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.ssl;

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import java.lang.reflect.*;

import javax.security.auth.x500.X500Principal;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import javax.net.ssl.*;

import sun.security.action.GetPropertyAction;

import sun.security.internal.spec.TlsPrfParameterSpec;

import sun.security.ssl.CipherSuite.*;

/**
 * Many data structures are involved in the handshake messages.  These
 * classes are used as structures, with public data members.  They are
 * not visible outside the SSL package.
 *
 * Handshake messages all have a common header format, and they are all
 * encoded in a "handshake data" SSL record substream.  The base class
 * here (HandshakeMessage) provides a common framework and records the
 * SSL record type of the particular handshake message.
 *
 * This file contains subclasses for all the basic handshake messages.
 * All handshake messages know how to encode and decode themselves on
 * SSL streams; this facilitates using the same code on SSL client and
 * server sides, although they don't send and receive the same messages.
 *
 * Messages also know how to print themselves, which is quite handy
 * for debugging.  They always identify their type, and can optionally
 * dump all of their content.
 *
 * @author David Brownell
 */
public abstract class HandshakeMessage {

    HandshakeMessage() { }

    // enum HandshakeType:
    static final byte   ht_hello_request = 0;
    static final byte   ht_client_hello = 1;
    static final byte   ht_server_hello = 2;

    static final byte   ht_certificate = 11;
    static final byte   ht_server_key_exchange = 12;
    static final byte   ht_certificate_request = 13;
    static final byte   ht_server_hello_done = 14;
    static final byte   ht_certificate_verify = 15;
    static final byte   ht_client_key_exchange = 16;

    static final byte   ht_finished = 20;

    /* Class and subclass dynamic debugging support */
    public static final Debug debug = Debug.getInstance("ssl");

    /**
     * Utility method to convert a BigInteger to a byte array in unsigned
     * format as needed in the handshake messages. BigInteger uses
     * 2's complement format, i.e. it prepends an extra zero if the MSB
     * is set. We remove that.
     */
    static byte[] toByteArray(BigInteger bi) {
        byte[] b = bi.toByteArray();
        if ((b.length > 1) && (b[0] == 0)) {
            int n = b.length - 1;
            byte[] newarray = new byte[n];
            System.arraycopy(b, 1, newarray, 0, n);
            b = newarray;
        }
        return b;
    }

    /*
     * SSL 3.0 MAC padding constants.
     * Also used by CertificateVerify and Finished during the handshake.
     */
    static final byte[] MD5_pad1 = genPad(0x36, 48);
    static final byte[] MD5_pad2 = genPad(0x5c, 48);

    static final byte[] SHA_pad1 = genPad(0x36, 40);
    static final byte[] SHA_pad2 = genPad(0x5c, 40);

    private static byte[] genPad(int b, int count) {
        byte[] padding = new byte[count];
        Arrays.fill(padding, (byte)b);
        return padding;
    }

    /*
     * Write a handshake message on the (handshake) output stream.
     * This is just a four byte header followed by the data.
     *
     * NOTE that huge messages -- notably, ones with huge cert
     * chains -- are handled correctly.
     */
    final void write(HandshakeOutStream s) throws IOException {
        int len = messageLength();
        if (len > (1 << 24)) {
            throw new SSLException("Handshake message too big"
                + ", type = " + messageType() + ", len = " + len);
        }
        s.write(messageType());
        s.putInt24(len);
        send(s);
    }

    /*
     * Subclasses implement these methods so those kinds of
     * messages can be emitted.  Base class delegates to subclass.
     */
    abstract int  messageType();
    abstract int  messageLength();
    abstract void send(HandshakeOutStream s) throws IOException;

    /*
     * Write a descriptive message on the output stream; for debugging.
     */
    abstract void print(PrintStream p) throws IOException;

//
// NOTE:  the rest of these classes are nested within this one, and are
// imported by other classes in this package.  There are a few other
// handshake message classes, not neatly nested here because of current
// licensing requirement for native (RSA) methods.  They belong here,
// but those native methods complicate things a lot!
//


/*
 * HelloRequest ... SERVER --> CLIENT
 *
 * Server can ask the client to initiate a new handshake, e.g. to change
 * session parameters after a connection has been (re)established.
 */
static final
class HelloRequest extends HandshakeMessage
{
    int messageType() { return ht_hello_request; }

    HelloRequest() { }

    HelloRequest(HandshakeInStream in) throws IOException
    {
        // nothing in this message
    }

    int messageLength() { return 0; }

    void send(HandshakeOutStream out) throws IOException
    {
        // nothing in this messaage
    }

    void print(PrintStream out) throws IOException
    {
        out.println("*** HelloRequest (empty)");
    }

}


/*
 * ClientHello ... CLIENT --> SERVER
 *
 * Client initiates handshake by telling server what it wants, and what it
 * can support (prioritized by what's first in the ciphe suite list).
 *
 * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
 * will have more data added at the end ... e.g. what CAs the client trusts.
 * Until we know how to parse it, we will just read what we know
 * about, and let our caller handle the jumps over unknown data.
 */
static final
class ClientHello extends HandshakeMessage
{
    int messageType() { return ht_client_hello; }

    ProtocolVersion     protocolVersion;
    RandomCookie        clnt_random;
    SessionId           sessionId;
    private CipherSuiteList    cipherSuites;
    byte[]              compression_methods;

    HelloExtensions extensions = new HelloExtensions();

    private final static byte[]  NULL_COMPRESSION = new byte[] {0};

    ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
        this.protocolVersion = protocolVersion;
        clnt_random = new RandomCookie(generator);
        compression_methods = NULL_COMPRESSION;
        // sessionId, cipher_suites TBS later
    }

    CipherSuiteList getCipherSuites() {
        return cipherSuites;
    }

    // Set the ciphersuites.
    // This method may only be called once.
    void setCipherSuites(CipherSuiteList cipherSuites) {
        this.cipherSuites = cipherSuites;
        if (cipherSuites.containsEC()) {
            extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
            extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
        }
    }

    int messageLength() {
        /*
         * Add fixed size parts of each field...
         * version + random + session + cipher + compress
         */
        return (2 + 32 + 1 + 2 + 1
            + sessionId.length()                /* ... + variable parts */
            + (cipherSuites.size() * 2)
            + compression_methods.length)
            + extensions.length();
    }

    ClientHello(HandshakeInStream s, int messageLength) throws IOException {
        protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
        clnt_random = new RandomCookie(s);
        sessionId = new SessionId(s.getBytes8());
        cipherSuites = new CipherSuiteList(s);
        compression_methods = s.getBytes8();
        if (messageLength() != messageLength) {
            extensions = new HelloExtensions(s);
        }
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putInt8(protocolVersion.major);
        s.putInt8(protocolVersion.minor);
        clnt_random.send(s);
        s.putBytes8(sessionId.getId());
        cipherSuites.send(s);
        s.putBytes8(compression_methods);
        extensions.send(s);
    }

    void print(PrintStream s) throws IOException {
        s.println("*** ClientHello, " + protocolVersion);

        if (debug != null && Debug.isOn("verbose")) {
            s.print   ("RandomCookie:  "); clnt_random.print(s);

            s.print("Session ID:  ");
            s.println(sessionId);

            s.println("Cipher Suites: " + cipherSuites);

            Debug.println(s, "Compression Methods", compression_methods);
            extensions.print(s);
            s.println("***");
        }
    }
}

/*
 * ServerHello ... SERVER --> CLIENT
 *
 * Server chooses protocol options from among those it supports and the
 * client supports.  Then it sends the basic session descriptive parameters
 * back to the client.
 */
static final
class ServerHello extends HandshakeMessage
{
    int messageType() { return ht_server_hello; }

    ProtocolVersion     protocolVersion;
    RandomCookie        svr_random;
    SessionId           sessionId;
    CipherSuite         cipherSuite;
    byte                compression_method;
    HelloExtensions extensions = new HelloExtensions();
    int extensionLength;

    ServerHello() {
        // empty
    }

    ServerHello(HandshakeInStream input, int messageLength) throws IOException {
        protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
                                                  input.getInt8());
        svr_random = new RandomCookie(input);
        sessionId = new SessionId(input.getBytes8());
        cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
        compression_method = (byte)input.getInt8();
        if (messageLength() != messageLength) {
            extensions = new HelloExtensions(input);
        }
    }

    int messageLength()
    {
        // almost fixed size, except session ID and extensions:
        //      major + minor = 2
        //      random = 32
        //      session ID len field = 1
        //      cipher suite + compression = 3
        //      extensions: if present, 2 + length of extensions
        return 38 + sessionId.length() + extensions.length();
    }

    void send(HandshakeOutStream s) throws IOException
    {
        s.putInt8(protocolVersion.major);
        s.putInt8(protocolVersion.minor);
        svr_random.send(s);
        s.putBytes8(sessionId.getId());
        s.putInt8(cipherSuite.id >> 8);
        s.putInt8(cipherSuite.id & 0xff);
        s.putInt8(compression_method);
        extensions.send(s);
    }

    void print(PrintStream s) throws IOException
    {
        s.println("*** ServerHello, " + protocolVersion);

        if (debug != null && Debug.isOn("verbose")) {
            s.print   ("RandomCookie:  "); svr_random.print(s);

            int i;

            s.print("Session ID:  ");
            s.println(sessionId);

            s.println("Cipher Suite: " + cipherSuite);
            s.println("Compression Method: " + compression_method);
            extensions.print(s);
            s.println("***");
        }
    }
}


/*
 * CertificateMsg ... send by both CLIENT and SERVER
 *
 * Each end of a connection may need to pass its certificate chain to
 * the other end.  Such chains are intended to validate an identity with
 * reference to some certifying authority.  Examples include companies
 * like Verisign, or financial institutions.  There's some control over
 * the certifying authorities which are sent.
 *
 * NOTE: that these messages might be huge, taking many handshake records.
 * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
 * bytes each ... up to 2^32 records sent on the output stream.
 */
static final
class CertificateMsg extends HandshakeMessage
{
    int messageType() { return ht_certificate; }

    private X509Certificate[] chain;

    private List<byte[]> encodedChain;

    private int messageLength;

    CertificateMsg(X509Certificate[] certs) {
        chain = certs;
    }

    CertificateMsg(HandshakeInStream input) throws IOException {
        int chainLen = input.getInt24();
        List<Certificate> v = new ArrayList<Certificate>(4);

        CertificateFactory cf = null;
        while (chainLen > 0) {
            byte[] cert = input.getBytes24();
            chainLen -= (3 + cert.length);
            try {
                if (cf == null) {
                    cf = CertificateFactory.getInstance("X.509");
                }
                v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
            } catch (CertificateException e) {
                throw (SSLProtocolException)new SSLProtocolException
                        (e.getMessage()).initCause(e);
            }
        }

        chain = v.toArray(new X509Certificate[v.size()]);
    }

    int messageLength() {
        if (encodedChain == null) {
            messageLength = 3;
            encodedChain = new ArrayList<byte[]>(chain.length);
            try {
                for (X509Certificate cert : chain) {
                    byte[] b = cert.getEncoded();
                    encodedChain.add(b);
                    messageLength += b.length + 3;
                }
            } catch (CertificateEncodingException e) {
                encodedChain = null;
                throw new RuntimeException("Could not encode certificates", e);
            }
        }
        return messageLength;
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putInt24(messageLength() - 3);
        for (byte[] b : encodedChain) {
            s.putBytes24(b);
        }
    }

    void print(PrintStream s) throws IOException {
        s.println("*** Certificate chain");

        if (debug != null && Debug.isOn("verbose")) {
            for (int i = 0; i < chain.length; i++)
                s.println("chain [" + i + "] = " + chain[i]);
            s.println("***");
        }
    }

    X509Certificate[] getCertificateChain() {
        return chain;
    }
}

/*
 * ServerKeyExchange ... SERVER --> CLIENT
 *
 * The cipher suite selected, when combined with the certificate exchanged,
 * implies one of several different kinds of key exchange.  Most current
 * cipher suites require the server to send more than its certificate.
 *
 * The primary exceptions are when a server sends an encryption-capable
 * RSA public key in its cert, to be used with RSA (or RSA_export) key
 * exchange; and when a server sends its Diffie-Hellman cert.  Those kinds
 * of key exchange do not require a ServerKeyExchange message.
 *
 * Key exchange can be viewed as having three modes, which are explicit
 * for the Diffie-Hellman flavors and poorly specified for RSA ones:
 *
 *      - "Ephemeral" keys.  Here, a "temporary" key is allocated by the
 *        server, and signed.  Diffie-Hellman keys signed using RSA or
 *        DSS are ephemeral (DHE flavor).  RSA keys get used to do the same
 *        thing, to cut the key size down to 512 bits (export restrictions)
 *        or for signing-only RSA certificates.
 *
 *      - Anonymity.  Here no server certificate is sent, only the public
 *        key of the server.  This case is subject to man-in-the-middle
 *        attacks.  This can be done with Diffie-Hellman keys (DH_anon) or
 *        with RSA keys, but is only used in SSLv3 for DH_anon.
 *
 *      - "Normal" case.  Here a server certificate is sent, and the public
 *        key there is used directly in exchanging the premaster secret.
 *        For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
 *        only 512 bit keys.
 *
 * If a server certificate is sent, there is no anonymity.  However,
 * when a certificate is sent, ephemeral keys may still be used to
 * exchange the premaster secret.  That's how RSA_EXPORT often works,
 * as well as how the DHE_* flavors work.
 */
static abstract class ServerKeyExchange extends HandshakeMessage
{
    int messageType() { return ht_server_key_exchange; }
}


/*
 * Using RSA for Key Exchange:  exchange a session key that's not as big
 * as the signing-only key.  Used for export applications, since exported
 * RSA encryption keys can't be bigger than 512 bytes.
 *
 * This is never used when keys are 512 bits or smaller, and isn't used
 * on "US Domestic" ciphers in any case.
 */
static final
class RSA_ServerKeyExchange extends ServerKeyExchange
{
    private byte rsa_modulus[];     // 1 to 2^16 - 1 bytes
    private byte rsa_exponent[];    // 1 to 2^16 - 1 bytes

    private Signature signature;
    private byte[] signatureBytes;

    /*
     * Hash the nonces and the ephemeral RSA public key.
     */
    private void updateSignature(byte clntNonce[], byte svrNonce[])
            throws SignatureException {
        int tmp;

        signature.update(clntNonce);
        signature.update(svrNonce);

        tmp = rsa_modulus.length;
        signature.update((byte)(tmp >> 8));
        signature.update((byte)(tmp & 0x0ff));
        signature.update(rsa_modulus);

        tmp = rsa_exponent.length;
        signature.update((byte)(tmp >> 8));
        signature.update((byte)(tmp & 0x0ff));
        signature.update(rsa_exponent);
    }


    /*
     * Construct an RSA server key exchange message, using data
     * known _only_ to the server.
     *
     * The client knows the public key corresponding to this private
     * key, from the Certificate message sent previously.  To comply
     * with US export regulations we use short RSA keys ... either
     * long term ones in the server's X509 cert, or else ephemeral
     * ones sent using this message.
     */
    RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
            RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
            throws GeneralSecurityException {
        RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
        rsa_modulus = toByteArray(rsaKey.getModulus());
        rsa_exponent = toByteArray(rsaKey.getPublicExponent());
        signature = RSASignature.getInstance();
        signature.initSign(privateKey, sr);
        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
        signatureBytes = signature.sign();
    }


    /*
     * Parse an RSA server key exchange message, using data known
     * to the client (and, in some situations, eavesdroppers).
     */
    RSA_ServerKeyExchange(HandshakeInStream input)
            throws IOException, NoSuchAlgorithmException {
        signature = RSASignature.getInstance();
        rsa_modulus = input.getBytes16();
        rsa_exponent = input.getBytes16();
        signatureBytes = input.getBytes16();
    }

    /*
     * Get the ephemeral RSA public key that will be used in this
     * SSL connection.
     */
    PublicKey getPublicKey() {
        try {
            KeyFactory kfac = JsseJce.getKeyFactory("RSA");
            // modulus and exponent are always positive
            RSAPublicKeySpec kspec = new RSAPublicKeySpec
                                         (new BigInteger(1, rsa_modulus),
                                          new BigInteger(1, rsa_exponent));
            return kfac.generatePublic(kspec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /*
     * Verify the signed temporary key using the hashes computed
     * from it and the two nonces.  This is called by clients
     * with "exportable" RSA flavors.
     */
    boolean verify(PublicKey certifiedKey, RandomCookie clntNonce,
            RandomCookie svrNonce) throws GeneralSecurityException {
        signature.initVerify(certifiedKey);
        updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
        return signature.verify(signatureBytes);
    }

    int messageLength() {
        return 6 + rsa_modulus.length + rsa_exponent.length
               + signatureBytes.length;
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putBytes16(rsa_modulus);
        s.putBytes16(rsa_exponent);
        s.putBytes16(signatureBytes);
    }

    void print(PrintStream s) throws IOException {
        s.println("*** RSA ServerKeyExchange");

        if (debug != null && Debug.isOn("verbose")) {
            Debug.println(s, "RSA Modulus", rsa_modulus);
            Debug.println(s, "RSA Public Exponent", rsa_exponent);
        }
    }
}


/*
 * Using Diffie-Hellman algorithm for key exchange.  All we really need to
 * do is securely get Diffie-Hellman keys (using the same P, G parameters)
 * to our peer, then we automatically have a shared secret without need
 * to exchange any more data.  (D-H only solutions, such as SKIP, could
 * eliminate key exchange negotiations and get faster connection setup.
 * But they still need a signature algorithm like DSS/DSA to support the
 * trusted distribution of keys without relying on unscalable physical
 * key distribution systems.)
 *
 * This class supports several DH-based key exchange algorithms, though
 * perhaps eventually each deserves its own class.  Notably, this has
 * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
 */
static final
class DH_ServerKeyExchange extends ServerKeyExchange
{
    // Fix message encoding, see 4348279
    private final static boolean dhKeyExchangeFix =
        Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);

    private byte                dh_p [];        // 1 to 2^16 - 1 bytes
    private byte                dh_g [];        // 1 to 2^16 - 1 bytes
    private byte                dh_Ys [];       // 1 to 2^16 - 1 bytes

    private byte                signature [];

    /* Return the Diffie-Hellman modulus */
    BigInteger getModulus() {
        return new BigInteger(1, dh_p);
    }

    /* Return the Diffie-Hellman base/generator */
    BigInteger getBase() {
        return new BigInteger(1, dh_g);
    }

    /* Return the server's Diffie-Hellman public key */
    BigInteger getServerPublicKey() {
        return new BigInteger(1, dh_Ys);
    }

    /*
     * Update sig with nonces and Diffie-Hellman public key.
     */
    private void updateSignature(Signature sig, byte clntNonce[],
            byte svrNonce[]) throws SignatureException {
        int tmp;

        sig.update(clntNonce);
        sig.update(svrNonce);

        tmp = dh_p.length;
        sig.update((byte)(tmp >> 8));
        sig.update((byte)(tmp & 0x0ff));
        sig.update(dh_p);

        tmp = dh_g.length;
        sig.update((byte)(tmp >> 8));
        sig.update((byte)(tmp & 0x0ff));
        sig.update(dh_g);

        tmp = dh_Ys.length;
        sig.update((byte)(tmp >> 8));
        sig.update((byte)(tmp & 0x0ff));
        sig.update(dh_Ys);
    }

    /*
     * Construct from initialized DH key object, for DH_anon
     * key exchange.
     */
    DH_ServerKeyExchange(DHCrypt obj) {
        getValues(obj);
        signature = null;
    }

    /*
     * Construct from initialized DH key object and the key associated
     * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
     * key exchange.  (Constructor called by server.)
     */
    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
            byte svrNonce[], SecureRandom sr) throws GeneralSecurityException {

        getValues(obj);

        Signature sig;
        if (key.getAlgorithm().equals("DSA")) {
            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
        } else {
            sig = RSASignature.getInstance();
        }
        sig.initSign(key, sr);
        updateSignature(sig, clntNonce, svrNonce);
        signature = sig.sign();
    }

    private void getValues(DHCrypt obj) {
        dh_p = toByteArray(obj.getModulus());
        dh_g = toByteArray(obj.getBase());
        dh_Ys = toByteArray(obj.getPublicKey());
    }

    /*
     * Construct a DH_ServerKeyExchange message from an input
     * stream, as if sent from server to client for use with
     * DH_anon key exchange
     */
    DH_ServerKeyExchange(HandshakeInStream input) throws IOException {
        dh_p = input.getBytes16();
        dh_g = input.getBytes16();
        dh_Ys = input.getBytes16();
        signature = null;
    }

    /*
     * Construct a DH_ServerKeyExchange message from an input stream
     * and a certificate, as if sent from server to client for use with
     * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
     */
    DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
            byte clntNonce[], byte svrNonce[], int messageSize)
            throws IOException, GeneralSecurityException {

        dh_p = input.getBytes16();
        dh_g = input.getBytes16();
        dh_Ys = input.getBytes16();

        byte signature[];
        if (dhKeyExchangeFix) {
            signature = input.getBytes16();
        } else {
            messageSize -= (dh_p.length + 2);
            messageSize -= (dh_g.length + 2);
            messageSize -= (dh_Ys.length + 2);

            signature = new byte[messageSize];
            input.read(signature);
        }

        Signature sig;
        String algorithm = publicKey.getAlgorithm();
        if (algorithm.equals("DSA")) {
            sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
        } else if (algorithm.equals("RSA")) {
            sig = RSASignature.getInstance();
        } else {
            throw new SSLKeyException("neither an RSA or a DSA key");
        }

        sig.initVerify(publicKey);
        updateSignature(sig, clntNonce, svrNonce);

        if (sig.verify(signature) == false ) {
            throw new SSLKeyException("Server D-H key verification failed");
        }
    }

    int messageLength() {
        int temp = 6;   // overhead for p, g, y(s) values.

        temp += dh_p.length;
        temp += dh_g.length;
        temp += dh_Ys.length;
        if (signature != null) {
            temp += signature.length;
            if (dhKeyExchangeFix) {
                temp += 2;
            }
        }
        return temp;
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putBytes16(dh_p);
        s.putBytes16(dh_g);
        s.putBytes16(dh_Ys);
        if (signature != null) {
            if (dhKeyExchangeFix) {
                s.putBytes16(signature);
            } else {
                s.write(signature);
            }
        }
    }

    void print(PrintStream s) throws IOException {
        s.println("*** Diffie-Hellman ServerKeyExchange");

        if (debug != null && Debug.isOn("verbose")) {
            Debug.println(s, "DH Modulus", dh_p);
            Debug.println(s, "DH Base", dh_g);
            Debug.println(s, "Server DH Public Key", dh_Ys);

            if (signature == null) {
                s.println("Anonymous");
            } else {
                s.println("Signed with a DSA or RSA public key");
            }
        }
    }
}

/*
 * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
 * ciphersuites to communicate its ephemeral public key (including the
 * EC domain parameters).
 *
 * We support named curves only, no explicitly encoded curves.
 */
static final
class ECDH_ServerKeyExchange extends ServerKeyExchange
{

    // constants for ECCurveType
    private final static int CURVE_EXPLICIT_PRIME = 1;
    private final static int CURVE_EXPLICIT_CHAR2 = 2;
    private final static int CURVE_NAMED_CURVE    = 3;

    // id of the curve we are using
    private int curveId;
    // encoded public point
    private byte[] pointBytes;

    // signature bytes (or null if anonymous)
    private byte[] signatureBytes;

    // public key object encapsulated in this message
    private ECPublicKey publicKey;

    ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
            byte[] clntNonce, byte[] svrNonce, SecureRandom sr)
            throws GeneralSecurityException {
        publicKey = (ECPublicKey)obj.getPublicKey();
        ECParameterSpec params = publicKey.getParams();
        ECPoint point = publicKey.getW();
        pointBytes = JsseJce.encodePoint(point, params.getCurve());
        curveId = SupportedEllipticCurvesExtension.getCurveIndex(params);

        if (privateKey == null) {
            // ECDH_anon
            return;
        }

        Signature sig = getSignature(privateKey.getAlgorithm());
        sig.initSign(privateKey);

        updateSignature(sig, clntNonce, svrNonce);
        signatureBytes = sig.sign();
    }

    /*
     * Parse an ECDH server key exchange message.
     */
    ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
            byte[] clntNonce, byte[] svrNonce)
            throws IOException, GeneralSecurityException {
        int curveType = input.getInt8();
        ECParameterSpec parameters;
        // These parsing errors should never occur as we negotiated
        // the supported curves during the exchange of the Hello messages.
        if (curveType == CURVE_NAMED_CURVE) {
            curveId = input.getInt16();
            if (SupportedEllipticCurvesExtension.isSupported(curveId) == false) {
                throw new SSLHandshakeException("Unsupported curveId: " + curveId);
            }
            String curveOid = SupportedEllipticCurvesExtension.getCurveOid(curveId);
            if (curveOid == null) {
                throw new SSLHandshakeException("Unknown named curve: " + curveId);
            }
            parameters = JsseJce.getECParameterSpec(curveOid);
            if (parameters == null) {
                throw new SSLHandshakeException("Unsupported curve: " + curveOid);
            }
        } else {
            throw new SSLHandshakeException("Unsupported ECCurveType: " + curveType);
        }
        pointBytes = input.getBytes8();

        ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
        KeyFactory factory = JsseJce.getKeyFactory("EC");
        publicKey = (ECPublicKey)factory.generatePublic(new ECPublicKeySpec(point, parameters));

        if (signingKey == null) {
            // ECDH_anon
            return;
        }

        // verify the signature
        signatureBytes = input.getBytes16();
        Signature sig = getSignature(signingKey.getAlgorithm());
        sig.initVerify(signingKey);

        updateSignature(sig, clntNonce, svrNonce);

        if (sig.verify(signatureBytes) == false ) {
            throw new SSLKeyException
                ("Invalid signature on ECDH server key exchange message");
        }
    }

    /*
     * Get the ephemeral EC public key encapsulated in this message.
     */
    ECPublicKey getPublicKey() {
        return publicKey;
    }

    private static Signature getSignature(String keyAlgorithm) throws NoSuchAlgorithmException {
        if (keyAlgorithm.equals("EC")) {
            return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
        } else if (keyAlgorithm.equals("RSA")) {
            return RSASignature.getInstance();
        } else {
            throw new NoSuchAlgorithmException("neither an RSA or a EC key");
        }
    }

    private void updateSignature(Signature sig, byte clntNonce[],
            byte svrNonce[]) throws SignatureException {
        sig.update(clntNonce);
        sig.update(svrNonce);

        sig.update((byte)CURVE_NAMED_CURVE);
        sig.update((byte)(curveId >> 8));
        sig.update((byte)curveId);
        sig.update((byte)pointBytes.length);
        sig.update(pointBytes);
    }

    int messageLength() {
        int sigLen = (signatureBytes == null) ? 0 : 2 + signatureBytes.length;
        return 4 + pointBytes.length + sigLen;
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putInt8(CURVE_NAMED_CURVE);
        s.putInt16(curveId);
        s.putBytes8(pointBytes);
        if (signatureBytes != null) {
            s.putBytes16(signatureBytes);
        }
    }

    void print(PrintStream s) throws IOException {
        s.println("*** ECDH ServerKeyExchange");

        if (debug != null && Debug.isOn("verbose")) {
            s.println("Server key: " + publicKey);
        }
    }
}

static final class DistinguishedName {

    /*
     * DER encoded distinguished name.
     * TLS requires that its not longer than 65535 bytes.
     */
    byte name[];

    DistinguishedName(HandshakeInStream input) throws IOException {
        name = input.getBytes16();
    }

    DistinguishedName(X500Principal dn) {
        name = dn.getEncoded();
    }

    X500Principal getX500Principal() throws IOException {
        try {
            return new X500Principal(name);
        } catch (IllegalArgumentException e) {
            throw (SSLProtocolException)new SSLProtocolException
                    (e.getMessage()).initCause(e);
        }
    }

    int length() {
        return 2 + name.length;
    }

    void send(HandshakeOutStream output) throws IOException {
        output.putBytes16(name);
    }

    void print(PrintStream output) throws IOException {
        X500Principal principal = new X500Principal(name);
        output.println("<" + principal.toString() + ">");
    }
}

/*
 * CertificateRequest ... SERVER --> CLIENT
 *
 * Authenticated servers may ask clients to authenticate themselves
 * in turn, using this message.
 */
static final
class CertificateRequest extends HandshakeMessage
{
    int messageType() { return ht_certificate_request; }

    // enum ClientCertificateType
    static final int   cct_rsa_sign = 1;
    static final int   cct_dss_sign = 2;
    static final int   cct_rsa_fixed_dh = 3;
    static final int   cct_dss_fixed_dh = 4;

    // The existance of these two values is a bug in the SSL specification.
    // They are never used in the protocol.
    static final int   cct_rsa_ephemeral_dh = 5;
    static final int   cct_dss_ephemeral_dh = 6;

    // From RFC 4492 (ECC)
    static final int    cct_ecdsa_sign       = 64;
    static final int    cct_rsa_fixed_ecdh   = 65;
    static final int    cct_ecdsa_fixed_ecdh = 66;

    private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
    private final static byte[] TYPES_ECC =
        { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };

    byte                types [];               // 1 to 255 types
    DistinguishedName   authorities [];         // 3 to 2^16 - 1
        // ... "3" because that's the smallest DER-encoded X500 DN

    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange)
            throws IOException {
        // always use X500Principal
        authorities = new DistinguishedName[ca.length];
        for (int i = 0; i < ca.length; i++) {
            X500Principal x500Principal = ca[i].getSubjectX500Principal();
            authorities[i] = new DistinguishedName(x500Principal);
        }
        // we support RSA, DSS, and ECDSA client authentication and they
        // can be used with all ciphersuites. If this changes, the code
        // needs to be adapted to take keyExchange into account.
        // We only request ECDSA client auth if we have ECC crypto available.
        this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
    }

    CertificateRequest(HandshakeInStream input) throws IOException {
        types = input.getBytes8();
        int len = input.getInt16();
        ArrayList<DistinguishedName> v = new ArrayList<DistinguishedName>();
        while (len >= 3) {
            DistinguishedName dn = new DistinguishedName(input);
            v.add(dn);
            len -= dn.length();
        }

        if (len != 0) {
            throw new SSLProtocolException("Bad CertificateRequest DN length");
        }

        authorities = v.toArray(new DistinguishedName[v.size()]);
    }

    X500Principal[] getAuthorities() throws IOException {
        X500Principal[] ret = new X500Principal[authorities.length];
        for (int i = 0; i < authorities.length; i++) {
            ret[i] = authorities[i].getX500Principal();
        }
        return ret;
    }

    int messageLength()
    {
        int len;

        len = 1 + types.length + 2;
        for (int i = 0; i < authorities.length; i++)
            len += authorities[i].length();
        return len;
    }

    void send(HandshakeOutStream output) throws IOException
    {
        int     len = 0;

        for (int i = 0; i < authorities.length; i++)
            len += authorities[i].length();

        output.putBytes8(types);
        output.putInt16(len);
        for (int i = 0; i < authorities.length; i++)
            authorities[i].send(output);
    }

    void print(PrintStream s) throws IOException
    {
        s.println("*** CertificateRequest");

        if (debug != null && Debug.isOn("verbose")) {
            s.print("Cert Types: ");
            for (int i = 0; i < types.length; i++) {
                switch (types[i]) {
                  case cct_rsa_sign:
                    s.print("RSA"); break;
                  case cct_dss_sign:
                    s.print("DSS"); break;
                  case cct_rsa_fixed_dh:
                    s.print("Fixed DH (RSA sig)"); break;
                  case cct_dss_fixed_dh:
                    s.print("Fixed DH (DSS sig)"); break;
                  case cct_rsa_ephemeral_dh:
                    s.print("Ephemeral DH (RSA sig)"); break;
                  case cct_dss_ephemeral_dh:
                    s.print("Ephemeral DH (DSS sig)"); break;
                  case cct_ecdsa_sign:
                    s.print("ECDSA"); break;
                  case cct_rsa_fixed_ecdh:
                    s.print("Fixed ECDH (RSA sig)"); break;
                  case cct_ecdsa_fixed_ecdh:
                    s.print("Fixed ECDH (ECDSA sig)"); break;
                  default:
                    s.print("Type-" + (types[i] & 0xff)); break;
                }
                if (i != types.length - 1) {
                    s.print(", ");
                }
            }
            s.println();

            s.println("Cert Authorities:");
            for (int i = 0; i < authorities.length; i++)
                authorities[i].print(s);
        }
    }
}


/*
 * ServerHelloDone ... SERVER --> CLIENT
 *
 * When server's done sending its messages in response to the client's
 * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
 * client certificate request) it sends this message to flag that it's
 * done that part of the handshake.
 */
static final
class ServerHelloDone extends HandshakeMessage
{
    int messageType() { return ht_server_hello_done; }

    ServerHelloDone() { }

    ServerHelloDone(HandshakeInStream input)
    {
        // nothing to do
    }

    int messageLength()
    {
        return 0;
    }

    void send(HandshakeOutStream s) throws IOException
    {
        // nothing to send
    }

    void print(PrintStream s) throws IOException
    {
        s.println("*** ServerHelloDone");
    }
}


/*
 * CertificateVerify ... CLIENT --> SERVER
 *
 * Sent after client sends signature-capable certificates (e.g. not
 * Diffie-Hellman) to verify.
 */
static final class CertificateVerify extends HandshakeMessage {

    int messageType() { return ht_certificate_verify; }

    private byte[] signature;

    /*
     * Create an RSA or DSA signed certificate verify message.
     */
    CertificateVerify(ProtocolVersion protocolVersion, HandshakeHash
            handshakeHash, PrivateKey privateKey, SecretKey masterSecret,
            SecureRandom sr) throws GeneralSecurityException {
        String algorithm = privateKey.getAlgorithm();
        Signature sig = getSignature(protocolVersion, algorithm);
        sig.initSign(privateKey, sr);
        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
                        masterSecret);
        signature = sig.sign();
    }

    //
    // Unmarshal the signed data from the input stream.
    //
    CertificateVerify(HandshakeInStream input) throws IOException  {
        signature = input.getBytes16();
    }

    /*
     * Verify a certificate verify message. Return the result of verification,
     * if there is a problem throw a GeneralSecurityException.
     */
    boolean verify(ProtocolVersion protocolVersion,
            HandshakeHash handshakeHash, PublicKey publicKey,
            SecretKey masterSecret) throws GeneralSecurityException {
        String algorithm = publicKey.getAlgorithm();
        Signature sig = getSignature(protocolVersion, algorithm);
        sig.initVerify(publicKey);
        updateSignature(sig, protocolVersion, handshakeHash, algorithm,
                        masterSecret);
        return sig.verify(signature);
    }

    /*
     * Get the Signature object appropriate for verification using the
     * given signature algorithm and protocol version.
     */
    private static Signature getSignature(ProtocolVersion protocolVersion,
            String algorithm) throws GeneralSecurityException {
        if (algorithm.equals("RSA")) {
            return RSASignature.getInternalInstance();
        } else if (algorithm.equals("DSA")) {
            return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
        } else if (algorithm.equals("EC")) {
            return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
        } else {
            throw new SignatureException("Unrecognized algorithm: "
                + algorithm);
        }
    }

    /*
     * Update the Signature with the data appropriate for the given
     * signature algorithm and protocol version so that the object is
     * ready for signing or verifying.
     */
    private static void updateSignature(Signature sig,
            ProtocolVersion protocolVersion,
            HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
            throws SignatureException {
        MessageDigest md5Clone = handshakeHash.getMD5Clone();
        MessageDigest shaClone = handshakeHash.getSHAClone();
        boolean tls = protocolVersion.v >= ProtocolVersion.TLS10.v;
        if (algorithm.equals("RSA")) {
            if (tls) {
                // nothing to do
            } else { // SSLv3
                updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
            }
            // need to use these hashes directly
            RSASignature.setHashes(sig, md5Clone, shaClone);
        } else { // DSA, ECDSA
            if (tls) {
                // nothing to do
            } else { // SSLv3
                updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
            }
            sig.update(shaClone.digest());
        }
    }

    /*
     * Update the MessageDigest for SSLv3 certificate verify or finished
     * message calculation. The digest must already have been updated with
     * all preceding handshake messages.
     * Used by the Finished class as well.
     */
    static void updateDigest(MessageDigest md, byte[] pad1, byte[] pad2,
            SecretKey masterSecret) {
        // Digest the key bytes if available.
        // Otherwise (sensitive key), try digesting the key directly.
        // That is currently only implemented in SunPKCS11 using a private
        // reflection API, so we avoid that if possible.
        byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
                        ? masterSecret.getEncoded() : null;
        if (keyBytes != null) {
            md.update(keyBytes);
        } else {
            digestKey(md, masterSecret);
        }
        md.update(pad1);
        byte[] temp = md.digest();

        if (keyBytes != null) {
            md.update(keyBytes);
        } else {
            digestKey(md, masterSecret);
        }
        md.update(pad2);
        md.update(temp);
    }

    private final static Class delegate;
    private final static Field spiField;

    static {
        try {
            delegate = Class.forName("java.security.MessageDigest$Delegate");
            spiField = delegate.getDeclaredField("digestSpi");
        } catch (Exception e) {
            throw new RuntimeException("Reflection failed", e);
        }
        makeAccessible(spiField);
    }

    private static void makeAccessible(final AccessibleObject o) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                o.setAccessible(true);
                return null;
            }
        });
    }

    // ConcurrentHashMap does not allow null values, use this marker object
    private final static Object NULL_OBJECT = new Object();

    // cache Method objects per Spi class
    // Note that this will prevent the Spi classes from being GC'd. We assume
    // that is not a problem.
    private final static Map<Class,Object> methodCache =
                                        new ConcurrentHashMap<Class,Object>();

    private static void digestKey(MessageDigest md, SecretKey key) {
        try {
            // Verify that md is implemented via MessageDigestSpi, not
            // via JDK 1.1 style MessageDigest subclassing.
            if (md.getClass() != delegate) {
                throw new Exception("Digest is not a MessageDigestSpi");
            }
            MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
            Class<?> clazz = spi.getClass();
            Object r = methodCache.get(clazz);
            if (r == null) {
                try {
                    r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
                    makeAccessible((Method)r);
                } catch (NoSuchMethodException e) {
                    r = NULL_OBJECT;
                }
                methodCache.put(clazz, r);
            }
            if (r == NULL_OBJECT) {
                throw new Exception("Digest does not support implUpdate(SecretKey)");
            }
            Method update = (Method)r;
            update.invoke(spi, key);
        } catch (Exception e) {
            throw new RuntimeException
            ("Could not obtain encoded key and MessageDigest cannot digest key", e);
        }
    }

    int messageLength() {
        return 2 + signature.length;
    }

    void send(HandshakeOutStream s) throws IOException {
        s.putBytes16(signature);
    }

    void print(PrintStream s) throws IOException {
        s.println("*** CertificateVerify");
    }
}


/*
 * FINISHED ... sent by both CLIENT and SERVER
 *
 * This is the FINISHED message as defined in the SSL and TLS protocols.
 * Both protocols define this handshake message slightly differently.
 * This class supports both formats.
 *
 * When handshaking is finished, each side sends a "change_cipher_spec"
 * record, then immediately sends a "finished" handshake message prepared
 * according to the newly adopted cipher spec.
 *
 * NOTE that until this is sent, no application data may be passed, unless
 * some non-default cipher suite has already been set up on this connection
 * connection (e.g. a previous handshake arranged one).
 */
static final class Finished extends HandshakeMessage {

    int messageType() { return ht_finished; }

    // constant for a Finished message sent by the client
    final static int CLIENT = 1;

    // constant for a Finished message sent by the server
    final static int SERVER = 2;

    // enum Sender:  "CLNT" and "SRVR"
    private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
    private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };

    /*
     * Contents of the finished message ("checksum"). For TLS, it
     * is 12 bytes long, for SSLv3 36 bytes.
     */
    private byte[] verifyData;

    /*
     * Create a finished message to send to the remote peer.
     */
    Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
            int sender, SecretKey master) {
        verifyData = getFinished(protocolVersion, handshakeHash, sender,
                                 master);
    }

    /*
     * Constructor that reads FINISHED message from stream.
     */
    Finished(ProtocolVersion protocolVersion, HandshakeInStream input)
            throws IOException {
        int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
        verifyData = new byte[msgLen];
        input.read(verifyData);
    }

    /*
     * Verify that the hashes here are what would have been produced
     * according to a given set of inputs.  This is used to ensure that
     * both client and server are fully in sync, and that the handshake
     * computations have been successful.
     */
     boolean verify(ProtocolVersion protocolVersion,
             HandshakeHash handshakeHash, int sender, SecretKey master) {
        byte[] myFinished = getFinished(protocolVersion, handshakeHash,
                                        sender, master);
        return Arrays.equals(myFinished, verifyData);
    }

    /*
     * Perform the actual finished message calculation.
     */
    private static byte[] getFinished(ProtocolVersion protocolVersion,
            HandshakeHash handshakeHash, int sender, SecretKey masterKey) {
        byte[] sslLabel;
        String tlsLabel;
        if (sender == CLIENT) {
            sslLabel = SSL_CLIENT;
            tlsLabel = "client finished";
        } else if (sender == SERVER) {
            sslLabel = SSL_SERVER;
            tlsLabel = "server finished";
        } else {
            throw new RuntimeException("Invalid sender: " + sender);
        }
        MessageDigest md5Clone = handshakeHash.getMD5Clone();
        MessageDigest shaClone = handshakeHash.getSHAClone();
        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
            // TLS
            try {
                byte[] seed = new byte[36];
                md5Clone.digest(seed, 0, 16);
                shaClone.digest(seed, 16, 20);

                TlsPrfParameterSpec spec = new TlsPrfParameterSpec
                                                (masterKey, tlsLabel, seed, 12);
                KeyGenerator prf = JsseJce.getKeyGenerator("SunTlsPrf");
                prf.init(spec);
                SecretKey prfKey = prf.generateKey();
                if ("RAW".equals(prfKey.getFormat()) == false) {
                    throw new ProviderException
                        ("Invalid PRF output, format must be RAW");
                }
                byte[] finished = prfKey.getEncoded();
                return finished;
            } catch (GeneralSecurityException e) {
                throw new RuntimeException("PRF failed", e);
            }
        } else {
            // SSLv3
            updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
            updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
            byte[] finished = new byte[36];
            try {
                md5Clone.digest(finished, 0, 16);
                shaClone.digest(finished, 16, 20);
            } catch (DigestException e) {
                // cannot occur
                throw new RuntimeException("Digest failed", e);
            }
            return finished;
        }
    }

    /*
     * Update the MessageDigest for SSLv3 finished message calculation.
     * The digest must already have been updated with all preceding handshake
     * messages. This operation is almost identical to the certificate verify
     * hash, reuse that code.
     */
    private static void updateDigest(MessageDigest md, byte[] sender,
            byte[] pad1, byte[] pad2, SecretKey masterSecret) {
        md.update(sender);
        CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
    }

    int messageLength() {
        return verifyData.length;
    }

    void send(HandshakeOutStream out) throws IOException {
        out.write(verifyData);
    }

    void print(PrintStream s) throws IOException {
        s.println("*** Finished");
        if (debug != null && Debug.isOn("verbose")) {
            Debug.println(s, "verify_data", verifyData);
            s.println("***");
        }
    }

}

//
// END of nested classes
//

}
