Merge pull request #108 from cconlon/spring
Fixes and Cleanup to SSLEngine Implementationpull/114/head
commit
fd002c1a2b
|
@ -65,6 +65,8 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
private byte[] toRead; /* encrypted packet coming in */
|
private byte[] toRead; /* encrypted packet coming in */
|
||||||
private int toReadSz = 0;
|
private int toReadSz = 0;
|
||||||
private HandshakeStatus hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
|
private HandshakeStatus hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
|
||||||
|
|
||||||
|
/* Does TLS handshake need initialization */
|
||||||
private boolean needInit = true;
|
private boolean needInit = true;
|
||||||
|
|
||||||
private boolean inBoundOpen = true;
|
private boolean inBoundOpen = true;
|
||||||
|
@ -83,8 +85,11 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
/* client/server mode has been set */
|
/* client/server mode has been set */
|
||||||
private boolean clientModeSet = false;
|
private boolean clientModeSet = false;
|
||||||
|
|
||||||
static private SendCB sendCb = null;
|
private SendCB sendCb = null;
|
||||||
static private RecvCB recvCb = null;
|
private RecvCB recvCb = null;
|
||||||
|
|
||||||
|
/* Locks for synchronization */
|
||||||
|
private static final Object ioLock = new Object();
|
||||||
|
|
||||||
/** Turn on extra/verbose SSLEngine debug logging */
|
/** Turn on extra/verbose SSLEngine debug logging */
|
||||||
public boolean extraDebugEnabled = false;
|
public boolean extraDebugEnabled = false;
|
||||||
|
@ -219,10 +224,12 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
* Helper function, updates internal close_notify alert status
|
* Helper function, updates internal close_notify alert status
|
||||||
* and inBound/outBoundOpen.
|
* and inBound/outBoundOpen.
|
||||||
*/
|
*/
|
||||||
private void UpdateCloseNotifyStatus() {
|
private synchronized void UpdateCloseNotifyStatus() {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
synchronized (ioLock) {
|
||||||
ret = ssl.getShutdown();
|
ret = ssl.getShutdown();
|
||||||
|
}
|
||||||
if (ret == (WolfSSL.SSL_RECEIVED_SHUTDOWN |
|
if (ret == (WolfSSL.SSL_RECEIVED_SHUTDOWN |
|
||||||
WolfSSL.SSL_SENT_SHUTDOWN)) {
|
WolfSSL.SSL_SENT_SHUTDOWN)) {
|
||||||
this.closeNotifySent = true;
|
this.closeNotifySent = true;
|
||||||
|
@ -242,7 +249,7 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
/**
|
/**
|
||||||
* Handles logic during shutdown
|
* Handles logic during shutdown
|
||||||
*/
|
*/
|
||||||
private int ClosingConnection() {
|
private synchronized int ClosingConnection() {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (this.getUseClientMode() == true) {
|
if (this.getUseClientMode() == true) {
|
||||||
|
@ -257,7 +264,9 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send/recv close_notify as needed */
|
/* send/recv close_notify as needed */
|
||||||
|
synchronized (ioLock) {
|
||||||
ret = ssl.shutdownSSL();
|
ret = ssl.shutdownSSL();
|
||||||
|
}
|
||||||
UpdateCloseNotifyStatus();
|
UpdateCloseNotifyStatus();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -267,20 +276,24 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
* Starts or continues SSL/TLS handshake.
|
* Starts or continues SSL/TLS handshake.
|
||||||
* Returns WolfSSL.SSL_SUCCESS or WolfSSL.SSL_FAILURE
|
* Returns WolfSSL.SSL_SUCCESS or WolfSSL.SSL_FAILURE
|
||||||
*/
|
*/
|
||||||
private int DoHandshake() throws SSLException {
|
private synchronized int DoHandshake() throws SSLException {
|
||||||
int ret = WolfSSL.SSL_SUCCESS;
|
int ret = WolfSSL.SSL_SUCCESS;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.getUseClientMode() == true) {
|
if (this.getUseClientMode() == true) {
|
||||||
|
synchronized (ioLock) {
|
||||||
ret = this.ssl.connect();
|
ret = this.ssl.connect();
|
||||||
|
}
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"ssl.connect() ret:err = " + ret + " : " +
|
"ssl.connect() ret:err = " + ret + " : " +
|
||||||
ssl.getError(ret));
|
ssl.getError(ret));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
synchronized (ioLock) {
|
||||||
ret = this.ssl.accept();
|
ret = this.ssl.accept();
|
||||||
|
}
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"ssl.connect() ret:err = " + ret + " : " +
|
"ssl.accept() ret:err = " + ret + " : " +
|
||||||
ssl.getError(ret));
|
ssl.getError(ret));
|
||||||
}
|
}
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
|
@ -297,7 +310,7 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
* (SSLSession.getApplicationBufferSize()).
|
* (SSLSession.getApplicationBufferSize()).
|
||||||
*
|
*
|
||||||
* Return bytes sent on success, negative on error */
|
* Return bytes sent on success, negative on error */
|
||||||
private int SendAppData(ByteBuffer[] in, int ofst, int len,
|
private synchronized int SendAppData(ByteBuffer[] in, int ofst, int len,
|
||||||
ByteBuffer out) throws SSLException {
|
ByteBuffer out) throws SSLException {
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -345,7 +358,9 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"calling ssl.write() with size: " + sendSz);
|
"calling ssl.write() with size: " + sendSz);
|
||||||
|
|
||||||
|
synchronized (ioLock) {
|
||||||
ret = this.ssl.write(dataArr, sendSz);
|
ret = this.ssl.write(dataArr, sendSz);
|
||||||
|
}
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
/* error, reset in[] positions for next call */
|
/* error, reset in[] positions for next call */
|
||||||
for (i = ofst; i < ofst + len; i++) {
|
for (i = ofst; i < ofst + len; i++) {
|
||||||
|
@ -425,6 +440,8 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
"outBoundOpen: " + this.outBoundOpen);
|
"outBoundOpen: " + this.outBoundOpen);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"status: " + status);
|
"status: " + status);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"handshakeStatus: " + hs);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"handshakeFinished: " + this.handshakeFinished);
|
"handshakeFinished: " + this.handshakeFinished);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
@ -509,10 +526,14 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
"inBoundOpen: " + this.outBoundOpen);
|
"inBoundOpen: " + this.outBoundOpen);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"outBoundOpen: " + this.outBoundOpen);
|
"outBoundOpen: " + this.outBoundOpen);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"handshakeStatus: " + hs);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"status: " + status);
|
"status: " + status);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"handshakeStatus: " + hs);
|
"consumed: " + consumed);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"produced: " + produced);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"===========================================================");
|
"===========================================================");
|
||||||
}
|
}
|
||||||
|
@ -520,6 +541,32 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
return new SSLEngineResult(status, hs, consumed, produced);
|
return new SSLEngineResult(status, hs, consumed, produced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return total remaining space in array of ByteBuffers.
|
||||||
|
*
|
||||||
|
* @param out array of ByteBuffers to be polled for available space
|
||||||
|
* @param ofst offset into out array to begin
|
||||||
|
* @param length length of ByteBuffer array
|
||||||
|
*
|
||||||
|
* @return number of available/remaining bytes in array of ByteBuffers
|
||||||
|
* @throws IllegalArgumentException if readonly buffer found
|
||||||
|
*/
|
||||||
|
private static synchronized int getTotalOutputSize(ByteBuffer[] out,
|
||||||
|
int ofst, int length) {
|
||||||
|
int i = 0;
|
||||||
|
int maxOutSz = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
if (out[i + ofst] == null || out[i + ofst].isReadOnly()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"null or readonly out buffer found");
|
||||||
|
}
|
||||||
|
maxOutSz += out[i + ofst].remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxOutSz;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receive application data using ssl.read() from in buffer, placing
|
* Receive application data using ssl.read() from in buffer, placing
|
||||||
* processed/decrypted data into out[].
|
* processed/decrypted data into out[].
|
||||||
|
@ -528,25 +575,30 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
* @param out output ByteBuffer arrays, to hold processed/decoded plaintext
|
* @param out output ByteBuffer arrays, to hold processed/decoded plaintext
|
||||||
* @param ofst offset into out[] array to begin writing data
|
* @param ofst offset into out[] array to begin writing data
|
||||||
* @param length length of out[] array
|
* @param length length of out[] array
|
||||||
* @param maxOutSz maximum size of all output buffers in out[]
|
|
||||||
*
|
*
|
||||||
* @return number of plaintext bytes received, or negative on error.
|
* @return number of plaintext bytes received, or negative on error.
|
||||||
*/
|
*/
|
||||||
private int RecvAppData(ByteBuffer in, ByteBuffer[] out, int ofst,
|
private synchronized int RecvAppData(ByteBuffer in, ByteBuffer[] out,
|
||||||
int length, int maxOutSz) throws SSLException {
|
int ofst, int length) throws SSLException {
|
||||||
|
|
||||||
int i, sz, bufSpace;
|
int i, sz, bufSpace;
|
||||||
int totalRead = 0;
|
int totalRead = 0;
|
||||||
|
int maxOutSz = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int idx = 0; /* index into out[] array */
|
int idx = 0; /* index into out[] array */
|
||||||
byte[] tmp;
|
byte[] tmp;
|
||||||
|
|
||||||
|
/* pre-calculate max output size */
|
||||||
|
maxOutSz = getTotalOutputSize(out, ofst, length);
|
||||||
|
|
||||||
/* read all data we have cached, if it fits in output buffers */
|
/* read all data we have cached, if it fits in output buffers */
|
||||||
while ((this.toReadSz > 0) && (totalRead < maxOutSz)) {
|
while ((this.toReadSz > 0) && (totalRead < maxOutSz)) {
|
||||||
|
|
||||||
tmp = new byte[maxOutSz];
|
tmp = new byte[maxOutSz - totalRead];
|
||||||
|
|
||||||
ret = this.ssl.read(tmp, maxOutSz);
|
synchronized (ioLock) {
|
||||||
|
ret = this.ssl.read(tmp, (maxOutSz - totalRead));
|
||||||
|
}
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int err = ssl.getError(ret);
|
int err = ssl.getError(ret);
|
||||||
|
|
||||||
|
@ -556,11 +608,17 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
break;
|
break;
|
||||||
case WolfSSL.SSL_ERROR_ZERO_RETURN:
|
case WolfSSL.SSL_ERROR_ZERO_RETURN:
|
||||||
/* check if is shutdown message */
|
/* check if is shutdown message */
|
||||||
|
synchronized (ioLock) {
|
||||||
if (ssl.getShutdown() ==
|
if (ssl.getShutdown() ==
|
||||||
WolfSSL.SSL_RECEIVED_SHUTDOWN) {
|
WolfSSL.SSL_RECEIVED_SHUTDOWN) {
|
||||||
ret = ClosingConnection();
|
ret = ClosingConnection();
|
||||||
|
if (ret > 0) {
|
||||||
|
/* Returns number of bytes read, 0, or err */
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new SSLException("wolfSSL_read() error: " +
|
throw new SSLException("wolfSSL_read() error: " +
|
||||||
|
@ -570,16 +628,24 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
else {
|
else {
|
||||||
/* write processed data into output buffers */
|
/* write processed data into output buffers */
|
||||||
for (i = 0; i < ret;) {
|
for (i = 0; i < ret;) {
|
||||||
if (idx + ofst >= length) { /* no more buffers left */
|
if (idx + ofst >= length) {
|
||||||
|
/* no more output buffers left */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufSpace = out[idx + ofst].remaining();
|
bufSpace = out[idx + ofst].remaining();
|
||||||
sz = (bufSpace >= ret) ? ret : bufSpace;
|
if (bufSpace == 0) {
|
||||||
|
/* no more space in current out buffer, advance */
|
||||||
|
idx++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = (bufSpace >= (ret - i)) ? (ret - i) : bufSpace;
|
||||||
out[idx + ofst].put(tmp, i, sz);
|
out[idx + ofst].put(tmp, i, sz);
|
||||||
i += sz;
|
i += sz;
|
||||||
totalRead += sz;
|
totalRead += sz;
|
||||||
|
|
||||||
if (bufSpace < ret) {
|
if ((ret - i) > 0) {
|
||||||
idx++; /* go to next output buffer */
|
idx++; /* go to next output buffer */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,7 +664,7 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
@Override
|
@Override
|
||||||
public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out,
|
public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out,
|
||||||
int ofst, int length) throws SSLException {
|
int ofst, int length) throws SSLException {
|
||||||
int i, ret = 0, sz = 0, idx = 0, maxOutSz = 0, pos;
|
int i, ret = 0, sz = 0, idx = 0, pos;
|
||||||
int consumed = 0;
|
int consumed = 0;
|
||||||
int produced = 0;
|
int produced = 0;
|
||||||
byte[] tmp;
|
byte[] tmp;
|
||||||
|
@ -616,15 +682,6 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
"setUseClientMode() has not been called on this SSLEngine");
|
"setUseClientMode() has not been called on this SSLEngine");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
if (out[i + ofst] == null || out[i + ofst].isReadOnly()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"null or readonly out buffer found");
|
|
||||||
}
|
|
||||||
/* pre-calculate max output size, used in RecvAppData */
|
|
||||||
maxOutSz += out[i + ofst].remaining();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extraDebugEnabled == true) {
|
if (extraDebugEnabled == true) {
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"==== [ entering unwrap() ] =================================");
|
"==== [ entering unwrap() ] =================================");
|
||||||
|
@ -665,6 +722,8 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
"outBoundOpen: " + this.outBoundOpen);
|
"outBoundOpen: " + this.outBoundOpen);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"handshakeFinished: " + this.handshakeFinished);
|
"handshakeFinished: " + this.handshakeFinished);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"handshakeStatus: " + hs);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"status: " + status);
|
"status: " + status);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
@ -704,9 +763,16 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
else {
|
else {
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"receiving application data");
|
"receiving application data");
|
||||||
ret = RecvAppData(in, out, ofst, length, maxOutSz);
|
ret = RecvAppData(in, out, ofst, length);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
consumed += ret;
|
produced += ret;
|
||||||
|
|
||||||
|
if (this.toReadSz > 0 &&
|
||||||
|
getTotalOutputSize(out, ofst, length) == 0) {
|
||||||
|
/* We have more data buffered to read, but no more
|
||||||
|
* output space left in ByteBuffer[], ask for more */
|
||||||
|
status = SSLEngineResult.Status.BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,6 +787,13 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
throw new SSLException(
|
throw new SSLException(
|
||||||
"wolfSSL error, ret:err = " + ret + " : " + err);
|
"wolfSSL error, ret:err = " + ret + " : " + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret < 0 && err == WolfSSL.SSL_ERROR_WANT_READ &&
|
||||||
|
this.toReadSz == 0 && (this.toSend == null ||
|
||||||
|
(this.toSend != null && this.toSend.length == 0))) {
|
||||||
|
/* Need more data */
|
||||||
|
status = SSLEngineResult.Status.BUFFER_UNDERFLOW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHandshakeStatus(ret);
|
SetHandshakeStatus(ret);
|
||||||
|
@ -769,6 +842,10 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
"handshakeStatus: " + hs);
|
"handshakeStatus: " + hs);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"status: " + status);
|
"status: " + status);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"consumed: " + consumed);
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"produced: " + produced);
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"===========================================================");
|
"===========================================================");
|
||||||
}
|
}
|
||||||
|
@ -779,7 +856,7 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
/**
|
/**
|
||||||
* Sets handshake status after I/O operation of unwrap(), helper function.
|
* Sets handshake status after I/O operation of unwrap(), helper function.
|
||||||
*/
|
*/
|
||||||
private void SetHandshakeStatus(int ret) {
|
private synchronized void SetHandshakeStatus(int ret) {
|
||||||
|
|
||||||
int err = ssl.getError(ret);
|
int err = ssl.getError(ret);
|
||||||
|
|
||||||
|
@ -804,8 +881,8 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ssl.handshakeDone() && this.toSend == null &&
|
synchronized (ioLock) {
|
||||||
this.toReadSz == 0) {
|
if (ssl.handshakeDone() && this.toSend == null) {
|
||||||
this.handshakeFinished = true;
|
this.handshakeFinished = true;
|
||||||
hs = SSLEngineResult.HandshakeStatus.FINISHED;
|
hs = SSLEngineResult.HandshakeStatus.FINISHED;
|
||||||
|
|
||||||
|
@ -826,34 +903,40 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
else if (this.toReadSz > 0) {
|
else if (this.toReadSz > 0) {
|
||||||
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
|
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
|
||||||
}
|
}
|
||||||
else if (ret < 0 && err == WolfSSL.SSL_ERROR_WANT_READ) {
|
else if (err == WolfSSL.SSL_ERROR_WANT_READ) {
|
||||||
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
|
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
|
||||||
}
|
}
|
||||||
else if (ret < 0 && err == WolfSSL.SSL_ERROR_WANT_WRITE) {
|
else if (err == WolfSSL.SSL_ERROR_WANT_WRITE) {
|
||||||
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
|
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
|
hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Runnable getDelegatedTask() {
|
public Runnable getDelegatedTask() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getDelegatedTask()");
|
||||||
/* no tasks left to run */
|
/* no tasks left to run */
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void closeInbound() throws SSLException {
|
public synchronized void closeInbound() throws SSLException {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered closeInbound");
|
||||||
|
|
||||||
if (!inBoundOpen)
|
if (!inBoundOpen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (inBoundOpen && !closed) {
|
if (inBoundOpen && !closed) {
|
||||||
/* this checks that peer sent back shutdown message */
|
/* this checks that peer sent back shutdown message */
|
||||||
throw new SSLException("Closing in bound before shutdonw is done");
|
throw new SSLException("Closing in bound before shutdown is done");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -863,111 +946,172 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isInboundDone() {
|
public synchronized boolean isInboundDone() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered isInboundDone()");
|
||||||
return !inBoundOpen;
|
return !inBoundOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void closeOutbound() {
|
public synchronized void closeOutbound() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered closeOutbound, outBoundOpen = false");
|
||||||
outBoundOpen = false;
|
outBoundOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isOutboundDone() {
|
public synchronized boolean isOutboundDone() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered isOutboundDone()");
|
||||||
return !outBoundOpen;
|
return !outBoundOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedCipherSuites() {
|
public String[] getSupportedCipherSuites() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getSupportedCipherSuites()");
|
||||||
return EngineHelper.getAllCiphers();
|
return EngineHelper.getAllCiphers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getEnabledCipherSuites() {
|
public String[] getEnabledCipherSuites() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getEnabledCipherSuites()");
|
||||||
return EngineHelper.getCiphers();
|
return EngineHelper.getCiphers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnabledCipherSuites(String[] suites) {
|
public void setEnabledCipherSuites(String[] suites) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setEnabledCipherSuites()");
|
||||||
EngineHelper.setCiphers(suites);
|
EngineHelper.setCiphers(suites);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedProtocols() {
|
public String[] getSupportedProtocols() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getSupportedProtocols()");
|
||||||
return EngineHelper.getAllProtocols();
|
return EngineHelper.getAllProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getEnabledProtocols() {
|
public String[] getEnabledProtocols() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getEnabledProtocols()");
|
||||||
return EngineHelper.getProtocols();
|
return EngineHelper.getProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnabledProtocols(String[] protocols) {
|
public synchronized void setEnabledProtocols(String[] protocols) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setEnabledProtocols()");
|
||||||
EngineHelper.setProtocols(protocols);
|
EngineHelper.setProtocols(protocols);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized SSLSession getSession() {
|
public synchronized SSLSession getSession() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getSession()");
|
||||||
|
return EngineHelper.getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized SSLSession getHandshakeSession() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getHandshakeSession()");
|
||||||
return EngineHelper.getSession();
|
return EngineHelper.getSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void beginHandshake() throws SSLException {
|
public synchronized void beginHandshake() throws SSLException {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered beginHandshake()");
|
||||||
|
|
||||||
|
if (needInit == true) {
|
||||||
|
/* will throw SSLHandshakeException if session creation is
|
||||||
|
not allowed */
|
||||||
EngineHelper.initHandshake();
|
EngineHelper.initHandshake();
|
||||||
|
needInit = false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
EngineHelper.doHandshake(1, 0);
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"calling EngineHelper.doHandshake()");
|
||||||
|
int ret = EngineHelper.doHandshake(1, 0);
|
||||||
|
SetHandshakeStatus(ret);
|
||||||
|
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
throw new SSLException(e);
|
throw new SSLException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
|
public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getHandshakeStatus(): " + hs);
|
||||||
return hs;
|
return hs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUseClientMode(boolean mode) {
|
public synchronized void setUseClientMode(boolean mode) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setUseClientMode()");
|
||||||
EngineHelper.setUseClientMode(mode);
|
EngineHelper.setUseClientMode(mode);
|
||||||
this.clientModeSet = true;
|
this.clientModeSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getUseClientMode() {
|
public boolean getUseClientMode() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getUseClientMode()");
|
||||||
return EngineHelper.getUseClientMode();
|
return EngineHelper.getUseClientMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNeedClientAuth(boolean need) {
|
public synchronized void setNeedClientAuth(boolean need) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setNeedClientAuth()");
|
||||||
EngineHelper.setNeedClientAuth(need);
|
EngineHelper.setNeedClientAuth(need);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getNeedClientAuth() {
|
public boolean getNeedClientAuth() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getNeedClientAuth()");
|
||||||
return EngineHelper.getNeedClientAuth();
|
return EngineHelper.getNeedClientAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWantClientAuth(boolean want) {
|
public synchronized void setWantClientAuth(boolean want) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setWantClientAuth()");
|
||||||
EngineHelper.setWantClientAuth(want);
|
EngineHelper.setWantClientAuth(want);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getWantClientAuth() {
|
public boolean getWantClientAuth() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getWantClientAuth()");
|
||||||
return EngineHelper.getWantClientAuth();
|
return EngineHelper.getWantClientAuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnableSessionCreation(boolean flag) {
|
public synchronized void setEnableSessionCreation(boolean flag) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setEnableSessionCreation()");
|
||||||
EngineHelper.setEnableSessionCreation(flag);
|
EngineHelper.setEnableSessionCreation(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getEnableSessionCreation() {
|
public boolean getEnableSessionCreation() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getEnableSessionCreation()");
|
||||||
return EngineHelper.getEnableSessionCreation();
|
return EngineHelper.getEnableSessionCreation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getApplicationProtocol() {
|
public synchronized String getApplicationProtocol() {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered getApplicationProtocol()");
|
||||||
return EngineHelper.getAlpnSelectedProtocolString();
|
return EngineHelper.getAlpnSelectedProtocolString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,6 +1121,8 @@ public class WolfSSLEngine extends SSLEngine {
|
||||||
* @param params SSLParameters to set for this SSLSocket object
|
* @param params SSLParameters to set for this SSLSocket object
|
||||||
*/
|
*/
|
||||||
public synchronized void setSSLParameters(SSLParameters params) {
|
public synchronized void setSSLParameters(SSLParameters params) {
|
||||||
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
|
"entered setSSLParameters()");
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
WolfSSLParametersHelper.importParams(params, this.params);
|
WolfSSLParametersHelper.importParams(params, this.params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -883,5 +883,115 @@ public class WolfSSLEngineTest {
|
||||||
}
|
}
|
||||||
pass("\t... passed");
|
pass("\t... passed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSSLEngineSplitInput() throws Exception {
|
||||||
|
|
||||||
|
int appBufMax, netBufMax;
|
||||||
|
int done = 0;
|
||||||
|
ByteBuffer cIn;
|
||||||
|
ByteBuffer cOut1;
|
||||||
|
ByteBuffer cOut2;
|
||||||
|
ByteBuffer[] cOutBuffs = new ByteBuffer[2];
|
||||||
|
ByteBuffer[] sOutBuffs = new ByteBuffer[2];
|
||||||
|
ByteBuffer sIn;
|
||||||
|
ByteBuffer sOut1;
|
||||||
|
ByteBuffer sOut2;
|
||||||
|
ByteBuffer clientToServer;
|
||||||
|
ByteBuffer serverToClient;
|
||||||
|
|
||||||
|
byte[] input1Buf = "Hello client, ".getBytes();
|
||||||
|
byte[] input2Buf = "from server".getBytes();
|
||||||
|
|
||||||
|
SSLEngineResult cResult;
|
||||||
|
SSLEngineResult sResult;
|
||||||
|
|
||||||
|
System.out.print("\tTesting split input data");
|
||||||
|
|
||||||
|
try {
|
||||||
|
/* create SSLContext */
|
||||||
|
this.ctx = tf.createSSLContext("TLS", engineProvider);
|
||||||
|
|
||||||
|
/* create server SSLEngine */
|
||||||
|
SSLEngine server = this.ctx.createSSLEngine();
|
||||||
|
server.setUseClientMode(false);
|
||||||
|
server.setNeedClientAuth(true);
|
||||||
|
|
||||||
|
/* create client SSLEngine */
|
||||||
|
SSLEngine client = this.ctx.createSSLEngine(
|
||||||
|
"wolfSSL client test", 11111);
|
||||||
|
client.setUseClientMode(true);
|
||||||
|
|
||||||
|
SSLSession session = client.getSession();
|
||||||
|
appBufMax = session.getApplicationBufferSize();
|
||||||
|
netBufMax = session.getPacketBufferSize();
|
||||||
|
|
||||||
|
cIn = ByteBuffer.allocate(appBufMax);
|
||||||
|
sIn = ByteBuffer.allocate(netBufMax);
|
||||||
|
clientToServer = ByteBuffer.allocate(netBufMax);
|
||||||
|
serverToClient = ByteBuffer.allocate(netBufMax);
|
||||||
|
|
||||||
|
/* Input data split across 2 ByteBuffers on both cli and svr */
|
||||||
|
cOut1 = ByteBuffer.wrap("Hello server, ".getBytes());
|
||||||
|
cOut2 = ByteBuffer.wrap("from client".getBytes());
|
||||||
|
cOutBuffs[0] = cOut1;
|
||||||
|
cOutBuffs[1] = cOut2;
|
||||||
|
|
||||||
|
sOut1 = ByteBuffer.wrap("Hello client, ".getBytes());
|
||||||
|
sOut2 = ByteBuffer.wrap("from server".getBytes());
|
||||||
|
sOutBuffs[0] = sOut1;
|
||||||
|
sOutBuffs[1] = sOut2;
|
||||||
|
|
||||||
|
while (!(client.isOutboundDone() && client.isInboundDone()) &&
|
||||||
|
!(server.isOutboundDone() && server.isInboundDone())) {
|
||||||
|
|
||||||
|
cResult = client.wrap(cOutBuffs, clientToServer);
|
||||||
|
sResult = server.wrap(sOutBuffs, serverToClient);
|
||||||
|
|
||||||
|
clientToServer.flip();
|
||||||
|
serverToClient.flip();
|
||||||
|
|
||||||
|
cResult = client.unwrap(serverToClient, cIn);
|
||||||
|
sResult = server.unwrap(clientToServer, sIn);
|
||||||
|
|
||||||
|
clientToServer.compact();
|
||||||
|
serverToClient.compact();
|
||||||
|
|
||||||
|
if (done == 0 &&
|
||||||
|
((cOut1.limit() + cOut2.limit()) == sIn.position()) &&
|
||||||
|
((sOut1.limit() + sOut2.limit()) == cIn.position())) {
|
||||||
|
|
||||||
|
/* check server out matches client in */
|
||||||
|
ByteBuffer cExpectedIn = ByteBuffer.wrap(
|
||||||
|
"Hello client, from server".getBytes());
|
||||||
|
cIn.flip();
|
||||||
|
|
||||||
|
if (!cIn.equals(cExpectedIn)) {
|
||||||
|
error("\t... failed");
|
||||||
|
fail("server output does not match expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check client out matches server in */
|
||||||
|
ByteBuffer sExpectedIn = ByteBuffer.wrap(
|
||||||
|
"Hello server, from client".getBytes());
|
||||||
|
sIn.flip();
|
||||||
|
|
||||||
|
if (!sIn.equals(sExpectedIn)) {
|
||||||
|
error("\t... failed");
|
||||||
|
fail("client output does not match expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close client outbound, mark done */
|
||||||
|
client.closeOutbound();
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
error("\t... failed");
|
||||||
|
e.printStackTrace();
|
||||||
|
fail("failed split input test with Exception");
|
||||||
|
}
|
||||||
|
pass("\t... passed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue