diff --git a/native/com_wolfssl_WolfSSL.c b/native/com_wolfssl_WolfSSL.c index 1d46dc7b..109bb808 100644 --- a/native/com_wolfssl_WolfSSL.c +++ b/native/com_wolfssl_WolfSSL.c @@ -2027,7 +2027,12 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSL_x509_1getDer derCert = wolfSSL_X509_get_der(x509, &outSz); - if (outSz >= 0) { + if (outSz >= 0 && derCert != NULL) { + + out = (*jenv)->NewByteArray(jenv, outSz); + if (out == NULL) { + return NULL; + } (*jenv)->SetByteArrayRegion(jenv, out, 0, outSz, (jbyte*)derCert); if ((*jenv)->ExceptionOccurred(jenv)) { diff --git a/native/com_wolfssl_WolfSSLCRL.c b/native/com_wolfssl_WolfSSLCRL.c index c0d6ef44..86a02dbe 100644 --- a/native/com_wolfssl_WolfSSLCRL.c +++ b/native/com_wolfssl_WolfSSLCRL.c @@ -174,7 +174,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1lastUpdate } } - (*jenv)->ReleaseByteArrayElements(jenv, time, (jbyte*)timeBuf, JNI_ABORT); + if (timeBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, time, + (jbyte*)timeBuf, JNI_ABORT); + } return (jint)ret; #else @@ -230,7 +233,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1nextUpdate } } - (*jenv)->ReleaseByteArrayElements(jenv, time, (jbyte*)timeBuf, JNI_ABORT); + if (timeBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, time, + (jbyte*)timeBuf, JNI_ABORT); + } return (jint)ret; #else @@ -285,8 +291,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1add_1revoked } } - (*jenv)->ReleaseByteArrayElements(jenv, serial, (jbyte*)serialBuf, - JNI_ABORT); + if (serialBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, serial, + (jbyte*)serialBuf, JNI_ABORT); + } if (serialInt != NULL) { wolfSSL_ASN1_INTEGER_free(serialInt); } @@ -329,8 +337,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1add_1revoked_1cert ret = wolfSSL_X509_CRL_add_revoked_cert(crl, certBuf, certSz); } - (*jenv)->ReleaseByteArrayElements(jenv, certDer, (jbyte*)certBuf, - JNI_ABORT); + if (certBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, certDer, + (jbyte*)certBuf, JNI_ABORT); + } return ret; #else diff --git a/native/com_wolfssl_WolfSSLCertManager.c b/native/com_wolfssl_WolfSSLCertManager.c index bff116e6..3ff2e035 100644 --- a/native/com_wolfssl_WolfSSLCertManager.c +++ b/native/com_wolfssl_WolfSSLCertManager.c @@ -119,9 +119,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertManager_CertManagerLoadCABuff buff = (byte*)(*jenv)->GetByteArrayElements(jenv, in, NULL); buffSz = (*jenv)->GetArrayLength(jenv, in); - ret = wolfSSL_CertManagerLoadCABuffer(cm, buff, buffSz, format); - - (*jenv)->ReleaseByteArrayElements(jenv, in, (jbyte*)buff, JNI_ABORT); + if (buff != NULL) { + ret = wolfSSL_CertManagerLoadCABuffer(cm, buff, buffSz, format); + (*jenv)->ReleaseByteArrayElements(jenv, in, + (jbyte*)buff, JNI_ABORT); + } + else { + ret = BAD_FUNC_ARG; + } return (jint)ret; } diff --git a/native/com_wolfssl_WolfSSLCertRequest.c b/native/com_wolfssl_WolfSSLCertRequest.c index b21f9843..5aee77af 100644 --- a/native/com_wolfssl_WolfSSLCertRequest.c +++ b/native/com_wolfssl_WolfSSLCertRequest.c @@ -136,7 +136,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1add1_1attr attr, attrSz); } - (*jenv)->ReleaseByteArrayElements(jenv, attrBytes, (jbyte*)attr, JNI_ABORT); + if (attr != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, attrBytes, + (jbyte*)attr, JNI_ABORT); + } return (jint)ret; #else @@ -338,8 +341,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1sign XMEMSET(derBuf, 0, derSz); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - (*jenv)->ReleaseByteArrayElements(jenv, keyBytes, (jbyte*)keyBuf, - JNI_ABORT); + if (keyBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, keyBytes, + (jbyte*)keyBuf, JNI_ABORT); + } if (mdName != NULL) { (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); } @@ -447,8 +452,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1pubke XMEMSET(derBuf, 0, derSz); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, - JNI_ABORT); + if (fileBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, + (jbyte*)fileBuf, JNI_ABORT); + } return (jint)ret; #else diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index dd5a12bc..be9e316e 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -156,7 +156,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1issuer_1na wolfSSL_X509_free(x509In); } - (*jenv)->ReleaseByteArrayElements(jenv, certDer, (jbyte*)der, JNI_ABORT); + if (der != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, certDer, + (jbyte*)der, JNI_ABORT); + } return ret; #else @@ -260,8 +263,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1pubkey_1na XMEMSET(derBuf, 0, derSz); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, - JNI_ABORT); + if (fileBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, + (jbyte*)fileBuf, JNI_ABORT); + } return (jint)ret; #else @@ -562,6 +567,11 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1serialNumb if (serial == NULL) { ret = WOLFSSL_FAILURE; } + else if (serialSz > (int)(serial->dataMax - 2)) { + wolfSSL_ASN1_INTEGER_free(serial); + serial = NULL; + ret = WOLFSSL_FAILURE; + } else { serial->data[0] = ASN_INTEGER; serial->data[1] = serialSz; @@ -579,8 +589,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1serialNumb wolfSSL_ASN1_INTEGER_free(serial); } - (*jenv)->ReleaseByteArrayElements(jenv, serialBytes, (jbyte*)serialBuf, - JNI_ABORT); + if (serialBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, serialBytes, + (jbyte*)serialBuf, JNI_ABORT); + } return ret; #else @@ -621,7 +633,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1subject_1k ret = wolfSSL_X509_set_subject_key_id(x509, skidBuf, skidSz); } - (*jenv)->ReleaseByteArrayElements(jenv, skid, (jbyte*)skidBuf, JNI_ABORT); + if (skidBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, skid, + (jbyte*)skidBuf, JNI_ABORT); + } return (jint)ret; #else @@ -693,7 +708,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1authority_ ret = wolfSSL_X509_set_authority_key_id(x509, akidBuf, akidSz); } - (*jenv)->ReleaseByteArrayElements(jenv, akid, (jbyte*)akidBuf, JNI_ABORT); + if (akidBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, akid, + (jbyte*)akidBuf, JNI_ABORT); + } return (jint)ret; #else @@ -767,7 +785,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1CRL_1set_1dist_ ret = wolfSSL_X509_CRL_set_dist_points(x509, derBuf, derSz); } - (*jenv)->ReleaseByteArrayElements(jenv, der, (jbyte*)derBuf, JNI_ABORT); + if (derBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, der, + (jbyte*)derBuf, JNI_ABORT); + } return (jint)ret; #else @@ -968,8 +989,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1sign XMEMSET(derBuf, 0, derSz); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, - JNI_ABORT); + if (fileBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, + (jbyte*)fileBuf, JNI_ABORT); + } if (mdName != NULL) { (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); } @@ -1008,7 +1031,10 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1load_1certific } /* release array, don't copy back contents */ - (*jenv)->ReleaseByteArrayElements(jenv, in, (jbyte*)certBuf, JNI_ABORT); + if (certBuf != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, in, + (jbyte*)certBuf, JNI_ABORT); + } return (jlong)(uintptr_t)x509; } diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c index 3a0633a4..1606c5b6 100644 --- a/native/com_wolfssl_WolfSSLContext.c +++ b/native/com_wolfssl_WolfSSLContext.c @@ -558,6 +558,7 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) JNIEnv* jenv; jint vmret = 0; jint retval = -1; + int needsDetach = 0; jclass excClass = NULL; jclass verifyClass = NULL; jmethodID verifyMethod = NULL; @@ -579,6 +580,7 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) if (vmret) { return -101; /* failed to attach JNIEnv to thread */ } + needsDetach = 1; } else if (vmret != JNI_OK) { return -102; /* unable to get JNIEnv from JavaVM */ } @@ -588,6 +590,8 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) if( (*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -103; } @@ -605,6 +609,8 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) (*jenv)->ThrowNew(jenv, excClass, "Can't get native WolfSSLVerifyCallback class reference"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -104; } @@ -618,6 +624,8 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) (*jenv)->ThrowNew(jenv, excClass, "Error getting verifyCallback method from JNI"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -105; } @@ -628,6 +636,8 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) /* exception occurred on the Java side during method call */ (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -106; } @@ -639,9 +649,14 @@ int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) (*jenv)->ThrowNew(jenv, excClass, "Object reference invalid in NativeVerifyCallback"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -1; } + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); + return retval; } diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index a4bca55f..795696d8 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -105,6 +105,7 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) JNIEnv* jenv; jint vmret = 0; jint retval = -1; + int needsDetach = 0; jobjectRefType refcheck; SSLAppData* appData; /* WOLFSSL app data, stored verify cb obj */ jobject* g_verifySSLCbIfaceObj; /* Global jobject, stored in app data */ @@ -125,6 +126,7 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) if (vmret) { return -101; /* failed to attach JNIEnv to thread */ } + needsDetach = 1; } else if (vmret != JNI_OK) { return -102; /* unable to get JNIEnv from JavaVM */ } @@ -134,6 +136,8 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) wolfSSL_X509_STORE_CTX_get_ex_data(store, 0)); if (appData == NULL) { printf("Error getting app data from WOLFSSL\n"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -105; } @@ -141,6 +145,8 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) g_verifySSLCbIfaceObj = appData->g_verifySSLCbIfaceObj; if (g_verifySSLCbIfaceObj == NULL || *g_verifySSLCbIfaceObj == NULL) { printf("Error getting g_verifySSLCbIfaceObj from appData\n"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -106; } @@ -156,6 +162,8 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) throwWolfSSLJNIException(jenv, "verifyCallback method ID is null in NativeSSLVerifyCallback"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -107; } @@ -167,6 +175,8 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) /* exception occurred on the Java side during method call */ (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -109; } @@ -178,9 +188,14 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) throwWolfSSLJNIException(jenv, "Object reference invalid in NativeSSLVerifyCallback"); + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); return -1; } + if (needsDetach) + (*g_vm)->DetachCurrentThread(g_vm); + return retval; } diff --git a/native/com_wolfssl_WolfSSLX509Name.c b/native/com_wolfssl_WolfSSLX509Name.c index f9d0c8c0..d80787ed 100644 --- a/native/com_wolfssl_WolfSSLX509Name.c +++ b/native/com_wolfssl_WolfSSLX509Name.c @@ -106,8 +106,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1add_1entry_1 entry, len, (int)loc, (int)set); } - (*jenv)->ReleaseByteArrayElements(jenv, entryArr, (jbyte*)entry, JNI_ABORT); - (*jenv)->ReleaseStringUTFChars(jenv, fieldStr, field); + if (entry != NULL) { + (*jenv)->ReleaseByteArrayElements(jenv, entryArr, + (jbyte*)entry, JNI_ABORT); + } + if (field != NULL) { + (*jenv)->ReleaseStringUTFChars(jenv, fieldStr, field); + } return (jint)ret; #else diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLAuthStore.java b/src/java/com/wolfssl/provider/jsse/WolfSSLAuthStore.java index 10858f45..1ff24ea5 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLAuthStore.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLAuthStore.java @@ -284,7 +284,7 @@ protected void resizeCache(int sz, int side) { /* @TODO check for side server/client, currently a resize is for all */ synchronized (storeLock) { - store.putAll(newStore); + newStore.putAll(store); store = newStore; } } diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java index 9b347989..8959d60c 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSessionContextTest.java @@ -250,6 +250,70 @@ private void testSetCacheSize(SSLSession ses) { pass("\t\t... passed"); } + private void testResizeCache(SSLSession ses) { + System.out.print("\tTesting ResizeCache"); + + if (ctx.getProvider() != Security.getProvider("wolfJSSE")) { + pass("\t\t... skipped"); + return; + } + + SSLSessionContext sesCtx = ses.getSessionContext(); + if (sesCtx == null) { + error("\t\t... failed"); + fail("session context was null"); + } + + int originalSize = sesCtx.getSessionCacheSize(); + + /* get session IDs and count before resize */ + Enumeration idsBefore = sesCtx.getIds(); + int countBefore = 0; + byte[] firstId = null; + while (idsBefore.hasMoreElements()) { + byte[] id = idsBefore.nextElement(); + if (firstId == null) { + firstId = id; + } + countBefore++; + } + + if (countBefore == 0 || firstId == null) { + error("\t\t... failed"); + fail("no sessions in cache before resize"); + } + + /* resize up, all sessions should survive */ + sesCtx.setSessionCacheSize(countBefore + 10); + + Enumeration idsAfter = sesCtx.getIds(); + int countAfter = 0; + boolean found = false; + while (idsAfter.hasMoreElements()) { + byte[] id = idsAfter.nextElement(); + if (Arrays.equals(id, firstId)) { + found = true; + } + countAfter++; + } + + if (countAfter != countBefore) { + error("\t\t... failed"); + fail("resize-up lost sessions: before=" + + countBefore + " after=" + countAfter); + } + + if (!found) { + error("\t\t... failed"); + fail("original session ID not found after resize"); + } + + /* restore original cache size */ + sesCtx.setSessionCacheSize(originalSize); + + pass("\t\t... passed"); + } + @Test public void testSessionIDsTLS13() throws NoSuchProviderException, NoSuchAlgorithmException, @@ -518,6 +582,7 @@ public void testSessionIDs() /* additional tests on the engines and sessions while open */ testSetCacheSize(ses); + testResizeCache(ses); try {