/* ClientHandshake.java --
   Copyright (C) 2006  Free Software Foundation, Inc.

This file is a part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.javax.net.ssl.provider;

import static gnu.javax.net.ssl.provider.ClientHandshake.State.*;
import static gnu.javax.net.ssl.provider.KeyExchangeAlgorithm.*;

import gnu.classpath.debug.Component;
import gnu.java.security.action.GetSecurityPropertyAction;
import gnu.javax.crypto.key.dh.GnuDHPublicKey;
import gnu.javax.net.ssl.AbstractSessionContext;
import gnu.javax.net.ssl.Session;
import gnu.javax.net.ssl.provider.Alert.Description;
import gnu.javax.net.ssl.provider.Alert.Level;
import gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType;
import gnu.javax.net.ssl.provider.ServerNameList.NameType;
import gnu.javax.net.ssl.provider.ServerNameList.ServerName;

import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.security.auth.x500.X500Principal;

/**
 * @author Casey Marshall (csm@gnu.org)
 */
public class ClientHandshake extends AbstractHandshake
{
  static enum State
  {
    WRITE_CLIENT_HELLO (false, true),
    READ_SERVER_HELLO (true, false),
    READ_CERTIFICATE (true, false),
    READ_SERVER_KEY_EXCHANGE (true, false),
    READ_CERTIFICATE_REQUEST (true, false),
    READ_SERVER_HELLO_DONE (true, false),
    WRITE_CERTIFICATE (false, true),
    WRITE_CLIENT_KEY_EXCHANGE (false, true),
    WRITE_CERTIFICATE_VERIFY (false, true),
    WRITE_FINISHED (false, true),
    READ_FINISHED (true, false),
    DONE (false, false);

    private final boolean isWriteState;
    private final boolean isReadState;

    private State(boolean isReadState, boolean isWriteState)
    {
      this.isReadState = isReadState;
      this.isWriteState = isWriteState;
    }

    boolean isReadState()
    {
      return isReadState;
    }

    boolean isWriteState()
    {
      return isWriteState;
    }
  }

  private State state;
  private ByteBuffer outBuffer;
  private boolean continuedSession;
  private SessionImpl continued;
  private KeyPair dhPair;
  private String keyAlias;
  private PrivateKey privateKey;
  private MaxFragmentLength maxFragmentLengthSent;
  private boolean truncatedHMacSent;
  private ProtocolVersion sentVersion;

  // Delegated tasks.
  private CertVerifier certVerifier;
  private ParamsVerifier paramsVerifier;
  private DelegatedTask keyExchange;
  private CertLoader certLoader;
  private GenCertVerify genCertVerify;

  public ClientHandshake(SSLEngineImpl engine) throws NoSuchAlgorithmException
  {
    super(engine);
    state = WRITE_CLIENT_HELLO;
    continuedSession = false;
  }

