diff --git a/native/com_wolfssl_WolfSSL.c b/native/com_wolfssl_WolfSSL.c index f8a279f..dc0c5fb 100644 --- a/native/com_wolfssl_WolfSSL.c +++ b/native/com_wolfssl_WolfSSL.c @@ -53,6 +53,22 @@ JavaVM* g_vm; /* global object refs for logging callbacks */ static jobject g_loggingCbIfaceObj; +/* global method IDs we can cache for performance */ +jmethodID g_sslIORecvMethodId = NULL; +jmethodID g_sslIORecvMethodId_BB = NULL; +jmethodID g_sslIOSendMethodId = NULL; +jmethodID g_sslIOSendMethodId_BB = NULL; +jmethodID g_isArrayIORecvCallbackSet = NULL; +jmethodID g_isArrayIOSendCallbackSet = NULL; +jmethodID g_isByteBufferIORecvCallbackSet = NULL; +jmethodID g_isByteBufferIOSendCallbackSet = NULL; +jmethodID g_bufferPositionMethodId = NULL; +jmethodID g_bufferLimitMethodId = NULL; +jmethodID g_bufferHasArrayMethodId = NULL; +jmethodID g_bufferArrayMethodId = NULL; +jmethodID g_bufferSetPositionMethodId = NULL; +jmethodID g_verifyCallbackMethodId = NULL; + #ifdef HAVE_FIPS /* global object ref for FIPS error callback */ static jobject g_fipsCbIfaceObj; @@ -61,16 +77,192 @@ static jobject g_fipsCbIfaceObj; /* custom native fn prototypes */ void NativeLoggingCallback(const int logLevel, const char *const logMessage); -/* called when native library is loaded */ +/* Called when native library is loaded. + * We also cache global jmethodIDs here for performance. */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { + JNIEnv* env = NULL; + jclass sslClass = NULL; + jclass byteBufferClass = NULL; + jclass verifyClass = NULL; (void)reserved; /* store JavaVM */ g_vm = vm; + + /* get JNIEnv from JavaVM */ + if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { + printf("Unable to get JNIEnv from JavaVM in JNI_OnLoad()\n"); + return JNI_ERR; + } + + /* Cache the method ID for IO send and recv callbacks */ + sslClass = (*env)->FindClass(env, "com/wolfssl/WolfSSLSession"); + if (sslClass == NULL) { + return JNI_ERR; + } + + g_sslIORecvMethodId = (*env)->GetMethodID(env, sslClass, + "internalIOSSLRecvCallback", + "(Lcom/wolfssl/WolfSSLSession;[BI)I"); + if (g_sslIORecvMethodId == NULL) { + return JNI_ERR; + } + + g_sslIORecvMethodId_BB = (*env)->GetMethodID(env, sslClass, + "internalIOSSLRecvCallback", + "(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;I)I"); + if (g_sslIORecvMethodId_BB == NULL) { + return JNI_ERR; + } + + g_sslIOSendMethodId = (*env)->GetMethodID(env, sslClass, + "internalIOSSLSendCallback", + "(Lcom/wolfssl/WolfSSLSession;[BI)I"); + if (g_sslIOSendMethodId == NULL) { + return JNI_ERR; + } + + g_sslIOSendMethodId_BB = (*env)->GetMethodID(env, sslClass, + "internalIOSSLSendCallback", + "(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;I)I"); + if (g_sslIOSendMethodId_BB == NULL) { + return JNI_ERR; + } + + g_isArrayIORecvCallbackSet = (*env)->GetMethodID(env, sslClass, + "isArrayIORecvCallbackSet", "()Z"); + if (g_isArrayIORecvCallbackSet == NULL) { + return JNI_ERR; + } + + g_isArrayIOSendCallbackSet = (*env)->GetMethodID(env, sslClass, + "isArrayIOSendCallbackSet", "()Z"); + if (g_isArrayIOSendCallbackSet == NULL) { + return JNI_ERR; + } + + g_isByteBufferIORecvCallbackSet = (*env)->GetMethodID(env, sslClass, + "isByteBufferIORecvCallbackSet", "()Z"); + if (g_isByteBufferIORecvCallbackSet == NULL) { + return JNI_ERR; + } + + g_isByteBufferIOSendCallbackSet = (*env)->GetMethodID(env, sslClass, + "isByteBufferIOSendCallbackSet", "()Z"); + if (g_isByteBufferIOSendCallbackSet == NULL) { + return JNI_ERR; + } + + /* Cache ByteBuffer method IDs */ + byteBufferClass = (*env)->FindClass(env, "java/nio/ByteBuffer"); + if (byteBufferClass == NULL) { + return JNI_ERR; + } + + g_bufferPositionMethodId = (*env)->GetMethodID(env, byteBufferClass, + "position", "()I"); + if (g_bufferPositionMethodId == NULL) { + return JNI_ERR; + } + + g_bufferLimitMethodId = (*env)->GetMethodID(env, byteBufferClass, + "limit", "()I"); + if (g_bufferLimitMethodId == NULL) { + return JNI_ERR; + } + + g_bufferHasArrayMethodId = (*env)->GetMethodID(env, byteBufferClass, + "hasArray", "()Z"); + if (g_bufferHasArrayMethodId == NULL) { + return JNI_ERR; + } + + g_bufferArrayMethodId = (*env)->GetMethodID(env, byteBufferClass, + "array", "()[B"); + if (g_bufferArrayMethodId == NULL) { + return JNI_ERR; + } + + g_bufferSetPositionMethodId = (*env)->GetMethodID(env, byteBufferClass, + "position", "(I)Ljava/nio/Buffer;"); + if (g_bufferSetPositionMethodId == NULL) { + return JNI_ERR; + } + + /* Cache verify callback method ID */ + verifyClass = (*env)->FindClass(env, "com/wolfssl/WolfSSLVerifyCallback"); + if (verifyClass == NULL) { + return JNI_ERR; + } + + g_verifyCallbackMethodId = (*env)->GetMethodID(env, verifyClass, + "verifyCallback", "(IJ)I"); + if (g_verifyCallbackMethodId == NULL) { + return JNI_ERR; + } + + /* Clean up local reference to class, not needed */ + (*env)->DeleteLocalRef(env, sslClass); + (*env)->DeleteLocalRef(env, byteBufferClass); + (*env)->DeleteLocalRef(env, verifyClass); + return JNI_VERSION_1_6; } +/* Called when native library is unloaded. + * We clear cached method IDs here. */ +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) +{ + JNIEnv* env; + + if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { + return; + } + + /* Clear cached method ID */ + g_sslIORecvMethodId = NULL; + g_sslIORecvMethodId_BB = NULL; + g_sslIOSendMethodId = NULL; + g_sslIOSendMethodId_BB = NULL; + g_isArrayIORecvCallbackSet = NULL; + g_isArrayIOSendCallbackSet = NULL; + g_isByteBufferIORecvCallbackSet = NULL; + g_isByteBufferIOSendCallbackSet = NULL; + g_bufferPositionMethodId = NULL; + g_bufferLimitMethodId = NULL; + g_bufferHasArrayMethodId = NULL; + g_bufferArrayMethodId = NULL; + g_bufferSetPositionMethodId = NULL; + g_verifyCallbackMethodId = NULL; +} + +/** + * Throw WolfSSLJNIException + */ +void throwWolfSSLJNIException(JNIEnv* jenv, const char* msg) +{ + jclass excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); + if (excClass == NULL) { + /* Unable to find exception class, give up trying to throw */ + return; + } + (*jenv)->ThrowNew(jenv, excClass, msg); +} + +/** + * Throw WolfSSLException + */ +void throwWolfSSLException(JNIEnv* jenv, const char* msg) +{ + jclass excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); + if (excClass == NULL) { + /* Unable to find exception class, give up trying to throw */ + return; + } + (*jenv)->ThrowNew(jenv, excClass, msg); +} + JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_init (JNIEnv* jenv, jobject jcl) { diff --git a/native/com_wolfssl_WolfSSLContext.c b/native/com_wolfssl_WolfSSLContext.c index 1da4b23..cf4de17 100644 --- a/native/com_wolfssl_WolfSSLContext.c +++ b/native/com_wolfssl_WolfSSLContext.c @@ -1028,7 +1028,6 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) jobject ctxRef; /* WolfSSLContext object */ jclass innerCtxClass; /* WolfSSLContext class */ - jmethodID recvCbMethodId; /* internalIORecvCallback ID */ jbyteArray inData; if (!g_vm || !ssl || !buf || !ctx) { @@ -1140,18 +1139,10 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - /* call internal I/O recv callback */ - recvCbMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass, - "internalIORecvCallback", - "(Lcom/wolfssl/WolfSSLSession;[BI)I"); - if (!recvCbMethodId) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } + /* make sure cached recv callback method ID is not null */ + if (!g_sslIORecvMethodId) { (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIORecvCallback method from JNI"); - (*jenv)->DeleteLocalRef(jenv, ctxRef); + "Cached recv callback method ID is null in NativeIORecvCb"); if (needsDetach) (*g_vm)->DetachCurrentThread(g_vm); return WOLFSSL_CBIO_ERR_GENERAL; @@ -1161,7 +1152,7 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) inData = (*jenv)->NewByteArray(jenv, sz); if (!inData) { (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIORecvCallback method from JNI"); + "Error creating jbyteArray in NativeIORecvCb"); (*jenv)->DeleteLocalRef(jenv, ctxRef); if (needsDetach) (*g_vm)->DetachCurrentThread(g_vm); @@ -1170,7 +1161,7 @@ int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) /* call Java send callback, ignore native ctx since Java * handles it */ - retval = (*jenv)->CallIntMethod(jenv, ctxRef, recvCbMethodId, + retval = (*jenv)->CallIntMethod(jenv, ctxRef, g_sslIORecvMethodId, (jobject)(*g_cachedSSLObj), inData, (jint)sz); diff --git a/native/com_wolfssl_WolfSSLSession.c b/native/com_wolfssl_WolfSSLSession.c index 897e530..832b7a2 100644 --- a/native/com_wolfssl_WolfSSLSession.c +++ b/native/com_wolfssl_WolfSSLSession.c @@ -102,9 +102,6 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) JNIEnv* jenv; jint vmret = 0; jint retval = -1; - jclass excClass; - jclass verifyClass = NULL; - jmethodID verifyMethod; jobjectRefType refcheck; SSLAppData* appData; /* WOLFSSL app data, stored verify cb obj */ jobject* g_verifySSLCbIfaceObj; /* Global jobject, stored in app data */ @@ -129,14 +126,6 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) return -102; /* unable to get JNIEnv from JavaVM */ } - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if( (*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return -103; - } - /* get app data to retrieve stored Java jobject callback object */ appData = (SSLAppData*)wolfSSL_get_app_data( wolfSSL_X509_STORE_CTX_get_ex_data(store, 0)); @@ -156,34 +145,20 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) refcheck = (*jenv)->GetObjectRefType(jenv, *g_verifySSLCbIfaceObj); if (refcheck == 2) { - /* lookup WolfSSLVerifyCallback class from global object ref */ - verifyClass = (*jenv)->GetObjectClass(jenv, *g_verifySSLCbIfaceObj); - if (!verifyClass) { + if (!g_verifyCallbackMethodId) { if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, - "Can't get native WolfSSLVerifyCallback class reference"); + throwWolfSSLJNIException(jenv, + "verifyCallback method ID is null in NativeSSLVerifyCallback"); return -107; } - verifyMethod = (*jenv)->GetMethodID(jenv, verifyClass, - "verifyCallback", "(IJ)I"); - if (verifyMethod == 0) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - - (*jenv)->ThrowNew(jenv, excClass, - "Error getting verifyCallback method from JNI"); - return -108; - } - retval = (*jenv)->CallIntMethod(jenv, *g_verifySSLCbIfaceObj, - verifyMethod, preverify_ok, (jlong)(uintptr_t)store); + g_verifyCallbackMethodId, preverify_ok, + (jlong)(uintptr_t)store); if ((*jenv)->ExceptionOccurred(jenv)) { /* exception occurred on the Java side during method call */ @@ -198,7 +173,7 @@ int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store) (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Object reference invalid in NativeSSLVerifyCallback"); return -1; } @@ -710,7 +685,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainFile JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setUsingNonblock (JNIEnv* jenv, jobject jcl, jlong sslPtr, jint nonblock) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -719,13 +693,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setUsingNonblock } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null in setUsingNonblock"); } @@ -735,7 +703,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setUsingNonblock JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getUsingNonblock (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -744,13 +711,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getUsingNonblock } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return 0; - } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null in getUsingNonblock"); } @@ -760,7 +721,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getUsingNonblock JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getFd (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -769,13 +729,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getFd } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return 0; - } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null in getFd"); return 0; } @@ -1416,14 +1370,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff byte* data = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; - jclass excClass; - jclass buffClass; - jmethodID positionMeth; - jmethodID limitMeth; - jmethodID hasArrayMeth; - jmethodID arrayMeth; - jmethodID setPositionMeth; - jint position; jint limit; jboolean hasArray; @@ -1436,59 +1382,15 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff } if (length > 0) { - /* Get WolfSSLException class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return -1; - } - - /* Get ByteBuffer class */ - buffClass = (*jenv)->GetObjectClass(jenv, buf); - if (buffClass == NULL) { - (*jenv)->ThrowNew(jenv, excClass, - "Failed to find ByteBuffer class in native read()"); - return -1; - } - /* Get ByteBuffer position */ - positionMeth = (*jenv)->GetMethodID(jenv, buffClass, "position", "()I"); - if (positionMeth == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Failed to find ByteBuffer position() method in native read()"); - return -1; - } - position = (*jenv)->CallIntMethod(jenv, buf, positionMeth); + position = (*jenv)->CallIntMethod(jenv, buf, g_bufferPositionMethodId); /* Get ByteBuffer limit */ - limitMeth = (*jenv)->GetMethodID(jenv, buffClass, "limit", "()I"); - if (limitMeth == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Failed to find ByteBuffer limit() method in native read()"); - return -1; - } - limit = (*jenv)->CallIntMethod(jenv, buf, limitMeth); + limit = (*jenv)->CallIntMethod(jenv, buf, g_bufferLimitMethodId); /* Get and call ByteBuffer.hasArray() before calling array() */ - hasArrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "hasArray", "()Z"); - if (hasArrayMeth == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Failed to find ByteBuffer hasArray() method in native read()"); - return -1; - } + hasArray = (*jenv)->CallBooleanMethod(jenv, buf, + g_bufferHasArrayMethodId); /* Only read up to maximum space we have in this ByteBuffer */ maxOutputSz = (limit - position); @@ -1496,54 +1398,43 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff outSz = maxOutputSz; } - hasArray = (*jenv)->CallBooleanMethod(jenv, buf, hasArrayMeth); - if (hasArray) { /* Get reference to underlying byte[] from ByteBuffer */ - arrayMeth = (*jenv)->GetMethodID(jenv, buffClass, "array", "()[B"); - if (arrayMeth == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Failed to find ByteBuffer array() method in native read()"); - return -1; - } - bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, arrayMeth); + bufArr = (jbyteArray)(*jenv)->CallObjectMethod(jenv, buf, + g_bufferArrayMethodId); /* Get array elements */ data = (byte *)(*jenv)->GetByteArrayElements(jenv, bufArr, NULL); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, - "Exception when calling ByteBuffer.array() in native read()"); + throwWolfSSLJNIException(jenv, + "Exception when calling ByteBuffer.array() in native read()"); return -1; } } else { data = (byte *)(*jenv)->GetDirectBufferAddress(jenv, buf); if (data == NULL) { - (*jenv)->ThrowNew(jenv, excClass, - "Failed to get DirectBuffer address in native read()"); + throwWolfSSLJNIException(jenv, + "Failed to get DirectBuffer address in native read()"); return BAD_FUNC_ARG; } } if (data != NULL) { size = SSLReadNonblockingWithSelectPoll(ssl, data + position, - maxOutputSz, (int)timeout); + maxOutputSz, (int)timeout); /* Relase array elements */ if (hasArray) { if (size < 0) { - (*jenv)->ReleaseByteArrayElements(jenv, bufArr, (jbyte *)data, - JNI_ABORT); + (*jenv)->ReleaseByteArrayElements(jenv, bufArr, + (jbyte *)data, JNI_ABORT); } else { (*jenv)->ReleaseByteArrayElements(jenv, bufArr, - (jbyte *)data, 0); + (jbyte *)data, 0); } } @@ -1551,22 +1442,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read__JLjava_nio_ByteBuff if (size > 0) { /* Update ByteBuffer position() based on bytes written */ - setPositionMeth = (*jenv)->GetMethodID(jenv, buffClass, - "position", "(I)Ljava/nio/Buffer;"); - if (setPositionMeth == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Failed to set ByteBuffer position() from " - "native read()"); - size = -1; - } - else { - (*jenv)->CallVoidMethod(jenv, buf, setPositionMeth, - position + size); - } + (*jenv)->CallVoidMethod(jenv, buf, g_bufferSetPositionMethodId, + position + size); } } } @@ -1695,7 +1572,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL { jobject* g_cachedSSLObj; jobject* g_cachedVerifyCb; - jclass excClass; SSLAppData* appData; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -1703,16 +1579,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL internCtx* pkCtx = NULL; #endif - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if (ssl == NULL) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in freeSSL"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in freeSSL"); return; } @@ -1760,8 +1629,8 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL (*jenv)->ExceptionClear(jenv); return; } - (*jenv)->ThrowNew(jenv, excClass, - "Error reseting internal wolfSSL JNI pointer to NULL, freeSSL"); + throwWolfSSLException(jenv, + "Error reseting internal wolfSSL JNI pointer to NULL, freeSSL"); return; } @@ -2400,20 +2269,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetCurrentTimeout (JNIEnv* jenv, jobject jcl, jlong sslPtr) { #if !defined(WOLFSSL_LEANPSK) && defined(WOLFSSL_DTLS) - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return 0; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "dtlsGetCurrentTimeout()"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in " + "dtlsGetCurrentTimeout()"); return 0; } @@ -2490,7 +2352,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer struct sockaddr_in sa; const char* ipAddress = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; - jclass excClass = NULL; jclass inetsockaddr = NULL; jclass inetaddr = NULL; jmethodID portID = NULL; @@ -2507,7 +2368,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer } /* get class references */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); inetsockaddr = (*jenv)->FindClass(jenv, "java/net/InetSocketAddress"); inetaddr = (*jenv)->FindClass(jenv, "java/net/InetAddress"); @@ -2517,7 +2377,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, "Can't get getPort() method ID"); + throwWolfSSLException(jenv, "Can't get getPort() method ID"); return SSL_FAILURE; } (*jenv)->ExceptionClear(jenv); @@ -2535,7 +2395,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, "Can't get getAddress() method ID"); + throwWolfSSLException(jenv, "Can't get getAddress() method ID"); return SSL_FAILURE; } (*jenv)->ExceptionClear(jenv); @@ -2552,8 +2412,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, - "Can't get isAnyLocalAddress() method ID"); + throwWolfSSLException(jenv, "Can't get isAnyLocalAddress() method ID"); return SSL_FAILURE; } (*jenv)->ExceptionClear(jenv); @@ -2572,8 +2431,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, - "Can't get getHostAddress() method ID"); + throwWolfSSLException(jenv, "Can't get getHostAddress() method ID"); return SSL_FAILURE; } ipAddr = (*jenv)->CallObjectMethod(jenv, addrObj, ipAddrID); @@ -2631,7 +2489,6 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer jmethodID constr; jstring ipAddr; - jclass excClass = NULL; jclass isa = NULL; (void)jcl; @@ -2668,13 +2525,12 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer port = ntohs(peer.sin_port); /* create new InetSocketAddress with this IP/port info */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); isa = (*jenv)->FindClass(jenv, "java/net/InetSocketAddress"); if (!isa) { if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, "Can't find InetSocketAddress class"); + throwWolfSSLException(jenv, "Can't find InetSocketAddress class"); return NULL; } @@ -2685,13 +2541,13 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer if (peer.sin_addr.s_addr != INADDR_ANY) { constr = (*jenv)->GetMethodID(jenv, isa, "", - "(Ljava/lang/String;I)V"); + "(Ljava/lang/String;I)V"); if (!constr) { if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, - "Can't find InetSocketAddress(String,port)"); + throwWolfSSLException(jenv, + "Can't find InetSocketAddress(String,port)"); return NULL; } @@ -2705,8 +2561,8 @@ JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer if ((*jenv)->ExceptionOccurred(jenv)) (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, - "Can't find InetSocketAddress(port)"); + throwWolfSSLException(jenv, + "Can't find InetSocketAddress(port)"); return NULL; } @@ -2836,21 +2692,36 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_stateStringLong #endif } +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getMaxOutputSize + (JNIEnv* jenv, jobject jcl, jlong sslPtr) +{ +#ifndef NO_TLS + int ret; + WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; + + if (jenv == NULL || ssl == NULL) { + return 0; + } + + ret = wolfSSL_GetMaxOutputSize(ssl); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)sslPtr; + return (jint)NOT_COMPILED_IN; +#endif +} + JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in sessionReused()"); return SSL_FAILURE; } @@ -2977,20 +2848,12 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPeerX509AltName JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getVersion (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "getVersion"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in getVersion"); return NULL; } @@ -3000,20 +2863,12 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getVersion JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getCurrentCipher (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "getVersion"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in getVersion"); return SSL_FAILURE; } @@ -3025,7 +2880,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_checkDomainName { int ret; const char* dname; - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3034,15 +2888,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_checkDomainName } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "checkDomainName"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in checkDomainName"); return SSL_FAILURE; } @@ -3061,7 +2908,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDH { #ifndef NO_DH int ret; - jclass excClass; unsigned char* pBuf = NULL; unsigned char* gBuf = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; @@ -3072,15 +2918,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDH } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "setTmpDH"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in setTmpDH"); return SSL_FAILURE; } @@ -3139,7 +2978,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDHFile #if !defined(NO_DH) && !defined(NO_FILESYSTEM) int ret; const char* fname; - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3148,15 +2986,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDHFile } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "setTmpDHFile"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in setTmpDHFile"); return SSL_FAILURE; } @@ -3182,7 +3013,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateBuffer jint format) { int ret = SSL_SUCCESS; - jclass excClass; unsigned char* buff = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3192,15 +3022,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateBuffer } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "useCertificateBuffer"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in useCertificateBuffer"); return SSL_FAILURE; } @@ -3230,7 +3053,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_usePrivateKeyBuffer jint format) { int ret; - jclass excClass; unsigned char* buff = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3240,15 +3062,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_usePrivateKeyBuffer } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "usePrivateKeyBuffer"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in usePrivateKeyBuffer"); return SSL_FAILURE; } @@ -3277,7 +3092,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBuffer (JNIEnv* jenv, jobject jcl, jlong sslPtr, jbyteArray in, jlong sz) { int ret; - jclass excClass; unsigned char* buff = NULL; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3287,15 +3101,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBuffer } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "useCertificateChainBuffer"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in " + "useCertificateChainBuffer"); return SSL_FAILURE; } @@ -3350,20 +3158,12 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBuffer JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setGroupMessages (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "setGroupMessages"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in setGroupMessages"); return BAD_FUNC_ARG; } return wolfSSL_set_group_messages(ssl); @@ -3373,7 +3173,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_enableCRL (JNIEnv* jenv, jobject jcl, jlong sslPtr, jint options) { #ifdef HAVE_CRL - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3382,15 +3181,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_enableCRL } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "enableCRL"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in enableCRL"); return SSL_FAILURE; } @@ -3408,7 +3200,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_disableCRL (JNIEnv* jenv, jobject jcl, jlong sslPtr) { #ifdef HAVE_CRL - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3417,15 +3208,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_disableCRL } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "disableCRL"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in disableCRL"); return SSL_FAILURE; } @@ -3445,7 +3229,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_loadCRL #if defined(HAVE_CRL) && !defined(NO_FILESYSTEM) int ret; const char* crlPath; - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3454,15 +3237,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_loadCRL } if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was null in " - "loadCRL"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was null in loadCRL"); return SSL_FAILURE; } @@ -3489,7 +3265,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCRLCb { #ifdef HAVE_CRL int ret = 0; - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; @@ -3497,18 +3272,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCRLCb return BAD_FUNC_ARG; } - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return SSL_FAILURE; - } - if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, - "Input WolfSSLSession object was NULL in " - "setCRLCb"); + throwWolfSSLException(jenv, + "Input WolfSSLSession object was NULL in setCRLCb"); return SSL_FAILURE; } @@ -3522,8 +3288,8 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCRLCb /* store Java CRL callback Interface object */ g_crlCbIfaceObj = (*jenv)->NewGlobalRef(jenv, cb); if (g_crlCbIfaceObj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, - "Error storing global missingCRLCallback interface"); + throwWolfSSLException(jenv, + "Error storing global missingCRLCallback interface"); } ret = wolfSSL_SetCRL_Cb(ssl, NativeMissingCRLCallback); @@ -3545,7 +3311,6 @@ void NativeMissingCRLCallback(const char* url) { JNIEnv* jenv; jint vmret = 0; - jclass excClass = NULL; jclass crlClass = NULL; jmethodID crlMethod = NULL; jobjectRefType refcheck; @@ -3566,14 +3331,6 @@ void NativeMissingCRLCallback(const char* url) printf("Unable to get JNIEnv from JavaVM\n"); } - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - /* check if our stored object reference is valid */ refcheck = (*jenv)->GetObjectRefType(jenv, g_crlCbIfaceObj); if (refcheck == 2) { @@ -3581,7 +3338,7 @@ void NativeMissingCRLCallback(const char* url) /* lookup WolfSSLMissingCRLCallback class from global object ref */ crlClass = (*jenv)->GetObjectClass(jenv, g_crlCbIfaceObj); if (!crlClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get native WolfSSLMissingCRLCallback class reference"); return; } @@ -3595,7 +3352,7 @@ void NativeMissingCRLCallback(const char* url) (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Error getting missingCRLCallback method from JNI"); return; } @@ -3617,8 +3374,8 @@ void NativeMissingCRLCallback(const char* url) (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, - "Object reference invalid in NativeMissingCRLCallback"); + throwWolfSSLException(jenv, + "Object reference invalid in NativeMissingCRLCallback"); } } @@ -3629,18 +3386,11 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_cipherGetName { const char* cipherName; WOLFSSL_CIPHER* cipher; - jclass excClass; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; if (ssl == NULL) { - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "cipherGetName"); return NULL; @@ -3659,7 +3409,6 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_cipherGetName JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret (JNIEnv* jenv, jobject jcl, jlong sslPtr, jint verify) { - jclass excClass; #ifdef ATOMIC_USER int macLength; jbyteArray retSecret; @@ -3668,17 +3417,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - #ifdef ATOMIC_USER if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "getMacSecret"); return NULL; @@ -3694,7 +3435,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret /* create byte array to return */ retSecret = (*jenv)->NewByteArray(jenv, macLength); if (!retSecret) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to create byte array in native getMacSecret"); return NULL; } @@ -3713,7 +3454,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret return NULL; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with ATOMIC_USER"); return NULL; #endif @@ -3722,7 +3463,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #ifdef ATOMIC_USER int keyLength; jbyteArray retKey; @@ -3731,17 +3471,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - #ifdef ATOMIC_USER if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "getClientWriteKey"); return NULL; @@ -3756,7 +3488,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey /* create byte array to return */ retKey = (*jenv)->NewByteArray(jenv, keyLength); if (!retKey) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to create byte array in native getClientWriteKey"); return NULL; } @@ -3775,7 +3507,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey return NULL; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with ATOMIC_USER"); return NULL; #endif @@ -3784,7 +3516,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #ifdef ATOMIC_USER jbyteArray retIV; const unsigned char* iv; @@ -3793,17 +3524,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - #ifdef ATOMIC_USER if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "getClientWriteIV"); return NULL; @@ -3818,7 +3541,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV /* create byte array to return */ retIV = (*jenv)->NewByteArray(jenv, ivLength); if (!retIV) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to create byte array in native getClientWriteIV"); return NULL; } @@ -3837,7 +3560,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV return NULL; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with ATOMIC_USER"); return NULL; #endif @@ -3846,7 +3569,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #ifdef ATOMIC_USER jbyteArray retKey; const unsigned char* key; @@ -3855,17 +3577,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - #ifdef ATOMIC_USER if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "getServerWriteKey"); return NULL; @@ -3880,7 +3594,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey /* create byte array to return */ retKey = (*jenv)->NewByteArray(jenv, keyLength); if (!retKey) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to create byte array in native getServerWriteKey"); return NULL; } @@ -3899,7 +3613,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey return NULL; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with ATOMIC_USER"); return NULL; #endif @@ -3908,7 +3622,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteIV (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #ifdef ATOMIC_USER jbyteArray retIV; const unsigned char* iv; @@ -3917,17 +3630,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteIV WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return NULL; - } - #ifdef ATOMIC_USER if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "getServerWriteIV"); return NULL; @@ -3942,7 +3647,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteIV /* create byte array to return */ retIV = (*jenv)->NewByteArray(jenv, ivLength); if (!retIV) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to create byte array in native getServerWriteIV"); return NULL; } @@ -3961,7 +3666,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteIV return NULL; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with ATOMIC_USER"); return NULL; #endif @@ -4098,14 +3803,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTlsHmacInner return BAD_FUNC_ARG; } - /* find exception class */ - jclass excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return -1; - } - ret = wolfSSL_SetTlsHmacInner(ssl, hmacInner, (long)sz, content, verify); /* copy hmacInner back into inner jbyteArray */ @@ -4114,7 +3811,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTlsHmacInner if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Failed to set byte region in native setTlsHmacInner"); return -1; } @@ -4125,7 +3822,6 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTlsHmacInner JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) jclass sslClass; @@ -4134,17 +3830,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setEccSignCtx"); return; @@ -4153,7 +3841,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4175,7 +3863,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!myCtx) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for ECC sign context\n"); return; } @@ -4186,7 +3874,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (!myCtx->obj) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4195,7 +3883,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or ECC"); return; #endif @@ -4204,7 +3892,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) jclass sslClass; @@ -4213,17 +3900,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setEccVerifyCtx"); return; @@ -4232,7 +3911,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4254,7 +3933,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!myCtx) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for ECC verify context\n"); return; } @@ -4265,7 +3944,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4274,7 +3953,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or ECC"); return; #endif @@ -4283,7 +3962,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) jclass sslClass; @@ -4292,17 +3970,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setEccSharedSecretCtx"); return; @@ -4311,7 +3981,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4333,7 +4003,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (myCtx == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for ECC shared secret context\n"); return; } @@ -4344,7 +4014,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4353,7 +4023,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or ECC"); return; #endif @@ -4362,7 +4032,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) jclass sslClass; @@ -4371,17 +4040,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setRsaSignCtx"); return; @@ -4390,7 +4051,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4412,7 +4073,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (myCtx == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for RSA sign context\n"); return; } @@ -4423,7 +4084,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4432,7 +4093,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or RSA support"); return; #endif @@ -4441,7 +4102,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) jclass sslClass; @@ -4450,17 +4110,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setRsaVerifyCtx"); return; @@ -4469,7 +4121,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4491,7 +4143,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (myCtx == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for RSA verify context\n"); return; } @@ -4502,7 +4154,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4511,7 +4163,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or RSA support"); return; #endif @@ -4520,7 +4172,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) jclass sslClass; @@ -4529,18 +4180,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) - if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setRsaEncCtx"); return; @@ -4549,7 +4191,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4571,7 +4213,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (myCtx == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for RSA encrypt context\n"); return; } @@ -4582,7 +4224,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4591,7 +4233,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or RSA support"); return; #endif @@ -4600,7 +4242,6 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx (JNIEnv* jenv, jobject jcl, jlong sslPtr) { - jclass excClass; #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) jclass sslClass; @@ -4609,17 +4250,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; #endif - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) if (ssl == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Input WolfSSLSession object was null in " "setRsaDecCtx"); return; @@ -4628,7 +4261,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx /* get WolfSSLSession class from object ref */ sslClass = (*jenv)->GetObjectClass(jenv, jcl); if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Can't get WolfSSLSession object class"); return; } @@ -4650,7 +4283,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx /* allocate memory for internal JNI object reference */ myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (myCtx == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to allocate memory for RSA decrypt context\n"); return; } @@ -4661,7 +4294,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx /* store global ref to WolfSSLSession object */ myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl); if (myCtx->obj == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "Unable to store WolfSSLSession object as global reference"); return; } @@ -4670,7 +4303,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx #else (void)jcl; (void)sslPtr; - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLException(jenv, "wolfSSL not compiled with PK Callbacks and/or RSA support"); return; #endif @@ -4682,28 +4315,19 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setPskClientCb WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - jclass excClass = (*jenv)->FindClass(jenv, - "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #ifndef NO_PSK if (ssl != NULL) { /* set PSK client callback */ wolfSSL_set_psk_client_callback(ssl, NativePskClientCb); } else { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null when setting " "NativePskClientCb"); return; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "wolfSSL not compiled with PSK support"); return; #endif @@ -4715,28 +4339,19 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setPskServerCb WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; (void)jcl; - /* find exception class */ - jclass excClass = (*jenv)->FindClass(jenv, - "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - return; - } - #ifndef NO_PSK if (ssl != NULL) { /* set PSK server callback */ wolfSSL_set_psk_server_callback(ssl, NativePskServerCb); } else { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Input WolfSSLSession object was null when setting " "NativePskServerCb"); return; } #else - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "wolfSSL not compiled with PSK support"); return; #endif @@ -5244,7 +4859,6 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, unsigned int inlen, void *arg) { JNIEnv* jenv; /* JNI environment */ - jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ jint vmret = 0; @@ -5289,21 +4903,10 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, return SSL_TLSEXT_ERR_ALERT_FATAL; } - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - if (needsDetach) { - (*g_vm)->DetachCurrentThread(g_vm); - } - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - /* get stored WolfSSLSession object */ g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl); if (!g_cachedSSLObj) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession object reference in " "NativeALPNSelectCb"); if (needsDetach) { @@ -5315,7 +4918,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, /* lookup WolfSSLSession class from object */ sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj)); if (sslClass == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession class reference in " "NativeALPNSelectCb"); if (needsDetach) { @@ -5333,7 +4936,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error getting internalAlpnSelectCallback method from JNI"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5350,7 +4953,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error in wolfSSL_ALPN_GetPeerProtocol()"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5367,7 +4970,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error allocating memory for peer protocols array"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5391,7 +4994,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "ALPN peer protocol list size is 0"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5408,7 +5011,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Failed to create JNI String[] for ALPN protocols"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5426,7 +5029,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionClear(jenv); wolfSSL_ALPN_FreePeerProtocol(ssl, &peerProtos); - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Failed to add String to JNI String[] for ALPN protocols"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5449,7 +5052,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Failed to create JNI String[1] for output ALPN protocol"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5464,7 +5067,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Exception while calling internalAlpnSelectCallback()"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5480,7 +5083,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Output String[] for ALPN result not size 1"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5496,7 +5099,7 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Selected ALPN protocol in String[] is NULL"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5659,7 +5262,6 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, int secretSz, void* ctx) { JNIEnv* jenv; /* JNI environment */ - jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ jint retval = 0; jint vmret = 0; @@ -5690,21 +5292,10 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, return TLS13_SECRET_CB_E; } - /* Find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - if (needsDetach) { - (*g_vm)->DetachCurrentThread(g_vm); - } - return TLS13_SECRET_CB_E; - } - /* Get stored WolfSSLSession object */ g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl); if (!g_cachedSSLObj) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession object reference in " "NativeTls13SecretCb"); if (needsDetach) { @@ -5716,7 +5307,7 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, /* Lookup WolfSSLSession class from object */ sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj)); if (sslClass == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession class reference in " "NativeTls13SecretCb"); if (needsDetach) { @@ -5733,7 +5324,7 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error getting internalTls13SecretCallback method from JNI"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5745,7 +5336,7 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, /* Create jbyteArray to hold secret data */ secretArr = (*jenv)->NewByteArray(jenv, secretSz); if (secretArr == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error creating new jbyteArray in NativeTls13SecretCb"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5772,7 +5363,7 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret, if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Exception while calling internalTls13SecretCallback()"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5800,7 +5391,6 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, int ticketLen, void* ctx) { JNIEnv* jenv; /* JNI environment */ - jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ jint retval = 0; jint vmret = 0; @@ -5831,21 +5421,10 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, return -1; } - /* Find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - if (needsDetach) { - (*g_vm)->DetachCurrentThread(g_vm); - } - return -1; - } - /* Get stored WolfSSLSession object */ g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl); if (!g_cachedSSLObj) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession object reference in " "NativeSessionTicketCb"); if (needsDetach) { @@ -5857,7 +5436,7 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, /* Lookup WolfSSLSession class from object */ sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj)); if (sslClass == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession class reference in " "NativeSessionTicketCb"); if (needsDetach) { @@ -5874,7 +5453,7 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); } - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error getting internalSessionTicketCallback method from JNI"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5886,7 +5465,7 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, /* Create jbyteArray to hold session ticket */ ticketArr = (*jenv)->NewByteArray(jenv, ticketLen); if (ticketArr == NULL) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Error creating new jbyteArray in NativeSessionTicketCb"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -5912,7 +5491,7 @@ int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket, if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Exception while calling internalSessionTicketCallback()"); if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); @@ -6117,15 +5696,13 @@ int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) jint vmret = 0; JNIEnv* jenv; /* JNI environment */ - jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ - jclass sslClass; /* WolfSSLSession class */ - jmethodID recvCbMethodId; /* internalIORecvCallback ID */ jbyteArray inData; + jobject directBuf; - if (!g_vm || !ssl || !buf || !ctx) { + if (g_vm == NULL || ssl == NULL || buf == NULL || ctx == NULL) { /* can't throw exception yet, just return error */ return WOLFSSL_CBIO_ERR_GENERAL; } @@ -6146,96 +5723,121 @@ int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } - /* get stored WolfSSLSession jobject */ g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl); if (!g_cachedSSLObj) { - (*jenv)->ThrowNew(jenv, excClass, - "Can't get native WolfSSLSession object reference in " - "NativeSSLIORecvCb"); - if (needsDetach) + throwWolfSSLJNIException(jenv, + "Can't get native WolfSSLSession object reference in " + "NativeSSLIORecvCb"); + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return 0; } - /* lookup WolfSSLSession class from object */ - sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj)); - if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, - "Can't get native WolfSSLSession class reference in " - "NativeSSLIORecvCb"); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } + /* Detect if we should use ByteBuffer or byte[] I/O callbacks */ + if ((*jenv)->CallBooleanMethod(jenv, (jobject)(*g_cachedSSLObj), + g_isByteBufferIORecvCallbackSet)) { + + /* Call receive callback using ByteBuffer */ + if (!g_sslIORecvMethodId_BB) { + throwWolfSSLJNIException(jenv, + "Cached recv callback method ID is null in " + "internalIORecvCallback"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + /* create ByteBuffer to hold received data */ + directBuf = (*jenv)->NewDirectByteBuffer(jenv, buf, sz); + if (!directBuf) { + throwWolfSSLJNIException(jenv, + "Error creating ByteBuffer in NativeSSLIORecvCb"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + /* call Java receive callback, ignore ctx since Java handles it */ + retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), + g_sslIORecvMethodId_BB, (jobject)(*g_cachedSSLObj), directBuf, + (jint)sz); - /* call internal I/O recv callback */ - recvCbMethodId = (*jenv)->GetMethodID(jenv, sslClass, - "internalIOSSLRecvCallback", - "(Lcom/wolfssl/WolfSSLSession;[BI)I"); - if (!recvCbMethodId) { if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, directBuf); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; } - (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIORecvCallback method from JNI"); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; + + /* delete local refs */ + (*jenv)->DeleteLocalRef(jenv, directBuf); } + else { + /* Call receive callback using byte[] */ + if (!g_sslIORecvMethodId) { + throwWolfSSLJNIException(jenv, + "Cached recv callback method ID is null in " + "internalIORecvCallback"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } - /* create jbyteArray to hold received data */ - inData = (*jenv)->NewByteArray(jenv, sz); - if (!inData) { - (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIORecvCallback method from JNI"); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } + /* create jbyteArray to hold received data */ + inData = (*jenv)->NewByteArray(jenv, sz); + if (inData == NULL) { + throwWolfSSLJNIException(jenv, + "Error getting internalIORecvCallback method from JNI"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } - /* call Java send callback, ignore native ctx since Java - * handles it */ - retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), - recvCbMethodId, (jobject)(*g_cachedSSLObj), inData, (jint)sz); + /* call Java send callback, ignore ctx since Java handles it */ + retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), + g_sslIORecvMethodId, (jobject)(*g_cachedSSLObj), inData, (jint)sz); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - (*jenv)->DeleteLocalRef(jenv, inData); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - /* copy jbyteArray into char array */ - if (retval >= 0) { - (*jenv)->GetByteArrayRegion(jenv, inData, 0, retval, - (jbyte*)buf); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); (*jenv)->DeleteLocalRef(jenv, inData); - if (needsDetach) + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return WOLFSSL_CBIO_ERR_GENERAL; } + + /* copy jbyteArray into char array */ + if (retval >= 0) { + (*jenv)->GetByteArrayRegion(jenv, inData, 0, retval, (jbyte*)buf); + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, inData); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + /* delete local refs */ + (*jenv)->DeleteLocalRef(jenv, inData); } - /* delete local refs, detach JNIEnv from thread */ - (*jenv)->DeleteLocalRef(jenv, inData); - if (needsDetach) + /* detach JNIEnv from thread */ + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return retval; } @@ -6259,15 +5861,13 @@ int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) jint vmret = 0; JNIEnv* jenv; /* JNI environment */ - jclass excClass; /* WolfSSLJNIException class */ int needsDetach = 0; /* Should we explicitly detach? */ jobject* g_cachedSSLObj; /* WolfSSLSession cached object */ - jclass sslClass; /* WolfSSLSession class */ - jmethodID sendCbMethodId; /* internalIOSendCallback ID */ jbyteArray outData; /* jbyteArray for data to send */ + jobject directBuf; - if (!g_vm || !ssl || !buf || !ctx) { + if (g_vm == NULL || ssl == NULL || buf == NULL || ctx == NULL) { /* can't throw exception yet, just return error */ return WOLFSSL_CBIO_ERR_GENERAL; } @@ -6288,96 +5888,122 @@ int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx) return WOLFSSL_CBIO_ERR_GENERAL; } - /* find exception class in case we need it */ - excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } - /* get stored WolfSSLSession jobject */ g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl); if (!g_cachedSSLObj) { - (*jenv)->ThrowNew(jenv, excClass, + throwWolfSSLJNIException(jenv, "Can't get native WolfSSLSession object reference in " "NativeSSLIOSendCb"); - if (needsDetach) + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return 0; } - /* lookup WolfSSLSession class from object */ - sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj)); - if (!sslClass) { - (*jenv)->ThrowNew(jenv, excClass, - "Can't get native WolfSSLSession class reference"); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } + /* Detect if we should use ByteBuffer or byte[] I/O callbacks */ + if ((*jenv)->CallBooleanMethod(jenv, (jobject)(*g_cachedSSLObj), + g_isByteBufferIOSendCallbackSet)) { - /* call internal I/O send callback */ - sendCbMethodId = (*jenv)->GetMethodID(jenv, sslClass, - "internalIOSSLSendCallback", - "(Lcom/wolfssl/WolfSSLSession;[BI)I"); - if (!sendCbMethodId) { - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - } - (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIOSendCallback method from JNI"); - if (needsDetach) - (*g_vm)->DetachCurrentThread(g_vm); - return WOLFSSL_CBIO_ERR_GENERAL; - } - - if (sz >= 0) - { - /* create jbyteArray to hold received data */ - outData = (*jenv)->NewByteArray(jenv, sz); - if (!outData) { - (*jenv)->ThrowNew(jenv, excClass, - "Error getting internalIOSendCallback method from JNI"); - if (needsDetach) + /* Call send callback using ByteBuffer */ + if (!g_sslIOSendMethodId_BB) { + throwWolfSSLJNIException(jenv, + "Cached send callback method ID is null in internalIOSendCb"); + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return WOLFSSL_CBIO_ERR_GENERAL; } - (*jenv)->SetByteArrayRegion(jenv, outData, 0, sz, (jbyte*)buf); - if ((*jenv)->ExceptionOccurred(jenv)) { - (*jenv)->ExceptionDescribe(jenv); - (*jenv)->ExceptionClear(jenv); - (*jenv)->DeleteLocalRef(jenv, outData); - if (needsDetach) + /* create ByteBuffer to wrap data to send */ + directBuf = (*jenv)->NewDirectByteBuffer(jenv, buf, sz); + if (!directBuf) { + throwWolfSSLJNIException(jenv, + "Error creating ByteBuffer in NativeSSLIOSendCb, not direct"); + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return WOLFSSL_CBIO_ERR_GENERAL; } - /* call Java send callback, ignore native ctx since Java - * handles it */ + /* call Java send callback, ignore ctx since Java handles it */ retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), - sendCbMethodId, (jobject)(*g_cachedSSLObj), outData, (jint)sz); - + g_sslIOSendMethodId_BB, (jobject)(*g_cachedSSLObj), directBuf, + (jint)sz); if ((*jenv)->ExceptionOccurred(jenv)) { (*jenv)->ExceptionDescribe(jenv); (*jenv)->ExceptionClear(jenv); - (*jenv)->DeleteLocalRef(jenv, outData); - if (needsDetach) + (*jenv)->DeleteLocalRef(jenv, directBuf); + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return WOLFSSL_CBIO_ERR_GENERAL; } /* delete local refs */ - (*jenv)->DeleteLocalRef(jenv, outData); + (*jenv)->DeleteLocalRef(jenv, directBuf); + } + else { + /* Call send callbaack using byte[] */ + if (!g_sslIOSendMethodId) { + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + } + throwWolfSSLJNIException(jenv, + "internalIOSendCallback method ID is null in internalIOSendCb"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if (sz >= 0) { + /* create jbyteArray to hold received data */ + outData = (*jenv)->NewByteArray(jenv, sz); + if (!outData) { + throwWolfSSLJNIException(jenv, + "Error getting internalIOSendCallback method from JNI"); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + (*jenv)->SetByteArrayRegion(jenv, outData, 0, sz, (jbyte*)buf); + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, outData); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + /* call Java send callback, ignore ctx since Java handles it */ + retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj), + g_sslIOSendMethodId, (jobject)(*g_cachedSSLObj), outData, + (jint)sz); + + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, outData); + if (needsDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + return WOLFSSL_CBIO_ERR_GENERAL; + } + + /* delete local refs */ + (*jenv)->DeleteLocalRef(jenv, outData); + } } /* detach JNIEnv from thread */ - if (needsDetach) + if (needsDetach) { (*g_vm)->DetachCurrentThread(g_vm); + } return retval; } diff --git a/native/com_wolfssl_WolfSSLSession.h b/native/com_wolfssl_WolfSSLSession.h index 017e457..d50019d 100644 --- a/native/com_wolfssl_WolfSSLSession.h +++ b/native/com_wolfssl_WolfSSLSession.h @@ -967,6 +967,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setMTU JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_stateStringLong (JNIEnv *, jobject, jlong); +/* + * Class: com_wolfssl_WolfSSLSession + * Method: getMaxOutputSize + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getMaxOutputSize + (JNIEnv *, jobject, jlong); + #ifdef __cplusplus } #endif diff --git a/native/com_wolfssl_globals.h b/native/com_wolfssl_globals.h index af3b0fc..39db1d3 100644 --- a/native/com_wolfssl_globals.h +++ b/native/com_wolfssl_globals.h @@ -25,7 +25,25 @@ #define _Included_com_wolfssl_globals /* global JavaVM reference for JNIEnv lookup */ -extern JavaVM* g_vm; +extern JavaVM* g_vm; + +/* Cache static jmethodIDs for performance, since they are guaranteed to be the + * same across all threads once cached. Initialized in JNI_OnLoad() and freed in + * JNI_OnUnload(). */ +extern jmethodID g_sslIORecvMethodId; /* WolfSSLSession.internalIOSSLRecvCallback */ +extern jmethodID g_sslIORecvMethodId_BB; /* WolfSSLSession.internalIOSSLRecvCallback_BB */ +extern jmethodID g_sslIOSendMethodId; /* WolfSSLSession.internalIOSSLSendCallback */ +extern jmethodID g_sslIOSendMethodId_BB; /* WolfSSLSession.internalIOSSLSendCallback_BB */ +extern jmethodID g_isArrayIORecvCallbackSet; /* WolfSSL.isArrayIORecvCallbackSet */ +extern jmethodID g_isArrayIOSendCallbackSet; /* WolfSSL.isArrayIOSendCallbackSet */ +extern jmethodID g_isByteBufferIORecvCallbackSet; /* WolfSSL.isByteBufferIORecvCallbackSet */ +extern jmethodID g_isByteBufferIOSendCallbackSet; /* WolfSSL.isByteBufferIOSendCallbackSet */ +extern jmethodID g_bufferPositionMethodId; /* ByteBuffer.position() */ +extern jmethodID g_bufferLimitMethodId; /* ByteBuffer.limit() */ +extern jmethodID g_bufferHasArrayMethodId; /* ByteBuffer.hasArray() */ +extern jmethodID g_bufferArrayMethodId; /* ByteBuffer.array() */ +extern jmethodID g_bufferSetPositionMethodId; /* ByteBuffer.position(int) */ +extern jmethodID g_verifyCallbackMethodId; /* WolfSSLVerifyCallback.verifyCallback */ /* struct to hold I/O class, object refs */ typedef struct { @@ -38,5 +56,8 @@ unsigned int NativePskClientCb(WOLFSSL* ssl, const char* hint, char* identity, unsigned int NativePskServerCb(WOLFSSL* ssl, const char* identity, unsigned char* key, unsigned int max_key_len); -#endif +/* Helper functions to throw exceptions */ +void throwWolfSSLJNIException(JNIEnv* jenv, const char* msg); +void throwWolfSSLException(JNIEnv* jenv, const char* msg); +#endif diff --git a/scripts/infer.sh b/scripts/infer.sh index 531b0d4..7ccd112 100755 --- a/scripts/infer.sh +++ b/scripts/infer.sh @@ -35,6 +35,8 @@ done infer --fail-on-issue run -- javac \ src/java/com/wolfssl/WolfSSL.java \ src/java/com/wolfssl/WolfSSLALPNSelectCallback.java \ + src/java/com/wolfssl/WolfSSLByteBufferIORecvCallback.java \ + src/java/com/wolfssl/WolfSSLByteBufferIOSendCallback.java \ src/java/com/wolfssl/WolfSSLCertManager.java \ src/java/com/wolfssl/WolfSSLCertRequest.java \ src/java/com/wolfssl/WolfSSLCertificate.java \ diff --git a/src/java/com/wolfssl/WolfSSL.java b/src/java/com/wolfssl/WolfSSL.java index e4c9b4a..11f21f4 100644 --- a/src/java/com/wolfssl/WolfSSL.java +++ b/src/java/com/wolfssl/WolfSSL.java @@ -626,6 +626,9 @@ public class WolfSSL { getTls13SecretEnum_EXPORTER_SECRET(); this.active = true; + + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, "wolfSSL library initialization done"); } /* ------------------- private/protected methods -------------------- */ diff --git a/src/java/com/wolfssl/WolfSSLByteBufferIORecvCallback.java b/src/java/com/wolfssl/WolfSSLByteBufferIORecvCallback.java new file mode 100644 index 0000000..7fe9320 --- /dev/null +++ b/src/java/com/wolfssl/WolfSSLByteBufferIORecvCallback.java @@ -0,0 +1,67 @@ +/* WolfSSLByteBufferIORecvCallback.java + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +package com.wolfssl; + +import java.nio.ByteBuffer; + +/** + * wolfSSL ByteBuffer I/O Receive Callback Interface. + * + * This interface specifies how applicaitons should implement the I/O receive + * callback class to be used by wolfSSL, using a ByteBuffer as the buffer. + *

