/* SSLEngineImpl.java -- implementation of SSLEngine.
   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 gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;

import gnu.java.security.util.ByteBufferOutputStream;
import gnu.javax.net.ssl.Session;
import gnu.javax.net.ssl.SSLRecordHandler;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;

import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;

public final class SSLEngineImpl extends SSLEngine
{
  final SSLContextImpl contextImpl;
  private SSLRecordHandler[] handlers;
  private static final SystemLogger logger = SystemLogger.SYSTEM;
  private SessionImpl session;
  private InputSecurityParameters insec;
  private OutputSecurityParameters outsec;
  private boolean inClosed;
  private boolean outClosed;
  private boolean createSessions;
  private boolean needClientAuth;
  private boolean wantClientAuth;
  private boolean initialHandshakeDone;
  private AbstractHandshake handshake;
  private Alert lastAlert;
  private SSLEngineResult.HandshakeStatus handshakeStatus;
  private boolean changeCipherSpec;

  private String[] enabledSuites;
  private String[] enabledProtocols;

  /**
   * We can receive any message chunked across multiple records,
   * including alerts, even though all alert messages are only two
   * bytes long. Handshake messages are de-chunked in the handshake
   * handler, change-cipher-spec messages are always empty, and we
   * don't care about chunking of application messages.
   *
   * This buffer will hold the incomplete alert that we receive, if
   * any.
   */
  private final ByteBuffer alertBuffer;

  private Mode mode;

  private enum Mode { SERVER, CLIENT }

  SSLEngineImpl (SSLContextImpl contextImpl, String host, int port)
  {
    super(host, port);
    this.contextImpl = contextImpl;
    handlers = new SSLRecordHandler[256];
    session = new SessionImpl();
    session.suite = CipherSuite.TLS_NULL_WITH_NULL_NULL;
    session.version = ProtocolVersion.TLS_1_1;
    byte[] sid = new byte[32];
    contextImpl.random.nextBytes(sid);
    session.setId(new Session.ID(sid));
    session.setRandom(contextImpl.random);

    if (Debug.DEBUG)
      logger.logv(Component.SSL_RECORD_LAYER, "generated session ID {0} with random {1}",
                  session.id(), contextImpl.random);

    // Begin with no encryption.
    insec = new InputSecurityParameters (null, null, null, session,
                                         CipherSuite.TLS_NULL_WITH_NULL_NULL);
    outsec = new OutputSecurityParameters (null, null, null, session,
                                           CipherSuite.TLS_NULL_WITH_NULL_NULL);
    inClosed = false;
    outClosed = false;
    needClientAuth = false;
    wantClientAuth = false;
    createSessions = true;
    initialHandshakeDone = false;
    alertBuffer = ByteBuffer.wrap (new byte[2]);
    mode = null;
    lastAlert = null;
    handshakeStatus = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
    changeCipherSpec = false;

    // Set up default protocols and suites.
    enabledProtocols = new String[] {
      ProtocolVersion.TLS_1_1.toString(),
      ProtocolVersion.TLS_1.toString(),
      ProtocolVersion.SSL_3.toString()
    };
    enabledSuites = defaultSuites();
  }

  static String[] defaultSuites()
  {
    return new String[] {
      CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA.toString(),
      CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA.toString(),
      CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA.toString(),
      CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA.toString(),
      CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
      CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
      CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_RC4_128_MD5.toString(),
      CipherSuite.TLS_RSA_WITH_RC4_128_SHA.toString(),
      CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA.toString(),
      CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA.toString(),
      CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_DES_CBC_SHA.toString(),
      CipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
      CipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5.toString(),
      CipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
      CipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
      CipherSuite.TLS_RSA_WITH_NULL_MD5.toString(),
      CipherSuite.TLS_RSA_WITH_NULL_SHA.toString()
    };
  }

  // XXX implement?
  /*public void registerHandler (final int contentType,
                               SSLRecordHandler handler)
    throws SSLException
  {
    if (type.equals (ContentType.CHANGE_CIPHER_SPEC)
        || type.equals (ContentType.ALERT)
        || type.equals (ContentType.HANDSHAKE)
        || type.equals (ContentType.APPLICATION_DATA))
      throw new SSLException ("can't override handler for content type " + type);
    int i = type.getValue ();
    if (i < 0 || i > 255)
      throw new SSLException ("illegal content type: " + type);
    handlers[i] = handler;
  }*/

  @Override
  public void beginHandshake () throws SSLException
  {
    if (Debug.DEBUG)
      logger.log(Component.SSL_HANDSHAKE, "{0} handshake begins", mode);

    if (mode == null)
      throw new IllegalStateException("setUseClientMode was never used");

    switch (mode)
      {
      case SERVER:
        if (getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
          throw new SSLException("handshake already in progress");
        try
          {
            handshake = new ServerHandshake(initialHandshakeDone, this);
          }
        catch (NoSuchAlgorithmException nsae)
          {
            throw new SSLException(nsae);
          }
        break;

      case CLIENT:
        try
          {
            handshake = new ClientHandshake(this);
          }
        catch (NoSuchAlgorithmException nsae)
          {
            throw new SSLException(nsae);
          }
        break;
      }
  }

  @Override
  public void closeInbound()
  {
    inClosed = true;
  }

  @Override
  public void closeOutbound()
  {
    lastAlert = new Alert(Alert.Level.WARNING, Alert.Description.CLOSE_NOTIFY);
  }

  @Override
  public Runnable getDelegatedTask()
  {
    if (handshake == null)
      return null;
    return handshake.getTask();
  }

  @Override
  public String[] getEnabledCipherSuites()
  {
    return (String[]) enabledSuites.clone();
  }

  @Override
  public String[] getEnabledProtocols()
  {
    return (String[]) enabledProtocols.clone();
  }

  @Override
  public boolean getEnableSessionCreation()
  {
    return createSessions;
  }

  @Override
  public HandshakeStatus getHandshakeStatus()
  {
    if (handshake == null)
      return HandshakeStatus.NOT_HANDSHAKING;
    return handshake.status();
  }

  @Override
  public boolean getNeedClientAuth()
  {
    return needClientAuth;
  }

  @Override
  public SSLSession getSession()
  {
    return session;
  }

  @Override
  public boolean getUseClientMode ()
  {
    return (mode == Mode.CLIENT);
  }

  @Override
  public boolean getWantClientAuth()
  {
    return wantClientAuth;
  }

  @Override
  public boolean isInboundDone()
  {
    return inClosed;
  }

  @Override
  public boolean isOutboundDone()
  {
    return outClosed;
  }

  @Override
  public void setEnableSessionCreation(final boolean createSessions)
  {
    this.createSessions = createSessions;
  }

  @Override
  public void setEnabledCipherSuites(final String[] suites)
  {
    if (suites.length == 0)
      throw new IllegalArgumentException("need at least one suite");
    enabledSuites = (String[]) suites.clone();
  }

  @Override
  public void setEnabledProtocols(final String[] protocols)
  {
    if (protocols.length == 0)
      throw new IllegalArgumentException("need at least one protocol");
    enabledProtocols = (String[]) protocols.clone();
  }

  @Override
  public String[] getSupportedCipherSuites()
  {
    // XXX if we ever want to support "pluggable" cipher suites, we'll need
    // to figure this out.

    return CipherSuite.availableSuiteNames().toArray(new String[0]);
  }

  @Override
  public String[] getSupportedProtocols()
  {
    return new String[] { ProtocolVersion.SSL_3.toString(),
                          ProtocolVersion.TLS_1.toString(),
                          ProtocolVersion.TLS_1_1.toString() };
  }

  @Override
  public void setNeedClientAuth(final boolean needClientAuth)
  {
    this.needClientAuth = needClientAuth;
  }

  @Override
  public void setUseClientMode (final boolean clientMode)
  {
    if (clientMode)
      mode = Mode.CLIENT;
    else
      mode = Mode.SERVER;
  }

  public @Override void setWantClientAuth(final boolean wantClientAuth)
  {
    this.wantClientAuth = wantClientAuth;
  }

  public @Override SSLEngineResult unwrap (final ByteBuffer source,
                                           final ByteBuffer[] sinks,
                                           final int offset, final int length)
    throws SSLException
  {
    if (mode == null)
      throw new IllegalStateException ("setUseClientMode was never called");

    if (inClosed)
      return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
                                 handshakeStatus, 0, 0);

    if (source.remaining() < 5)
      {
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW,
                                   handshakeStatus, 0, 0);
      }

    Record record = null;
    boolean helloV2 = false;

    // XXX: messages may be chunked across multiple records; does this
    // include the SSLv2 message? I don't think it does, but we should
    // make sure.
    if (!getUseClientMode() && (source.get(source.position()) & 0x80) == 0x80)
      {
        if (handshake == null)
          beginHandshake();
        int hellolen = source.getShort(source.position()) & 0x7FFF;
        this.handshake.handleV2Hello(source.slice());
        if (!insec.cipherSuite().equals (CipherSuite.TLS_NULL_WITH_NULL_NULL))
          throw new SSLException ("received SSLv2 client hello in encrypted "
                                  + "session; this is invalid.");
        if (Debug.DEBUG)
          logger.log (Component.SSL_RECORD_LAYER,
                      "converting SSLv2 client hello to version 3 hello");

        source.getShort(); // skip length
        ClientHelloV2 v2 = new ClientHelloV2(source.slice());

        if (Debug.DEBUG)
          logger.log(Component.SSL_RECORD_LAYER, "v2 hello: {0}", v2);

        List<CipherSuite> suites = v2.cipherSpecs();

        ClientHelloBuilder hello = new ClientHelloBuilder();
        hello.setVersion(v2.version ());

        Random random = hello.random();
        byte[] challenge = v2.challenge();
        if (challenge.length < 32)
          {
            byte[] b = new byte[32];
            System.arraycopy(challenge, 0, b, b.length - challenge.length,
                             challenge.length);
            challenge = b;
          }
        random.setGmtUnixTime((challenge[0] & 0xFF) << 24
                              | (challenge[1] & 0xFF) << 16
                              | (challenge[2] & 0xFF) <<  8
                              | (challenge[3] & 0xFF));
        random.setRandomBytes(challenge, 4);

        byte[] sessionId = v2.sessionId();
        hello.setSessionId(sessionId, 0, sessionId.length);
        hello.setCipherSuites(suites);
        ArrayList<CompressionMethod> comps = new ArrayList<CompressionMethod>(1);
        comps.add(CompressionMethod.NULL);
        hello.setCompressionMethods(comps);

        record = new Record(ByteBuffer.allocate(hello.length() + 9));
        record.setContentType(ContentType.HANDSHAKE);
        record.setVersion(v2.version());
        record.setLength(hello.length() + 4);

        Handshake handshake = new Handshake(record.fragment());
        handshake.setLength(hello.length());
        handshake.setType(Handshake.Type.CLIENT_HELLO);

        handshake.bodyBuffer().put(hello.buffer());
        source.position(source.position() + hellolen);
        helloV2 = true;
      }
    else
      record = new Record(source);

    ContentType type = record.contentType ();

    if (Debug.DEBUG)
      logger.log(Component.SSL_RECORD_LAYER, "input record:\n{0}", record);

    if (record.length() > session.getPacketBufferSize() - 5)
      {
        lastAlert = new Alert(Alert.Level.FATAL,
                              Alert.Description.RECORD_OVERFLOW);
        throw new AlertException(lastAlert);
      }

    ByteBufferOutputStream sysMsg = null;
    ByteBuffer msg = null;

    int produced = 0;
    try
      {
        // Application data will get decrypted directly into the user's
        // output buffers.
        if (record.contentType() == ContentType.APPLICATION_DATA)
          produced = insec.decrypt(record, sinks, offset, length);
        else
          {
            if (insec.cipherSuite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
              msg = record.fragment();
            else
              {
                sysMsg = new ByteBufferOutputStream();
                insec.decrypt(record, sysMsg);
              }
          }

        // Advance the input buffer past the record we just read.
        if (!helloV2)
          source.position(source.position() + record.length() + 5);
      }
    catch (BufferOverflowException boe)
      {
        // We throw this if the output buffers are not large enough; signal
        // the caller about this.
        logger.log(Component.SSL_RECORD_LAYER, "buffer overflow when decrypting", boe);
        return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW,
                                   handshakeStatus, 0, 0);
      }
    catch (IllegalBlockSizeException ibse)
      {
        lastAlert = new Alert(Alert.Level.FATAL,
                              Alert.Description.BAD_RECORD_MAC);
        throw new AlertException(lastAlert, ibse);
      }
    catch (DataFormatException dfe)
      {
        lastAlert = new Alert(Alert.Level.FATAL,
                              Alert.Description.DECOMPRESSION_FAILURE);
        throw new AlertException(lastAlert, dfe);
      }
    catch (MacException me)
      {
        lastAlert = new Alert(Alert.Level.FATAL,
                              Alert.Description.BAD_RECORD_MAC);
        throw new AlertException(lastAlert, me);
      }
    catch (ShortBufferException sbe)
      {
        // We've messed up if this happens.
        lastAlert = new Alert(Alert.Level.FATAL,
                              Alert.Description.INTERNAL_ERROR);
        throw new AlertException(lastAlert, sbe);
      }

    SSLEngineResult result = null;

    // If we need to handle the output here, do it. Otherwise, the output
    // has been stored in the supplied output buffers.
    if (sysMsg != null)
      {
        if (Debug.DEBUG)
          logger.logv(Component.SSL_RECORD_LAYER, "sysmessage {0}", sysMsg);
        msg = sysMsg.buffer();
      }

    if (type == ContentType.CHANGE_CIPHER_SPEC)
      {
        // We *may* get a partial message, even though the message is only
        // one byte long.
        if (msg.remaining() == 0)
          {
            result = new SSLEngineResult (SSLEngineResult.Status.OK,
                                          handshakeStatus,
                                          record.length() + 5, 0);
          }
        else
          {
            byte b = msg.get();
            if (b != 1)
              throw new SSLException ("unknown ChangeCipherSpec value: " + (b & 0xFF));
            InputSecurityParameters params = handshake.getInputParams();
            logger.log (Component.SSL_RECORD_LAYER,
                        "switching to input security parameters {0}",
                        params.cipherSuite());
            insec = params;
            result = new SSLEngineResult (SSLEngineResult.Status.OK,
                                          handshakeStatus,
                                          record.length() + 5, 0);
          }
      }
    else if (type == ContentType.ALERT)
      {
        int len = 0;
        if (alertBuffer.position() > 0)
          {
            alertBuffer.put(msg.get());
            len = 1;
          }
        if (Debug.DEBUG)
          logger.logv(Component.SSL_RECORD_LAYER, "processing alerts {0}",
                      Util.wrapBuffer(msg));
        len += msg.remaining() / 2;
        Alert[] alerts = new Alert[len];
        int i = 0;
        if (alertBuffer.position() > 0)
          {
            alertBuffer.flip();
            alerts[0] = new Alert(alertBuffer);
            i++;
          }
        while (i < alerts.length)
          {
            alerts[i++] = new Alert(msg.duplicate());
            msg.position(msg.position() + 2);
          }
        if (Debug.DEBUG)
          logger.logv(Component.SSL_RECORD_LAYER, "alerts: {0}", alerts.length);

        for (i = 0; i < alerts.length; i++)
          {
            if (alerts[i].level() == Alert.Level.FATAL)
              throw new AlertException(alerts[i], false);
            if (alerts[i].description() != Alert.Description.CLOSE_NOTIFY)
              logger.log(java.util.logging.Level.WARNING,
                         "received alert: {0}", alerts[i]);
            if (alerts[i].description() == Alert.Description.CLOSE_NOTIFY)
              inClosed = true;
          }

        if (msg.hasRemaining())
          alertBuffer.position(0).limit(2);

        result = new SSLEngineResult (SSLEngineResult.Status.OK,
                                      handshakeStatus,
                                      record.length() + 5, 0);
      }
    else if (type == ContentType.HANDSHAKE)
      {
        if (handshake == null)
          beginHandshake();
        try
          {
            handshakeStatus = handshake.handleInput(msg);
          }
        catch (AlertException ae)
          {
            lastAlert = ae.alert();
            return new SSLEngineResult(SSLEngineResult.Status.OK,
                                       SSLEngineResult.HandshakeStatus.NEED_WRAP,
                                       0, 0);
          }
        if (Debug.DEBUG)
          logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}", handshakeStatus);
        result = new SSLEngineResult(SSLEngineResult.Status.OK,
                                     handshakeStatus,
                                     record.length() + 5,
                                     0);
        if (handshakeStatus == HandshakeStatus.FINISHED)
          {
            handshake = null;
            handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
          }
      }
    else if (type == ContentType.APPLICATION_DATA)
      {
        // Do nothing more; the application data has been put into
        // the output buffers.
        result = new SSLEngineResult(SSLEngineResult.Status.OK,
                                     handshakeStatus,
                                     record.length() + 5,
                                     produced);
      }
    else
      {
        SSLRecordHandler handler = handlers[type.getValue()];
        if (handler != null)
          {
            result = new SSLEngineResult(SSLEngineResult.Status.OK,
                                         handshakeStatus,
                                         record.length() + 5,
                                         0);
          }
        else
          throw new SSLException ("unknown content type: " + type);
      }

    if (Debug.DEBUG)
      logger.logv(Component.SSL_RECORD_LAYER, "return result: {0}", result);

    return result;
  }

  public @Override SSLEngineResult wrap (ByteBuffer[] sources, int offset, int length,
                                         ByteBuffer sink)
    throws SSLException
  {
    if (mode == null)
      throw new IllegalStateException ("setUseClientMode was never called");

    if (outClosed)
      return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
                                 handshakeStatus, 0, 0);

    ContentType type = null;
    ByteBuffer sysMessage = null;
    if (Debug.DEBUG)
      logger.logv(Component.SSL_RECORD_LAYER, "wrap {0} {1} {2} {3} / {4}",
                  sources, offset, length, sink, getHandshakeStatus());
    if (lastAlert != null)
      {
        type = ContentType.ALERT;
        sysMessage = ByteBuffer.allocate(2);
        Alert alert = new Alert(sysMessage);
        alert.setDescription(lastAlert.description());
        alert.setLevel(lastAlert.level());
        if (lastAlert.description() == Alert.Description.CLOSE_NOTIFY)
          outClosed = true;
      }
    else if (changeCipherSpec)
      {
        type = ContentType.CHANGE_CIPHER_SPEC;
        sysMessage = ByteBuffer.allocate(1);
        sysMessage.put(0, (byte) 1);
      }
    else if (getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP)
      {
        // If we are not encrypting, optimize the handshake to fill
        // the buffer directly.
        if (outsec.suite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
          {
            int orig = sink.position();
            sink.order(ByteOrder.BIG_ENDIAN);
            sink.put((byte) ContentType.HANDSHAKE.getValue());
            sink.putShort((short) session.version.rawValue());
            sink.putShort((short) 0);
            handshakeStatus = handshake.handleOutput(sink);
            int produced = sink.position() - orig;
            sink.putShort(orig + 3, (short) (produced - 5));
            if (Debug.DEBUG)
              logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
                          new Record((ByteBuffer) sink.duplicate().position(orig)));
            SSLEngineResult result = new SSLEngineResult(SSLEngineResult.Status.OK,
                                                         handshakeStatus, 0, produced);

            // Note, this will only happen if we transition from
            // TLS_NULL_WITH_NULL_NULL *to* TLS_NULL_WITH_NULL_NULL, which
            // doesn't make a lot of sense, but we support it anyway.
            if (handshakeStatus == HandshakeStatus.FINISHED)
              {
                handshake = null; // finished with it.
                handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
              }
            return result;
          }

        // Rough guideline; XXX.
        sysMessage = ByteBuffer.allocate(sink.remaining() - 2048);
        type = ContentType.HANDSHAKE;
        try
          {
            handshakeStatus = handshake.handleOutput(sysMessage);
          }
        catch (AlertException ae)
          {
            lastAlert = ae.alert();
            return new SSLEngineResult(Status.OK,
                                       HandshakeStatus.NEED_WRAP, 0, 0);
          }
        sysMessage.flip();
        if (Debug.DEBUG)
          logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}",
                      handshakeStatus);
      }

    int produced = 0;
    int consumed = 0;

    try
      {
        int orig = sink.position();
        int[] inout = null;
        if (sysMessage != null)
          {
            if (Debug.DEBUG)
              logger.logv(Component.SSL_RECORD_LAYER, "encrypt system message {0} to {1}", sysMessage, sink);
            inout = outsec.encrypt(new ByteBuffer[] { sysMessage }, 0, 1,
                                   type, sink);
            produced = inout[1];
          }
        else
          {
            if (outsec.needToSplitPayload())
              {
                inout = outsec.encrypt(sources, offset, 1,
                                       ContentType.APPLICATION_DATA, sink);
                consumed = inout[0];
                produced = inout[1];
                if (length > 1)
                  {
                    inout = outsec.encrypt(sources, offset+1, length-1,
                                           ContentType.APPLICATION_DATA, sink);
                    consumed += inout[0];
                    produced += inout[1];
                  }
              }
            else
              {
                inout = outsec.encrypt(sources, offset, length,
                                       ContentType.APPLICATION_DATA, sink);
                consumed = inout[0];
                produced = inout[1];
              }
          }

        if (Debug.DEBUG)
          logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
                      new Record((ByteBuffer) sink.duplicate().position(orig).limit(produced)));
      }
    catch (ShortBufferException sbe)
      {
        // We don't expect this to happen, except for bugs; signal an
        // internal error.
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
      }
    catch (IllegalBlockSizeException ibse)
      {
        // We don't expect this to happen, except for bugs; signal an
        // internal error.
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
      }
    catch (DataFormatException dfe)
      {
        // We don't expect this to happen; signal an internal error.
        lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
        return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
      }

    if (lastAlert != null && lastAlert.level() == Alert.Level.FATAL)
      {
        AlertException ae = new AlertException(lastAlert);
        lastAlert = null;
        throw ae;
      }

    if (changeCipherSpec)
      {
        outsec = handshake.getOutputParams();
        changeCipherSpec = false;
      }
    SSLEngineResult result
      = new SSLEngineResult(outClosed ? SSLEngineResult.Status.CLOSED
                                      : SSLEngineResult.Status.OK,
                            handshakeStatus, consumed, produced);
    if (handshakeStatus == HandshakeStatus.FINISHED)
      {
        handshake = null; // done with it.
        handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
      }
    return result;
  }

  // Package-private methods.

  SessionImpl session ()
  {
    return session;
  }

  void setSession(SessionImpl session)
  {
    this.session = session;
  }

  void changeCipherSpec()
  {
    changeCipherSpec = true;
  }
}
