Java Code Examples for javax.net.ssl.SSLEngineResult.HandshakeStatus#NEED_UNWRAP

The following examples show how to use javax.net.ssl.SSLEngineResult.HandshakeStatus#NEED_UNWRAP . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SecureNio2Channel.java    From Tomcat8-Source-Read with MIT License 6 votes vote down vote up
/**
 * Perform handshake unwrap
 * @return the result
 * @throws IOException An IO error occurred
 */
protected SSLEngineResult handshakeUnwrap() throws IOException {
    SSLEngineResult result;
    boolean cont = false;
    //loop while we can perform pure SSLEngine data
    do {
        //prepare the buffer with the incoming data
        netInBuffer.flip();
        //call unwrap
        getBufHandler().configureReadBufferForWrite();
        result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
        //compact the buffer, this is an optional method, wonder what would happen if we didn't
        netInBuffer.compact();
        //read in the status
        handshakeStatus = result.getHandshakeStatus();
        if (result.getStatus() == SSLEngineResult.Status.OK &&
             result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
            //execute tasks if we need to
            handshakeStatus = tasks();
        }
        //perform another unwrap?
        cont = result.getStatus() == SSLEngineResult.Status.OK &&
               handshakeStatus == HandshakeStatus.NEED_UNWRAP;
    } while (cont);
    return result;
}
 
Example 2
Source File: SSLSocketChannel2.java    From ans-android-sdk with GNU General Public License v3.0 6 votes vote down vote up
/**
 * performs the unwrap operation by unwrapping from {@link #inCrypt} to {@link #inData}
 **/
private synchronized ByteBuffer unwrap() throws SSLException {
    int rem;
    //There are some ssl test suites, which get around the selector.select() call, which
    // cause an infinite unwrap and 100% cpu usage (see #459 and #458)
    if (readEngineResult.getStatus() == Status.CLOSED
            && sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
        try {
            close();
        } catch (IOException e) {
            //Not really interesting
        }
    }
    do {
        rem = inData.remaining();
        readEngineResult = sslEngine.unwrap(inCrypt, inData);
    } while (readEngineResult.getStatus() == Status.OK && (rem != inData.remaining()
            || sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP));
    inData.flip();
    return inData;
}
 
Example 3
Source File: SSLSocketChannel2.java    From RipplePower with Apache License 2.0 6 votes vote down vote up
/**
 * performs the unwrap operation by unwrapping from {@link #inCrypt} to {@link #inData}
 **/
private synchronized ByteBuffer unwrap() throws SSLException {
	int rem;
	//There are some ssl test suites, which get around the selector.select() call, which cause an infinite unwrap and 100% cpu usage (see #459 and #458)
	if(readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED && sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING){
		try {
			close();
		} catch (IOException e) {
			//Not really interesting
		}
	}
	do {
		rem = inData.remaining();
		readEngineResult = sslEngine.unwrap( inCrypt, inData );
	} while ( readEngineResult.getStatus() == SSLEngineResult.Status.OK && ( rem != inData.remaining() || sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) );
	inData.flip();
	return inData;
}
 
Example 4
Source File: TransportContext.java    From openjsse with GNU General Public License v2.0 6 votes vote down vote up
boolean needUnwrapAgain() {
    if (!outputRecord.isEmpty()) {
        // If no handshaking, special case to wrap alters or
        // post-handshake messages.
        return false;
    } else if (isOutboundClosed() && isInboundClosed()) {
        return false;
    } else if (handshakeContext != null) {
        if (!handshakeContext.delegatedActions.isEmpty()) {
            return false;
        } else if (!isInboundClosed()) {
            if (sslContext.isDTLS() &&
                    !inputRecord.isEmpty()) {
                return (getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP);
            }
        }
    }

    return false;
}
 
Example 5
Source File: SSLSocketChannel2.java    From clevertap-android-sdk with MIT License 6 votes vote down vote up
/**
 * performs the unwrap operation by unwrapping from {@link #inCrypt} to {@link #inData}
 **/
