Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/java/com/wolfssl/WolfSSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,17 @@ public enum TLS_VERSION {
/* Track if library loading was skipped via system property */
private static volatile boolean libraryLoadSkipped = false;

/* Have FIPS CASTs passed in init(), guarded by castLock */
private static boolean fipsCastsDone = false;

/* ---------------------------- locks ------------------------------- */

/* lock for cleanup */
private final Object cleanupLock = new Object();

/* lock for running FIPS CASTs in init() */
private static final Object castLock = new Object();

/* ------------------------ constructors ---------------------------- */

/**
Expand All @@ -698,6 +704,9 @@ public enum TLS_VERSION {
* {@code Security.setProperty("wolfjsse.skipFIPSCAST", "true")} or
* in the {@code java.security} configuration file.
*
* CASTs are run at most once per process. After one WolfSSL object runs
* them successfully, later objects skip them.
*
* @throws com.wolfssl.WolfSSLException if wolfSSL library fails to
* initialize correctly
*/
Expand All @@ -721,7 +730,7 @@ public WolfSSL() throws WolfSSLException {
"init (wolfjsse.skipFIPSCAST=true)");
}

ret = init(skipCAST);
ret = initOnce(skipCAST);
if (ret != SSL_SUCCESS) {
throw new WolfSSLException(
"Failed to initialize wolfSSL library: " + ret);
Expand Down Expand Up @@ -797,6 +806,23 @@ public WolfSSL() throws WolfSSLException {

private native int init(int skipFIPSCAST);

/* Run CASTs only once per process */
private int initOnce(int skipCAST) {
int ret;

synchronized (castLock) {
if (fipsCastsDone) {
skipCAST = 1;
}
ret = init(skipCAST);
if (ret == SSL_SUCCESS && skipCAST == 0) {
fipsCastsDone = true;
}
}

return ret;
}

/**
* Free native memory allocated at pointer provided.
* @param ptr native pointer
Expand Down
4 changes: 4 additions & 0 deletions src/test/com/wolfssl/test/WolfSSLCertRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public class WolfSSLCertRequestTest {
public static String cliEccKeyDer = "examples/certs/ecc-client-key.der";
public static String cliEccKeyPem = "examples/certs/ecc-client-key.pem";

/* WolfSSL() sets the NID values these tests use */
private static WolfSSL sslLib = null;

@BeforeClass
public static void setCertPaths() throws WolfSSLException {

Expand All @@ -75,6 +78,7 @@ public static void setCertPaths() throws WolfSSLException {
} catch (UnsatisfiedLinkError ule) {
fail("failed to load native JNI library");
}
sslLib = new WolfSSL();

cliKeyDer = WolfSSLTestCommon.getPath(cliKeyDer);
cliKeyPem = WolfSSLTestCommon.getPath(cliKeyPem);
Expand Down
4 changes: 4 additions & 0 deletions src/test/com/wolfssl/test/WolfSSLCertificateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ private void runOrAllowNotCompiled(ThrowingRunnable r)
@Rule
public TestRule testWatcher = TimedTestWatcher.create();

/* WolfSSL() sets the NID values these tests use */
private static WolfSSL sslLib = null;

@BeforeClass
public static void setCertPaths() throws WolfSSLException {

Expand All @@ -151,6 +154,7 @@ public static void setCertPaths() throws WolfSSLException {
} catch (UnsatisfiedLinkError ule) {
fail("failed to load native JNI library");
}
sslLib = new WolfSSL();

cliCertDer = WolfSSLTestCommon.getPath(cliCertDer);
cliCertPem = WolfSSLTestCommon.getPath(cliCertPem);
Expand Down
69 changes: 69 additions & 0 deletions src/test/com/wolfssl/test/WolfSSLTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLContext;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLLoggingCallback;
import com.wolfssl.WolfSSLFIPSErrorCallback;

Expand Down Expand Up @@ -67,6 +71,71 @@ public void test_WolfSSL_new() {
}
}

/* Creating WolfSSL objects must not break other threads creating sessions.
* On FIPS builds, rerunning CASTs in each constructor fails other threads
* using those algorithms at the same time. */
@Test
public void test_WolfSSL_newWithConcurrentSessions()
throws InterruptedException, WolfSSLException {

/* First object runs the CASTs before session threads start */
new WolfSSL();

final int numThreads = 4;
final AtomicBoolean stop = new AtomicBoolean(false);
final AtomicInteger sessions = new AtomicInteger(0);
final AtomicReference<Throwable> firstError =
new AtomicReference<Throwable>();
Thread[] threads = new Thread[numThreads];

for (int i = 0; i < numThreads; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
try {
while (!stop.get()) {
WolfSSLContext ctx = new WolfSSLContext(
WolfSSL.SSLv23_ClientMethod());
WolfSSLSession ssl = new WolfSSLSession(ctx);
ssl.freeSSL();
ctx.free();
sessions.incrementAndGet();
}
} catch (Throwable t) {
firstError.compareAndSet(null, t);
}
}
});
threads[i].start();
}

try {
/* Wait for session threads to start, up to 5 seconds */
for (int i = 0; i < 5000 && sessions.get() < 100 &&
firstError.get() == null; i++) {
Thread.sleep(1);
}
for (int i = 0; i < 20 && firstError.get() == null; i++) {
new WolfSSL();
}
} catch (WolfSSLException e) {
firstError.compareAndSet(null, e);
} finally {
stop.set(true);
for (int i = 0; i < numThreads; i++) {
threads[i].join();
}
}

Throwable err = firstError.get();
if (err != null) {
AssertionError ae = new AssertionError(
"WolfSSL() with concurrent sessions failed: " +
err.getMessage());
ae.initCause(err);
throw ae;
}
}

@Test
public void test_WolfSSL_bulkCipherEnumsDistinct()
throws WolfSSLException {
Expand Down
Loading