add getShutdown, sslengine close connection, and addSession method

pull/23/head
Jacob Barthelmeh 2019-03-22 11:04:40 -06:00
parent 9feceec9b5
commit 00e050810d
10 changed files with 684 additions and 187 deletions

View File

@ -13,6 +13,8 @@ extern "C" {
#define com_wolfssl_WolfSSL_SSL_FAILURE 0L
#undef com_wolfssl_WolfSSL_SSL_SUCCESS
#define com_wolfssl_WolfSSL_SSL_SUCCESS 1L
#undef com_wolfssl_WolfSSL_SSL_SHUTDOWN_NOT_DONE
#define com_wolfssl_WolfSSL_SSL_SHUTDOWN_NOT_DONE 2L
#undef com_wolfssl_WolfSSL_SSL_BAD_CERTTYPE
#define com_wolfssl_WolfSSL_SSL_BAD_CERTTYPE -8L
#undef com_wolfssl_WolfSSL_SSL_BAD_STAT

View File

@ -2686,6 +2686,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_setOptions
return wolfSSL_set_options((WOLFSSL*)ssl, op);
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getShutdown
(JNIEnv *jenv, jobject jcl, jlong ssl)
{
return (jint)wolfSSL_get_shutdown((WOLFSSL*)ssl);
}
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setSSLIORecv
(JNIEnv* jenv, jobject jcl, jlong ssl)
{

View File

@ -647,6 +647,14 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setVerify
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_setOptions
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: getShutdown
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getShutdown
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: setSSLIORecv

View File

@ -39,6 +39,7 @@ public class WolfSSL {
public final static int SSL_ERROR_NONE = 0;
public final static int SSL_FAILURE = 0;
public final static int SSL_SUCCESS = 1;
public final static int SSL_SHUTDOWN_NOT_DONE = 2;
public final static int SSL_BAD_CERTTYPE = -8;
public final static int SSL_BAD_STAT = -7;

View File

@ -260,6 +260,7 @@ public class WolfSSLSession {
private native void setAcceptState(long ssl);
private native void setVerify(long ssl, int mode, WolfSSLVerifyCallback vc);
private native long setOptions(long ssl, long op);
private native int getShutdown(long ssl);
private native void setSSLIORecv(long ssl);
private native void setSSLIOSend(long ssl);
@ -2405,6 +2406,14 @@ public class WolfSSLSession {
setSSLIOSend(getSessionPtr());
}
/**
*
* @return
*/
public int getShutdown() {
return getShutdown(getSessionPtr());
}
/* this will be registered with native wolfSSL library */
private int internalIOSSLRecvCallback(WolfSSLSession ssl, byte[] buf, int sz)
{

View File

@ -21,6 +21,7 @@
package com.wolfssl.provider.jsse;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLSession;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@ -178,10 +179,21 @@ public class WolfSSLAuthStore {
return this.alias;
}
/** Returns either an existing session to use or creates a new session
/** Returns either an existing session to use or creates a new session. Can
* return null on error case or the case where session could not be created.
*/
protected WolfSSLImplementSSLSession getSession(WolfSSLSession ssl, int port, String host) {
/* @TODO session management, for now just always creating a new one */
if (ssl == null) {
return null;
}
/* case with no host */
if (host == null) {
return this.getSession(ssl);
}
return new WolfSSLImplementSSLSession(ssl, port, host, this);
}
@ -191,5 +203,15 @@ public class WolfSSLAuthStore {
/* @TODO session management, for now just always creating a new one */
return new WolfSSLImplementSSLSession(ssl, this);
}
/**
* Add the session for possible resumption
* @param session
* @return SSL_SUCCESS on success
*/
protected int addSession(WolfSSLImplementSSLSession session) {
session.fromTable = true; /* registered into session table for resumption */
return WolfSSL.SSL_SUCCESS;
}
}

View File

@ -55,8 +55,12 @@ public class WolfSSLEngine extends SSLEngine {
private byte[] toRead; /* encrypted packet comming in */
private int toReadSz = 0;
private HandshakeStatus hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
private boolean waiting = false;
private boolean needInit = true;
private boolean inBoundOpen = true;
private boolean outBoundOpen = true;
private boolean closed = true; /* closed completely (post shutdown or before handshake) */
static private SendCB sendCb = null;
static private RecvCB recvCb = null;
@ -105,23 +109,17 @@ public class WolfSSLEngine extends SSLEngine {
if (recvCb == null) {
recvCb = new RecvCB();
}
//System.out.println("setting io callbacks for SSL Engine");
ssl.setIORecv(recvCb);
//System.out.println("set recv callback");
ssl.setIOSend(sendCb);
//System.out.println("set send callback");
}
private void initSSL() throws WolfSSLException, WolfSSLJNIException {
/* @TODO for testing still cettins ctx cbio */
if (sendCb == null) {
sendCb = new SendCB();
}
if (recvCb == null) {
recvCb = new RecvCB();
}
// ctx.setIORecv(recvCb);
// ctx.setIOSend(sendCb);
ssl = new WolfSSLSession(ctx);
if (ssl == null) {
@ -132,6 +130,71 @@ public class WolfSSLEngine extends SSLEngine {
ssl.setIOWriteCtx(this);
}
/**
* returns 0 if no data was waiting and size of copied on success
* negative values are returned in error cases
*/
private int CopyOutPacket(ByteBuffer out, Status status) {
int max = 0;
if (this.toSend != null) {
byte tmp[];
max = out.remaining();
tmp = new byte[max];
if (this.toSend.length > max) {
/* output not large enough to read packet */
status = Status.BUFFER_OVERFLOW;
return -1;
// /* partial read from toSend */
// int nSz = this.toSend.length - max;
// System.arraycopy(this.toSend, 0, tmp, 0, max);
// out.put(tmp);
// System.arraycopy(this.toSend, max, this.toSend, 0, nSz);
// this.toSend = Arrays.copyOf(this.toSend, nSz);
}
else {
/* read all from toSend */
out.put(this.toSend);
max = this.toSend.length;
this.toSend = null;
}
}
return max;
}
/**
* Handles logic during shutdown
*/
private int ClosingConnection() {
int ret;
ret = ssl.shutdownSSL();
if (ret == WolfSSL.SSL_SUCCESS) {
/* if shutdown is successfull then is closed */
closed = true;
hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
else if (ret == WolfSSL.SSL_SHUTDOWN_NOT_DONE) {
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
}
else {
int err = ssl.getError(ret);
switch (err) {
case WolfSSL.SSL_ERROR_WANT_READ:
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
break;
case WolfSSL.SSL_ERROR_WANT_WRITE:
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
break;
default:
}
}
return ret;
}
@Override
public SSLEngineResult wrap(ByteBuffer in, ByteBuffer out)
throws SSLException {
@ -142,82 +205,78 @@ public class WolfSSLEngine extends SSLEngine {
@Override
public SSLEngineResult wrap(ByteBuffer[] in, int ofst, int len,
ByteBuffer out) throws SSLException {
int i, max = 0, ret, idx = 0, pro = 0;
int i, max = 0, ret = 0, idx = 0, pro = 0;
ByteBuffer tmp;
byte[] msg;
int pos[] = new int[len];
if (needInit) {
EngineHelper.initHandshake();
needInit = false;
closed = false; /* opened a connection */
}
/* for sslengineresults return */
Status status = SSLEngineResult.Status.OK;
if (ofst + len > in.length || out == null) {
throw new SSLException("bad arguments");
}
/* get buffer size */
for (i = ofst; i < ofst + len; i++) {
max += in[i].remaining();
}
//System.out.println("buffer max = " + max);
tmp = ByteBuffer.allocate(max);
for (i = ofst; i < len; i++) {
pos[idx++] = in[i].position();
tmp.put(in[i]);
/* check if left over data to be wrapped (pro can be negative on error) */
pro = CopyOutPacket(out, status);
/* check if closing down connection */
if (pro >=0 && !outBoundOpen) {
status = SSLEngineResult.Status.CLOSED;
ClosingConnection();
pro += CopyOutPacket(out, status);
}
//System.out.println("getting byte version of input");
msg = new byte[max];
tmp.rewind();
tmp.get(msg);
//System.out.println("calling wolfssl write");
ret = this.ssl.write(msg, max);
if (ret <= 0) {
//@TODO handle error
int err = ssl.getError(ret);
//System.out.println("need to handle error case err = " + err);
switch (err) {
case WolfSSL.SSL_ERROR_WANT_READ:
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
waiting = true;
break;
case WolfSSL.SSL_ERROR_WANT_WRITE:
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
waiting = false;
break;
default:
throw new SSLException("wolfSSL error case " + ret);
}
else if (pro == 0) {
/* get buffer size */
for (i = ofst; i < ofst + len; i++) {
max += in[i].remaining();
}
tmp = ByteBuffer.allocate(max);
for (i = ofst; i < len; i++) {
pos[idx++] = in[i].position();
tmp.put(in[i]);
}
msg = new byte[max];
tmp.rewind();
tmp.get(msg);
ret = this.ssl.write(msg, max);
if (ret <= 0) {
int err = ssl.getError(ret);
switch (err) {
case WolfSSL.SSL_ERROR_WANT_READ:
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
break;
case WolfSSL.SSL_ERROR_WANT_WRITE:
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
break;
default:
throw new SSLException("wolfSSL error case " + ret);
}
}
/* if the handshake is not done then reset input buffer postions */
if (!ssl.handshakeDone()) {
idx = 0;
for (i = ofst; i < ofst + len; i++) {
in[i].position(pos[idx++]);
}
}
else {
hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
pro = CopyOutPacket(out, status);
}
/* if the handshake is not done then reset input buffer postions */
if (!ssl.handshakeDone()) {
idx = 0;
//System.out.println("trying to reset positions");
for (i = ofst; i < ofst + len; i++) {
in[i].position(pos[idx++]);
}
}
if (this.toSend != null) {
//System.out.println("returning packet of size %d\n" + this.toSend.length);
max = out.remaining();
if (this.toSend.length > max) {
/* partial read from toSend */
int nSz = this.toSend.length - max;
System.arraycopy(this.toSend, 0, msg, 0, max);
out.put(msg);
pro = max;
System.arraycopy(this.toSend, max, this.toSend, 0, nSz);
this.toSend = Arrays.copyOf(this.toSend, nSz);
}
else {
/* read all from toSend */
out.put(this.toSend);
pro = this.toSend.length;
this.toSend = null;
}
}
/* consumed no bytes */
if (ret < 0) {
ret = 0;
@ -234,12 +293,19 @@ public class WolfSSLEngine extends SSLEngine {
@Override
public SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out, int ofst,
int length) throws SSLException {
int i, ret, sz, idx = 0, max = 0, pos, cns = 0;
int i, ret = 0, sz = 0, idx = 0, max = 0, pos, cns = 0, pro = 0;
byte[] tmp;
Status status;
if (needInit) {
EngineHelper.initHandshake();
needInit = false;
closed = false;
}
/* for sslengineresults return */
Status status = SSLEngineResult.Status.OK;
status = SSLEngineResult.Status.OK;
if (in == null || out == null || ofst + length > out.length) {
throw new IllegalArgumentException();
}
@ -259,35 +325,52 @@ public class WolfSSLEngine extends SSLEngine {
in.get(tmp);
addToRead(tmp);
}
tmp = new byte[max];
//System.out.println("calling ssl read");
ret = this.ssl.read(tmp, max);
if (ret <= 0) {
int err = ssl.getError(ret);
//
// if (ssl.handshakeDone()) {
// in.position(pos); /* no data was consumed from buffer */
// cns = 0;
// System.out.println("reset positiong to " + pos + "remaning now is " + in.remaining());
// }
else {
switch (err) {
case WolfSSL.SSL_ERROR_WANT_READ:
break;
case WolfSSL.SSL_ERROR_WANT_WRITE:
break;
default:
throw new SSLException("wolfSSL error case " + ret);
}
tmp = new byte[max];
if (!outBoundOpen) {
if (ClosingConnection() == WolfSSL.SSL_SUCCESS) {
status = SSLEngineResult.Status.CLOSED;
}
}
if (waiting && this.toReadSz > 0) {
hs = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
}
else {
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
ret = this.ssl.read(tmp, max);
if (ret <= 0) {
int err = ssl.getError(ret);
//
// if (ssl.handshakeDone()) {
// in.position(pos); /* no data was consumed from buffer */
// cns = 0;
// System.out.println("reset positiong to " + pos + "remaning now is " + in.remaining());
// }
switch (err) {
case WolfSSL.SSL_ERROR_WANT_READ:
if (cns > 0) {
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
}
break;
case WolfSSL.SSL_ERROR_WANT_WRITE:
break;
case WolfSSL.SSL_ERROR_ZERO_RETURN:
/* check if is shutdown message */
if (ssl.getShutdown() == WolfSSL.SSL_RECEIVED_SHUTDOWN) {
this.outBoundOpen = false;
ClosingConnection();
status = SSLEngineResult.Status.CLOSED;
if (toSend != null && toSend.length > 0) {
hs = SSLEngineResult.HandshakeStatus.NEED_WRAP;
}
}
break;
default:
throw new SSLException("wolfSSL error case " + err);
}
}
}
for (i = 0; i < ret;) {
@ -297,11 +380,15 @@ public class WolfSSLEngine extends SSLEngine {
sz = out[idx + ofst].remaining();
sz = (sz > ret)? ret : sz;
out[idx + ofst].put(tmp, i, sz);
i += sz;
i += sz;
pro += sz;
idx++;
}
return new SSLEngineResult(status, hs, cns, i);
if (ssl.handshakeDone()) {
hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
return new SSLEngineResult(status, hs, cns, pro);
}
@Override
@ -313,22 +400,32 @@ public class WolfSSLEngine extends SSLEngine {
@Override
public void closeInbound() throws SSLException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
if (!inBoundOpen)
return;
if (inBoundOpen && !closed) {
/* this checks that peer sent back shutdown message */
throw new SSLException("Closing in bound before shutdonw is done");
}
else
{
inBoundOpen = false;
}
}
@Override
public boolean isInboundDone() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return !inBoundOpen;
}
@Override
public void closeOutbound() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
outBoundOpen = false;
}
@Override
public boolean isOutboundDone() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return !outBoundOpen;
}
@Override
@ -374,9 +471,6 @@ public class WolfSSLEngine extends SSLEngine {
@Override
public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
if (ssl.handshakeDone()) {
return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
return hs;
}
@ -425,8 +519,7 @@ public class WolfSSLEngine extends SSLEngine {
protected int setOut(byte[] in, int sz) {
int totalSz = sz, idx = 0;
byte[] tmp;
//System.out.println("setout callback, adding " + sz + " bytes to toSend");
if (this.toSend != null) {
totalSz += this.toSend.length;
}
@ -437,7 +530,6 @@ public class WolfSSLEngine extends SSLEngine {
}
System.arraycopy(in, 0, tmp, idx, in.length);
this.toSend = tmp;
//System.out.println("Added " + sz + " bytes toSend length now " + this.toSend.length);
return sz;
}
@ -446,10 +538,11 @@ public class WolfSSLEngine extends SSLEngine {
protected int setIn(byte[] toRead, int sz) {
int max = (sz < toReadSz)? sz : toReadSz;
//System.out.println("setin callback");
if (this.toRead == null || this.toReadSz == 0) {
/* nothing to be read */
//System.out.println("No buffer to read returning want read");
if (WolfSSLDebug.DEBUG) {
log("No buffer to read returning want read");
}
return WolfSSL.WOLFSSL_CBIO_ERR_WANT_READ;
}
System.arraycopy(this.toRead, 0, toRead, 0, max);
@ -458,14 +551,21 @@ public class WolfSSLEngine extends SSLEngine {
int left = this.toReadSz - max;
System.arraycopy(this.toRead, max, this.toRead, 0, left);
this.toReadSz = left;
//System.out.println("reading " + max + " from toRead : " + left + " bytes left");
}
else {
/* read all from buffer */
//System.out.println("read all " + max + " bytes from toRead ");
this.toRead = null;
this.toReadSz = 0;
}
if (WolfSSLDebug.DEBUG) {
System.out.println("CB Read ["+max+"] :");
for (int i = 0; i < max; i++) {
System.out.printf("%02X", toRead[i]);
}
System.out.println("");
}
return max;
}
@ -483,7 +583,7 @@ public class WolfSSLEngine extends SSLEngine {
}
private void log(String msg) {
WolfSSLDebug.print("[WolfSSLSocket] " + msg);
WolfSSLDebug.print("[WolfSSLEngine] " + msg);
}
private class SendCB implements WolfSSLIOSendCallback {

View File

@ -25,6 +25,7 @@ import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLSession;
import java.io.IOException;
import java.util.Arrays;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
/**
@ -41,11 +42,19 @@ public class WolfSSLEngineHelper {
private WolfSSLImplementSSLSession session = null;
private SSLParameters params;
private WolfSSLDebug debug;
private int port;
private String host = null;
private WolfSSLAuthStore authStore = null;
private boolean clientMode;
private boolean sessionCreation = true;
/**
* Always creates a new session
* @param ssl
* @param store
* @param params
* @throws WolfSSLException
*/
protected WolfSSLEngineHelper(WolfSSLSession ssl, WolfSSLAuthStore store,
SSLParameters params) throws WolfSSLException {
if (params == null || ssl == null || store == null) {
@ -54,9 +63,19 @@ public class WolfSSLEngineHelper {
this.ssl = ssl;
this.params = params;
this.session = store.getSession(ssl);
this.authStore = store;
this.session = this.authStore.getSession(ssl, 0, null);
}
/**
* Allows for new session and resume session by default
* @param ssl
* @param store
* @param params
* @param port
* @param host
* @throws WolfSSLException
*/
protected WolfSSLEngineHelper(WolfSSLSession ssl, WolfSSLAuthStore store,
SSLParameters params, int port, String host)
throws WolfSSLException {
@ -66,7 +85,10 @@ public class WolfSSLEngineHelper {
this.ssl = ssl;
this.params = params;
this.session = store.getSession(ssl, port, host);
this.port = port;
this.host = host;
this.authStore = store;
this.session = this.authStore.getSession(ssl, this.port, this.host);
}
protected WolfSSLSession getWolfSSLSession() {
@ -250,9 +272,15 @@ public class WolfSSLEngineHelper {
this.setLocalAuth();
}
/* sets all parameters from SSLParameters into WOLFSSL object.
/* sets all parameters from SSLParameters into WOLFSSL object and creates
* session.
* Should be called before doHandshake */
protected void initHandshake() {
protected void initHandshake() throws SSLException {
if (this.sessionCreation) {
/* can only add new sessions to the resumption table if session
* creation is allowed */
this.authStore.addSession(this.session);
}
this.setLocalParams();
}
@ -260,22 +288,29 @@ public class WolfSSLEngineHelper {
* WolfSSL.SSL_FAILURE */
protected int doHandshake() {
if (this.sessionCreation == false) {
if (this.sessionCreation == false && !this.session.fromTable) {
/* new handshakes can not be made in this case. */
if (debug.DEBUG) {
log("session created not allowed for this session");
if (WolfSSLDebug.DEBUG) {
log("session creation not allowed");
}
return WolfSSL.SSL_HANDSHAKE_FAILURE;
}
if (!this.session.isValid()) {
if (WolfSSLDebug.DEBUG) {
log("session is marked as invalid");
}
return WolfSSL.SSL_HANDSHAKE_FAILURE;
}
if (this.clientMode) {
if (debug.DEBUG) {
if (WolfSSLDebug.DEBUG) {
log("calling native wolfSSL_connect()");
}
return this.ssl.connect();
} else {
if (debug.DEBUG) {
if (WolfSSLDebug.DEBUG) {
log("calling native wolfSSL_accept()");
}
return this.ssl.accept();

View File

@ -52,6 +52,7 @@ public class WolfSSLImplementSSLSession implements SSLSession {
private final String host;
Date creation;
Date accessed; /* when new connection was made using session */
protected boolean fromTable = false; /* has this session been registered */
public WolfSSLImplementSSLSession (WolfSSLSession in, int port, String host,
WolfSSLAuthStore params) {

View File

@ -37,6 +37,7 @@ import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.KeyManager;
@ -62,6 +63,8 @@ public class WolfSSLEngineTest {
public final static String clientJKS = "./examples/provider/client.jks";
public final static String serverJKS = "./examples/provider/server.jks";
public final static char[] jksPass = "wolfSSL test".toCharArray();
public final static String engineProvider = "wolfJSSE";
private static boolean extraDebug = false;
private SSLContext ctx = null;
private static String allProtocols[] = {
@ -135,82 +138,253 @@ public class WolfSSLEngineTest {
}
private void createSSLContext(String protocol) {
SSLContext ctx;
try {
//ctx = SSLContext.getInstance(protocol, "wolfJSSE");
this.ctx = SSLContext.getInstance(protocol);
if (engineProvider != null) {
this.ctx = SSLContext.getInstance(protocol, engineProvider);
}
else {
this.ctx = SSLContext.getInstance(protocol);
}
this.ctx.init(createKeyManager("SunX509", clientJKS),
createTrustManager("SunX509", clientJKS), null);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
//} catch (NoSuchProviderException ex) {
// Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (KeyManagementException ex) {
Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchProviderException ex) {
System.out.println("Could not find the provider : " + engineProvider);
Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
private int CloseConnection(SSLEngine server, SSLEngine client, boolean earlyClose) throws SSLException {
ByteBuffer serToCli = ByteBuffer.allocateDirect(server.getSession().getPacketBufferSize());
ByteBuffer cliToSer = ByteBuffer.allocateDirect(client.getSession().getPacketBufferSize());
ByteBuffer empty = ByteBuffer.allocate(server.getSession().getPacketBufferSize());
SSLEngineResult result;
HandshakeStatus s;
boolean passed;
Runnable run;
client.closeOutbound();
result = client.wrap(empty, cliToSer);
if (extraDebug) {
System.out.println("[client wrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
while ((run = client.getDelegatedTask()) != null) {
run.run();
}
s = client.getHandshakeStatus();
if (extraDebug) {
System.out.println("client status = " + s.toString());
}
if (result.bytesProduced() <= 0 || result.bytesConsumed() != 0) {
throw new SSLException("Client wrap consumed/produced error");
}
if (!s.toString().equals("NEED_UNWRAP") ||
!result.getStatus().name().equals("CLOSED") ) {
throw new SSLException("Bad status");
}
cliToSer.flip();
/* check that early close inbounds fail */
if (earlyClose) {
try {
passed = false;
server.closeInbound();
}
catch (SSLException e) {
passed = true;
}
if (!passed) {
throw new SSLException("Expected to fail on early close inbound");
}
try {
passed = false;
client.closeInbound();
}
catch (SSLException e) {
passed = true;
}
if (!passed) {
throw new SSLException("Expected to fail on early close inbound");
}
return 0;
}
result = server.unwrap(cliToSer, empty);
if (extraDebug) {
System.out.println("[server unwrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
if (result.getStatus().name().equals("CLOSED")) {
/* odd case where server tries to send "empty" if not set close */
server.closeOutbound();
}
while ((run = server.getDelegatedTask()) != null) {
run.run();
}
s = server.getHandshakeStatus();
if (result.bytesProduced() != 0 || result.bytesConsumed() <= 0) {
throw new SSLException("Server unwrap consumed/produced error");
}
if (!s.toString().equals("NEED_WRAP") ||
!result.getStatus().name().equals("CLOSED") ) {
throw new SSLException("Bad status");
}
result = server.wrap(empty, serToCli);
if (extraDebug) {
System.out.println("[server wrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
while ((run = server.getDelegatedTask()) != null) {
run.run();
}
s = server.getHandshakeStatus();
if (result.bytesProduced() <= 0 || result.bytesConsumed() != 0) {
throw new SSLException("Server wrap consumed/produced error");
}
if (extraDebug) {
System.out.println("server status = " + s.toString());
}
if (!s.toString().equals("NOT_HANDSHAKING") ||
!result.getStatus().name().equals("CLOSED")) {
throw new SSLException("Bad status");
}
serToCli.flip();
result = client.unwrap(serToCli, empty);
if (extraDebug) {
System.out.println("[client unwrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
while ((run = client.getDelegatedTask()) != null) {
run.run();
}
s = client.getHandshakeStatus();
if (result.bytesProduced() != 0 || result.bytesConsumed() <= 0) {
throw new SSLException("Client unwrap consumed/produced error");
}
if (!s.toString().equals("NOT_HANDSHAKING") ||
!result.getStatus().name().equals("CLOSED")) {
throw new SSLException("Bad status");
}
if (extraDebug) {
System.out.println("client status = " + s.toString());
}
server.closeInbound();
client.closeInbound();
return 0;
}
private int testConnection(SSLEngine server, SSLEngine client,
String[] cipherSuites, String[] protocols, String appData) {
ByteBuffer serToCli = ByteBuffer.allocateDirect(server.getSession().getPacketBufferSize());
ByteBuffer cliToSer = ByteBuffer.allocateDirect(client.getSession().getPacketBufferSize());
ByteBuffer toSend = ByteBuffer.wrap(appData.getBytes());
ByteBuffer serPlain = ByteBuffer.allocate(appData.length());
ByteBuffer cliPlain = ByteBuffer.allocate(appData.length());
ByteBuffer toSendCli = ByteBuffer.wrap(appData.getBytes());
ByteBuffer toSendSer = ByteBuffer.wrap(appData.getBytes());
ByteBuffer serPlain = ByteBuffer.allocate(server.getSession().getApplicationBufferSize());
ByteBuffer cliPlain = ByteBuffer.allocate(client.getSession().getApplicationBufferSize());
boolean done = false;
int i;
server.setUseClientMode(false);
server.setEnabledCipherSuites(cipherSuites);
String[] p = server.getSupportedProtocols();
server.setEnabledProtocols(protocols);
server.setNeedClientAuth(false);
client.setUseClientMode(true);
client.setEnabledCipherSuites(cipherSuites);
client.setEnabledProtocols(protocols);
if (cipherSuites != null) {
server.setEnabledCipherSuites(cipherSuites);
client.setEnabledCipherSuites(cipherSuites);
}
if (protocols != null) {
server.setEnabledProtocols(protocols);
client.setEnabledProtocols(protocols);
}
while (!done) {
try {
Runnable run;
SSLEngineResult result;
HandshakeStatus s;
result = client.wrap(toSend, cliToSer);
// System.out.println("[client wrap] consumed = " + result.bytesConsumed() +
// " produced = " + result.bytesProduced() +
// " status = " + result.getStatus().name());
result = client.wrap(toSendCli, cliToSer);
if (extraDebug) {
System.out.println("[client wrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
// + " sequence # = " + result.sequenceNumber());
}
while ((run = client.getDelegatedTask()) != null) {
run.run();
}
result = server.wrap(toSend, serToCli);
// System.out.println("[server wrap] consumed = " + result.bytesConsumed() +
// " produced = " + result.bytesProduced() +
// " status = " + result.getStatus().name());
result = server.wrap(toSendSer, serToCli);
if (extraDebug) {
System.out.println("[server wrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name()
+ " sequence # = " + result.sequenceNumber());
}
while ((run = server.getDelegatedTask()) != null) {
run.run();
}
if (extraDebug) {
s = client.getHandshakeStatus();
System.out.println("client status = " + s.toString());
s = server.getHandshakeStatus();
System.out.println("server status = " + s.toString());
}
cliToSer.flip();
serToCli.flip();
if (extraDebug) {
if (cliToSer.remaining() > 0) {
System.out.println("Client -> Server");
while (cliToSer.remaining() > 0)
System.out.printf("%02X", cliToSer.get());
System.out.println("");
cliToSer.flip();
}
if (serToCli.remaining() > 0) {
System.out.println("Server -> Client");
while (serToCli.remaining() > 0)
System.out.printf("%02X", serToCli.get());
System.out.println("");
serToCli.flip();
}
System.out.println("cliToSer remaning = " + cliToSer.remaining());
System.out.println("serToCli remaning = " + serToCli.remaining());
}
result = client.unwrap(serToCli, cliPlain);
// System.out.println("[client unwrap] consumed = " + result.bytesConsumed() +
// " produced = " + result.bytesProduced() +
// " status = " + result.getStatus().name());
if (extraDebug) {
System.out.println("[client unwrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
while ((run = client.getDelegatedTask()) != null) {
run.run();
}
result = server.unwrap(cliToSer, serPlain);
// System.out.println("[server unwrap] consumed = " + result.bytesConsumed() +
// " produced = " + result.bytesProduced() +
// " status = " + result.getStatus().name());
if (extraDebug) {
System.out.println("[server unwrap] consumed = " + result.bytesConsumed() +
" produced = " + result.bytesProduced() +
" status = " + result.getStatus().name());
}
while ((run = server.getDelegatedTask()) != null) {
run.run();
}
@ -219,21 +393,35 @@ public class WolfSSLEngineTest {
serToCli.compact();
HandshakeStatus s = client.getHandshakeStatus();
// System.out.println("client status = " + s.toString());
s = server.getHandshakeStatus();
// System.out.println("server status = " + s.toString());
if (extraDebug) {
s = client.getHandshakeStatus();
System.out.println("client status = " + s.toString());
s = server.getHandshakeStatus();
System.out.println("server status = " + s.toString());
}
if (toSend.remaining() == 0) {
if (toSendCli.remaining() == 0 && toSendSer.remaining() == 0) {
byte[] b;
String st;
/* check what the client received */
cliPlain.rewind();
b = new byte[cliPlain.remaining()];
cliPlain.get(b);
st = new String(b, StandardCharsets.UTF_8).trim();
if (!appData.equals(st)) {
return -1;
}
/* check what the server received */
serPlain.rewind();
b = new byte[serPlain.remaining()];
serPlain.get(b);
String st = new String(b, StandardCharsets.UTF_8);
st = new String(b, StandardCharsets.UTF_8).trim();
if (!appData.equals(st)) {
System.out.println("unexpected application data");
return -1;
}
done = true;
}
@ -263,6 +451,41 @@ public class WolfSSLEngineTest {
System.out.println("\t\t... passed");
}
@Test
public void testSSLEngineSetCipher()
throws NoSuchProviderException, NoSuchAlgorithmException {
SSLEngine e;
String sup[];
System.out.print("\tTesting setting cipher");
createSSLContext("TLSv1.2");
e = this.ctx.createSSLEngine();
if (e == null) {
System.out.println("\t\t... failed");
fail("failed to create engine");
}
/* should be null when not set , is not null? */
// if (e.getEnabledCipherSuites() != null) {
// System.out.println("\t\t... failed");
// System.out.println("not null ");
// for (String s : e.getEnabledCipherSuites()) {
// System.out.print("" + s);
// }
// System.out.println("");
// fail("unexpected cipher list");
// }
sup = e.getSupportedCipherSuites();
e.setEnabledCipherSuites(new String[] {sup[0]});
if (e.getEnabledCipherSuites() == null ||
!sup[0].equals(e.getEnabledCipherSuites()[0])) {
System.out.println("\t\t... failed");
fail("unexpected empty cipher list");
}
System.out.println("\t\t... passed");
}
@Test
public void testCipherConnection()
throws NoSuchProviderException, NoSuchAlgorithmException {
@ -270,37 +493,127 @@ public class WolfSSLEngineTest {
SSLEngine client;
String cipher = null;
int ret, i;
String[] ciphers;
/* create new SSLEngine */
System.out.print("\tTesting setting cipher");
System.out.print("\tTesting cipher connection");
createSSLContext("TLS");
server = this.ctx.createSSLEngine();
// client = this.ctx.createSSLEngine("client", 80);
client = this.ctx.createSSLEngine("wolfSSL client test", 11111);
/* use wolfJSSE client */
SSLContext c = SSLContext.getInstance("TLSv1.2", "wolfJSSE");
try {
c.init(createKeyManager("SunX509", clientJKS),
createTrustManager("SunX509", clientJKS), null);
} catch (KeyManagementException ex) {
System.out.println("unable to init context");
Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
}
client = c.createSSLEngine("client", 80);
// /* use wolfJSSE client */
// SSLContext c = SSLContext.getInstance("TLS", "wolfJSSE");
// try {
// c.init(createKeyManager("SunX509", clientJKS),
// createTrustManager("SunX509", clientJKS), null);
// } catch (KeyManagementException ex) {
// Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
// }
// client = c.createSSLEngine("wolfSSL client test", 11111);
// server = c.createSSLEngine();
String[] ciphers = server.getSupportedCipherSuites();
for (i = 0; i < ciphers.length; i++)
if (ciphers[i].equals("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"))
cipher = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
ciphers = client.getSupportedCipherSuites();
/* use a ECDHE-RSA suite if available */
for (String x : ciphers) {
if (x.contains("ECDHE_RSA")) {
cipher = x;
break;
}
}
ret = testConnection(server, client, new String[] { cipher },
new String[] { "TLSv1.2" }, "Test cipher suite");
if (ret != 0) {
System.out.println("\t\t... failed");
System.out.println("\t... failed");
fail("failed to create engine");
}
System.out.println("\t\t... passed");
System.out.println("\t... passed");
System.out.print("\tTesting close connection");
try {
/* test close connection */
CloseConnection(server, client, false);
} catch (SSLException ex) {
System.out.println("\t... failed");
fail("failed to create engine");
}
System.out.println("\t... passed");
}
@Test
public void testReuseSession()
throws NoSuchProviderException, NoSuchAlgorithmException {
SSLEngine server;
SSLEngine client;
String cipher = null;
int ret, i;
String[] ciphers;
/* create new SSLEngine */
System.out.print("\tTesting reuse of session");
createSSLContext("TLS");
server = this.ctx.createSSLEngine();
client = this.ctx.createSSLEngine("wolfSSL client test", 11111);
/* use wolfJSSE client */
// SSLContext c = SSLContext.getInstance("TLSv1.2", "wolfJSSE");
// try {
// c.init(createKeyManager("SunX509", clientJKS),
// createTrustManager("SunX509", clientJKS), null);
// } catch (KeyManagementException ex) {
// Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
// }
// client = c.createSSLEngine("wolfSSL client test", 11111);
// server = c.createSSLEngine();
ret = testConnection(server, client, null, null, "Test reuse");
if (ret != 0) {
System.out.println("\t... failed");
fail("failed to create engine");
}
try {
/* test close connection */
CloseConnection(server, client, false);
} catch (SSLException ex) {
System.out.println("\t... failed");
fail("failed to create engine");
}
/* use wolfJSSE client */
// c = SSLContext.getInstance("TLSv1.2", "wolfJSSE");
// try {
// c.init(createKeyManager("SunX509", clientJKS),
// createTrustManager("SunX509", clientJKS), null);
// } catch (KeyManagementException ex) {
// Logger.getLogger(WolfSSLEngineTest.class.getName()).log(Level.SEVERE, null, ex);
// }
// client = c.createSSLEngine("wolfSSL client test", 11111);
// server = c.createSSLEngine();
server = this.ctx.createSSLEngine();
client = this.ctx.createSSLEngine("wolfSSL client test", 11111);
client.setEnableSessionCreation(false);
ret = testConnection(server, client, null, null, "Test reuse");
if (ret != 0) {
System.out.println("\t... failed");
fail("failed to create engine");
}
try {
/* test close connection */
CloseConnection(server, client, false);
} catch (SSLException ex) {
System.out.println("\t... failed");
fail("failed to create engine");
}
System.out.println("\t... passed");
}
/* status tests buffer overflow/underflow/closed test */
}