diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c
index 6105f986..738fa493 100644
--- a/native/com_wolfssl_WolfSSLCertificate.c
+++ b/native/com_wolfssl_WolfSSLCertificate.c
@@ -2425,20 +2425,27 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1exte
sz = getOBJSize(obj);
ret = (*jenv)->NewByteArray(jenv, sz);
- if (!ret) {
+ if (ret == NULL) {
throwWolfSSLJNIException(jenv,
"Failed to create byte array in native X509_get_extension");
- return NULL;
}
-
- (*jenv)->SetByteArrayRegion(jenv, ret, 0, sz, (jbyte*)data);
- if ((*jenv)->ExceptionOccurred(jenv)) {
- (*jenv)->ExceptionDescribe(jenv);
- (*jenv)->ExceptionClear(jenv);
- (*jenv)->DeleteLocalRef(jenv, ret);
- return NULL;
+ else {
+ (*jenv)->SetByteArrayRegion(jenv, ret, 0, sz, (jbyte*)data);
+ if ((*jenv)->ExceptionOccurred(jenv)) {
+ (*jenv)->ExceptionDescribe(jenv);
+ (*jenv)->ExceptionClear(jenv);
+ (*jenv)->DeleteLocalRef(jenv, ret);
+ ret = NULL;
+ }
}
}
+
+#if LIBWOLFSSL_VERSION_HEX < 0x04002000
+ /* obj was popped from sk, both are owned here */
+ wolfSSL_ASN1_OBJECT_free(obj);
+ wolfSSL_sk_ASN1_OBJECT_free((WOLFSSL_STACK*)sk);
+#endif
+
return ret;
}
diff --git a/native/com_wolfssl_WolfSSLX509StoreCtx.c b/native/com_wolfssl_WolfSSLX509StoreCtx.c
index 321fcd29..2b1e2050 100644
--- a/native/com_wolfssl_WolfSSLX509StoreCtx.c
+++ b/native/com_wolfssl_WolfSSLX509StoreCtx.c
@@ -60,12 +60,13 @@ JNIEXPORT jobjectArray JNICALL Java_com_wolfssl_WolfSSLX509StoreCtx_X509_1STORE_
/* get WOLFSSL_STACK of WOLFSSL_X509 certs */
sk = wolfSSL_X509_STORE_GetCerts(store);
- skNum = wolfSSL_sk_X509_num(sk);
+ if (sk == NULL) {
+ return NULL;
+ }
- if (sk == NULL || skNum == 0) {
- if (sk != NULL) {
- wolfSSL_sk_X509_pop_free(sk, NULL);
- }
+ skNum = wolfSSL_sk_X509_num(sk);
+ if (skNum <= 0) {
+ wolfSSL_sk_X509_pop_free(sk, NULL);
return NULL;
}
diff --git a/src/java/com/wolfssl/WolfSSLContext.java b/src/java/com/wolfssl/WolfSSLContext.java
index 728348e8..627252df 100644
--- a/src/java/com/wolfssl/WolfSSLContext.java
+++ b/src/java/com/wolfssl/WolfSSLContext.java
@@ -1514,6 +1514,15 @@ WolfSSLDebug.INFO, getContextPtr(),
* Registers CRL callback to be called when CRL lookup fails, using
* specified Context.
*
+ * The native wolfSSL missing CRL callback carries only the CRL URL, with
+ * no context or session identity, so wolfJNI keeps a single process-wide
+ * callback for all WolfSSLContext registrations. The most recently
+ * registered callback receives the notifications for every context, and
+ * registering null on any context stops delivery for all of them. Calling
+ * {@link WolfSSLSession#setCRLCb(WolfSSLMissingCRLCallback)} on a session
+ * replaces the native registration for that session's context, since the
+ * session and context share the same native certificate manager.
+ *
* @param cb callback to be registered with SSL context, called
* when CRL lookup fails.
* @return SSL_SUCCESS upon success,
diff --git a/src/java/com/wolfssl/WolfSSLSession.java b/src/java/com/wolfssl/WolfSSLSession.java
index 65ecb484..4334f193 100644
--- a/src/java/com/wolfssl/WolfSSLSession.java
+++ b/src/java/com/wolfssl/WolfSSLSession.java
@@ -4181,6 +4181,15 @@ public int loadCRL(String path, int type, int monitor)
/**
* Registers CRL callback to be called when CRL lookup fails.
*
+ * The native wolfSSL missing CRL callback carries only the CRL URL, with
+ * no context or session identity, so wolfJNI keeps a single process-wide
+ * callback for all WolfSSLSession registrations. The most recently
+ * registered callback receives the notifications for every session, and
+ * registering null on any session stops delivery for all of them. This
+ * also replaces any callback registered through
+ * {@link WolfSSLContext#setCRLCb(WolfSSLMissingCRLCallback)} for this
+ * session's context.
+ *
* @param cb callback to be registered with SSL session, called
* when CRL lookup fails.
* @return SSL_SUCCESS upon success,
diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java b/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
index 7e09860b..2864547d 100644
--- a/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
+++ b/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
@@ -269,6 +269,9 @@ public WolfSSLImplementSSLSession (WolfSSLImplementSSLSession orig) {
this.peerCerts = orig.peerCerts.clone();
}
this.protocol = orig.protocol;
+ if (orig.sniServerNames != null) {
+ this.sniServerNames = new ArrayList<>(orig.sniServerNames);
+ }
/* This session has been copied and is therefore not inside the
* WolfSSLAuthStore session cache table currently */
diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java
index 5b057725..de1cedfc 100644
--- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java
+++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionTest.java
@@ -26,6 +26,8 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
@@ -48,6 +50,9 @@
import java.net.InetSocketAddress;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
@@ -67,6 +72,7 @@
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
+import com.wolfssl.provider.jsse.WolfSSLImplementSSLSession;
import com.wolfssl.provider.jsse.WolfSSLProvider;
import com.wolfssl.provider.jsse.WolfSSLX509X;
import com.wolfssl.test.TimedTestWatcher;
@@ -1316,6 +1322,35 @@ private void testSSLSession(SSLSocket sock, boolean handshakeDone)
}
}
+ @Test
+ public void testCopyConstructorPreservesSNIServerNames()
+ throws NoSuchAlgorithmException, KeyManagementException,
+ KeyStoreException, CertificateException, IOException,
+ NoSuchProviderException, UnrecoverableKeyException {
+
+ SSLContext ctx = tf.createSSLContext("TLS", engineProvider);
+ SSLEngine engine = ctx.createSSLEngine("localhost", 12345);
+ if (engine == null) {
+ fail("failed to create engine");
+ }
+ engine.setUseClientMode(true);
+
+ /* setSSLParameters() stores server names in the engine session */
+ SSLParameters params = engine.getSSLParameters();
+ params.setServerNames(Arrays.asList(new SNIHostName("localhost")));
+ engine.setSSLParameters(params);
+
+ WolfSSLImplementSSLSession orig =
+ (WolfSSLImplementSSLSession)engine.getSession();
+ assertNotNull(orig);
+ List names = orig.getSNIServerNames();
+ assertNotNull(names);
+ assertEquals(1, names.size());
+
+ WolfSSLImplementSSLSession copy = new WolfSSLImplementSSLSession(orig);
+ assertEquals(names, copy.getSNIServerNames());
+ }
+
private class listner implements SSLSessionBindingListener {
private SSLSession ses;
diff --git a/src/test/com/wolfssl/test/WolfSSLCRLTest.java b/src/test/com/wolfssl/test/WolfSSLCRLTest.java
index 3e1f12fd..b19bbc5c 100644
--- a/src/test/com/wolfssl/test/WolfSSLCRLTest.java
+++ b/src/test/com/wolfssl/test/WolfSSLCRLTest.java
@@ -28,8 +28,10 @@
import org.junit.rules.TestRule;
import static org.junit.Assert.*;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
+import java.math.BigInteger;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
@@ -39,7 +41,10 @@
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
+import java.security.cert.CRLException;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
import java.util.Date;
import java.util.Calendar;
@@ -121,6 +126,12 @@ private WolfSSLX509Name GenerateTestIssuerName() throws WolfSSLException {
*/
private WolfSSLCRL generateSignedTestCRL()
throws WolfSSLException, WolfSSLJNIException, NoSuchAlgorithmException {
+ return generateSignedTestCRL(new byte[] { 0x01, 0x02, 0x03, 0x04 });
+ }
+
+ /* Same as above, revoking the given serial */
+ private WolfSSLCRL generateSignedTestCRL(byte[] serial)
+ throws WolfSSLException, WolfSSLJNIException, NoSuchAlgorithmException {
WolfSSLCRL crl = new WolfSSLCRL();
crl.setVersion(1);
@@ -134,7 +145,6 @@ private WolfSSLCRL generateSignedTestCRL()
cal.add(Calendar.DAY_OF_YEAR, 30);
crl.setNextUpdate(cal.getTime());
- byte[] serial = new byte[] { 0x01, 0x02, 0x03, 0x04 };
crl.addRevoked(serial, new Date());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
@@ -343,6 +353,39 @@ public void testAddRevoked()
crl.free();
}
+ @Test
+ public void testAddRevokedSerialRoundTrip()
+ throws WolfSSLException, WolfSSLJNIException, NoSuchAlgorithmException,
+ CertificateException, CRLException {
+
+ Assume.assumeTrue(WolfSSL.CrlGenerationEnabled());
+
+ /* Second serial has the top bit set, so the DER INTEGER needs a
+ * leading zero to stay positive */
+ byte[][] serials = new byte[][] {
+ { 0x01, 0x02, 0x03, 0x04 },
+ { (byte)0x80, 0x01, 0x02, 0x03 }
+ };
+ for (byte[] serial : serials) {
+ WolfSSLCRL crl = generateSignedTestCRL(serial);
+ byte[] der = null;
+ try {
+ der = crl.getDer();
+ }
+ finally {
+ crl.free();
+ }
+ assertNotNull(der);
+
+ X509CRL decoded = (X509CRL)CertificateFactory.getInstance("X.509")
+ .generateCRL(new ByteArrayInputStream(der));
+ assertNotNull(decoded.getRevokedCertificates());
+ assertEquals(1, decoded.getRevokedCertificates().size());
+ assertNotNull("revoked serial should match the input bytes",
+ decoded.getRevokedCertificate(new BigInteger(1, serial)));
+ }
+ }
+
@Test
public void testAddRevokedCert_ByteArray()
throws WolfSSLException, WolfSSLJNIException, IOException,