  /* (non-Javadoc)
   * @see gnu.javax.net.ssl.provider.AbstractHandshake#implHandleInput()
   */
  @Override protected HandshakeStatus implHandleInput() throws SSLException
  {
    if (state == DONE)
      return HandshakeStatus.FINISHED;

    if (state.isWriteState()
        || (outBuffer != null && outBuffer.hasRemaining()))
      return HandshakeStatus.NEED_WRAP;

    // Copy the current buffer, and prepare it for reading.
    ByteBuffer buffer = handshakeBuffer.duplicate ();
    buffer.flip();
    buffer.position(handshakeOffset);

    Handshake handshake = new Handshake(buffer.slice(),
                                        engine.session().suite,
                                        engine.session().version);

    if (Debug.DEBUG)
      logger.logv(Component.SSL_HANDSHAKE, "processing in state {0}:\n{1}",
                  state, handshake);

    switch (state)
      {
        // Server Hello.
        case READ_SERVER_HELLO:
        {
          if (handshake.type() != Handshake.Type.SERVER_HELLO)
            throw new AlertException(new Alert(Alert.Level.FATAL,
                                               Alert.Description.UNEXPECTED_MESSAGE));
          ServerHello hello = (ServerHello) handshake.body();
          serverRandom = hello.random().copy();
          engine.session().suite = hello.cipherSuite();
          engine.session().version = hello.version();
          compression = hello.compressionMethod();
          Session.ID serverId = new Session.ID(hello.sessionId());
          if (continued != null
              && continued.id().equals(serverId))
            {
              continuedSession = true;
              engine.setSession(continued);
            }
          else if (engine.getEnableSessionCreation())
            {
              ((AbstractSessionContext) engine.contextImpl
                  .engineGetClientSessionContext()).put(engine.session());
            }
          ExtensionList extensions = hello.extensions();
          if (extensions != null)
            {
              for (Extension extension : extensions)
                {
                  Extension.Type type = extension.type();
                  if (type == null)
                    continue;
                  switch (type)
                    {
                      case MAX_FRAGMENT_LENGTH:
                        MaxFragmentLength mfl
                          = (MaxFragmentLength) extension.value();
                        if (maxFragmentLengthSent == mfl)
                          engine.session().setApplicationBufferSize(mfl.maxLength());
                        break;

                      case TRUNCATED_HMAC:
                        if (truncatedHMacSent)
                          engine.session().setTruncatedMac(true);
                        break;
                    }
                }
            }

          KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
          if (continuedSession)
            {
              byte[][] keys = generateKeys(clientRandom, serverRandom,
                                           engine.session());
              setupSecurityParameters(keys, true, engine, compression);
              state = READ_FINISHED;
            }
          else if (kex == RSA || kex == DH_DSS || kex == DH_RSA
                   || kex == DHE_DSS || kex == DHE_RSA || kex == RSA_PSK)
            state = READ_CERTIFICATE;
          else if (kex == DH_anon || kex == PSK || kex == DHE_PSK)
            state = READ_SERVER_KEY_EXCHANGE;
          else
            state = READ_CERTIFICATE_REQUEST;
        }
        break;

        // Server Certificate.
        case READ_CERTIFICATE:
        {
          if (handshake.type() != Handshake.Type.CERTIFICATE)
            {
              // We need a certificate for non-anonymous suites.
              if (engine.session().suite.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
                throw new AlertException(new Alert(Level.FATAL,
                                                   Description.UNEXPECTED_MESSAGE));
              state = READ_SERVER_KEY_EXCHANGE;
            }
          Certificate cert = (Certificate) handshake.body();
          X509Certificate[] chain = null;
          try
            {
              chain = cert.certificates().toArray(new X509Certificate[0]);
            }
          catch (CertificateException ce)
            {
              throw new AlertException(new Alert(Level.FATAL,
                                                 Description.BAD_CERTIFICATE),
                                       ce);
            }
          catch (NoSuchAlgorithmException nsae)
            {
              throw new AlertException(new Alert(Level.FATAL,
                                                 Description.UNSUPPORTED_CERTIFICATE),
                                       nsae);
            }
          engine.session().setPeerCertificates(chain);
          certVerifier = new CertVerifier(true, chain);
          tasks.add(certVerifier);

          // If we are doing an RSA key exchange, generate our parameters.
          KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
          if (kea == RSA || kea == RSA_PSK)
            {
              keyExchange = new RSAGen(kea == RSA);
              tasks.add(keyExchange);
              if (kea == RSA)
                state = READ_CERTIFICATE_REQUEST;
              else
                state = READ_SERVER_KEY_EXCHANGE;
            }
          else
            state = READ_SERVER_KEY_EXCHANGE;
        }
        break;

        // Server Key Exchange.
        case READ_SERVER_KEY_EXCHANGE:
        {
          CipherSuite s = engine.session().suite;
          KeyExchangeAlgorithm kexalg = s.keyExchangeAlgorithm();
          // XXX also SRP.
          if (kexalg != DHE_DSS && kexalg != DHE_RSA && kexalg != DH_anon
              && kexalg != DHE_PSK && kexalg != PSK && kexalg != RSA_PSK)
            throw new AlertException(new Alert(Level.FATAL,
                                               Description.UNEXPECTED_MESSAGE));

          if (handshake.type() != Handshake.Type.SERVER_KEY_EXCHANGE)
            {
              if (kexalg != RSA_PSK && kexalg != PSK)
                throw new AlertException(new Alert(Level.FATAL,
                                                   Description.UNEXPECTED_MESSAGE));
              state = READ_CERTIFICATE_REQUEST;
              return HandshakeStatus.NEED_UNWRAP;
            }

          ServerKeyExchange skex = (ServerKeyExchange) handshake.body();
          ByteBuffer paramsBuffer = null;
          if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
            {
              ServerDHParams dhParams = (ServerDHParams) skex.params();
              ByteBuffer b = dhParams.buffer();
              paramsBuffer = ByteBuffer.allocate(b.remaining());
              paramsBuffer.put(b);
            }

          if (s.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
            {
              byte[] signature = skex.signature().signature();
              paramsVerifier = new ParamsVerifier(paramsBuffer, signature);
              tasks.add(paramsVerifier);
            }

          if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
            {
              ServerDHParams dhParams = (ServerDHParams) skex.params();
              DHPublicKey serverKey = new GnuDHPublicKey(null,
                                                         dhParams.p(),
                                                         dhParams.g(),
                                                         dhParams.y());
              DHParameterSpec params = new DHParameterSpec(dhParams.p(),
                                                           dhParams.g());
              keyExchange = new ClientDHGen(serverKey, params, true);
              tasks.add(keyExchange);
            }
          if (kexalg == DHE_PSK)
            {
              ServerDHE_PSKParameters pskParams = (ServerDHE_PSKParameters)
                skex.params();
              ServerDHParams dhParams = pskParams.params();
              DHPublicKey serverKey = new GnuDHPublicKey(null,
                                                         dhParams.p(),
                                                         dhParams.g(),
                                                         dhParams.y());
              DHParameterSpec params = new DHParameterSpec(dhParams.p(),
                                                           dhParams.g());
              keyExchange = new ClientDHGen(serverKey, params, false);
              tasks.add(keyExchange);
            }
          state = READ_CERTIFICATE_REQUEST;
        }
        break;

        // Certificate Request.
        case READ_CERTIFICATE_REQUEST:
        {
          if (handshake.type() != Handshake.Type.CERTIFICATE_REQUEST)
            {
              state = READ_SERVER_HELLO_DONE;
              return HandshakeStatus.NEED_UNWRAP;
            }

          CertificateRequest req = (CertificateRequest) handshake.body();
          ClientCertificateTypeList types = req.types();
          LinkedList<String> typeList = new LinkedList<String>();
          for (ClientCertificateType t : types)
            typeList.add(t.name());

          X500PrincipalList issuers = req.authorities();
          LinkedList<X500Principal> issuerList = new LinkedList<X500Principal>();
          for (X500Principal p : issuers)
            issuerList.add(p);

          certLoader = new CertLoader(typeList, issuerList);
          tasks.add(certLoader);
        }
        break;

        // Server Hello Done.
        case READ_SERVER_HELLO_DONE:
        {
          if (handshake.type() != Handshake.Type.SERVER_HELLO_DONE)
            throw new AlertException(new Alert(Level.FATAL,
                                               Description.UNEXPECTED_MESSAGE));
          state = WRITE_CERTIFICATE;
        }
        break;

        // Finished.
        case READ_FINISHED:
        {
          if (handshake.type() != Handshake.Type.FINISHED)
            throw new AlertException(new Alert(Level.FATAL,
                                               Description.UNEXPECTED_MESSAGE));

          Finished serverFinished = (Finished) handshake.body();
          MessageDigest md5copy = null;
          MessageDigest shacopy = null;
          try
            {
              md5copy = (MessageDigest) md5.clone();
              shacopy = (MessageDigest) sha.clone();
            }
          catch (CloneNotSupportedException cnse)
            {
              // We're improperly configured to use a non-cloneable
              // md5/sha-1, OR there's a runtime bug.
              throw new SSLException(cnse);
            }
          Finished clientFinished =
            new Finished(generateFinished(md5copy, shacopy,
                                          false, engine.session()),
                                          engine.session().version);

          if (Debug.DEBUG)
            logger.logv(Component.SSL_HANDSHAKE, "clientFinished: {0}",
                        clientFinished);

          if (engine.session().version == ProtocolVersion.SSL_3)
            {
              if (!Arrays.equals(clientFinished.md5Hash(),
                                 serverFinished.md5Hash())
                  || !Arrays.equals(clientFinished.shaHash(),
                                    serverFinished.shaHash()))
                {
                  engine.session().invalidate();
                  throw new SSLException("session verify failed");
                }
            }
          else
            {
              if (!Arrays.equals(clientFinished.verifyData(),
                                 serverFinished.verifyData()))
                {
                  engine.session().invalidate();
                  throw new SSLException("session verify failed");
                }
            }

          if (continuedSession)
            {
              engine.changeCipherSpec();
              state = WRITE_FINISHED;
            }
          else
            state = DONE;
        }
        break;

        default:
          throw new IllegalStateException("invalid state: " + state);
      }

    handshakeOffset += handshake.length() + 4;

    if (!tasks.isEmpty())
      return HandshakeStatus.NEED_TASK;
    if (state.isWriteState()
        || (outBuffer != null && outBuffer.hasRemaining()))
      return HandshakeStatus.NEED_WRAP;
    if (state.isReadState())
      return HandshakeStatus.NEED_UNWRAP;

    return HandshakeStatus.FINISHED;
  }

  /* (non-Javadoc)
   * @see gnu.javax.net.ssl.provider.AbstractHandshake#implHandleOutput(java.nio.ByteBuffer)
   */
  @Override protected HandshakeStatus implHandleOutput(ByteBuffer fragment)
    throws SSLException
  {
    if (Debug.DEBUG)
      logger.logv(Component.SSL_HANDSHAKE, "output to {0}; state:{1}; outBuffer:{2}",
                  fragment, state, outBuffer);

    // Drain the output buffer, if it needs it.
    if (outBuffer != null && outBuffer.hasRemaining())
      {
        int l = Math.min(fragment.remaining(), outBuffer.remaining());
        fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
        outBuffer.position(outBuffer.position() + l);
      }

    if (!fragment.hasRemaining())
      {
        if (state.isWriteState() || outBuffer.hasRemaining())
          return HandshakeStatus.NEED_WRAP;
        else
          return HandshakeStatus.NEED_UNWRAP;
      }

outer_loop:
    while (fragment.remaining() >= 4 && state.isWriteState())
      {
        if (Debug.DEBUG)
          logger.logv(Component.SSL_HANDSHAKE, "loop state={0}", state);

        switch (state)
          {
            case WRITE_CLIENT_HELLO:
            {
              ClientHelloBuilder hello = new ClientHelloBuilder();
              AbstractSessionContext ctx = (AbstractSessionContext)
                engine.contextImpl.engineGetClientSessionContext();
              continued = (SessionImpl) ctx.getSession(engine.getPeerHost(),
                                                       engine.getPeerPort());
              engine.session().setId(new Session.ID(new byte[0]));
              Session.ID sid = engine.session().id();
              // If we have a session that we may want to continue, send
              // that ID.
              if (continued != null)
                sid = continued.id();

              hello.setSessionId(sid.id());
              sentVersion = chooseVersion();
              hello.setVersion(sentVersion);
              hello.setCipherSuites(getSuites());
              hello.setCompressionMethods(getCompressionMethods());
              Random r = hello.random();
              r.setGmtUnixTime(Util.unixTime());
              byte[] nonce = new byte[28];
              engine.session().random().nextBytes(nonce);
              r.setRandomBytes(nonce);
              clientRandom = r.copy();
              if (enableExtensions())
                {
                  List<Extension> extensions = new LinkedList<Extension>();
                  MaxFragmentLength fraglen = maxFragmentLength();
                  if (fraglen != null)
                    {
                      extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH,
                                                   fraglen));
                      maxFragmentLengthSent = fraglen;
                    }

                  String host = engine.getPeerHost();
                  if (host != null)
                    {
                      ServerName name
                        = new ServerName(NameType.HOST_NAME, host);
                      ServerNameList names
                        = new ServerNameList(Collections.singletonList(name));
                      extensions.add(new Extension(Extension.Type.SERVER_NAME,
                                                   names));
                    }

                  if (truncatedHMac())
                    {
                      extensions.add(new Extension(Extension.Type.TRUNCATED_HMAC,
                                                   new TruncatedHMAC()));
                      truncatedHMacSent = true;
                    }

                  ExtensionList elist = new ExtensionList(extensions);
                  hello.setExtensions(elist.buffer());
                }
              else
                hello.setDisableExtensions(true);

              if (Debug.DEBUG)
                logger.logv(Component.SSL_HANDSHAKE, "{0}", hello);

              fragment.putInt((Handshake.Type.CLIENT_HELLO.getValue() << 24)
                              | (hello.length() & 0xFFFFFF));
              outBuffer = hello.buffer();
              int l = Math.min(fragment.remaining(), outBuffer.remaining());
              fragment.put((ByteBuffer) outBuffer.duplicate()
                           .limit(outBuffer.position() + l));
              outBuffer.position(outBuffer.position() + l);

              state = READ_SERVER_HELLO;
            }
            break;

            case WRITE_CERTIFICATE:
            {
              java.security.cert.Certificate[] chain
                = engine.session().getLocalCertificates();
              if (chain != null)
                {
                  CertificateBuilder cert
                    = new CertificateBuilder(CertificateType.X509);
                  try
                    {
                      cert.setCertificates(Arrays.asList(chain));
                    }
                  catch (CertificateException ce)
                    {
                      throw new AlertException(new Alert(Level.FATAL,
                                                         Description.INTERNAL_ERROR),
                                               ce);
                    }

                  outBuffer = cert.buffer();

                  fragment.putInt((Handshake.Type.CERTIFICATE.getValue() << 24)
                                  | (cert.length() & 0xFFFFFF));

                  int l = Math.min(fragment.remaining(), outBuffer.remaining());
                  fragment.put((ByteBuffer) outBuffer.duplicate()
                               .limit(outBuffer.position() + l));
                  outBuffer.position(outBuffer.position() + l);
                }
              state = WRITE_CLIENT_KEY_EXCHANGE;
            }
            break;

            case WRITE_CLIENT_KEY_EXCHANGE:
            {
              KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
              ClientKeyExchangeBuilder ckex
                = new ClientKeyExchangeBuilder(engine.session().suite,
                                               engine.session().version);
              if (kea == DHE_DSS || kea == DHE_RSA || kea == DH_anon
                  || kea == DH_DSS || kea == DH_RSA)
                {
                  assert(dhPair != null);
                  DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
                  ClientDiffieHellmanPublic pub
                    = new ClientDiffieHellmanPublic(pubkey.getY());
                  ckex.setExchangeKeys(pub.buffer());
                }
              if (kea == RSA || kea == RSA_PSK)
                {
                  assert(keyExchange instanceof RSAGen);
                  assert(keyExchange.hasRun());
                  if (keyExchange.thrown() != null)
                    throw new AlertException(new Alert(Level.FATAL,
                                                       Description.HANDSHAKE_FAILURE),
                                             keyExchange.thrown());
                  EncryptedPreMasterSecret epms
                    = new EncryptedPreMasterSecret(((RSAGen) keyExchange).encryptedSecret(),
                                                   engine.session().version);
                  if (kea == RSA)
                    ckex.setExchangeKeys(epms.buffer());
                  else
                    {
                      String identity = getPSKIdentity();
                      if (identity == null)
                        throw new SSLException("no pre-shared-key identity;"
                                               + " set the security property"
                                               + " \"jessie.client.psk.identity\"");
                      ClientRSA_PSKParameters params =
                        new ClientRSA_PSKParameters(identity, epms.buffer());
                      ckex.setExchangeKeys(params.buffer());
                      generatePSKSecret(identity, preMasterSecret, true);
                    }
                }
              if (kea == DHE_PSK)
                {
                  assert(keyExchange instanceof ClientDHGen);
                  assert(dhPair != null);
                  String identity = getPSKIdentity();
                  if (identity == null)
                    throw new SSLException("no pre-shared key identity; set"
                                           + " the security property"
                                           + " \"jessie.client.psk.identity\"");
                  DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
                  ClientDHE_PSKParameters params =
                    new ClientDHE_PSKParameters(identity,
                                                new ClientDiffieHellmanPublic(pubkey.getY()));
                  ckex.setExchangeKeys(params.buffer());
                  generatePSKSecret(identity, preMasterSecret, true);
                }
              if (kea == PSK)
                {
                  String identity = getPSKIdentity();
                  if (identity == null)
                    throw new SSLException("no pre-shared key identity; set"
                                           + " the security property"
                                           + " \"jessie.client.psk.identity\"");
                  generatePSKSecret(identity, null, true);
                  ClientPSKParameters params = new ClientPSKParameters(identity);
                  ckex.setExchangeKeys(params.buffer());
                }
              if (kea == NONE)
                {
                  Inflater inflater = null;
                  Deflater deflater = null;
                  if (compression == CompressionMethod.ZLIB)
                    {
                      inflater = new Inflater();
                      deflater = new Deflater();
                    }
                  inParams = new InputSecurityParameters(null, null, inflater,
                                                         engine.session(),
                                                         engine.session().suite);
                  outParams = new OutputSecurityParameters(null, null, deflater,
                                                           engine.session(),
                                                           engine.session().suite);
                  engine.session().privateData.masterSecret = new byte[0];
                }

              if (Debug.DEBUG)
                logger.logv(Component.SSL_HANDSHAKE, "{0}", ckex);

              outBuffer = ckex.buffer();
              if (Debug.DEBUG)
                logger.logv(Component.SSL_HANDSHAKE, "client kex buffer {0}", outBuffer);
              fragment.putInt((Handshake.Type.CLIENT_KEY_EXCHANGE.getValue() << 24)
                              | (ckex.length() & 0xFFFFFF));
              int l = Math.min(fragment.remaining(), outBuffer.remaining());
              fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
              outBuffer.position(outBuffer.position() + l);

              if (privateKey != null)
                {
                  genCertVerify = new GenCertVerify(md5, sha);
                  tasks.add(genCertVerify);
                  state = WRITE_CERTIFICATE_VERIFY;
                }
              else
                {
                  engine.changeCipherSpec();
                  state = WRITE_FINISHED;
                }
            }
            // Both states terminate in a NEED_TASK, or a need to change cipher
            // specs; so we can't write any more messages here.
            break outer_loop;

            case WRITE_CERTIFICATE_VERIFY:
            {
              assert(genCertVerify != null);
              assert(genCertVerify.hasRun());
              CertificateVerify verify = new CertificateVerify(genCertVerify.signed(),
                                                               engine.session().suite.signatureAlgorithm());

              outBuffer = verify.buffer();
              fragment.putInt((Handshake.Type.CERTIFICATE_VERIFY.getValue() << 24)
                              | (verify.length() & 0xFFFFFF));
              int l = Math.min(fragment.remaining(), outBuffer.remaining());
              fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
              outBuffer.position(outBuffer.position() + l);

              // XXX This is a potential problem: we may not have drained
              // outBuffer, but set the changeCipherSpec toggle.
              engine.changeCipherSpec();
              state = WRITE_FINISHED;
            }
            break outer_loop;

            case WRITE_FINISHED:
            {
              MessageDigest md5copy = null;
              MessageDigest shacopy = null;
              try
                {
                  md5copy = (MessageDigest) md5.clone();
                  shacopy = (MessageDigest) sha.clone();
                }
              catch (CloneNotSupportedException cnse)
                {
                  // We're improperly configured to use a non-cloneable
                  // md5/sha-1, OR there's a runtime bug.
                  throw new SSLException(cnse);
                }
              outBuffer
                = generateFinished(md5copy, shacopy, true,
                                   engine.session());

              fragment.putInt((Handshake.Type.FINISHED.getValue() << 24)
                              | outBuffer.remaining() & 0xFFFFFF);

              int l = Math.min(outBuffer.remaining(), fragment.remaining());
              fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
              outBuffer.position(outBuffer.position() + l);

              if (continuedSession)
                state = DONE;
              else
                state = READ_FINISHED;
            }
            break;

            default:
              throw new IllegalStateException("invalid state: " + state);
          }
      }

    if (!tasks.isEmpty())
      return HandshakeStatus.NEED_TASK;
    if (state.isWriteState() ||
        (outBuffer != null && outBuffer.hasRemaining()))
      return HandshakeStatus.NEED_WRAP;
    if (state.isReadState())
      return HandshakeStatus.NEED_UNWRAP;

    return HandshakeStatus.FINISHED;
  }