private synchronized ByteBuffer unwrap() throws SSLException {
    int rem;
    //There are some ssl test suites, which get around the selector.select() call, which cause an infinite unwrap and 100% cpu usage (see #459 and #458)
    if(readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED && sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING){
        try {
            close();
        } catch (IOException e) {
            //Not really interesting
        }
    }
    do {
        rem = inData.remaining();
        readEngineResult = sslEngine.unwrap( inCrypt, inData );
    } while ( readEngineResult.getStatus() == SSLEngineResult.Status.OK && ( rem != inData.remaining() || sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) );
    inData.flip();
    return inData;
}
 
Example 6
Source File: SslReadWriteSelectorHandler.java    From simplewebserver with Apache License 2.0 6 votes vote down vote up
/**
 * Constructor for a secure ChannelIO variant.
 */
public SslReadWriteSelectorHandler(SocketChannel sc, SelectionKey selectionKey,
                                   SSLContext sslContext) throws IOException {
    super(sc);

    sslEngine = sslContext.createSSLEngine();
    sslEngine.setUseClientMode(false);
    initialHSStatus = HandshakeStatus.NEED_UNWRAP;
    initialHSComplete = false;

    int netBBSize = sslEngine.getSession().getPacketBufferSize();
    inNetBB = ByteBuffer.allocate(netBBSize);
    outNetBB = ByteBuffer.allocate(netBBSize);
    outNetBB.position(0);
    outNetBB.limit(0);

    int appBBSize = sslEngine.getSession().getApplicationBufferSize();
    requestBB = ByteBuffer.allocate(appBBSize);

    while (!doHandshake(selectionKey)) {

    }
}
 
Example 7
Source File: TransportContext.java    From Bytecoder with Apache License 2.0 6 votes vote down vote up
HandshakeStatus getHandshakeStatus() {
    if (!outputRecord.isEmpty()) {
        // If no handshaking, special case to wrap alters or
        // post-handshake messages.
        return HandshakeStatus.NEED_WRAP;
    } else if (isOutboundClosed() && isInboundClosed()) {
        return HandshakeStatus.NOT_HANDSHAKING;
    } else if (handshakeContext != null) {
        if (!handshakeContext.delegatedActions.isEmpty()) {
            return HandshakeStatus.NEED_TASK;
        } else if (!isInboundClosed()) {
            if (sslContext.isDTLS() &&
                    !inputRecord.isEmpty()) {
                return HandshakeStatus.NEED_UNWRAP_AGAIN;
            } else {
                return HandshakeStatus.NEED_UNWRAP;
            }
        } else if (!isOutboundClosed()) {
            // Special case that the inbound was closed, but outbound open.
            return HandshakeStatus.NEED_WRAP;
        }   // Otherwise, both inbound and outbound are closed.
    }

    return HandshakeStatus.NOT_HANDSHAKING;
}
 
Example 8
Source File: SslHandler.java    From jane with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Decrypt the incoming buffer and move the decrypted data to an application buffer.
 */
private SSLEngineResult unwrap() throws SSLException {
	// We first have to create the application buffer if it does not exist
	if (appBuffer == null)
		appBuffer = IoBuffer.allocate(inNetBuffer.remaining());
	else {
		// We already have one, just add the new data into it
		appBuffer = IoBuffer.reallocateRemain(appBuffer, inNetBuffer.remaining());
	}

	SSLEngineResult res;
	Status status;
	HandshakeStatus localHandshakeStatus;

	do {
		// Decode the incoming data
		res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf());
		status = res.getStatus();

		// We can be processing the Handshake
		localHandshakeStatus = res.getHandshakeStatus();

		if (status == Status.BUFFER_OVERFLOW) {
			// We have to grow the target buffer, it's too small. Then we can call the unwrap method again
			int newCapacity = sslEngine.getSession().getApplicationBufferSize();
			if (appBuffer.remaining() >= newCapacity) {
				// The buffer is already larger than the max buffer size suggested by the SSL engine.
				// Raising it any more will not make sense and it will end up in an endless loop. Throwing an error is safer
				throw new SSLException("SSL buffer overflow");
			}

			appBuffer = IoBuffer.reallocateRemain(appBuffer, newCapacity);
		}
	} while ((status == Status.OK || status == Status.BUFFER_OVERFLOW) &&
			(localHandshakeStatus == HandshakeStatus.NOT_HANDSHAKING || localHandshakeStatus == HandshakeStatus.NEED_UNWRAP));

	return res;
}
 
Example 9
Source File: SecureNioChannel.java    From Tomcat8-Source-Read with MIT License 5 votes vote down vote up
/**
 * Perform handshake unwrap
 * @param doread boolean
 * @return the result
 * @throws IOException An IO error occurred
 */
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {

    if (netInBuffer.position() == netInBuffer.limit()) {
        //clear the buffer if we have emptied it out on data
        netInBuffer.clear();
    }
    if (doread)  {
        //if we have data to read, read it
        int read = sc.read(netInBuffer);
        if (read == -1) {
            throw new IOException(sm.getString("channel.nio.ssl.eofDuringHandshake"));
        }
    }
    SSLEngineResult result;
    boolean cont = false;
    //loop while we can perform pure SSLEngine data
    do {
        //prepare the buffer with the incoming data
        netInBuffer.flip();
        //call unwrap
        getBufHandler().configureReadBufferForWrite();
        result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
        //compact the buffer, this is an optional method, wonder what would happen if we didn't
        netInBuffer.compact();
        //read in the status
        handshakeStatus = result.getHandshakeStatus();
        if ( result.getStatus() == SSLEngineResult.Status.OK &&
             result.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) {
            //execute tasks if we need to
            handshakeStatus = tasks();
        }
        //perform another unwrap?
        cont = result.getStatus() == SSLEngineResult.Status.OK &&
               handshakeStatus == HandshakeStatus.NEED_UNWRAP;
    }while ( cont );
    return result;
}
 
Example 10
Source File: SSLSocketChannel2.java    From Slyther with MIT License 5 votes vote down vote up
/**
 * performs the unwrap operation by unwrapping from {@link #inCrypt} to {@link #inData}
 **/
private synchronized ByteBuffer unwrap() throws SSLException {
	int rem;
	do {
		rem = inData.remaining();
		readEngineResult = sslEngine.unwrap( inCrypt, inData );
	} while ( readEngineResult.getStatus() == SSLEngineResult.Status.OK && ( rem != inData.remaining() || sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) );
	inData.flip();
	return inData;
}
 
Example 11
Source File: SecureNioChannel.java    From tomcatsrc with Apache License 2.0 5 votes vote down vote up
/**
 * Perform handshake unwrap
 * @param doread boolean
 * @return SSLEngineResult
 * @throws IOException
 */
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {

    if (netInBuffer.position() == netInBuffer.limit()) {
        //clear the buffer if we have emptied it out on data
        netInBuffer.clear();
    }
    if ( doread )  {
        //if we have data to read, read it
        int read = sc.read(netInBuffer);
        if (read == -1) throw new IOException("EOF encountered during handshake.");
    }
    SSLEngineResult result;
    boolean cont = false;
    //loop while we can perform pure SSLEngine data
    do {
        //prepare the buffer with the incoming data
        netInBuffer.flip();
        //call unwrap
        result = sslEngine.unwrap(netInBuffer, bufHandler.getReadBuffer());
        //compact the buffer, this is an optional method, wonder what would happen if we didn't
        netInBuffer.compact();
        //read in the status
        handshakeStatus = result.getHandshakeStatus();
        if ( result.getStatus() == SSLEngineResult.Status.OK &&
             result.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) {
            //execute tasks if we need to
            handshakeStatus = tasks();
        }
        //perform another unwrap?
        cont = result.getStatus() == SSLEngineResult.Status.OK &&
               handshakeStatus == HandshakeStatus.NEED_UNWRAP;
    }while ( cont );
    return result;
}
 
