/** * Encrypt provided buffer. Encrypted data returned by getOutNetBuffer(). * * @param src * data to encrypt * @throws SSLException * on errors */ /* no qualifier */void encrypt(ByteBuffer src) throws SSLException { if (!handshakeComplete) { throw new IllegalStateException(); } if (!src.hasRemaining()) { if (outNetBuffer == null) { outNetBuffer = emptyBuffer; } return; } createOutNetBuffer(src.remaining()); // Loop until there is no more data in src while (src.hasRemaining()) { SSLEngineResult result = sslEngine.wrap(src, outNetBuffer.buf()); if (result.getStatus() == SSLEngineResult.Status.OK) { if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { doTasks(); } } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) { outNetBuffer.capacity(outNetBuffer.capacity() << 1); outNetBuffer.limit(outNetBuffer.capacity()); } else { throw new SSLException("SSLEngine error during encrypt: " + result.getStatus() + " src: " + src + "outNetBuffer: " + outNetBuffer); } } outNetBuffer.flip(); }
/** * Start SSL shutdown process. * * @return <tt>true</tt> if shutdown process is started. <tt>false</tt> if * shutdown process is already finished. * @throws SSLException * on errors */ /* no qualifier */boolean closeOutbound() throws SSLException { if (sslEngine == null || sslEngine.isOutboundDone()) { return false; } sslEngine.closeOutbound(); createOutNetBuffer(0); SSLEngineResult result; for (;;) { result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer.buf()); if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) { outNetBuffer.capacity(outNetBuffer.capacity() << 1); outNetBuffer.limit(outNetBuffer.capacity()); } else { break; } } if (result.getStatus() != SSLEngineResult.Status.CLOSED) { throw new SSLException("Improper close state: " + result); } outNetBuffer.flip(); return true; }
/** * @param res * @throws SSLException */ private void checkStatus(SSLEngineResult res) throws SSLException { SSLEngineResult.Status status = res.getStatus(); /* * The status may be: * OK - Normal operation * OVERFLOW - Should never happen since the application buffer is sized to hold the maximum * packet size. * UNDERFLOW - Need to read more data from the socket. It's normal. * CLOSED - The other peer closed the socket. Also normal. */ if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) { throw new SSLException("SSLEngine error during decrypt: " + status + " inNetBuffer: " + inNetBuffer + "appBuffer: " + appBuffer); } }
private void checkResult(SSLEngineResult result, boolean wrap) throws SSLException { handshakeStatus = result.getHandshakeStatus(); resultStatus = result.getStatus(); if (resultStatus != Status.OK && (wrap || resultStatus != Status.BUFFER_UNDERFLOW)) { throw new SSLException("TODO"); } if (wrap && result.bytesConsumed() != 0) { throw new SSLException("TODO"); } if (!wrap && result.bytesProduced() != 0) { throw new SSLException("TODO"); } }
/** * Executes all the tasks needed on the same thread. * @return HandshakeStatus */ protected SSLEngineResult.HandshakeStatus tasks() { Runnable r = null; while ( (r = sslEngine.getDelegatedTask()) != null) { r.run(); } return sslEngine.getHandshakeStatus(); }
/** * Sends a SSL close message, will not physically close the connection here.<br> * To close the connection, you could do something like * <pre><code> * close(); * while (isOpen() && !myTimeoutFunction()) Thread.sleep(25); * if ( isOpen() ) close(true); //forces a close if you timed out * </code></pre> * @throws IOException if an I/O error occurs * @throws IOException if there is data on the outgoing network buffer and we are unable to flush it * TODO Implement this java.io.Closeable method */ @Override public void close() throws IOException { if (closing) return; closing = true; sslEngine.closeOutbound(); if (!flush(netOutBuffer)) { throw new IOException("Remaining data in the network buffer, can't send SSL close message, force a close with close(true) instead"); } //prep the buffer for the close message netOutBuffer.clear(); //perform the close, since we called sslEngine.closeOutbound SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer); //we should be in a close state if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) { throw new IOException("Invalid close state, will not send network data."); } //prepare the buffer for writing netOutBuffer.flip(); //if there is data to be written flush(netOutBuffer); //is the channel closed? closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); }
public SSLSocketChannel2( SocketChannel channel , SSLEngine sslEngine , ExecutorService exec , SelectionKey key ) throws IOException { if( channel == null || sslEngine == null || exec == null ) throw new IllegalArgumentException( "parameter must not be null" ); this.socketChannel = channel; this.sslEngine = sslEngine; this.exec = exec; readEngineResult = writeEngineResult = new SSLEngineResult( Status.BUFFER_UNDERFLOW, sslEngine.getHandshakeStatus(), 0, 0 ); // init to prevent NPEs tasks = new ArrayList<Future<?>>( 3 ); if( key != null ) { key.interestOps( key.interestOps() | SelectionKey.OP_WRITE ); this.selectionKey = key; } createBuffers( sslEngine.getSession() ); // kick off handshake socketChannel.write( wrap( emptybuffer ) );// initializes res processHandshake(); }
private void runDelegatedTasks(SSLEngineResult result) throws IOException { if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("Running delegated task for " + result); } /* * Delegated tasks are just invisible steps inside the sslEngine state machine. * Call them every time they have NEED_TASK otherwise the sslEngine won't make progress */ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = sslEngine.getDelegatedTask()) != null) { runnable.run(); } HandshakeStatus hsStatus = sslEngine.getHandshakeStatus(); if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { logger.logDebug("Handshake status after delegated tasks " + hsStatus); } if (hsStatus == HandshakeStatus.NEED_TASK) { throw new IOException( "handshake shouldn't need additional tasks"); } } }
public SSLSocketChannel2(SocketChannel channel, SSLEngine sslEngine, ExecutorService exec, SelectionKey key) throws IOException { if (channel == null || sslEngine == null || exec == null) { throw new IllegalArgumentException("parameter must not be null"); } this.socketChannel = channel; this.sslEngine = sslEngine; this.exec = exec; readEngineResult = writeEngineResult = new SSLEngineResult(Status.BUFFER_UNDERFLOW, sslEngine.getHandshakeStatus(), 0, 0); // init to prevent NPEs tasks = new ArrayList<Future<?>>(3); if (key != null) { key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); this.selectionKey = key; } createBuffers(sslEngine.getSession()); // kick off handshake socketChannel.write(wrap(emptybuffer));// initializes res processHandshake(); }
public int write(ByteBuffer src) throws IOException { if (!isHandShakeComplete()) { processHandshake(); return 0; } // assert ( bufferallocations > 1 ); //see #190 //if( bufferallocations <= 1 ) { // createBuffers( sslEngine.getSession() ); //} int num = socketChannel.write(wrap(src)); if (writeEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) { throw new EOFException("Connection is closed"); } return num; }
/** * {@link #read(ByteBuffer)} may not be to leave all buffers(inData, * inCrypt) * */ private int readRemaining(ByteBuffer dst) throws SSLException { if (inData.hasRemaining()) { return transfereTo(inData, dst); } if (!inData.hasRemaining()) { inData.clear(); } // test if some bytes left from last read (e.g. BUFFER_UNDERFLOW) if (inCrypt.hasRemaining()) { unwrap(); int amount = transfereTo(inData, dst); if (readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) { return -1; } if (amount > 0) { return amount; } } return 0; }
/** * Performs the WRAP function * @param doWrite boolean * @return SSLEngineResult * @throws IOException */ private SSLEngineResult handshakeWrap(boolean doWrite) throws IOException { log.trace("SSLHandshake handshakeWrap {}", channelId); if (netWriteBuffer.hasRemaining()) throw new IllegalStateException("handshakeWrap called with netWriteBuffer not empty"); //this should never be called with a network buffer that contains data //so we can clear it here. netWriteBuffer.clear(); SSLEngineResult result = sslEngine.wrap(emptyBuf, netWriteBuffer); //prepare the results to be written netWriteBuffer.flip(); handshakeStatus = result.getHandshakeStatus(); if (result.getStatus() == SSLEngineResult.Status.OK && result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { handshakeStatus = runDelegatedTasks(); } if (doWrite) flush(netWriteBuffer); return result; }
/** * Perform handshake unwrap * @param doRead boolean * @return SSLEngineResult * @throws IOException */ private SSLEngineResult handshakeUnwrap(boolean doRead) throws IOException { log.trace("SSLHandshake handshakeUnwrap {}", channelId); SSLEngineResult result; if (doRead) { int read = socketChannel.read(netReadBuffer); if (read == -1) throw new EOFException("EOF during handshake."); } boolean cont; do { //prepare the buffer with the incoming data netReadBuffer.flip(); result = sslEngine.unwrap(netReadBuffer, appReadBuffer); netReadBuffer.compact(); handshakeStatus = result.getHandshakeStatus(); if (result.getStatus() == SSLEngineResult.Status.OK && result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { handshakeStatus = runDelegatedTasks(); } cont = result.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP; log.trace("SSLHandshake handshakeUnwrap: handshakeStatus {} status {}", handshakeStatus, result.getStatus()); } while (netReadBuffer.position() != 0 && cont); return result; }
/** * Wraps data with the specified engine. * * @param engine - SSLEngine that wraps data. * @param wrapper - Set wrapper id, e.g. "server" of "client". * Used for logging only. * @param maxPacketSize - Max packet size to check that MFLN extension * works or zero for no check. * @param app - Buffer with data to wrap. * @param wantedStatus - Specifies expected result status of wrapping. * @param result - Array which first element will be used to output * wrap result object. * @return - Buffer with wrapped data. * @throws SSLException - thrown on engine errors. */ public static ByteBuffer doWrap(SSLEngine engine, String wrapper, int maxPacketSize, ByteBuffer app, SSLEngineResult.Status wantedStatus, SSLEngineResult[] result) throws SSLException { ByteBuffer net = ByteBuffer.allocate(engine.getSession() .getPacketBufferSize()); SSLEngineResult r = engine.wrap(app, net); net.flip(); int length = net.remaining(); System.out.println(wrapper + " wrapped " + length + " bytes."); System.out.println(wrapper + " handshake status is " + engine.getHandshakeStatus()); if (maxPacketSize < length && maxPacketSize != 0) { throw new AssertionError("Handshake wrapped net buffer length " + length + " exceeds maximum packet size " + maxPacketSize); } checkResult(r, wantedStatus); if (result != null && result.length > 0) { result[0] = r; } return net; }
/** * Unwraps data with the specified engine. * * @param engine - SSLEngine that unwraps data. * @param unwrapper - Set unwrapper id, e.g. "server" of "client". * Used for logging only. * @param net - Buffer with data to unwrap. * @param wantedStatus - Specifies expected result status of wrapping. * @param result - Array which first element will be used to output * wrap result object. * @return - Buffer with unwrapped data. * @throws SSLException - thrown on engine errors. */ public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper, ByteBuffer net, SSLEngineResult.Status wantedStatus, SSLEngineResult[] result) throws SSLException { ByteBuffer app = ByteBuffer.allocate( engine.getSession().getApplicationBufferSize()); int length = net.remaining(); System.out.println(unwrapper + " unwrapping " + length + " bytes..."); SSLEngineResult r = engine.unwrap(net, app); app.flip(); System.out.println(unwrapper + " handshake status is " + engine.getHandshakeStatus()); checkResult(r, wantedStatus); if (result != null && result.length > 0) { result[0] = r; } return app; }
private void checkBufferOverflowOnWrap(SSLEngine engine) throws SSLException { String mode = engine.getUseClientMode() ? "client" : "server"; System.out.println("=================================================" + "==========="); System.out.println("Testing SSLEngine buffer overflow" + " on wrap by " + mode); ByteBuffer app = ByteBuffer.wrap(MESSAGE.getBytes()); //Making net buffer size less than required by 1 byte. ByteBuffer net = ByteBuffer .allocate(engine.getSession().getPacketBufferSize() - 1); SSLEngineResult r = engine.wrap(app, net); checkResult(r, SSLEngineResult.Status.BUFFER_OVERFLOW); System.out.println("Passed"); }
private void checkBufferOverflowOnUnWrap(SSLEngine wrappingEngine, SSLEngine unwrappingEngine) throws SSLException { String wrapperMode = wrappingEngine.getUseClientMode() ? "client" : "server"; String unwrapperMode = unwrappingEngine.getUseClientMode() ? "client" : "server"; if (wrapperMode.equals(unwrapperMode)) { throw new Error("Test error: both engines are in the same mode!"); } System.out.println("=================================================" + "==========="); System.out.println("Testing SSLEngine buffer overflow" + " on unwrap by " + unwrapperMode); ByteBuffer app = ByteBuffer.wrap(MESSAGE.getBytes()); ByteBuffer net = ByteBuffer .allocate(wrappingEngine.getSession().getPacketBufferSize()); SSLEngineResult r = wrappingEngine.wrap(app, net); checkResult(r, SSLEngineResult.Status.OK); //Making app buffer size less than required by 1 byte. app = ByteBuffer.allocate(MESSAGE.length() - 1); net.flip(); r = unwrappingEngine.unwrap(net, app); checkResult(r, SSLEngineResult.Status.BUFFER_OVERFLOW); System.out.println("Passed"); }
/** * Performs the WRAP function * * @param doWrite * boolean * @return SSLEngineResult * @throws IOException */ protected SSLEngineResult handshakeWrap(boolean doWrite) throws IOException { // this should never be called with a network buffer that contains data // so we can clear it here. netOutBuffer.clear(); // perform the wrap SSLEngineResult result = sslEngine.wrap(bufHandler.getWriteBuffer(), netOutBuffer); // prepare the results to be written netOutBuffer.flip(); // set the status handshakeStatus = result.getHandshakeStatus(); // optimization, if we do have a writable channel, write it now if (doWrite) flush(netOutBuffer); return result; }
/** * Wraps data with the specified engine. * * @param engine - SSLEngine that wraps data. * @param wrapper - Set wrapper id, e.g. "server" of "client". Used for * logging only. * @param maxPacketSize - Max packet size to check that MFLN extension works * or zero for no check. * @param app - Buffer with data to wrap. * @param wantedStatus - Specifies expected result status of wrapping. * @param result - Array which first element will be used to output wrap * result object. * @return - Buffer with wrapped data. * @throws SSLException - thrown on engine errors. */ public static ByteBuffer doWrap(SSLEngine engine, String wrapper, int maxPacketSize, ByteBuffer app, SSLEngineResult.Status wantedStatus, SSLEngineResult[] result) throws SSLException { ByteBuffer net = ByteBuffer.allocate(engine.getSession() .getPacketBufferSize()); SSLEngineResult r = engine.wrap(app, net); net.flip(); int length = net.remaining(); System.out.println(wrapper + " wrapped " + length + " bytes."); System.out.println(wrapper + " handshake status is " + engine.getHandshakeStatus()); if (maxPacketSize < length && maxPacketSize != 0) { throw new AssertionError("Handshake wrapped net buffer length " + length + " exceeds maximum packet size " + maxPacketSize); } checkResult(r, wantedStatus); if (result != null && result.length > 0) { result[0] = r; } return net; }
/** * Unwraps data with the specified engine. * * @param engine - SSLEngine that unwraps data. * @param unwrapper - Set unwrapper id, e.g. "server" of "client". Used for * logging only. * @param net - Buffer with data to unwrap. * @param wantedStatus - Specifies expected result status of wrapping. * @param result - Array which first element will be used to output wrap * result object. * @return - Buffer with unwrapped data. * @throws SSLException - thrown on engine errors. */ public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper, ByteBuffer net, SSLEngineResult.Status wantedStatus, SSLEngineResult[] result) throws SSLException { ByteBuffer app = ByteBuffer.allocate(engine.getSession() .getApplicationBufferSize()); int length = net.remaining(); System.out.println(unwrapper + " unwrapping " + length + " bytes..."); SSLEngineResult r = engine.unwrap(net, app); app.flip(); System.out.println(unwrapper + " handshake status is " + engine.getHandshakeStatus()); checkResult(r, wantedStatus); if (result != null && result.length > 0) { result[0] = r; } return app; }
public SSLSocketChannel2( SocketChannel channel , SSLEngine sslEngine , ExecutorService exec , SelectionKey key ) throws IOException { if( channel == null || sslEngine == null || exec == null ) throw new IllegalArgumentException( "parameter must not be null" ); this.socketChannel = channel; this.sslEngine = sslEngine; this.exec = exec; readEngineResult = writeEngineResult = new SSLEngineResult( Status.BUFFER_UNDERFLOW, sslEngine.getHandshakeStatus(), 0, 0 ); // init to prevent NPEs tasks = new ArrayList<Future<?>>( 3 ); if( key != null ) { key.interestOps( key.interestOps() | SelectionKey.OP_WRITE ); this.selectionKey = key; } createBuffers( sslEngine.getSession() ); // kick off request socketChannel.write( wrap( emptybuffer ) );// initializes res processHandshake(); }
public int write( ByteBuffer src ) throws IOException { if( !isHandShakeComplete() ) { processHandshake(); return 0; } // assert ( bufferallocations > 1 ); //see #190 //if( bufferallocations <= 1 ) { // createBuffers( sslEngine.getSession() ); //} int num = socketChannel.write( wrap( src ) ); if (writeEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) { throw new EOFException("Connection is closed"); } return num; }
/** * {@link #read(ByteBuffer)} may not be to leave all buffers(inData, inCrypt) **/ private int readRemaining( ByteBuffer dst ) throws SSLException { if( inData.hasRemaining() ) { return transfereTo( inData, dst ); } if( !inData.hasRemaining() ) inData.clear(); // test if some bytes left from last read (e.g. BUFFER_UNDERFLOW) if( inCrypt.hasRemaining() ) { unwrap(); int amount = transfereTo( inData, dst ); if (readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) { return -1; } if( amount > 0 ) return amount; } return 0; }
public SSLSocketChannel(SocketChannel channel, SSLEngine sslEngine, ExecutorService exec, SelectionKey key) throws IOException { if(channel == null || sslEngine == null || exec == null) throw new IllegalArgumentException("parameter must not be null"); this.socketChannel = channel; this.sslEngine = sslEngine; this.exec = exec; readEngineResult = writeEngineResult = new SSLEngineResult(Status.BUFFER_UNDERFLOW, sslEngine.getHandshakeStatus(), 0, 0); // init to prevent NPEs tasks = new ArrayList<Future<?>>(3); if(key != null) { key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); this.selectionKey = key; } createBuffers(sslEngine.getSession()); socketChannel.write(wrap(emptybuffer)); processHandshake(); }
private int readRemaining(ByteBuffer dst) throws SSLException { if(inData.hasRemaining()) { return transfereTo(inData, dst); } if(!inData.hasRemaining()) inData.clear(); if(inCrypt.hasRemaining()) { unwrap(); int amount = transfereTo(inData, dst); if (readEngineResult.getStatus() == SSLEngineResult.Status.CLOSED) { return -1; } if(amount > 0) return amount; } return 0; }
public ByteBuf unwrap(SocketChannel channel, ByteBuf src) throws IOException { SSLEngine sslEngine = channel.getSSLEngine(); ByteBuf dst = getTempDst(sslEngine); for (;;) { dst.clear(); SSLEngineResult result = sslEngine.unwrap(src.nioBuffer(), dst.nioBuffer()); HandshakeStatus handshakeStatus = result.getHandshakeStatus(); synchByteBuf(result, src, dst); if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) { if (handshakeStatus == HandshakeStatus.NEED_WRAP) { channel.doFlush(forgeFuture.duplicate()); return null; } else if (handshakeStatus == HandshakeStatus.NEED_TASK) { runDelegatedTasks(sslEngine); continue; } else if (handshakeStatus == HandshakeStatus.FINISHED) { channel.finishHandshake(null); return null; } else if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) { return null; } } return gc(channel, dst.flip()); } }
/** * Produce more handshake output. This is called in response to a * call to {@link javax.net.ssl.SSLEngine#wrap}, when the handshake * is still in progress. * * @param record The output record; the callee should put its output * handshake message (or a part of it) in the argument's * <code>fragment</code>, and should set the record length * appropriately. * @return An {@link SSLEngineResult} describing the result. */ public final HandshakeStatus handleOutput (ByteBuffer fragment) throws SSLException { if (!tasks.isEmpty()) return HandshakeStatus.NEED_TASK; int orig = fragment.position(); SSLEngineResult.HandshakeStatus status = implHandleOutput(fragment); if (doHash()) { if (Debug.DEBUG) logger.logv(Component.SSL_HANDSHAKE, "hashing output:\n{0}", Util.hexDump((ByteBuffer) fragment.duplicate().flip().position(orig), " >> ")); sha.update((ByteBuffer) fragment.duplicate().flip().position(orig)); md5.update((ByteBuffer) fragment.duplicate().flip().position(orig)); } return status; }
private void renegotiateIfNeeded(NextFilter nextFilter, SSLEngineResult res) throws SSLException { if ((res.getStatus() != SSLEngineResult.Status.CLOSED) && (res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW) && (res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) { // Renegotiation required. handshakeComplete = false; handshakeStatus = res.getHandshakeStatus(); handshake(nextFilter); } }
/** * 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.expand(inNetBuffer.remaining()); } SSLEngineResult res; Status status = null; HandshakeStatus handshakeStatus = null; do { // Decode the incoming data res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf()); status = res.getStatus(); // We can be processing the Handshake handshakeStatus = res.getHandshakeStatus(); if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) { // We have to grow the target buffer, it's too small. // Then we can call the unwrap method again appBuffer.capacity(appBuffer.capacity() << 1); appBuffer.limit(appBuffer.capacity()); continue; } } while (((status == SSLEngineResult.Status.OK) || (status == SSLEngineResult.Status.BUFFER_OVERFLOW)) && ((handshakeStatus == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) || (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP))); return res; }
/** * Do all the outstanding handshake tasks in the current Thread. */ private SSLEngineResult.HandshakeStatus doTasks() { /* * We could run this in a separate thread, but I don't see the need for * this when used from SSLFilter. Use thread filters in MINA instead? */ Runnable runnable; while ((runnable = sslEngine.getDelegatedTask()) != null) { // TODO : we may have to use a thread pool here to improve the // performances runnable.run(); } return sslEngine.getHandshakeStatus(); }
/** * Performs the WRAP function * @param doWrite boolean * @return SSLEngineResult * @throws IOException */ protected SSLEngineResult handshakeWrap(boolean doWrite) throws IOException { //this should never be called with a network buffer that contains data //so we can clear it here. netOutBuffer.clear(); //perform the wrap SSLEngineResult result = sslEngine.wrap(bufHandler.getWriteBuffer(), netOutBuffer); //prepare the results to be written netOutBuffer.flip(); //set the status handshakeStatus = result.getHandshakeStatus(); //optimization, if we do have a writable channel, write it now if ( doWrite ) flush(netOutBuffer); return result; }
/** * 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; }
/** * 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; }
/** * 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; }
public SSLEngineResult.HandshakeStatus doTasks() { synchronized(this.engine){ Runnable runnable; /* * We could run this in a separate thread, but * do in the current for now. */ while ((runnable = this.engine.getDelegatedTask()) != null) { runnable.run(); } return this.engine.getHandshakeStatus(); } }