  /* (non-Javadoc)
   * @see gnu.javax.net.ssl.provider.AbstractHandshake#status()
   */
  @Override HandshakeStatus status()
  {
    if (state.isReadState())
      return HandshakeStatus.NEED_UNWRAP;
    if (state.isWriteState())
      return HandshakeStatus.NEED_WRAP;
    return HandshakeStatus.FINISHED;
  }

  @Override void checkKeyExchange() throws SSLException
  {
    // XXX implement.
  }

  /* (non-Javadoc)
   * @see gnu.javax.net.ssl.provider.AbstractHandshake#handleV2Hello(java.nio.ByteBuffer)
   */
  @Override void handleV2Hello(ByteBuffer hello) throws SSLException
  {
    throw new SSLException("this should be impossible");
  }

  private ProtocolVersion chooseVersion() throws SSLException
  {
    // Select the highest enabled version, for our initial key exchange.
    ProtocolVersion version = null;
    for (String ver : engine.getEnabledProtocols())
      {
        try
          {
            ProtocolVersion v = ProtocolVersion.forName(ver);
            if (version == null || version.compareTo(v) < 0)
              version = v;
          }
        catch (Exception x)
          {
            continue;
          }
      }

    if (version == null)
      throw new SSLException("no suitable enabled versions");

    return version;
  }

