use of java.nio.ReadOnlyBufferException in project tomcat by apache.
the class OpenSSLEngine method unwrap.
@Override
public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
// Check to make sure the engine has not been closed
if (destroyed) {
return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
// Throw required runtime exceptions
if (src == null || dsts == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBuffer"));
}
if (offset >= dsts.length || offset + length > dsts.length) {
throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), Integer.toString(length), Integer.toString(dsts.length)));
}
int capacity = 0;
final int endOffset = offset + length;
for (int i = offset; i < endOffset; i++) {
ByteBuffer dst = dsts[i];
if (dst == null) {
throw new IllegalArgumentException(sm.getString("engine.nullBufferInArray"));
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
capacity += dst.remaining();
}
// Prepare OpenSSL to work in server mode and receive handshake
if (accepted == 0) {
beginHandshakeImplicitly();
}
// In handshake or close_notify stages, check if call to unwrap was made
// without regard to the handshake status.
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
if ((!handshakeFinished || engineClosed) && handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
return new SSLEngineResult(getEngineStatus(), SSLEngineResult.HandshakeStatus.NEED_WRAP, 0, 0);
}
int len = src.remaining();
// protect against protocol overflow attack vector
if (len > MAX_ENCRYPTED_PACKET_LENGTH) {
isInboundDone = true;
isOutboundDone = true;
engineClosed = true;
shutdown();
throw new SSLException(sm.getString("engine.oversizedPacket"));
}
// Write encrypted data to network BIO
int written = -1;
try {
written = writeEncryptedData(src);
} catch (Exception e) {
throw new SSLException(e);
}
// OpenSSL can return 0 or -1 to these calls if nothing was written
if (written < 0) {
written = 0;
}
// There won't be any application data until we're done handshaking
//
// We first check handshakeFinished to eliminate the overhead of extra JNI call if possible.
int pendingApp = pendingReadableBytesInSSL();
if (!handshakeFinished) {
pendingApp = 0;
}
int bytesProduced = 0;
int idx = offset;
// Do we have enough room in dsts to write decrypted data?
if (capacity < pendingApp) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), written, 0);
}
while (pendingApp > 0) {
// Write decrypted data to dsts buffers
while (idx < endOffset) {
ByteBuffer dst = dsts[idx];
if (!dst.hasRemaining()) {
idx++;
continue;
}
if (pendingApp <= 0) {
break;
}
int bytesRead;
try {
bytesRead = readPlaintextData(dst);
} catch (Exception e) {
throw new SSLException(e);
}
if (bytesRead == 0) {
break;
}
bytesProduced += bytesRead;
pendingApp -= bytesRead;
capacity -= bytesRead;
if (!dst.hasRemaining()) {
idx++;
}
}
if (capacity == 0) {
break;
} else if (pendingApp == 0) {
pendingApp = pendingReadableBytesInSSL();
}
}
// Check to see if we received a close_notify message from the peer
if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
receivedShutdown = true;
closeOutbound();
closeInbound();
}
if (bytesProduced == 0 && written == 0) {
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
} else {
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(), written, bytesProduced);
}
}
use of java.nio.ReadOnlyBufferException in project netty by netty.
the class ReferenceCountedOpenSslEngine method wrap.
@Override
public final SSLEngineResult wrap(final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
// Throw required runtime exceptions
if (srcs == null) {
throw new IllegalArgumentException("srcs is null");
}
if (dst == null) {
throw new IllegalArgumentException("dst is null");
}
if (offset >= srcs.length || offset + length > srcs.length) {
throw new IndexOutOfBoundsException("offset: " + offset + ", length: " + length + " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
synchronized (this) {
if (isOutboundDone()) {
// All drained in the outbound buffer
return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
}
int bytesProduced = 0;
ByteBuf bioReadCopyBuf = null;
try {
// Setup the BIO buffer so that we directly write the encryption results into dst.
if (dst.isDirect()) {
SSL.bioSetByteBuffer(networkBIO, Buffer.address(dst) + dst.position(), dst.remaining(), true);
} else {
bioReadCopyBuf = alloc.directBuffer(dst.remaining());
SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(), true);
}
int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
// Explicit use outboundClosed as we want to drain any bytes that are still present.
if (outboundClosed) {
// There is something left to drain.
// See https://github.com/netty/netty/issues/6260
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
if (bytesProduced <= 0) {
return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
}
// OpenSSL can give us.
if (!doSSLShutdown()) {
return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
}
bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
}
// Flush any data that may be implicitly generated by OpenSSL (handshake, close, etc..).
SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
// Prepare OpenSSL to work in server mode and receive handshake
if (handshakeState != HandshakeState.FINISHED) {
if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
// Update accepted so we know we triggered the handshake via wrap
handshakeState = HandshakeState.STARTED_IMPLICITLY;
}
// Flush any data that may have been written implicitly during the handshake by OpenSSL.
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
if (bytesProduced > 0 && handshakeException != null) {
// we allow handshake() to throw the handshake exception.
return newResult(NEED_WRAP, 0, bytesProduced);
}
status = handshake();
if (renegotiationPending && status == FINISHED) {
// If renegotiationPending is true that means when we attempted to start renegotiation
// the BIO buffer didn't have enough space to hold the HelloRequest which prompts the
// client to initiate a renegotiation. At this point the HelloRequest has been written
// so we can actually start the handshake process.
renegotiationPending = false;
SSL.setState(ssl, SSL.SSL_ST_ACCEPT);
handshakeState = HandshakeState.STARTED_EXPLICITLY;
status = handshake();
}
// Handshake may have generated more data, for example if the internal SSL buffer is small
// we may have freed up space by flushing above.
bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
if (bytesProduced > 0) {
// It's important we call this before wrapStatus() as wrapStatus() may shutdown the engine.
return newResult(mayFinishHandshake(status != FINISHED ? getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED), 0, bytesProduced);
}
if (status == NEED_UNWRAP) {
// Signal if the outbound is done or not.
return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
}
// still present.
if (outboundClosed) {
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
return newResultMayFinishHandshake(status, 0, bytesProduced);
}
}
int srcsLen = 0;
final int endOffset = offset + length;
for (int i = offset; i < endOffset; ++i) {
final ByteBuffer src = srcs[i];
if (src == null) {
throw new IllegalArgumentException("srcs[" + i + "] is null");
}
if (srcsLen == MAX_PLAINTEXT_LENGTH) {
continue;
}
srcsLen += src.remaining();
if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
// If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH.
// This also help us to guard against overflow.
// We not break out here as we still need to check for null entries in srcs[].
srcsLen = MAX_PLAINTEXT_LENGTH;
}
}
if (dst.remaining() < calculateOutNetBufSize(srcsLen, endOffset - offset)) {
// buffer.
return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
}
// There was no pending data in the network BIO -- encrypt any application data
int bytesConsumed = 0;
// Flush any data that may have been written implicitly by OpenSSL in case a shutdown/alert occurs.
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
for (; offset < endOffset; ++offset) {
final ByteBuffer src = srcs[offset];
final int remaining = src.remaining();
if (remaining == 0) {
continue;
}
// Write plaintext application data to the SSL engine
int bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
if (bytesWritten > 0) {
bytesConsumed += bytesWritten;
// Determine how much encrypted data was generated:
final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
bytesProduced += bioLengthBefore - pendingNow;
bioLengthBefore = pendingNow;
if (bytesConsumed == MAX_PLAINTEXT_LENGTH || bytesProduced == dst.remaining()) {
return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
}
} else {
int sslError = SSL.getError(ssl, bytesWritten);
if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
// This means the connection was shutdown correctly, close inbound and outbound
if (!receivedShutdown) {
closeAll();
bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(status != FINISHED ? getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED);
return newResult(hs, bytesConsumed, bytesProduced);
}
return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
} else if (sslError == SSL.SSL_ERROR_WANT_READ) {
// been closed. [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
} else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
// [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
return newResult(NEED_WRAP, bytesConsumed, bytesProduced);
} else {
// Everything else is considered as error
throw shutdownWithError("SSL_write");
}
}
}
return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
} finally {
SSL.bioClearByteBuffer(networkBIO);
if (bioReadCopyBuf == null) {
dst.position(dst.position() + bytesProduced);
} else {
assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst + " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
bioReadCopyBuf.release();
}
}
}
}
use of java.nio.ReadOnlyBufferException in project netty by netty.
the class ReferenceCountedOpenSslEngine method unwrap.
public final SSLEngineResult unwrap(final ByteBuffer[] srcs, int srcsOffset, final int srcsLength, final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
// Throw required runtime exceptions
if (srcs == null) {
throw new NullPointerException("srcs");
}
if (srcsOffset >= srcs.length || srcsOffset + srcsLength > srcs.length) {
throw new IndexOutOfBoundsException("offset: " + srcsOffset + ", length: " + srcsLength + " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
}
if (dsts == null) {
throw new IllegalArgumentException("dsts is null");
}
if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
throw new IndexOutOfBoundsException("offset: " + dstsOffset + ", length: " + dstsLength + " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
}
long capacity = 0;
final int dstsEndOffset = dstsOffset + dstsLength;
for (int i = dstsOffset; i < dstsEndOffset; i++) {
ByteBuffer dst = dsts[i];
if (dst == null) {
throw new IllegalArgumentException("dsts[" + i + "] is null");
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
capacity += dst.remaining();
}
final int srcsEndOffset = srcsOffset + srcsLength;
long len = 0;
for (int i = srcsOffset; i < srcsEndOffset; i++) {
ByteBuffer src = srcs[i];
if (src == null) {
throw new IllegalArgumentException("srcs[" + i + "] is null");
}
len += src.remaining();
}
synchronized (this) {
if (isInboundDone()) {
return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
}
SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
// Prepare OpenSSL to work in server mode and receive handshake
if (handshakeState != HandshakeState.FINISHED) {
if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
// Update accepted so we know we triggered the handshake via wrap
handshakeState = HandshakeState.STARTED_IMPLICITLY;
}
status = handshake();
if (status == NEED_WRAP) {
return NEED_WRAP_OK;
}
// Check if the inbound is considered to be closed if so let us try to wrap again.
if (isInboundDone) {
return NEED_WRAP_CLOSED;
}
}
if (len < SSL_RECORD_HEADER_LENGTH) {
return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
}
int packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
if (packetLength == SslUtils.NOT_ENCRYPTED) {
throw new NotSslRecordException("not an SSL/TLS record");
}
if (packetLength - SSL_RECORD_HEADER_LENGTH > capacity) {
// that the buffer needs to be increased.
return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
}
if (len < packetLength) {
// the whole packet.
return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
}
// This must always be the case when we reached here as if not we returned BUFFER_UNDERFLOW.
assert srcsOffset < srcsEndOffset;
// This must always be the case if we reached here.
assert capacity > 0;
// Number of produced bytes
int bytesProduced = 0;
int bytesConsumed = 0;
try {
for (; srcsOffset < srcsEndOffset; ++srcsOffset) {
ByteBuffer src = srcs[srcsOffset];
int remaining = src.remaining();
if (remaining == 0) {
// with length 0.
continue;
}
// Write more encrypted data into the BIO. Ensure we only read one packet at a time as
// stated in the SSLEngine javadocs.
int pendingEncryptedBytes = min(packetLength, remaining);
ByteBuf bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
try {
readLoop: for (; dstsOffset < dstsEndOffset; ++dstsOffset) {
ByteBuffer dst = dsts[dstsOffset];
if (!dst.hasRemaining()) {
// No space left in the destination buffer, skip it.
continue;
}
int bytesRead = readPlaintextData(dst);
// We are directly using the ByteBuffer memory for the write, and so we only know what
// has been consumed after we let SSL decrypt the data. At this point we should update
// the number of bytes consumed, update the ByteBuffer position, and release temp
// ByteBuf.
int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
bytesConsumed += localBytesConsumed;
packetLength -= localBytesConsumed;
pendingEncryptedBytes -= localBytesConsumed;
src.position(src.position() + localBytesConsumed);
if (bytesRead > 0) {
bytesProduced += bytesRead;
if (!dst.hasRemaining()) {
// Move to the next dst buffer as this one is full.
continue;
}
if (packetLength == 0) {
// We read everything return now.
return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
}
// try to write again to the BIO. stop reading from it by break out of the readLoop.
break;
} else {
int sslError = SSL.getError(ssl, bytesRead);
if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
// write more to the BIO.
break readLoop;
} else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
// This means the connection was shutdown correctly, close inbound and outbound
if (!receivedShutdown) {
closeAll();
}
return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
} else {
return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed, bytesProduced);
}
}
}
// Either we have no more dst buffers to put the data, or no more data to generate; we are done.
if (dstsOffset >= dstsEndOffset || packetLength == 0) {
break;
}
} finally {
if (bioWriteCopyBuf != null) {
bioWriteCopyBuf.release();
}
}
}
} finally {
SSL.bioClearByteBuffer(networkBIO);
rejectRemoteInitiatedRenegation();
}
// Check to see if we received a close_notify message from the peer.
if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
closeAll();
}
return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
}
}
use of java.nio.ReadOnlyBufferException in project robovm by robovm.
the class CipherTest method test_updateLjava_nio_ByteBufferLjava_nio_ByteBuffer.
public void test_updateLjava_nio_ByteBufferLjava_nio_ByteBuffer() throws Exception {
byte[] b = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
ByteBuffer bInput = ByteBuffer.allocate(256);
ByteBuffer bOutput = ByteBuffer.allocate(256);
Cipher c = Cipher.getInstance("DES/CBC/NoPadding");
c.init(Cipher.ENCRYPT_MODE, CIPHER_KEY_DES);
bInput.put(b, 0, 10);
bInput.rewind();
bOutput.rewind();
c.update(bInput, bOutput);
c = Cipher.getInstance("DES/CBC/NoPadding");
try {
c.update(bInput, bOutput);
fail();
} catch (IllegalStateException expected) {
}
c = Cipher.getInstance("DES/CBC/NoPadding");
c.init(Cipher.ENCRYPT_MODE, CIPHER_KEY_DES);
bInput = ByteBuffer.allocate(16);
bInput.put(b, 0, 16);
bInput.rewind();
bOutput.rewind();
c.update(bInput, bOutput);
AlgorithmParameterSpec ap = new IvParameterSpec(IV);
c = Cipher.getInstance("DES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, CIPHER_KEY_DES, ap);
bInput = ByteBuffer.allocate(64);
c = Cipher.getInstance("DES/CBC/NoPadding");
c.init(Cipher.ENCRYPT_MODE, CIPHER_KEY_DES);
bInput.put(b, 0, 16);
bInput.rewind();
try {
c.update(bInput, bInput);
fail();
} catch (IllegalArgumentException expected) {
}
c = Cipher.getInstance("DES/CBC/NoPadding");
c.init(Cipher.ENCRYPT_MODE, CIPHER_KEY_DES);
bInput.put(b, 0, 16);
bInput.rewind();
bOutput.rewind();
try {
c.update(bInput, bOutput.asReadOnlyBuffer());
fail();
} catch (ReadOnlyBufferException expected) {
}
bInput.rewind();
bInput.put(b, 0, 16);
bInput.rewind();
bOutput = ByteBuffer.allocate(8);
c = Cipher.getInstance("DESede");
c.init(Cipher.ENCRYPT_MODE, CIPHER_KEY_3DES);
try {
c.update(bInput, bOutput);
fail();
} catch (ShortBufferException expected) {
}
}
use of java.nio.ReadOnlyBufferException in project robovm by robovm.
the class ReadOnlyBufferExceptionTest method test_Constructor.
/**
*@tests {@link java.nio.ReadOnlyBufferException#ReadOnlyBufferException()}
*/
public void test_Constructor() {
ReadOnlyBufferException exception = new ReadOnlyBufferException();
assertNull(exception.getMessage());
assertNull(exception.getLocalizedMessage());
assertNull(exception.getCause());
}
Aggregations