Example 12
Source File: SecureNioChannel.java    From Tomcat7.0.67 with Apache License 2.0 5 votes vote down vote up
/**
 * Perform handshake unwrap
 * @param doread boolean
 * @return SSLEngineResult
 * @throws IOException
 */
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {

    if (netInBuffer.position() == netInBuffer.limit()) {
        //clear the buffer if we have emptied it out on data
        netInBuffer.clear();
    }
    if ( doread )  {
        //if we have data to read, read it
        int read = sc.read(netInBuffer);
        if (read == -1) throw new IOException("EOF encountered during handshake.");
    }
    SSLEngineResult result;
    boolean cont = false;
    //loop while we can perform pure SSLEngine data
    do {
        //prepare the buffer with the incoming data
        netInBuffer.flip();
        //call unwrap
        result = sslEngine.unwrap(netInBuffer, bufHandler.getReadBuffer());
        //compact the buffer, this is an optional method, wonder what would happen if we didn't
        netInBuffer.compact();
        //read in the status
        handshakeStatus = result.getHandshakeStatus();
        if ( result.getStatus() == SSLEngineResult.Status.OK &&
             result.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) {
            //execute tasks if we need to
            handshakeStatus = tasks();
        }
        //perform another unwrap?
        cont = result.getStatus() == SSLEngineResult.Status.OK &&
               handshakeStatus == HandshakeStatus.NEED_UNWRAP;
    }while ( cont );
    return result;
}
 
Example 13
Source File: SqueakSSL.java    From trufflesqueak with MIT License 5 votes vote down vote up
private static void readHandshakeResponse(final SqSSL ssl) throws SSLException {
    HandshakeStatus status = ssl.engine.getHandshakeStatus();
    while (status == HandshakeStatus.NEED_UNWRAP) {

        ssl.buffer.flip();
        final SSLEngineResult result = unwrap(ssl, ssl.buffer, EMPTY_BUFFER);
        ssl.buffer.compact();

        checkStatus("Processing server handshake response",
                        result, Status.OK, Status.BUFFER_UNDERFLOW);

        if (result.getStatus() == Status.OK) {
            runTasks(ssl);
            if (result.getHandshakeStatus() == HandshakeStatus.FINISHED) {
                handshakeCompleted(ssl);
                break;
            }

            checkHandshake("Handshake", ssl, HandshakeStatus.NEED_WRAP, HandshakeStatus.NEED_UNWRAP);
        }

        if (result.getStatus() == Status.BUFFER_UNDERFLOW) {
            break;
        }

        status = ssl.engine.getHandshakeStatus();
    }
}
 
Example 14
Source File: SqueakSSL.java    From trufflesqueak with MIT License 5 votes vote down vote up
private static void unwrapEagerly(final SqSSL ssl) throws SSLException {
    do {
        ssl.buffer.flip();
        final SSLEngineResult result = unwrap(ssl, ssl.buffer, EMPTY_BUFFER);
        ssl.buffer.compact();
        checkStatus("Handshake unwrap", result, Status.OK, Status.BUFFER_UNDERFLOW);
        if (result.getStatus() == Status.BUFFER_UNDERFLOW) {
            break;
        }

        runTasks(ssl);
    } while (ssl.engine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP);
}
 
Example 15
Source File: TransportContext.java    From openjsse with GNU General Public License v2.0 5 votes vote down vote up
HandshakeStatus getHandshakeStatus() {
    if (!outputRecord.isEmpty()) {
        // If no handshaking, special case to wrap alters or
        // post-handshake messages.
        return HandshakeStatus.NEED_WRAP;
    } else if (isOutboundClosed() && isInboundClosed()) {
        return HandshakeStatus.NOT_HANDSHAKING;
    } else if (handshakeContext != null) {
        if (!handshakeContext.delegatedActions.isEmpty()) {
            return HandshakeStatus.NEED_TASK;
        } else if (!isInboundClosed()) {
              //JDK8 NEED_UNWRAP returnned for NEED_UNWRAP_AGAIN status
              // needUnwrapAgain should be used to determine NEED_UNWRAP_AGAIN
            return HandshakeStatus.NEED_UNWRAP;
        } else if (!isOutboundClosed()) {
            // Special case that the inbound was closed, but outbound open.
            return HandshakeStatus.NEED_WRAP;
        }
    } else if (isOutboundClosed() && !isInboundClosed()) {
        // Special case that the outbound was closed, but inbound open.
        return HandshakeStatus.NEED_UNWRAP;
    } else if (!isOutboundClosed() && isInboundClosed()) {
        // Special case that the inbound was closed, but outbound open.
        return HandshakeStatus.NEED_WRAP;
    }

    return HandshakeStatus.NOT_HANDSHAKING;
}
 