  private List<CipherSuite> getSuites() throws SSLException
  {
    List<CipherSuite> suites = new LinkedList<CipherSuite>();
    for (String s : engine.getEnabledCipherSuites())
      {
        CipherSuite suite = CipherSuite.forName(s);
        if (suite != null)
          suites.add(suite);
      }
    if (suites.isEmpty())
      throw new SSLException("no cipher suites enabled");
    return suites;
  }

  private List<CompressionMethod> getCompressionMethods()
  {
    List<CompressionMethod> methods = new LinkedList<CompressionMethod>();
    GetSecurityPropertyAction gspa = new GetSecurityPropertyAction("jessie.enable.compression");
    if (Boolean.valueOf(AccessController.doPrivileged(gspa)))
      methods.add(CompressionMethod.ZLIB);
    methods.add(CompressionMethod.NULL);
    return methods;
  }

  private boolean enableExtensions()
  {
    GetSecurityPropertyAction action
      = new GetSecurityPropertyAction("jessie.client.enable.extensions");
    return Boolean.valueOf(AccessController.doPrivileged(action));
  }

  private MaxFragmentLength maxFragmentLength()
  {
    GetSecurityPropertyAction action
      = new GetSecurityPropertyAction("jessie.client.maxFragmentLength");
    String s = AccessController.doPrivileged(action);
    if (s != null)
      {
        try
          {
            int len = Integer.parseInt(s);
            switch (len)
              {
                case 9:
                case (1 <<  9): return MaxFragmentLength.LEN_2_9;
                case 10:
                case (1 << 10): return MaxFragmentLength.LEN_2_10;
                case 11:
                case (1 << 11): return MaxFragmentLength.LEN_2_11;
                case 12:
                case (1 << 12): return MaxFragmentLength.LEN_2_12;
              }
          }
        catch (NumberFormatException nfe)
          {
          }
      }
    return null;
  }

