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,