Example 16
Source File: SSLSocketChannel.java    From mts with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Handshake unwrap.
 * 
 * @param ops the current ready operations set.
 * @return the interest set to continue or 0 if finished.
 * @throws IOException on I/O errors.
 */
private synchronized int unwrap(int ops) throws IOException
{
    // Fill the buffer, if applicable.
    if ((ops & SelectionKey.OP_READ) != 0)
    {
        fill(inputBuffer[0]);
    }

    // Unwrap the buffer.
    SSLEngineResult result;
    Status status;
    do
    {
        // Prepare the input cache, although no app
        // data should be produced during handshake.
        prepare(inputCache, minCacheSize);
        inputBuffer[0].flip();
        try
        {
            result = sslEngine.unwrap(inputBuffer[0], inputCache[0]);
        }
        finally
        {
            inputBuffer[0].compact();
            inputCache[0].flip();
        }
        handshake = result.getHandshakeStatus();

        status = result.getStatus();
        if (status == Status.OK)
        {
            if (handshake == HandshakeStatus.NEED_TASK)
            {
                handshake = runTasks();
            }
        }
        else if (status == Status.BUFFER_UNDERFLOW)
        {
            return SelectionKey.OP_READ;
        }
        else
        {
            // BUFFER_OVERFLOW/CLOSED
            throw new IOException("Handshake failed '" + status + '\'');
        }
    } while (handshake == HandshakeStatus.NEED_UNWRAP);

    return 0;
}
 
Example 17
Source File: SSLSocketChannel.java    From mts with GNU General Public License v3.0 4 votes vote down vote up
public synchronized int handshake(int ops) throws IOException
{
    if (initialized != 0)
    {
        if (handshake == null)
        {
            sslEngine.beginHandshake();
            handshake = sslEngine.getHandshakeStatus();
        }

        if (outputBuffer[0].hasRemaining())
        {
            if ((ops & SelectionKey.OP_WRITE) != 0)
            {
                flush(outputBuffer[0]);
                if (outputBuffer[0].hasRemaining())
                {
                    initialized = SelectionKey.OP_WRITE;
                }
                else
                {
                    initialized = SelectionKey.OP_READ;
                }
                ops = 0;
            }
            else
            {
                initialized = SelectionKey.OP_WRITE;
            }
        }
        else
        {
            initialized = SelectionKey.OP_READ;
        }

        while (initialized != 0)
        {
            if (handshake == HandshakeStatus.FINISHED)
            {
                initialized = 0;
            }
            else if (handshake == HandshakeStatus.NEED_TASK)
            {
                handshake = runTasks();
            }
            else if (handshake == HandshakeStatus.NEED_UNWRAP)
            {
                ops = unwrap(ops);
                if (ops != 0)
                {
                    initialized = ops;
                    return initialized;
                }
            }
            else if (handshake == HandshakeStatus.NEED_WRAP)
            {
                ops = wrap(ops);
                if (ops != 0)
                {
                    initialized = ops;
                    return initialized;
                }
            }
            else
            {
                // NOT_HANDSHAKING
                throw new IllegalStateException("Unexpected handshake status '" + handshake + '\'');
            }
        }
    }
    return initialized;
}
 
Example 18
Source File: TLSStreamHandler.java    From Openfire with Apache License 2.0 4 votes vote down vote up
/**
 * Creates a new TLSStreamHandler and secures the plain socket connection. When connecting
 * to a remote server then {@code clientMode} will be <code>true</code> and
 * {@code remoteServer} is the server name of the remote server. Otherwise {@code clientMode}
 * will be <code>false</code> and  {@code remoteServer} null.
 *
 * @param socket the plain socket connection to secure
 * @param configuration the configuration for the connection
 * @param clientMode boolean indicating if this entity is a client or a server.
 * @throws java.io.IOException if an exception occurs
 */