  private boolean truncatedHMac()
  {
    GetSecurityPropertyAction action
      = new GetSecurityPropertyAction("jessie.client.truncatedHMac");
    return Boolean.valueOf(AccessController.doPrivileged(action));
  }

  private String getPSKIdentity()
  {
    GetSecurityPropertyAction action
      = new GetSecurityPropertyAction("jessie.client.psk.identity");
    return AccessController.doPrivileged(action);
  }

  // Delegated tasks.

  class ParamsVerifier extends DelegatedTask
  {
    private final ByteBuffer paramsBuffer;
    private final byte[] signature;
    private boolean verified;

    ParamsVerifier(ByteBuffer paramsBuffer, byte[] signature)
    {
      this.paramsBuffer = paramsBuffer;
      this.signature = signature;
    }

    public void implRun()
      throws InvalidKeyException, NoSuchAlgorithmException,
             SSLPeerUnverifiedException, SignatureException
    {
      java.security.Signature s
        = java.security.Signature.getInstance(engine.session().suite
                                              .signatureAlgorithm().algorithm());
      s.initVerify(engine.session().getPeerCertificates()[0]);
      s.update(paramsBuffer);
      verified = s.verify(signature);
      synchronized (this)
        {
          notifyAll();
        }
    }

    boolean verified()
    {
      return verified;
    }
  }