+ * After implementing this interface, it should be passed as a parameter + * to the {@link WolfSSLContext#setIORecv(WolfSSLIORecvCallback) + * WolfSSLContext.setIORecv()} or + * {@link WolfSSLSession#setIORecv(WolfSSLIORecvCallback) + * WolfSSLSession.setIORecv()} methods to be registered with the native wolfSSL + * library. + */ +public interface WolfSSLByteBufferIORecvCallback { + + /** + * I/O receive callback method, using ByteBuffer. + * + * This method acts as the I/O receive callback to be used with wolfSSL. + * This can be registered with an SSL session at the WolfSSLContext level + * using WolfSSLContext#setIORecv(WolfSSLIORecvCallback), or at the + * WolfSSLSession level using + * WolfSSLSession#setIORecv(WolfSSLIORecvCallback). + * + * This method will be called by native wolfSSL when it needs data to + * be read from the transport layer. The callback should read data and + * place the data into the buffer provided. The number of bytes read should + * be returned. The callback should return an error code on error. + * + * @param ssl the current SSL session object from which the callback was + * initiated. + * @param buf buffer in which the application should place data which + * has been received from the peer. + * @param sz size of buffer, buf + * @param ctx I/O context to be used. + * @return the number of bytes read, or an error. For possible error + * codes, see the default EmbedRecv() function in + * wolfssl_package/src/io.c + */ + public int receiveCallback(WolfSSLSession ssl, ByteBuffer buf, int sz, + Object ctx); +} + diff --git a/src/java/com/wolfssl/WolfSSLByteBufferIOSendCallback.java b/src/java/com/wolfssl/WolfSSLByteBufferIOSendCallback.java new file mode 100644 index 0000000..f06adeb --- /dev/null +++ b/src/java/com/wolfssl/WolfSSLByteBufferIOSendCallback.java @@ -0,0 +1,67 @@ +/* WolfSSLByteBufferIOSendCallback.java + * + * Copyright (C) 2006-2025 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +package com.wolfssl; + +import java.nio.ByteBuffer; + +/** + * wolfSSL I/O Send Callback Interface. + * + * This interface specifies how applicaitons should implement the I/O send + * callback class to be used by wolfSSL. + *

+ * After implementing this interface, it should be passed as a parameter + * to the {@link WolfSSLContext#setIOSend(WolfSSLIOSendCallback) + * WolfSSLContext.setIOSend()} or + * {@link WolfSSLSession#setIOSend(WolfSSLIOSendCallback) + * WolfSSLSession.setIOSend()} methods to be registered with the native wolfSSL + * library. + */ +public interface WolfSSLByteBufferIOSendCallback { + + /** + * I/O send callback method, using ByteBuffer. + * + * This method acts as the I/O send callback to be used with wolfSSL. + * This can be registered with an SSL session at the WolfSSLContext level + * using WolfSSLContext#setIOSend(WolfSSLIOSendCallback), or at the + * WolfSSLSession level using + * WolfSSLSession#setIOSend(WolfSSLIOSendCallback). + * + * This method will be called by native wolfSSL when it needs to send data. + * The callback should send data from the provided ByteBuffer (buf) across + * the transport layer. The number of bytes sent should be returned, or + * a negative error code on error. + * + * @param ssl the current SSL session object from which the callback was + * initiated. + * @param buf buffer containing data to be sent to the peer. + * @param sz size of data in buffer "buf" + * @param ctx I/O context to be used. + * @return the number of bytes sent, or an error. For possible error + * codes, see the default EmbedSend() function in + * wolfssl_package/src/io.c + */ + public int sendCallback(WolfSSLSession ssl, ByteBuffer buf, int sz, + Object ctx); +} + diff --git a/src/java/com/wolfssl/WolfSSLSession.java b/src/java/com/wolfssl/WolfSSLSession.java index dd39fb6..70e60f5 100644 --- a/src/java/com/wolfssl/WolfSSLSession.java +++ b/src/java/com/wolfssl/WolfSSLSession.java @@ -71,11 +71,21 @@ public class WolfSSLSession { private WolfSSLPskClientCallback internPskClientCb = null; private WolfSSLPskServerCallback internPskServerCb = null; - /* user-registerd I/O callbacks, called by internal WolfSSLSession - * I/O callback. This is done in order to pass references to - * WolfSSLSession object */ - private WolfSSLIORecvCallback internRecvSSLCb; - private WolfSSLIOSendCallback internSendSSLCb; + /* User-registerd I/O callbacks: + * + * These are called by internal WolfSSLSession I/O callback. This is done + * in order to pass references to WolfSSLSession object. There are two sets + * of I/O callbacks here, one set that will use byte[] and one that will + * use ByteBuffer. Only one send and one recv callback can be set at a time + * between the two. Native JNI code will give preference to using the + * ByteBuffer variants for performance if set, since this will avoid an + * extra native allocation (NewByteArray()). The ByteBuffer variant will + * wrap the pre-allocated wolfSSL array in a Java direct ByteBuffer + * to pass back up to Java. */ + private WolfSSLIORecvCallback internRecvSSLCb_array; + private WolfSSLIOSendCallback internSendSSLCb_array; + private WolfSSLByteBufferIORecvCallback internRecvSSLCb_BB; + private WolfSSLByteBufferIOSendCallback internSendSSLCb_BB; /* user-registered ALPN select callback, called by internal WolfSSLSession * ALPN select callback */ @@ -237,20 +247,66 @@ public class WolfSSLSession { return this.rsaDecCtx; } + /* Methods to detect which I/O callback variants have been set */ + private boolean isArrayIOSendCallbackSet() { + return (internSendSSLCb_array != null); + } + + private boolean isByteBufferIOSendCallbackSet() { + return (internSendSSLCb_BB != null); + } + + private boolean isArrayIORecvCallbackSet() { + return (internRecvSSLCb_array != null); + } + + private boolean isByteBufferIORecvCallbackSet() { + return (internRecvSSLCb_BB != null); + } + /* These callbacks will be registered with native wolfSSL library */ - private int internalIOSSLRecvCallback(WolfSSLSession ssl, byte[] buf, - int sz) + + /** + * Internal wolfSSL I/O receive callback, using byte array. + */ + private int internalIOSSLRecvCallback(WolfSSLSession ssl, + byte[] buf, int sz) { /* call user-registered recv method */ - return internRecvSSLCb.receiveCallback(ssl, buf, sz, + return internRecvSSLCb_array.receiveCallback(ssl, buf, sz, ssl.getIOReadCtx()); } - private int internalIOSSLSendCallback(WolfSSLSession ssl, byte[] buf, - int sz) + /** + * Internal wolfSSL I/O receive callback, using ByteBuffer. + */ + private int internalIOSSLRecvCallback(WolfSSLSession ssl, + ByteBuffer buf, int sz) { /* call user-registered recv method */ - return internSendSSLCb.sendCallback(ssl, buf, sz, + return internRecvSSLCb_BB.receiveCallback(ssl, buf, sz, + ssl.getIOReadCtx()); + } + + /** + * Internal wolfSSL I/O send callback, using byte array. + */ + private int internalIOSSLSendCallback(WolfSSLSession ssl, + byte[] buf, int sz) + { + /* call user-registered recv method */ + return internSendSSLCb_array.sendCallback(ssl, buf, sz, + ssl.getIOWriteCtx()); + } + + /** + * Internal wolfSSL I/O send callback, using ByteBuffer. + */ + private int internalIOSSLSendCallback(WolfSSLSession ssl, + ByteBuffer buf, int sz) + { + /* call user-registered recv method */ + return internSendSSLCb_BB.sendCallback(ssl, buf, sz, ssl.getIOWriteCtx()); } @@ -440,6 +496,7 @@ public class WolfSSLSession { private native int getThreadsBlockedInPoll(long ssl); private native int setMTU(long ssl, int mtu); private native String stateStringLong(long ssl); + private native int getMaxOutputSize(long ssl); /* ------------------- session-specific methods --------------------- */ @@ -2556,6 +2613,35 @@ public class WolfSSLSession { return state; } + /** + * Return max record layer size plaintext input size + * + * @return max record layer size plaintext input size in bytes, or + * negative value on error. + * + * @throws IllegalStateException WolfSSLContext has been freed + */ + public int getMaxOutputSize() throws IllegalStateException { + + int ret; + + confirmObjectIsActive(); + + synchronized (sslLock) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, this.sslPtr, + "entered getOutputSize()"); + + ret = getMaxOutputSize(this.sslPtr); + + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, this.sslPtr, + "max output size: " + ret); + } + + return ret; + } + /** * Determine if a reused session was negotiated during the SSL * handshake. @@ -3098,9 +3184,6 @@ public class WolfSSLSession { confirmObjectIsActive(); synchronized (sslLock) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, - WolfSSLDebug.INFO, this.sslPtr, "entered getIOReadCtx()"); - return this.ioReadCtx; } } @@ -3149,9 +3232,6 @@ public class WolfSSLSession { confirmObjectIsActive(); synchronized (sslLock) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, - WolfSSLDebug.INFO, this.sslPtr, "entered getIOWriteCtx()"); - return this.ioWriteCtx; } } @@ -4338,11 +4418,18 @@ public class WolfSSLSession { /** * Registers a receive callback for wolfSSL to get input data. - * By default, wolfSSL uses EmbedReceive() in src/io.c as the callback. - * This uses the system's TCP recv() function. The user can register a - * function to get input from memory, some other network module, or from - * anywhere. Please see the EmbedReceive() function in src/io.c as a - * guide for how the function should work and for error codes. + * + * This receive callback uses WolfSSLIORecvCallback which uses + * byte arrays (byte[]). To use direct ByteBuffers, and avoid an extra + * JNI array allocaiton, use + * setIORecvByteBuffer(WolfSSLByteBufferIORecvCallback). + * + * By default, wolfSSL uses EmbedReceive() in src/io.c as the callback + * which uses the system TCP recv() function. The user can register a + * method here to get receive TLS-encoded data from memory, some other + * network module, or anywhere else. Please see the EmbedReceive() function + * in src/io.c as a guide for how the function should work and for error + * codes. *

* In particular, IO_ERR_WANT_READ should be returned for * non-blocking receive when no data is ready. @@ -4364,10 +4451,16 @@ public class WolfSSLSession { synchronized (sslLock) { WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, WolfSSLDebug.INFO, this.sslPtr, - "entered setIORecv(" + callback + ")"); + "entered setIORecv(" + callback + ") - byte array"); + + /* Only allow one recv callback registered at a time, if ByteBuffer + * version has been set, set to null before setting byte variant. */ + if (internRecvSSLCb_BB != null) { + internRecvSSLCb_BB = null; + } /* set user I/O recv */ - internRecvSSLCb = callback; + internRecvSSLCb_array = callback; if (callback != null) { /* register internal callback with native library */ @@ -4377,12 +4470,74 @@ public class WolfSSLSession { } /** - * Registers a send callback for wolfSSL to write output data. + * Registers a receive callback for wolfSSL to get input data. + * + * This receive callback uses WolfSSLByteBufferIORecvCallback which uses + * a direct ByteBuffer. To use a byte array instead use + * setIORecv(WolfSSLIORecvCallback), but this will incur one additional + * native JNI array allocation. + * + * By default, wolfSSL uses EmbedReceive() in src/io.c as the callback + * which uses the system TCP recv() function. The user can register a + * method here to get receive TLS-encoded data from memory, some other + * network module, or anywhere else. Please see the EmbedReceive() function + * in src/io.c as a guide for how the function should work and for error + * codes. + *

+ * In particular, IO_ERR_WANT_READ should be returned for + * non-blocking receive when no data is ready. + * + * @param callback method to be registered as the receive callback for + * the wolfSSL context. The signature of this function + * must follow that as shown in + * WolfSSLByteBufferIORecvCallback#receiveCallback( + * WolfSSLSession, ByteBuffer, int, long). + * @throws IllegalStateException WolfSSLContext has been freed + * @throws WolfSSLJNIException Internal JNI error + * @see #setIOSend(WolfSSLIOSendCallback) + */ + public void setIORecvByteBuffer(WolfSSLByteBufferIORecvCallback callback) + throws IllegalStateException, WolfSSLJNIException { + + confirmObjectIsActive(); + + synchronized (sslLock) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, this.sslPtr, + "entered setIORecv(" + callback + ") - ByteBuffer"); + + /* Only allow one recv callback registered at a time, if array + * version has been set, set to null before setting ByteBuffer. */ + if (internRecvSSLCb_array != null) { + internRecvSSLCb_array = null; + } + + /* set user I/O recv */ + internRecvSSLCb_BB = callback; + + if (callback != null) { + /* Register internal callback with native library, registers + * JNI NativeSSLIORecvCb() with native wolfSSL. + * NativeSSLIORecvCb() will then call back into + * internRecvSSLCb_array/BB(). */ + setSSLIORecv(this.sslPtr); + } + } + } + + /** + * Registers a send callback for wolfSSL to write TLS encoded output data. + * + * This send callback uses WolfSSLIOSendCallback which uses byte arrays + * (byte[]). To use direct ByteBuffers, and avoid an extra JNI array + * allocation, use setIOSendByteBuffer(WolfSSLByteBufferIOSendCallback). + * * By default, wolfSSL uses EmbedSend() in src/io.c as the callback, - * which uses the system's TCP send() function. The user can register - * a function to send output to memory, some other network module, or - * to anywhere. Please see the EmbedSend() function in src/io.c as a - * guide for how the function should work and for error codes. + * which uses the system TCP send() function. The user can register + * a method here to send TLS-encoded output data to memory, some other + * network module, or to anywhere else. Please see the EmbedSend() function + * in src/io.c as a guide for how the function should work and for error + * codes. *

* In particular, IO_ERR_WANT_WRITE should be returned for * non-blocking send when the action cannot be taken yet. @@ -4404,13 +4559,78 @@ public class WolfSSLSession { synchronized (sslLock) { WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, WolfSSLDebug.INFO, this.sslPtr, - "entered setIOSend(" + callback + ")"); + "entered setIOSend(" + callback + ") - byte array"); + + /* Only allow one send callback registered at a time, if ByteBuffer + * version has been set, set to null before setting byte variant. */ + if (internSendSSLCb_BB != null) { + internSendSSLCb_BB = null; + } /* set user I/O send */ - internSendSSLCb = callback; + internSendSSLCb_array = callback; if (callback != null) { - /* register internal callback with native library */ + /* Register internal callback with native library, registers + * JNI NativeSSLIOSendCb() with native wolfSSL. + * NativeSSLIOSendCb() will then call back into + * internSendSSLCb_array/BB(). */ + setSSLIOSend(this.sslPtr); + } + } + } + + /** + * Registers a send callback for wolfSSL to write TLS encoded output data. + * + * This send callback uses WolfSSLByteBufferIOSendCallback which uses a + * ByteBuffer. To use a byte array instead, use + * setIOSend(WolfSSLIOSendCallback), but this will incur one + * additional native JNI array allocation. + * + * By default, wolfSSL uses EmbedSend() in src/io.c as the callback, + * which uses the system TCP send() function. The user can register + * a method here to send TLS-encoded output data to memory, some other + * network module, or to anywhere else. Please see the EmbedSend() function + * in src/io.c as a guide for how the function should work and for error + * codes. + *

+ * In particular, IO_ERR_WANT_WRITE should be returned for + * non-blocking send when the action cannot be taken yet. + * + * @param callback method to be registered as the send callback for + * the wolfSSL context. The signature of this function + * must follow that as shown in + * WolfSSLByteBufferIOSendCallback#sendCallback( + * WolfSSLSession, ByteBuffer, int, Object). + * @throws IllegalStateException WolfSSLSession has been freed + * @throws WolfSSLJNIException Internal JNI error + * @see #setIORecv(WolfSSLIORecvCallback) + */ + public void setIOSendByteBuffer(WolfSSLByteBufferIOSendCallback callback) + throws IllegalStateException, WolfSSLJNIException { + + confirmObjectIsActive(); + + synchronized (sslLock) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI, + WolfSSLDebug.INFO, this.sslPtr, + "entered setIOSend(" + callback + ") - ByteBuffer"); + + /* Only allow one recv callback registered at a time, if array + * version has been set, set to null before setting ByteBuffer. */ + if (internSendSSLCb_array != null) { + internSendSSLCb_array = null; + } + + /* set user I/O send */ + internSendSSLCb_BB = callback; + + if (callback != null) { + /* Register internal callback with native library, registers + * JNI NativeSSLIOSendCb() with native wolfSSL. + * NativeSSLIOSendCb() will then call back into + * internSendSSLCb_array/BB(). */ setSSLIOSend(this.sslPtr); } } diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java b/src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java index 719c550..f70cd26 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java @@ -24,8 +24,8 @@ package com.wolfssl.provider.jsse; import com.wolfssl.WolfSSL; import com.wolfssl.WolfSSLDebug; import com.wolfssl.WolfSSLException; -import com.wolfssl.WolfSSLIORecvCallback; -import com.wolfssl.WolfSSLIOSendCallback; +import com.wolfssl.WolfSSLByteBufferIORecvCallback; +import com.wolfssl.WolfSSLByteBufferIOSendCallback; import com.wolfssl.WolfSSLJNIException; import com.wolfssl.WolfSSLSession; import com.wolfssl.WolfSSLALPNSelectCallback; @@ -37,7 +37,6 @@ import java.util.function.BiFunction; import java.util.List; import java.util.Arrays; import java.util.ArrayList; -import java.util.logging.Level; import java.security.cert.CertificateEncodingException; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -72,7 +71,6 @@ public class WolfSSLEngine extends SSLEngine { private com.wolfssl.WolfSSLContext ctx = null; private WolfSSLAuthStore authStore = null; private WolfSSLParameters params = null; - private byte[] toSend = null; /* encrypted packet to send */ private int nativeWantsToWrite = 0; private int nativeWantsToRead = 0; private HandshakeStatus hs = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; @@ -126,6 +124,22 @@ public class WolfSSLEngine extends SSLEngine { private ByteBuffer netData = null; private final Object netDataLock = new Object(); + /* Single buffer used to hold application data to be sent, allocated once + * inside SendAppData, of size SSLSession.getApplicationBufferSize() */ + private ByteBuffer staticAppDataBuf = null; + + /* Default size of internalIOSendBuf, 16k to match TLS record size. + * TODO - add upper bound on I/O send buf resize allocations. */ + private static final int INTERNAL_IOSEND_BUF_SZ = 16 * 1024; + /* static buffer used to hold encrypted data to be sent, allocated inside + * internalSendCb() and expanded only if needed. Synchronize on toSendLock + * when accessing this buffer. */ + private byte[] internalIOSendBuf = new byte[INTERNAL_IOSEND_BUF_SZ]; + /* Total size of internalIOSendBuf */ + private int internalIOSendBufSz = INTERNAL_IOSEND_BUF_SZ; + /* Offset into internalIOSendBuf to start writing data */ + private int internalIOSendBufOffset = 0; + /* Locks for synchronization */ private final Object ioLock = new Object(); private final Object toSendLock = new Object(); @@ -308,8 +322,8 @@ public class WolfSSLEngine extends SSLEngine { if (recvCb == null) { recvCb = new RecvCB(); } - ssl.setIORecv(recvCb); - ssl.setIOSend(sendCb); + ssl.setIORecvByteBuffer(recvCb); + ssl.setIOSendByteBuffer(sendCb); ssl.setIOReadCtx(this); ssl.setIOWriteCtx(this); @@ -335,8 +349,8 @@ public class WolfSSLEngine extends SSLEngine { private void unsetSSLCallbacks() throws WolfSSLJNIException { synchronized (ioLock) { - ssl.setIORecv(null); - ssl.setIOSend(null); + ssl.setIORecvByteBuffer(null); + ssl.setIOSendByteBuffer(null); ssl.setIOReadCtx(null); ssl.setIOWriteCtx(null); } @@ -373,19 +387,18 @@ public class WolfSSLEngine extends SSLEngine { int sendSz = 0; synchronized (toSendLock) { - if (this.toSend != null) { - sendSz = Math.min(this.toSend.length, out.remaining()); - out.put(this.toSend, 0, sendSz); + if (this.internalIOSendBuf != null) { + sendSz = Math.min(this.internalIOSendBufOffset, out.remaining()); + out.put(this.internalIOSendBuf, 0, sendSz); - if (sendSz != this.toSend.length) { - /* resize and adjust remaining toSend data */ - byte[] tmp = new byte[this.toSend.length - sendSz]; - System.arraycopy(this.toSend, sendSz, tmp, 0, - this.toSend.length - sendSz); - this.toSend = tmp; + if (sendSz != this.internalIOSendBufOffset) { + System.arraycopy(this.internalIOSendBuf, sendSz, + this.internalIOSendBuf, 0, + this.internalIOSendBufOffset - sendSz); } else { - this.toSend = null; + /* reset internalIOSendBufOffset to zero, no data left */ + this.internalIOSendBufOffset = 0; } } } @@ -407,7 +420,7 @@ public class WolfSSLEngine extends SSLEngine { this.closeNotifySent = true; this.closeNotifyReceived = true; this.inBoundOpen = false; - if (this.toSend == null || this.toSend.length == 0) { + if (this.internalIOSendBufOffset == 0) { /* Don't close outbound if we have a close_notify alert * send back to peer. Native wolfSSL may have already generated * it and is reflected in SSL_SENT_SHUTDOWN flag, but we @@ -590,17 +603,23 @@ public class WolfSSLEngine extends SSLEngine { int[] pos = new int[len]; /* in[] positions */ int[] limit = new int[len]; /* in[] limits */ - /* get total input data size, store input array positions */ + /* Get total input data size, store input array positions */ for (i = ofst; i < ofst + len; i++) { totalIn += in[i].remaining(); pos[i] = in[i].position(); limit[i] = in[i].limit(); } - /* only send up to maximum app data size chunk */ - sendSz = Math.min(totalIn, - this.engineHelper.getSession().getApplicationBufferSize()); - dataBuf = ByteBuffer.allocate(sendSz); + /* Allocate static buffer for application data, clear before use */ + sendSz = this.engineHelper.getSession().getApplicationBufferSize(); + if (this.staticAppDataBuf == null) { + /* allocate static buffer for application data */ + this.staticAppDataBuf = ByteBuffer.allocateDirect(sendSz); + } + this.staticAppDataBuf.clear(); + + /* Only send up to maximum app data size chunk */ + sendSz = Math.min(totalIn, sendSz); /* gather byte array of sendSz bytes from input buffers */ inputLeft = sendSz; @@ -608,7 +627,7 @@ public class WolfSSLEngine extends SSLEngine { int bufChunk = Math.min(in[i].remaining(), inputLeft); in[i].limit(in[i].position() + bufChunk); /* set limit */ - dataBuf.put(in[i]); /* get data */ + this.staticAppDataBuf.put(in[i]); /* get data */ inputLeft -= bufChunk; in[i].limit(limit[i]); /* reset limit */ @@ -618,8 +637,8 @@ public class WolfSSLEngine extends SSLEngine { } dataArr = new byte[sendSz]; - dataBuf.rewind(); - dataBuf.get(dataArr); + this.staticAppDataBuf.rewind(); + this.staticAppDataBuf.get(dataArr); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "calling ssl.write() with size: " + sendSz); @@ -707,13 +726,8 @@ public class WolfSSLEngine extends SSLEngine { "out.position(): " + out.position()); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "out.limit(): " + out.limit()); - if (this.toSend != null) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: " + this.toSend.length); - } else { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: 0"); - } + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "internalIOSendBufOffset: " + this.internalIOSendBufOffset); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "closeNotifySent: " + this.closeNotifySent); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -756,6 +770,10 @@ public class WolfSSLEngine extends SSLEngine { /* Force out buffer to be large enough to hold max packet size */ if (out.remaining() < this.engineHelper.getSession().getPacketBufferSize()) { + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "out.remaining() too small (" + + out.remaining() + "), need at least: " + + this.engineHelper.getSession().getPacketBufferSize()); return new SSLEngineResult(Status.BUFFER_OVERFLOW, hs, 0, 0); } @@ -832,13 +850,8 @@ public class WolfSSLEngine extends SSLEngine { "out.position(): " + out.position()); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "out.limit(): " + out.limit()); - if (this.toSend != null) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: " + this.toSend.length); - } else { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: 0"); - } + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "internalIOSendBufOffset: " + this.internalIOSendBufOffset); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "closeNotifySent: " + this.closeNotifySent); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -1064,7 +1077,7 @@ public class WolfSSLEngine extends SSLEngine { public synchronized SSLEngineResult unwrap(ByteBuffer in, ByteBuffer[] out, int ofst, int length) throws SSLException { - int i, ret = 0, sz = 0, err = 0; + int i, ret = 0, err = 0; int inPosition = 0; int inRemaining = 0; int consumed = 0; @@ -1072,7 +1085,6 @@ public class WolfSSLEngine extends SSLEngine { long dtlsPrevDropCount = 0; long dtlsCurrDropCount = 0; int prevSessionTicketCount = 0; - byte[] tmp; /* Set initial status for SSLEngineResult return */ Status status = SSLEngineResult.Status.OK; @@ -1130,13 +1142,8 @@ public class WolfSSLEngine extends SSLEngine { } WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "ofst: " + ofst + ", length: " + length); - if (this.toSend != null) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: " + this.toSend.length); - } else { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: 0"); - } + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "internalIOSendBufOffset: " + this.internalIOSendBufOffset); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "closeNotifySent: " + this.closeNotifySent); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -1174,7 +1181,7 @@ public class WolfSSLEngine extends SSLEngine { hs = SSLEngineResult.HandshakeStatus.NEED_WRAP; } else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP && - (this.toSend != null) && (this.toSend.length > 0)) { + this.internalIOSendBufOffset > 0) { /* Already have data buffered to send and in NEED_WRAP state, * just return so wrap() can be called */ hs = SSLEngineResult.HandshakeStatus.NEED_WRAP; @@ -1343,10 +1350,10 @@ public class WolfSSLEngine extends SSLEngine { synchronized (toSendLock) { synchronized (netDataLock) { if (ret <= 0 && err == WolfSSL.SSL_ERROR_WANT_READ && - in.remaining() == 0 && (this.toSend == null || - (this.toSend != null && this.toSend.length == 0)) - && (prevSessionTicketCount == - this.sessionTicketCount)) { + in.remaining() == 0 && + (this.internalIOSendBufOffset == 0) && + (prevSessionTicketCount == + this.sessionTicketCount)) { if ((this.ssl.dtls() == 0) || (this.handshakeFinished && @@ -1376,8 +1383,7 @@ public class WolfSSLEngine extends SSLEngine { if (this.getUseClientMode() && this.handshakeFinished && this.ssl.hasSessionTicket() && this.sessionTicketReceived == false) { - if (this.ssl.dtls() == 1 && this.toSend != null && - this.toSend.length > 0) { + if (this.ssl.dtls() == 1 && this.internalIOSendBufOffset > 0) { /* DTLS 1.3 ACK has been produced in response to * session ticket message, let's set HS status to * NEED_WRAP so application knows it needs to be sent. */ @@ -1414,13 +1420,8 @@ public class WolfSSLEngine extends SSLEngine { } WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "ofst: " + ofst + ", length: " + length); - if (this.toSend != null) { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: " + this.toSend.length); - } else { - WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, - "toSend.length: 0"); - } + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "internalIOSendBufOffset: " + this.internalIOSendBufOffset); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "handshakeFinished: " + this.handshakeFinished); WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, @@ -1500,12 +1501,12 @@ public class WolfSSLEngine extends SSLEngine { err = ssl.getError(ret); } - /* Lock access to this.toSend and this.toRead */ + /* Lock access to this.internalIOSendBuf and this.toRead */ synchronized (toSendLock) { if (this.handshakeFinished == true) { /* close_notify sent by wolfSSL but not across transport yet */ if (this.closeNotifySent == true && - this.toSend != null && this.toSend.length > 0) { + this.internalIOSendBufOffset > 0) { hs = SSLEngineResult.HandshakeStatus.NEED_WRAP; } /* close_notify received, need to send one back */ @@ -1533,7 +1534,7 @@ public class WolfSSLEngine extends SSLEngine { synchronized (netDataLock) { synchronized (ioLock) { if (sslConnectAcceptSuccess() && ssl.handshakeDone() && - (this.toSend == null) && + (this.internalIOSendBufOffset == 0) && (this.nativeWantsToWrite == 0) && (this.nativeWantsToRead == 0)) { @@ -1552,7 +1553,7 @@ public class WolfSSLEngine extends SSLEngine { } /* give priority of WRAP/UNWRAP to state of our internal * I/O data buffers first, then wolfSSL err status */ - else if (this.toSend != null && this.toSend.length > 0) { + else if (this.internalIOSendBufOffset > 0) { hs = SSLEngineResult.HandshakeStatus.NEED_WRAP; } else if (this.netData != null && @@ -2110,9 +2111,7 @@ public class WolfSSLEngine extends SSLEngine { * * @return number of bytes placed into send queue */ - protected synchronized int internalSendCb(byte[] in, int sz) { - int totalSz = sz, idx = 0; - byte[] prevToSend = null; + protected synchronized int internalSendCb(ByteBuffer in, int sz) { synchronized (toSendLock) { /* As per JSSE Reference Guide, Section 8 DTLS implementation @@ -2122,7 +2121,8 @@ public class WolfSSLEngine extends SSLEngine { /* TODO - do we need to fragment data here if larger than * SSLParameters.getMaximumPacketSize() with DTLS? */ if (this.ssl.dtls() == 1) { - if (this.toSend != null) { + if ((this.internalIOSendBuf != null) && + (this.internalIOSendBufOffset > 0)) { /* Cause SSLEngine to only send one packet at a time. * Keep track if wolfSSL had wanted to send data. We will * use that information when setting the handshake @@ -2139,27 +2139,39 @@ public class WolfSSLEngine extends SSLEngine { this.nativeWantsToWrite = 0; } - /* Make copy of existing toSend array before expanding */ - if (this.toSend != null) { - prevToSend = this.toSend.clone(); - totalSz += this.toSend.length; + if (sz <= 0) { + /* No data to send */ + return 0; } - /* Allocate new array to hold data to be sent */ - this.toSend = new byte[totalSz]; - - /* Copy existing toSend data over */ - if (prevToSend != null) { - System.arraycopy(prevToSend, 0, this.toSend, idx, - prevToSend.length); - idx += prevToSend.length; + /* If we have more data than internal static buffer, + * grow buffer 2x (or up to sz needed) and copy data over */ + if ((this.internalIOSendBufSz - + this.internalIOSendBufOffset) < sz) { + /* Allocate new buffer to hold data to be sent */ + int newSz = this.internalIOSendBufSz * 2; + if (newSz < sz) { + newSz = sz; + } + byte[] newBuf = new byte[newSz]; + System.arraycopy(this.internalIOSendBuf, 0, + newBuf, 0, + this.internalIOSendBufOffset); + this.internalIOSendBuf = newBuf; + this.internalIOSendBufSz = newSz; } - System.arraycopy(in, 0, this.toSend, idx, sz); - } - if (ioDebugEnabled == true) { - WolfSSLDebug.logHex(getClass(), WolfSSLDebug.INFO, - "CB Write", in, sz); + /* Add data to end of internal static buffer */ + in.get(this.internalIOSendBuf, this.internalIOSendBufOffset, sz); + + if (ioDebugEnabled == true) { + WolfSSLDebug.logHex(getClass(), WolfSSLDebug.INFO, + "CB Write", Arrays.copyOfRange(this.internalIOSendBuf, + this.internalIOSendBufOffset, + this.internalIOSendBufOffset + sz), sz); + } + + this.internalIOSendBufOffset += sz; } return sz; @@ -2169,15 +2181,16 @@ public class WolfSSLEngine extends SSLEngine { * Internal receive callback. Reads from netData and gives bytes back * to native wolfSSL for processing. * - * @param toRead byte array into which to place data read from transport + * @param toRead ByteBuffer into which to place data read from transport * @param sz number of bytes that should be read/copied from transport * * @return number of bytes read into toRead array or negative * value on error */ - protected synchronized int internalRecvCb(byte[] toRead, int sz) { + protected synchronized int internalRecvCb(ByteBuffer toRead, int sz) { int max = 0; + int originalLimit = 0; synchronized (netDataLock) { if (ioDebugEnabled == true) { @@ -2211,13 +2224,22 @@ public class WolfSSLEngine extends SSLEngine { this.nativeWantsToRead = 0; max = (sz < this.netData.remaining()) ? sz : this.netData.remaining(); - this.netData.get(toRead, 0, max); + /* Print out bytes read from toRead buffer */ if (ioDebugEnabled == true) { + int toReadPos = toRead.position(); + byte[] tmpArr = new byte[max]; + toRead.get(tmpArr, 0, max); WolfSSLDebug.logHex(getClass(), WolfSSLDebug.INFO, - "CB Read", toRead, max); + "CB Read", tmpArr, max); + toRead.position(toReadPos); } + originalLimit = this.netData.limit(); + this.netData.limit(this.netData.position() + max); + toRead.put(this.netData); + this.netData.limit(originalLimit); + return max; } } @@ -2248,28 +2270,28 @@ public class WolfSSLEngine extends SSLEngine { return 0; } - private class SendCB implements WolfSSLIOSendCallback { + private class SendCB implements WolfSSLByteBufferIOSendCallback { protected SendCB() { } - public int sendCallback(WolfSSLSession ssl, byte[] toSend, int sz, + public int sendCallback(WolfSSLSession ssl, ByteBuffer toSend, int sz, Object engine) { return ((WolfSSLEngine)engine).internalSendCb(toSend, sz); } } - private class RecvCB implements WolfSSLIORecvCallback { + private class RecvCB implements WolfSSLByteBufferIORecvCallback { protected RecvCB() { } - public int receiveCallback(WolfSSLSession ssl, byte[] out, int sz, + public int receiveCallback(WolfSSLSession ssl, ByteBuffer buf, int sz, Object engine) { - return ((WolfSSLEngine)engine).internalRecvCb(out, sz); + return ((WolfSSLEngine)engine).internalRecvCb(buf, sz); } } @@ -2292,6 +2314,11 @@ public class WolfSSLEngine extends SSLEngine { this.ssl.freeSSL(); this.ssl = null; } + /* Clear our reference to static application direct ByteBuffer */ + if (this.staticAppDataBuf != null) { + this.staticAppDataBuf.clear(); + this.staticAppDataBuf = null; + } super.finalize(); } } diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java b/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java index 3d97056..0f59eda 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java @@ -760,15 +760,52 @@ public class WolfSSLImplementSSLSession extends ExtendedSSLSession return this.port; } + /** + * Can be called by SSLEngine consumers to determine maximum + * output buffer size, to be used for buffer allocations. + * + * @return maximum output buffer size + */ @Override - public int getPacketBufferSize() { - /* Match conscrypt's calculations here for maximum potential - * SSL/TLS record length. Used by SSLEngine consumers to allocate - * output buffer size. + public synchronized int getPacketBufferSize() { + + /* JSSE implementations seem to set the SSL/TLS maximum packet size + * (record size) differently. + * + * Conscrypt calculates this as 18437 bytes: * * type(1) + version(2) + length(2) + 2^14 plaintext + - * max compression overhead (1024) + max AEAD overhead (1024) */ - return 18437; + * max compression overhead (1024) + max AEAD overhead (1024) + * + * wolfJSSE originally matched the Conscrypt value, but it conflicts + * with the maximum allowed/used by the tls-channel project, which + * we have a few customers using. tls-channel uses a maximum size of + * 17k. + * + * Native wolfSSL has the wolfSSL_GetMaxOutputSize() function, but + * it only works post-handshake. getPacketBufferSize() can be called + * pre-handshake, so we set a default value here that matches + * the upper limit for tls-channel, which is 17k, then if + * wolfSSL_GetMaxOutputSize() is larger, we increase to that value. + */ + int nativeMax; + int ret = 17 * 1024; + + /* Try to get maximum TLS record size from native wolfSSL */ + if (ssl != null) { + nativeMax = ssl.getMaxOutputSize(); + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "ssl.getMaxOutputSize() returned: " + nativeMax); + + if ((nativeMax > 0) && (nativeMax > ret)) { + ret = nativeMax; + } + } + + WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, + "getPacketBufferSize() returning: " + ret); + + return ret; } @Override diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java index ef37f48..b1399d4 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLEngineTest.java @@ -1662,8 +1662,8 @@ public class WolfSSLEngineTest { session = engine.getSession(); packetBufSz = session.getPacketBufferSize(); - /* expected to be 18437 */ - if (packetBufSz != 18437) { + /* expected to be 17k */ + if (packetBufSz != (17 * 1024)) { error("\t\t... failed"); fail("got incorrect packet buffer size (" + enabledProtocols.get(i) + ")"); diff --git a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java index a0f318e..d04a447 100644 --- a/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java +++ b/src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java @@ -3393,7 +3393,7 @@ public class WolfSSLSocketTest { throw cliException; } - System.out.println("\t\t... passed"); + System.out.println("\t... passed"); } finally { /* Restore original property value */ diff --git a/src/test/com/wolfssl/test/WolfSSLContextTest.java b/src/test/com/wolfssl/test/WolfSSLContextTest.java index ddac700..f0416b2 100644 --- a/src/test/com/wolfssl/test/WolfSSLContextTest.java +++ b/src/test/com/wolfssl/test/WolfSSLContextTest.java @@ -644,13 +644,6 @@ public class WolfSSLContextTest { fail("setMinECCKeySize should fail with negative key size"); } - /* key length not % 8 should fail */ - ret = ctx.setMinECCKeySize(255); - if (ret != WolfSSL.BAD_FUNC_ARG) { - System.out.println("\t\t... failed"); - fail("setMinECCKeySize should fail with non % 8 size"); - } - /* valid key length should succeed */ ret = ctx.setMinECCKeySize(128); if (ret != WolfSSL.SSL_SUCCESS) { diff --git a/src/test/com/wolfssl/test/WolfSSLSessionTest.java b/src/test/com/wolfssl/test/WolfSSLSessionTest.java index dbb1914..7e62ed5 100644 --- a/src/test/com/wolfssl/test/WolfSSLSessionTest.java +++ b/src/test/com/wolfssl/test/WolfSSLSessionTest.java @@ -23,13 +23,10 @@ package com.wolfssl.test; import org.junit.Test; import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; import static org.junit.Assert.*; import java.io.ByteArrayOutputStream; import java.io.PrintStream; -import java.io.IOException; import java.net.Socket; import java.net.ServerSocket; import java.net.InetAddress; @@ -43,6 +40,8 @@ import java.util.concurrent.Future; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.CountDownLatch; +import java.util.Arrays; +import java.nio.ByteBuffer; import com.wolfssl.WolfSSL; import com.wolfssl.WolfSSLDebug; @@ -53,12 +52,11 @@ import com.wolfssl.WolfSSLPskClientCallback; import com.wolfssl.WolfSSLPskServerCallback; import com.wolfssl.WolfSSLTls13SecretCallback; import com.wolfssl.WolfSSLSession; +import com.wolfssl.WolfSSLByteBufferIORecvCallback; +import com.wolfssl.WolfSSLByteBufferIOSendCallback; public class WolfSSLSessionTest { - private final static int TEST_FAIL = -1; - private final static int TEST_SUCCESS = 0; - private static String cliCert = "./examples/certs/client-cert.pem"; private static String cliKey = "./examples/certs/client-key.pem"; private static String srvCert = "./examples/certs/server-cert.pem"; @@ -69,6 +67,9 @@ public class WolfSSLSessionTest { private final static String exampleHost = "www.example.com"; private final static int examplePort = 443; + /* Maximum network buffer size, for test I/O callbacks */ + private final static int MAX_NET_BUF_SZ = 17 * 1024; + private static WolfSSLContext ctx = null; @BeforeClass @@ -889,7 +890,6 @@ public class WolfSSLSessionTest { public void test_WolfSSLSession_setTls13SecretCb() throws WolfSSLJNIException { - int ret; WolfSSL sslLib = null; WolfSSLContext sslCtx = null; WolfSSLSession ssl = null; @@ -1413,5 +1413,409 @@ public class WolfSSLSessionTest { System.out.println("\t... passed"); } + + /** + * wolfSSL I/O context, is passed to I/O callbacks when called + * by native wolfSSL. + */ + private class MyIOCtx { + private byte[] cliToSrv = new byte[MAX_NET_BUF_SZ]; + private byte[] srvToCli = new byte[MAX_NET_BUF_SZ]; + + private int cliToSrvUsed = 0; + private int srvToCliUsed = 0; + + private int CLIENT_END = 1; + private int SERVER_END = 2; + + private final Object cliLock = new Object(); + private final Object srvLock = new Object(); + + private int insertData(byte[] dest, int destUsed, + ByteBuffer src, int len) { + + int freeBufSpace = dest.length - destUsed; + + /* Check if buffer is full */ + if ((len > 0) && (freeBufSpace == 0)) { + return -1; + } + + int bytesToCopy = Math.min(len, freeBufSpace); + if (bytesToCopy > 0) { + src.get(dest, destUsed, bytesToCopy); + } + return bytesToCopy; + } + + private int getData(byte[] src, int srcUsed, + ByteBuffer dest, int len) { + + /* src buffer is empty */ + if ((len > 0) && (srcUsed == 0)) { + return -1; + } + + int bytesToCopy = Math.min(len, srcUsed); + if (bytesToCopy > 0) { + dest.put(src, 0, bytesToCopy); + srcUsed -= bytesToCopy; + /* Shift remaining data to front of buffer */ + if (srcUsed > 0) { + System.arraycopy(src, bytesToCopy, src, 0, srcUsed); + } + } + return bytesToCopy; + } + + public int insertCliToSrvData(ByteBuffer buf, int len) { + synchronized (cliLock) { + int ret = insertData(cliToSrv, cliToSrvUsed, buf, len); + if (ret > 0) { + cliToSrvUsed += ret; + } + return ret; + } + } + + public int insertSrvToCliData(ByteBuffer buf, int len) { + synchronized (srvLock) { + int ret = insertData(srvToCli, srvToCliUsed, buf, len); + if (ret > 0) { + srvToCliUsed += ret; + } + return ret; + } + } + + public int getCliToSrvData(ByteBuffer buf, int len) { + synchronized (cliLock) { + int ret = getData(cliToSrv, cliToSrvUsed, buf, len); + if (ret > 0) { + cliToSrvUsed -= ret; + } + return ret; + } + } + + public int getSrvToCliData(ByteBuffer buf, int len) { + synchronized (srvLock) { + int ret = getData(srvToCli, srvToCliUsed, buf, len); + if (ret > 0) { + srvToCliUsed -= ret; + } + return ret; + } + } + } + + /* Client I/O callback using ByteBuffers */ + private class ClientByteBufferIOCallback + implements WolfSSLByteBufferIORecvCallback, + WolfSSLByteBufferIOSendCallback { + /** + * Receive data is called when wolfSSL needs to read data from the + * transport layer. In this case, we read data from the beginning + * of the internal byte[] (buffer) and place it into the ByteBuffer buf. + * + * Return the number of bytes copied to the ByteBuffer buf, or negative + * on error. + */ + @Override + public synchronized int receiveCallback(WolfSSLSession ssl, + ByteBuffer buf, int len, Object ctx) { + + int ret; + MyIOCtx ioCtx = (MyIOCtx) ctx; + + ret = ioCtx.getSrvToCliData(buf, len); + if (ret == -1) { + /* No data available, return WOLFSSL_CBIO_ERR_WANT_READ */ + ret = WolfSSL.WOLFSSL_CBIO_ERR_WANT_READ; + } + + return ret; + } + + /** + * Send data is called when wolfSSL needs to write data to the + * transport layer. In this case, we read data from the ByteBuffer + * buf and place it into our internal byte[] (buffer). + * + * Return the number of bytes copied from the ByteBuffer buf, or + * negative on error. + */ + @Override + public synchronized int sendCallback( + WolfSSLSession ssl, ByteBuffer buf, int len, Object ctx) { + + int ret; + MyIOCtx ioCtx = (MyIOCtx) ctx; + + ret = ioCtx.insertCliToSrvData(buf, len); + if (ret == -1) { + /* No space available, return WOLFSSL_CBIO_ERR_WANT_WRITE */ + ret = WolfSSL.WOLFSSL_CBIO_ERR_WANT_WRITE; + } + + return ret; + } + } + + /* Server I/O callback using ByteBuffers */ + private class ServerByteBufferIOCallback + implements WolfSSLByteBufferIORecvCallback, + WolfSSLByteBufferIOSendCallback { + /** + * Receive data is called when wolfSSL needs to read data from the + * transport layer. In this case, we read data from the beginning + * of the internal byte[] (buffer) and place it into the ByteBuffer buf. + * + * Return the number of bytes copied to the ByteBuffer buf, or negative + * on error. + */ + @Override + public synchronized int receiveCallback(WolfSSLSession ssl, + ByteBuffer buf, int len, Object ctx) { + + int ret; + MyIOCtx ioCtx = (MyIOCtx) ctx; + + ret = ioCtx.getCliToSrvData(buf, len); + if (ret == -1) { + /* No data available, return WOLFSSL_CBIO_ERR_WANT_READ */ + ret = WolfSSL.WOLFSSL_CBIO_ERR_WANT_READ; + } + + return ret; + } + + /** + * Send data is called when wolfSSL needs to write data to the + * transport layer. In this case, we read data from the ByteBuffer + * buf and place it into our internal byte[] (buffer). + * + * Return the number of bytes copied from the ByteBuffer buf, or + * negative on error. + */ + @Override + public synchronized int sendCallback( + WolfSSLSession ssl, ByteBuffer buf, int len, Object ctx) { + + int ret; + MyIOCtx ioCtx = (MyIOCtx) ctx; + + ret = ioCtx.insertSrvToCliData(buf, len); + if (ret == -1) { + /* No space available, return WOLFSSL_CBIO_ERR_WANT_WRITE */ + ret = WolfSSL.WOLFSSL_CBIO_ERR_WANT_WRITE; + } + + return ret; + } + } + + @Test + public void test_WolfSSLSession_ioBuffers() throws Exception { + int ret = 0; + int err = 0; + Socket cliSock = null; + WolfSSLSession cliSes = null; + byte[] testData = "Hello from client".getBytes(); + byte[] servAppBuffer = new byte[MAX_NET_BUF_SZ]; + byte[] cliAppBuffer = new byte[MAX_NET_BUF_SZ]; + int bytesRead = 0; + + /* Create client/server WolfSSLContext objects */ + final WolfSSLContext srvCtx; + WolfSSLContext cliCtx; + + System.out.print("\tTesting I/O CB with ByteBuffers"); + + /* Initialize library */ + WolfSSL lib = new WolfSSL(); + + /* Create ServerSocket first to get ephemeral port */ + final ServerSocket srvSocket = new ServerSocket(0); + + srvCtx = createAndSetupWolfSSLContext(srvCert, srvKey, + WolfSSL.SSL_FILETYPE_PEM, cliCert, + WolfSSL.SSLv23_ServerMethod()); + cliCtx = createAndSetupWolfSSLContext(cliCert, cliKey, + WolfSSL.SSL_FILETYPE_PEM, caCert, + WolfSSL.SSLv23_ClientMethod()); + + MyIOCtx myIOCb = new MyIOCtx(); + ClientByteBufferIOCallback cliIOCb = new ClientByteBufferIOCallback(); + ServerByteBufferIOCallback srvIOCb = new ServerByteBufferIOCallback(); + + ExecutorService es = Executors.newSingleThreadExecutor(); + + /* Start server */ + try { + es.submit(new Callable() { + @Override + public Void call() throws Exception { + int ret; + int err; + Socket server = null; + WolfSSLSession srvSes = null; + int bytesRead = 0; + + try { + server = srvSocket.accept(); + srvSes = new WolfSSLSession(srvCtx); + + /* Set I/O callback and ctx */ + srvSes.setIOSendByteBuffer(srvIOCb); + srvSes.setIORecvByteBuffer(srvIOCb); + srvSes.setIOWriteCtx(myIOCb); + srvSes.setIOReadCtx(myIOCb); + + /* Do handshake */ + do { + ret = srvSes.accept(); + err = srvSes.getError(ret); + } while (ret != WolfSSL.SSL_SUCCESS && + (err == WolfSSL.SSL_ERROR_WANT_READ || + err == WolfSSL.SSL_ERROR_WANT_WRITE)); + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "Server accept failed: " + err); + } + + /* Read data from client */ + bytesRead = srvSes.read(servAppBuffer, + servAppBuffer.length, 0); + if (bytesRead <= 0) { + throw new Exception( + "Server read failed: " + bytesRead); + } + + /* Send same data back to client */ + ret = srvSes.write(servAppBuffer, bytesRead, 0); + if (ret != bytesRead) { + throw new Exception("Server write failed: " + ret); + } + + srvSes.shutdownSSL(); + srvSes.freeSSL(); + srvSes = null; + server.close(); + server = null; + + } finally { + if (srvSes != null) { + srvSes.freeSSL(); + } + if (server != null) { + server.close(); + } + } + + return null; + } + }); + + } catch (Exception e) { + System.out.println("\t... failed"); + e.printStackTrace(); + fail(); + } + + try { + /* Client connection */ + cliSock = new Socket(InetAddress.getLocalHost(), + srvSocket.getLocalPort()); + + cliSes = new WolfSSLSession(cliCtx); + + /* Set I/O callback and ctx */ + cliSes.setIOSendByteBuffer(cliIOCb); + cliSes.setIORecvByteBuffer(cliIOCb); + cliSes.setIOWriteCtx(myIOCb); + cliSes.setIOReadCtx(myIOCb); + + /* Do handshake */ + do { + ret = cliSes.connect(); + err = cliSes.getError(ret); + } while (ret != WolfSSL.SSL_SUCCESS && + (err == WolfSSL.SSL_ERROR_WANT_READ || + err == WolfSSL.SSL_ERROR_WANT_WRITE)); + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new Exception( + "Client connect failed: " + err); + } + + /* Send test data */ + ret = cliSes.write(testData, testData.length, 0); + if (ret != testData.length) { + throw new Exception( + "Client write failed: " + ret); + } + + /* Read response */ + do { + bytesRead = cliSes.read(cliAppBuffer, cliAppBuffer.length, 0); + err = cliSes.getError(bytesRead); + } while (ret != WolfSSL.SSL_SUCCESS && + err == WolfSSL.SSL_ERROR_WANT_READ || + err == WolfSSL.SSL_ERROR_WANT_WRITE); + + if (bytesRead != testData.length) { + throw new Exception( + "Client read failed: " + bytesRead); + } + + /* Verify received data matches sent data using Java 8 compatible + * array comparison */ + boolean arraysMatch = true; + if (testData.length != bytesRead) { + arraysMatch = false; + } else { + for (int i = 0; i < testData.length; i++) { + if (testData[i] != cliAppBuffer[i]) { + arraysMatch = false; + break; + } + } + } + if (!arraysMatch) { + throw new Exception("Received data does not match sent data"); + } + + cliSes.shutdownSSL(); + cliSes.freeSSL(); + cliSes = null; + cliSock.close(); + cliSock = null; + + } catch (Exception e) { + System.out.println("\t... failed"); + e.printStackTrace(); + fail(); + + } finally { + /* Free resources */ + if (cliSes != null) { + cliSes.freeSSL(); + } + if (cliSock != null) { + cliSock.close(); + } + if (srvSocket != null) { + srvSocket.close(); + } + if (srvCtx != null) { + srvCtx.free(); + } + es.shutdown(); + } + + System.out.println("\t... passed"); + } }