public TLSStreamHandler(Socket socket, ConnectionConfiguration configuration, boolean clientMode) throws IOException {
    wrapper = new TLSWrapper(configuration, clientMode);
    tlsEngine = wrapper.getTlsEngine();
    reader = new TLSStreamReader(wrapper, socket);
    writer = new TLSStreamWriter(wrapper, socket);

    // DANIELE: Add code to use directly the socket-channel.
    if (socket.getChannel() != null) {
        rbc = socket.getChannel();
        wbc = socket.getChannel();
    }
    else {
        rbc = Channels.newChannel(socket.getInputStream());
        wbc = Channels.newChannel(socket.getOutputStream());
    }
    initialHSStatus = HandshakeStatus.NEED_UNWRAP;
    initialHSComplete = false;

    netBBSize = tlsEngine.getSession().getPacketBufferSize();
    appBBSize = tlsEngine.getSession().getApplicationBufferSize();

    incomingNetBB = ByteBuffer.allocate(netBBSize);
    outgoingNetBB = ByteBuffer.allocate(netBBSize);
    outgoingNetBB.position(0);
    outgoingNetBB.limit(0);

    appBB = ByteBuffer.allocate(appBBSize);

    if (clientMode) {
        socket.setSoTimeout(0);
        socket.setKeepAlive(true);
        initialHSStatus = HandshakeStatus.NEED_WRAP;
        tlsEngine.beginHandshake();
    }
    else if (configuration.getClientAuth() == Connection.ClientAuth.needed) {
        // Only REQUIRE client authentication if we are fully verifying certificates
        if (JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
                JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
                !JiveGlobals
                        .getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false))
        {
            tlsEngine.setNeedClientAuth(true);
        }
        else {
            // Just indicate that we would like to authenticate the client but if client
            // certificates are self-signed or have no certificate chain then we are still
            // good
            tlsEngine.setWantClientAuth(true);
        }
    }
}
 
Example 19
Source File: SSLSocketChannel2.java    From ans-android-sdk with GNU General Public License v3.0 4 votes vote down vote up
/**
 * This method will do whatever necessary to process the sslengine handshake.
 * Thats why it's called both from the {@link #read(ByteBuffer)} and {@link #write(ByteBuffer)}
 **/
private synchronized void processHandshake() throws IOException {
    if (sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
        return; // since this may be called either from a reading or a writing thread and
        // because this method is synchronized it is necessary to double check if we are
        // still handshaking.
    }
    if (!tasks.isEmpty()) {
        Iterator<Future<?>> it = tasks.iterator();
        while (it.hasNext()) {
            Future<?> f = it.next();
            if (f.isDone()) {
                it.remove();
            } else {
                if (isBlocking()) {
                    consumeFutureUninterruptible(f);
                }
                return;
            }
        }
    }

    if (sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) {
        if (!isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW) {
            inCrypt.compact();
            int read = socketChannel.read(inCrypt);
            if (read == -1) {
                throw new IOException("connection closed unexpectedly by peer");
            }
            inCrypt.flip();
        }
        inData.compact();
        unwrap();
        if (readEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED) {
            createBuffers(sslEngine.getSession());
            return;
        }
    }
    consumeDelegatedTasks();
    if (tasks.isEmpty() || sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) {
        socketChannel.write(wrap(emptybuffer));
        if (writeEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED) {
            createBuffers(sslEngine.getSession());
            return;
        }
    }
    assert (sslEngine.getHandshakeStatus()
            != HandshakeStatus.NOT_HANDSHAKING);// this function could only leave
    // NOT_HANDSHAKING after createBuffers was called unless #190 occurs which means that nio
    // wrap/unwrap never return HandshakeStatus.FINISHED

    bufferallocations =
            1; // look at variable declaration why this line exists and #190. Without this
    // line buffers would not be be recreated when #190 AND a rehandshake occur.
}