  class ClientDHGen extends DelegatedTask
  {
    private final DHPublicKey serverKey;
    private final DHParameterSpec params;
    private final boolean full;

    ClientDHGen(DHPublicKey serverKey, DHParameterSpec params, boolean full)
    {
      this.serverKey = serverKey;
      this.params = params;
      this.full = full;
    }

    public void implRun()
      throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
             SSLException
    {
      if (Debug.DEBUG)
        logger.log(Component.SSL_DELEGATED_TASK, "running client DH phase");
      if (paramsVerifier != null)
        {
          synchronized (paramsVerifier)
            {
              try
                {
                  while (!paramsVerifier.hasRun())
                    paramsVerifier.wait(500);
                }
              catch (InterruptedException ie)
                {
                  // Ignore.
                }
            }
        }
      KeyPairGenerator gen = KeyPairGenerator.getInstance("DH");
      gen.initialize(params, engine.session().random());
      dhPair = gen.generateKeyPair();
      if (Debug.DEBUG_KEY_EXCHANGE)
        logger.logv(Component.SSL_KEY_EXCHANGE,
                    "client keys public:{0} private:{1}", dhPair.getPublic(),
                    dhPair.getPrivate());

      initDiffieHellman((DHPrivateKey) dhPair.getPrivate(), engine.session().random());

      // We have enough info to do the full key exchange; so let's do it.
      DHPhase phase = new DHPhase(serverKey, full);
      phase.run();
      if (phase.thrown() != null)
        throw new SSLException(phase.thrown());
    }

    DHPublicKey serverKey()
    {
      return serverKey;
    }
  }

  class CertLoader extends DelegatedTask
  {
    private final List<String> keyTypes;
    private final List<X500Principal> issuers;

    CertLoader(List<String> keyTypes, List<X500Principal> issuers)
    {
      this.keyTypes = keyTypes;
      this.issuers = issuers;
    }

    public void implRun()
    {
      X509ExtendedKeyManager km = engine.contextImpl.keyManager;
      if (km == null)
        return;
      keyAlias = km.chooseEngineClientAlias(keyTypes.toArray(new String[keyTypes.size()]),
                                            issuers.toArray(new X500Principal[issuers.size()]),
                                            engine);
      engine.session().setLocalCertificates(km.getCertificateChain(keyAlias));
      privateKey = km.getPrivateKey(keyAlias);
    }
  }

  class RSAGen extends DelegatedTask
  {
    private byte[] encryptedPreMasterSecret;
    private final boolean full;

    RSAGen()
    {
      this(true);
    }

    RSAGen(boolean full)
    {
      this.full = full;
    }

    public void implRun()
      throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
             NoSuchAlgorithmException, NoSuchPaddingException,
             SSLException
    {
      if (certVerifier != null)
        {
          synchronized (certVerifier)
            {
              try
                {
                  while (!certVerifier.hasRun())
                    certVerifier.wait(500);
                }
              catch (InterruptedException ie)
                {
                  // Ignore.
                }
            }
        }
      preMasterSecret = new byte[48];
      engine.session().random().nextBytes(preMasterSecret);
      preMasterSecret[0] = (byte) sentVersion.major();
      preMasterSecret[1] = (byte) sentVersion.minor();
      Cipher rsa = Cipher.getInstance("RSA");
      java.security.cert.Certificate cert
        = engine.session().getPeerCertificates()[0];
      if (cert instanceof X509Certificate)
        {
          boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
          if (keyUsage != null && !keyUsage[2])
            throw new InvalidKeyException("certificate's keyUsage does not permit keyEncipherment");
        }
      rsa.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
      encryptedPreMasterSecret = rsa.doFinal(preMasterSecret);

      // Generate our session keys, because we can.
      if (full)
        {
          generateMasterSecret(clientRandom, serverRandom, engine.session());
          byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
          setupSecurityParameters(keys, true, engine, compression);
        }
    }

    byte[] encryptedSecret()
    {
      return encryptedPreMasterSecret;
    }
  }

  class GenCertVerify extends DelegatedTask
  {
    private final MessageDigest md5, sha;
    private byte[] signed;

    GenCertVerify(MessageDigest md5, MessageDigest sha)
    {
      try
        {
          this.md5 = (MessageDigest) md5.clone();
          this.sha = (MessageDigest) sha.clone();
        }
      catch (CloneNotSupportedException cnse)
        {
          // Our message digests *should* be cloneable.
          throw new Error(cnse);
        }
    }

    public void implRun()
      throws InvalidKeyException, NoSuchAlgorithmException, SignatureException
    {
      byte[] toSign;
      if (engine.session().version == ProtocolVersion.SSL_3)
        {
          toSign = genV3CertificateVerify(md5, sha, engine.session());
        }
      else
        {
          if (engine.session().suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
            toSign = Util.concat(md5.digest(), sha.digest());
          else
            toSign = sha.digest();
        }

      java.security.Signature sig =
        java.security.Signature.getInstance(engine.session().suite.signatureAlgorithm().name());
      sig.initSign(privateKey);
      sig.update(toSign);
      signed = sig.sign();
    }

    byte[] signed()
    {
      return signed;
    }
  }
}
