4009 lines
113 KiB
C
4009 lines
113 KiB
C
/* com_wolfssl_WolfSSLSession.c
|
|
*
|
|
* Copyright (C) 2006-2022 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-1301, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <arpa/inet.h>
|
|
#include <wolfssl/options.h>
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/error-ssl.h>
|
|
|
|
#include "com_wolfssl_globals.h"
|
|
#include "com_wolfssl_WolfSSL.h"
|
|
|
|
/* custom I/O native fn prototypes */
|
|
int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
|
int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
|
#ifdef HAVE_CRL
|
|
/* global object refs for CRL callback */
|
|
static jobject g_crlCbIfaceObj;
|
|
#endif
|
|
|
|
/* Data used per-WOLFSSL session that needs to be stored across native
|
|
* function calls. Stored inside WOLFSSL app data, set with
|
|
* wolfSSL_set_app_data(), retrieved with wolfSSL_get_app_data().
|
|
* Global callback objects are created with NewGlobalRef(), then freed
|
|
* inside freeSSL() with DeleteGlobalRef(). */
|
|
typedef struct SSLAppData {
|
|
wolfSSL_Mutex* jniSessLock; /* WOLFSSL session lock */
|
|
jobject* g_verifySSLCbIfaceObj; /* Java verify callback [global ref] */
|
|
} SSLAppData;
|
|
|
|
/* custom native fn prototypes */
|
|
void NativeMissingCRLCallback(const char* url);
|
|
int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store);
|
|
|
|
int NativeSSLVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint vmret = 0;
|
|
jint retval = -1;
|
|
jclass excClass;
|
|
jmethodID verifyMethod;
|
|
jobjectRefType refcheck;
|
|
SSLAppData* appData; /* WOLFSSL app data, stored verify cb obj */
|
|
jobject* g_verifySSLCbIfaceObj; /* Global jobject, stored in app data */
|
|
|
|
if (!g_vm) {
|
|
/* we can't throw an exception yet, so just return 0 (failure) */
|
|
return 0;
|
|
}
|
|
|
|
/* get JNIEnv from JavaVM */
|
|
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
|
|
if (vmret == JNI_EDETACHED) {
|
|
#ifdef __ANDROID__
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
|
|
#else
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
|
|
#endif
|
|
if (vmret) {
|
|
return -101; /* failed to attach JNIEnv to thread */
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
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));
|
|
if (appData == NULL) {
|
|
printf("Error getting app data from WOLFSSL\n");
|
|
return -105;
|
|
}
|
|
|
|
/* get global Java verify callback object */
|
|
g_verifySSLCbIfaceObj = appData->g_verifySSLCbIfaceObj;
|
|
if (g_verifySSLCbIfaceObj == NULL || *g_verifySSLCbIfaceObj == NULL) {
|
|
printf("Error getting g_verifySSLCbIfaceObj from appData\n");
|
|
return -106;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, *g_verifySSLCbIfaceObj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLVerifyCallback class from global object ref */
|
|
jclass verifyClass = (*jenv)->GetObjectClass(jenv,
|
|
*g_verifySSLCbIfaceObj);
|
|
if (!verifyClass) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLVerifyCallback class reference");
|
|
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);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* exception occurred on the Java side during method call */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return -109;
|
|
}
|
|
|
|
} else {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeSSLVerifyCallback");
|
|
return -1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/* jni functions */
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_newSSL
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
int ret;
|
|
jlong sslPtr = 0;
|
|
jobject* g_cachedSSLObj = NULL;
|
|
wolfSSL_Mutex* jniSessLock = NULL;
|
|
SSLAppData* appData = NULL;
|
|
|
|
if (jenv == NULL) {
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* wolfSSL java caller checks for null pointer */
|
|
sslPtr = (jlong)(uintptr_t)wolfSSL_new((WOLFSSL_CTX*)(uintptr_t)ctx);
|
|
|
|
if (sslPtr != 0) {
|
|
/* create global reference to WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*)XMALLOC(sizeof(jobject), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (g_cachedSSLObj == NULL) {
|
|
printf("error mallocing memory in newSSL\n");
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
*g_cachedSSLObj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (*g_cachedSSLObj == NULL) {
|
|
printf("error storing global WolfSSLSession object\n");
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
appData = (SSLAppData*)XMALLOC(sizeof(SSLAppData), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (appData == NULL) {
|
|
printf("error allocating memory in newSSL for SSLAppData\n");
|
|
(*jenv)->DeleteGlobalRef(jenv, *g_cachedSSLObj);
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
XMEMSET(appData, 0, sizeof(SSLAppData));
|
|
|
|
/* store mutex lock in SSL app data, used for I/O and session lock.
|
|
* This is freed in freeSSL. */
|
|
jniSessLock = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (!jniSessLock) {
|
|
printf("error mallocing memory in newSSL for jniSessLock\n");
|
|
(*jenv)->DeleteGlobalRef(jenv, *g_cachedSSLObj);
|
|
XFREE(appData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
wc_InitMutex(jniSessLock);
|
|
appData->jniSessLock = jniSessLock;
|
|
|
|
/* cache associated WolfSSLSession jobject in native WOLFSSL */
|
|
ret = wolfSSL_set_jobject((WOLFSSL*)(uintptr_t)sslPtr, g_cachedSSLObj);
|
|
if (ret != SSL_SUCCESS) {
|
|
printf("error storing jobject in wolfSSL native session\n");
|
|
(*jenv)->DeleteGlobalRef(jenv, *g_cachedSSLObj);
|
|
XFREE(appData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* cache SSLAppData into native WOLFSSL */
|
|
if (wolfSSL_set_app_data(
|
|
(WOLFSSL*)(uintptr_t)sslPtr, appData) != SSL_SUCCESS) {
|
|
printf("error setting WOLFSSL app data in newSSL\n");
|
|
(*jenv)->DeleteGlobalRef(jenv, *g_cachedSSLObj);
|
|
XFREE(jniSessLock, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
XFREE(appData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
wolfSSL_set_jobject((WOLFSSL*)(uintptr_t)sslPtr, NULL);
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)sslPtr);
|
|
return SSL_FAILURE;
|
|
}
|
|
}
|
|
|
|
return sslPtr;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setFd(JNIEnv* jenv,
|
|
jobject jcl, jlong ssl, jobject jsock, jint type)
|
|
{
|
|
int fd;
|
|
jclass jcls;
|
|
jfieldID fid;
|
|
jobject impl;
|
|
jobject fdesc;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl || !jsock)
|
|
return SSL_FAILURE;
|
|
|
|
/* get SocketImpl or DatagramSocketImpl from Java Socket */
|
|
jcls = (*jenv)->GetObjectClass(jenv, jsock);
|
|
if (type == 1) {
|
|
fid = (*jenv)->GetFieldID(jenv, jcls, "impl", "Ljava/net/SocketImpl;");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
impl = (*jenv)->GetObjectField(jenv, jsock, fid);
|
|
|
|
} else if (type == 2) {
|
|
fid = (*jenv)->GetFieldID(jenv, jcls, "impl",
|
|
"Ljava/net/DatagramSocketImpl;");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
impl = (*jenv)->GetObjectField(jenv, jsock, fid);
|
|
} else {
|
|
return SSL_FAILURE; /* invalid class type */
|
|
}
|
|
|
|
if (!jcls || !fid || !impl)
|
|
return SSL_FAILURE;
|
|
|
|
/* get FileDescriptor from SocketImpl */
|
|
jcls = (*jenv)->GetObjectClass(jenv, impl);
|
|
fid = (*jenv)->GetFieldID(jenv, jcls, "fd", "Ljava/io/FileDescriptor;");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
fdesc = (*jenv)->GetObjectField(jenv, impl, fid);
|
|
|
|
if (!jcls || !fid || !fdesc)
|
|
return SSL_FAILURE;
|
|
|
|
/* get fd from FileDescriptor */
|
|
jcls = (*jenv)->GetObjectClass(jenv, fdesc);
|
|
#ifdef __ANDROID__
|
|
fid = (*jenv)->GetFieldID(jenv, jcls, "descriptor", "I");
|
|
#else
|
|
fid = (*jenv)->GetFieldID(jenv, jcls, "fd", "I");
|
|
#endif
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
if (!jcls || !fid )
|
|
return SSL_FAILURE;
|
|
|
|
fd = (*jenv)->GetIntField(jenv, fdesc, fid);
|
|
|
|
/* set socket to non-blocking so we can use select() to detect
|
|
* WANT_READ / WANT_WRITE */
|
|
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
|
|
|
|
return (jint)wolfSSL_set_fd((WOLFSSL*)(uintptr_t)ssl, fd);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring file, jint format)
|
|
{
|
|
#ifdef OPENSSL_EXTRA
|
|
jint ret = 0;
|
|
const char* certFile;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return SSL_FAILURE;
|
|
|
|
if (file == NULL)
|
|
return SSL_BAD_FILE;
|
|
|
|
certFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_use_certificate_file((WOLFSSL*)(uintptr_t)ssl, certFile,
|
|
(int)format);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, certFile);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)file;
|
|
(void)format;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_usePrivateKeyFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring file, jint format)
|
|
{
|
|
#ifdef OPENSSL_EXTRA
|
|
jint ret = 0;
|
|
const char* keyFile;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return SSL_FAILURE;
|
|
|
|
if (file == NULL)
|
|
return SSL_BAD_FILE;
|
|
|
|
keyFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_use_PrivateKey_file((WOLFSSL*)(uintptr_t)ssl, keyFile,
|
|
(int)format);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, keyFile);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)file;
|
|
(void)format;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring file)
|
|
{
|
|
#ifdef OPENSSL_EXTRA
|
|
jint ret = 0;
|
|
const char* chainFile;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return SSL_FAILURE;
|
|
|
|
if (file == NULL)
|
|
return SSL_BAD_FILE;
|
|
|
|
chainFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_use_certificate_chain_file((WOLFSSL*)(uintptr_t)ssl,
|
|
chainFile);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, chainFile);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)file;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setUsingNonblock
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jint nonblock)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return;
|
|
|
|
if (!ssl) {
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in setUsingNonblock");
|
|
}
|
|
|
|
wolfSSL_set_using_nonblock((WOLFSSL*)(uintptr_t)ssl, nonblock);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getUsingNonblock
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return 0;
|
|
|
|
if (!ssl) {
|
|
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 getUsingNonblock");
|
|
}
|
|
|
|
return wolfSSL_get_using_nonblock((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getFd
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return 0;
|
|
|
|
if (!ssl) {
|
|
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 getFd");
|
|
return 0;
|
|
}
|
|
|
|
return wolfSSL_get_fd((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
/* enum values used in socketSelect() */
|
|
enum {
|
|
WOLFJNI_SELECT_FAIL = -10,
|
|
WOLFJNI_TIMEOUT = -11,
|
|
WOLFJNI_RECV_READY = -12,
|
|
WOLFJNI_SEND_READY = -13,
|
|
WOLFJNI_ERROR_READY = -14
|
|
};
|
|
|
|
/* perform a select() call on underlying socket to wait for socket to be ready
|
|
* to read/write, or timeout. Note that we explicitly set the underlying
|
|
* socket descriptor to non-blocking so we can select() on it.
|
|
*
|
|
* The Java socket timeout value representing no timeout is NULL, not 0 like
|
|
* C. We adjust for this when handling timeout_ms here. timeout_ms is in
|
|
* milliseconds. */
|
|
static int socketSelect(int sockfd, int timeout_ms, int rx)
|
|
{
|
|
fd_set fds, errfds;
|
|
fd_set* recvfds = NULL;
|
|
fd_set* sendfds = NULL;
|
|
int nfds = sockfd + 1;
|
|
int result;
|
|
struct timeval timeout;
|
|
|
|
timeout.tv_sec = timeout_ms / 1000;
|
|
timeout.tv_usec = (timeout_ms % 1000) * 1000;
|
|
|
|
FD_ZERO(&fds);
|
|
FD_SET(sockfd, &fds);
|
|
FD_ZERO(&errfds);
|
|
FD_SET(sockfd, &errfds);
|
|
|
|
if (rx) {
|
|
recvfds = &fds;
|
|
} else {
|
|
sendfds = &fds;
|
|
}
|
|
|
|
if (timeout_ms == 0) {
|
|
result = select(nfds, recvfds, sendfds, &errfds, NULL);
|
|
} else {
|
|
result = select(nfds, recvfds, sendfds, &errfds, &timeout);
|
|
}
|
|
|
|
if (result == 0) {
|
|
return WOLFJNI_TIMEOUT;
|
|
} else if (result > 0) {
|
|
if (FD_ISSET(sockfd, &fds)) {
|
|
if (rx) {
|
|
return WOLFJNI_RECV_READY;
|
|
} else {
|
|
return WOLFJNI_SEND_READY;
|
|
}
|
|
} else if (FD_ISSET(sockfd, &errfds)) {
|
|
return WOLFJNI_ERROR_READY;
|
|
}
|
|
}
|
|
|
|
return WOLFJNI_SELECT_FAIL;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_connect
|
|
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
|
|
{
|
|
int ret = 0, err = 0, sockfd = 0;
|
|
WOLFSSL* ssl = NULL;
|
|
wolfSSL_Mutex* jniSessLock = NULL;
|
|
SSLAppData* appData = NULL;
|
|
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL || sslPtr <= 0) {
|
|
return SSL_FATAL_ERROR;
|
|
}
|
|
ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
|
|
|
/* make sure we don't have any outstanding exceptions pending */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* get session mutex from SSL app data */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
|
|
if (appData == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
jniSessLock = appData->jniSessLock;
|
|
if (jniSessLock == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
do {
|
|
/* get I/O lock */
|
|
if (wc_LockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
ret = wolfSSL_connect(ssl);
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
|
|
/* release I/O lock */
|
|
if (wc_UnLockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (ret < 0 && ((err == SSL_ERROR_WANT_READ) ||
|
|
(err == SSL_ERROR_WANT_WRITE))) {
|
|
|
|
sockfd = wolfSSL_get_fd(ssl);
|
|
if (sockfd == -1) {
|
|
/* For I/O that does not use sockets, sockfd may be -1,
|
|
* skip try to call select() */
|
|
break;
|
|
}
|
|
|
|
ret = socketSelect(sockfd, 0, 1);
|
|
if (ret == WOLFJNI_RECV_READY || ret == WOLFJNI_SEND_READY) {
|
|
/* I/O ready, continue handshake and try again */
|
|
continue;
|
|
} else {
|
|
/* error or timeout */
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ);
|
|
|
|
/* check for Java exceptions beofre returning */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_write(JNIEnv* jenv,
|
|
jobject jcl, jlong sslPtr, jbyteArray raw, jint length)
|
|
{
|
|
byte* data;
|
|
int ret = SSL_FAILURE, err, sockfd;
|
|
WOLFSSL* ssl = NULL;
|
|
wolfSSL_Mutex* jniSessLock = NULL;
|
|
SSLAppData* appData = NULL;
|
|
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL || sslPtr <= 0 || raw == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
|
|
|
if (length >= 0) {
|
|
data = (byte*)(*jenv)->GetByteArrayElements(jenv, raw, NULL);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* get session mutex from SSL app data */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
|
|
if (appData == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
jniSessLock = appData->jniSessLock;
|
|
if (jniSessLock == NULL) {
|
|
(*jenv)->ReleaseByteArrayElements(jenv, raw, (jbyte*)data,
|
|
JNI_ABORT);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
do {
|
|
|
|
/* lock mutex around session I/O before write attempt */
|
|
if (wc_LockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
ret = wolfSSL_write(ssl, data, length);
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
|
|
/* unlock mutex around session I/O after write attempt */
|
|
if (wc_UnLockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
|
|
|
sockfd = wolfSSL_get_fd(ssl);
|
|
if (sockfd == -1) {
|
|
/* For I/O that does not use sockets, sockfd may be -1,
|
|
* skip try to call select() */
|
|
break;
|
|
}
|
|
|
|
ret = socketSelect(sockfd, 0, 0);
|
|
if (ret == WOLFJNI_RECV_READY || ret == WOLFJNI_SEND_READY) {
|
|
/* loop around and try wolfSSL_write() again */
|
|
continue;
|
|
} else {
|
|
/* error or timeout occurred during select */
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ);
|
|
|
|
(*jenv)->ReleaseByteArrayElements(jenv, raw, (jbyte*)data, JNI_ABORT);
|
|
|
|
return ret;
|
|
|
|
} else {
|
|
return SSL_FAILURE;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_read(JNIEnv* jenv,
|
|
jobject jcl, jlong sslPtr, jbyteArray raw, jint length, int timeout)
|
|
{
|
|
byte* data;
|
|
int size = 0, ret, err, sockfd;
|
|
WOLFSSL* ssl = NULL;
|
|
wolfSSL_Mutex* jniSessLock = NULL;
|
|
SSLAppData* appData = NULL;
|
|
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL || sslPtr <= 0 || raw == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
|
|
|
if (length >= 0) {
|
|
data = (byte*)(*jenv)->GetByteArrayElements(jenv, raw, NULL);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* get session mutex from SSL app data */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
|
|
if (appData == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
jniSessLock = appData->jniSessLock;
|
|
if (jniSessLock == NULL) {
|
|
(*jenv)->ReleaseByteArrayElements(jenv, raw, (jbyte*)data,
|
|
JNI_ABORT);
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
do {
|
|
/* lock mutex around session I/O before read attempt */
|
|
if (wc_LockMutex(jniSessLock) != 0) {
|
|
size = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
size = wolfSSL_read(ssl, data, length);
|
|
err = wolfSSL_get_error(ssl, size);
|
|
|
|
/* unlock mutex around session I/O after read attempt */
|
|
if (wc_UnLockMutex(jniSessLock) != 0) {
|
|
size = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (size < 0 && ((err == SSL_ERROR_WANT_READ) || \
|
|
(err == SSL_ERROR_WANT_WRITE))) {
|
|
|
|
sockfd = wolfSSL_get_fd(ssl);
|
|
if (sockfd == -1) {
|
|
/* For I/O that does not use sockets, sockfd may be -1,
|
|
* skip try to call select() */
|
|
break;
|
|
}
|
|
|
|
ret = socketSelect(sockfd, timeout, 1);
|
|
if (ret == WOLFJNI_RECV_READY || ret == WOLFJNI_SEND_READY) {
|
|
/* loop around and try wolfSSL_read() again */
|
|
continue;
|
|
} else {
|
|
/* error or timeout occurred during select */
|
|
size = ret;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ);
|
|
|
|
/* JNI_COMMIT commits the data but does not free the local array
|
|
* 0 is used here to both commit and free */
|
|
(*jenv)->ReleaseByteArrayElements(jenv, raw, (jbyte*)data, 0);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_accept
|
|
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
|
|
{
|
|
int ret = 0, err, sockfd;
|
|
WOLFSSL* ssl = NULL;
|
|
wolfSSL_Mutex* jniSessLock = NULL;
|
|
SSLAppData* appData = NULL;
|
|
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL || sslPtr <= 0) {
|
|
return SSL_FATAL_ERROR;
|
|
}
|
|
ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
|
|
|
/* make sure we don't have any outstanding exceptions pending */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* get session mutex from SSL app data */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
|
|
if (appData == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
jniSessLock = appData->jniSessLock;
|
|
if (jniSessLock == NULL) {
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
do {
|
|
/* get I/O lock */
|
|
if (wc_LockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
ret = wolfSSL_accept(ssl);
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
|
|
/* release I/O lock */
|
|
if (wc_UnLockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (ret < 0 && ((err == SSL_ERROR_WANT_READ) ||
|
|
(err == SSL_ERROR_WANT_WRITE))) {
|
|
|
|
sockfd = wolfSSL_get_fd(ssl);
|
|
if (sockfd == -1) {
|
|
/* For I/O that does not use sockets, sockfd may be -1,
|
|
* skip try to call select() */
|
|
break;
|
|
}
|
|
|
|
ret = socketSelect(sockfd, 0, 1);
|
|
if (ret == WOLFJNI_RECV_READY || ret == WOLFJNI_SEND_READY) {
|
|
/* I/O ready, continue handshake and try again */
|
|
continue;
|
|
} else {
|
|
/* error or timeout */
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ);
|
|
|
|
/* check for Java exceptions beofre returning */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jobject* g_cachedSSLObj;
|
|
jobject* g_cachedVerifyCb;
|
|
jclass excClass;
|
|
SSLAppData* appData;
|
|
(void)jcl;
|
|
#if defined(HAVE_PK_CALLBACKS) && (defined(HAVE_ECC) || !defined(NO_RSA))
|
|
internCtx* pkCtx = NULL;
|
|
#endif
|
|
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException");
|
|
|
|
if (!ssl) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in freeSSL");
|
|
return;
|
|
}
|
|
|
|
/* free session mutex lock */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data((WOLFSSL*)(uintptr_t)ssl);
|
|
if (appData != NULL) {
|
|
if (appData->jniSessLock != NULL) {
|
|
wc_FreeMutex(appData->jniSessLock);
|
|
XFREE(appData->jniSessLock, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
appData->jniSessLock = NULL;
|
|
}
|
|
g_cachedVerifyCb = appData->g_verifySSLCbIfaceObj;
|
|
if (g_cachedVerifyCb != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, (jobject)(*g_cachedVerifyCb));
|
|
XFREE(g_cachedVerifyCb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
g_cachedVerifyCb = NULL;
|
|
}
|
|
/* free appData */
|
|
XFREE(appData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
appData = NULL;
|
|
}
|
|
|
|
/* delete global WolfSSLSession object reference */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)(uintptr_t)ssl);
|
|
if (g_cachedSSLObj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, (jobject)(*g_cachedSSLObj));
|
|
XFREE(g_cachedSSLObj, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
g_cachedSSLObj = NULL;
|
|
}
|
|
|
|
/* reset internal pointer to NULL to prevent accidental usage */
|
|
if (wolfSSL_set_jobject((WOLFSSL*)(uintptr_t)ssl, NULL) != SSL_SUCCESS) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error reseting internal wolfSSL JNI pointer to NULL, freeSSL");
|
|
return;
|
|
}
|
|
|
|
#ifdef HAVE_CRL
|
|
/* release global CRL callback ref if registered */
|
|
if (g_crlCbIfaceObj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, g_crlCbIfaceObj);
|
|
g_crlCbIfaceObj = NULL;
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAVE_PK_CALLBACKS)
|
|
#ifdef HAVE_ECC
|
|
/* free ECC sign callback CTX global reference if set */
|
|
pkCtx = (internCtx*) wolfSSL_GetEccSignCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
/* free ECC verify callback CTX global reference if set */
|
|
pkCtx = (internCtx*)wolfSSL_GetEccVerifyCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
/* free ECC shared secret callback CTX global reference if set */
|
|
pkCtx = (internCtx*)wolfSSL_GetEccSharedSecretCtx(
|
|
(WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif /* HAVE_ECC */
|
|
|
|
#ifndef NO_RSA
|
|
/* free RSA sign callback CTX global reference if set */
|
|
pkCtx = (internCtx*) wolfSSL_GetRsaSignCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
/* free RSA verify callback CTX global reference if set */
|
|
pkCtx = (internCtx*)wolfSSL_GetRsaVerifyCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
/* free RSA encrypt callback CTX global reference if set */
|
|
pkCtx = (internCtx*) wolfSSL_GetRsaEncCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
|
|
/* free RSA decrypt callback CTX global reference if set */
|
|
pkCtx = (internCtx*) wolfSSL_GetRsaDecCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
if (pkCtx != NULL) {
|
|
if (pkCtx->obj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, pkCtx->obj);
|
|
}
|
|
XFREE(pkCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif /* !NO_RSA */
|
|
#endif /* HAVE_PK_CALLBACKS */
|
|
|
|
/* native cleanup */
|
|
wolfSSL_free((WOLFSSL*)(uintptr_t)ssl);
|
|
ssl = 0;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_shutdownSSL
|
|
(JNIEnv* jenv, jobject jcl, jlong sslPtr, jint timeout)
|
|
{
|
|
int ret = 0, err, sockfd;
|
|
WOLFSSL* ssl = NULL;
|
|
wolfSSL_Mutex* jniSessLock;
|
|
SSLAppData* appData = NULL;
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL) {
|
|
return SSL_FAILURE;
|
|
}
|
|
ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
|
|
|
/* make sure we don't have any outstanding exceptions pending */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* get session mutex from SSL app data */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
|
|
if (appData == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
jniSessLock = appData->jniSessLock;
|
|
if (jniSessLock == NULL) {
|
|
return WOLFSSL_FAILURE;
|
|
}
|
|
|
|
do {
|
|
/* get I/O lock */
|
|
if (wc_LockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
ret = wolfSSL_shutdown(ssl);
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
|
|
/* release I/O lock */
|
|
if (wc_UnLockMutex(jniSessLock) != 0) {
|
|
ret = WOLFSSL_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (ret < 0 && ((err == SSL_ERROR_WANT_READ) ||
|
|
(err == SSL_ERROR_WANT_WRITE))) {
|
|
|
|
sockfd = wolfSSL_get_fd(ssl);
|
|
if (sockfd == -1) {
|
|
/* For I/O that does not use sockets, sockfd may be -1,
|
|
* skip try to call select() */
|
|
break;
|
|
}
|
|
|
|
ret = socketSelect(sockfd, timeout, 1);
|
|
if (ret == WOLFJNI_RECV_READY || ret == WOLFJNI_SEND_READY) {
|
|
/* I/O ready, continue handshake and try again */
|
|
continue;
|
|
} else {
|
|
/* error or timeout */
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ);
|
|
|
|
/* check for Java exceptions beofre returning */
|
|
if ((*jenv)->ExceptionCheck(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getError
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jint ret)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_get_error((WOLFSSL*)(uintptr_t)ssl, ret);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setSession
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong session)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return SSL_FAILURE;
|
|
|
|
/* wolfSSL checks session for NULL, but not ssl */
|
|
return wolfSSL_set_session((WOLFSSL*)(uintptr_t)ssl,
|
|
(WOLFSSL_SESSION*)(uintptr_t)session);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getSession
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
/* wolfSSL checks ssl for NULL */
|
|
return (jlong)(uintptr_t)wolfSSL_get_session((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getSessionID
|
|
(JNIEnv* jenv, jobject jcl, jlong session)
|
|
{
|
|
unsigned int sz;
|
|
const unsigned char* id;
|
|
jbyteArray ret;
|
|
|
|
id = wolfSSL_SESSION_get_id((WOLFSSL_SESSION*)(uintptr_t)session, &sz);
|
|
if (id == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
ret = (*jenv)->NewByteArray(jenv, sz);
|
|
if (!ret) {
|
|
(*jenv)->ThrowNew(jenv, jcl,
|
|
"Failed to create byte array in native getSessionID");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, ret, 0, sz, (jbyte*)id);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong t)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
return wolfSSL_set_timeout((WOLFSSL*)(uintptr_t)ssl, (unsigned int)t);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
return wolfSSL_get_timeout((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setSessTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong session, jlong sz)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
return wolfSSL_SSL_SESSION_set_timeout((WOLFSSL_SESSION*)(uintptr_t)session,
|
|
sz);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getSessTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong session)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
return wolfSSL_SESSION_get_timeout((WOLFSSL_SESSION*)(uintptr_t)session);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCipherList
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring list)
|
|
{
|
|
|
|
jint ret = 0;
|
|
const char* cipherList;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl || !list)
|
|
return SSL_FAILURE;
|
|
|
|
cipherList= (*jenv)->GetStringUTFChars(jenv, list, 0);
|
|
|
|
ret = (jint) wolfSSL_set_cipher_list((WOLFSSL*)(uintptr_t)ssl, cipherList);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, list, cipherList);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetCurrentTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
#if !defined(WOLFSSL_LEANPSK) && defined(WOLFSSL_DTLS)
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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()");
|
|
return 0;
|
|
}
|
|
|
|
return wolfSSL_dtls_get_current_timeout((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGotTimeout
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
#if !defined(WOLFSSL_LEANPSK) && defined(WOLFSSL_DTLS)
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FATAL_ERROR;
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"dtlsGotTimeout()");
|
|
return SSL_FATAL_ERROR;
|
|
}
|
|
|
|
return wolfSSL_dtls_got_timeout((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtls
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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 dtls()");
|
|
return 0;
|
|
}
|
|
|
|
return wolfSSL_dtls((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_dtlsSetPeer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jobject peer)
|
|
{
|
|
int ret;
|
|
jstring ipAddr = NULL;
|
|
struct sockaddr_in sa;
|
|
const char* ipAddress = NULL;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl || !peer)
|
|
return SSL_FAILURE;
|
|
|
|
/* get class references */
|
|
jclass excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException");
|
|
jclass inetsockaddr = (*jenv)->FindClass(jenv,
|
|
"java/net/InetSocketAddress");
|
|
jclass inetaddr = (*jenv)->FindClass(jenv, "java/net/InetAddress");
|
|
|
|
/* get port */
|
|
jmethodID portID = (*jenv)->GetMethodID(jenv, inetsockaddr,
|
|
"getPort", "()I");
|
|
if (!portID) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass, "Can't get getPort() method ID");
|
|
return SSL_FAILURE;
|
|
}
|
|
(*jenv)->ExceptionClear(jenv);
|
|
jint port = (*jenv)->CallIntMethod(jenv, peer, portID);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* an exception occurred on the Java side, how to handle it? */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* get InetAddress object */
|
|
jmethodID addrID = (*jenv)->GetMethodID(jenv, inetsockaddr, "getAddress",
|
|
"()Ljava/net/InetAddress;");
|
|
if (!addrID) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass, "Can't get getAddress() method ID");
|
|
return SSL_FAILURE;
|
|
}
|
|
(*jenv)->ExceptionClear(jenv);
|
|
jobject addrObj = (*jenv)->CallObjectMethod(jenv, peer, addrID);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* an exception occurred on the Java side, how to handle it? */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* is this a wildcard address, ie: INADDR_ANY? */
|
|
jmethodID isAnyID = (*jenv)->GetMethodID(jenv, inetaddr,
|
|
"isAnyLocalAddress", "()Z");
|
|
if (!isAnyID) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get isAnyLocalAddress() method ID");
|
|
return SSL_FAILURE;
|
|
}
|
|
(*jenv)->ExceptionClear(jenv);
|
|
jboolean isAny = (*jenv)->CallBooleanMethod(jenv, addrObj, isAnyID);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* an exception occurred on the Java side, how to handle it? */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* get IP address as a String */
|
|
if (!isAny) {
|
|
jmethodID ipAddrID = (*jenv)->GetMethodID(jenv, inetaddr,
|
|
"getHostAddress", "()Ljava/lang/String;");
|
|
if (!ipAddrID) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getHostAddress() method ID");
|
|
return SSL_FAILURE;
|
|
}
|
|
ipAddr = (*jenv)->CallObjectMethod(jenv, addrObj, ipAddrID);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* an exception occurred on the Java side, how to handle it? */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* convert IP string to char* */
|
|
ipAddress = (*jenv)->GetStringUTFChars(jenv, ipAddr, 0);
|
|
}
|
|
|
|
/* build sockaddr_in */
|
|
memset(&sa, 0, sizeof(struct sockaddr_in));
|
|
sa.sin_family = AF_INET;
|
|
sa.sin_port = htons(port);
|
|
if (isAny) {
|
|
//sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
sa.sin_addr.s_addr = INADDR_ANY;
|
|
} else {
|
|
sa.sin_addr.s_addr = inet_addr(ipAddress);
|
|
}
|
|
|
|
/* call native wolfSSL function */
|
|
ret = wolfSSL_dtls_set_peer((WOLFSSL*)(uintptr_t)ssl, &sa, sizeof(sa));
|
|
|
|
if (!isAny) {
|
|
(*jenv)->ReleaseStringUTFChars(jenv, ipAddr, ipAddress);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL Java_com_wolfssl_WolfSSLSession_dtlsGetPeer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
int ret, port;
|
|
unsigned int peerSz;
|
|
struct sockaddr_in peer;
|
|
char* ipAddrString;
|
|
|
|
jmethodID constr;
|
|
jstring ipAddr;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return NULL;
|
|
|
|
/* get native sockaddr_in peer */
|
|
memset(&peer, 0, sizeof(peer));
|
|
peerSz = sizeof(peer);
|
|
ret = wolfSSL_dtls_get_peer((WOLFSSL*)(uintptr_t)ssl, &peer, &peerSz);
|
|
if (ret != SSL_SUCCESS) {
|
|
return NULL;
|
|
}
|
|
ipAddrString = inet_ntoa(peer.sin_addr);
|
|
port = ntohs(peer.sin_port);
|
|
|
|
/* create new InetSocketAddress with this IP/port info */
|
|
jclass excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLException");
|
|
jclass 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");
|
|
return NULL;
|
|
}
|
|
|
|
/* create jstring from char* */
|
|
ipAddr = (*jenv)->NewStringUTF(jenv, ipAddrString);
|
|
|
|
/* find correct InetSocketAddress constructor */
|
|
if (peer.sin_addr.s_addr != INADDR_ANY) {
|
|
|
|
constr = (*jenv)->GetMethodID(jenv, isa, "<init>",
|
|
"(Ljava/lang/String;I)V");
|
|
if (!constr) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't find InetSocketAddress(String,port)");
|
|
return NULL;
|
|
}
|
|
|
|
return (*jenv)->NewObject(jenv, isa, constr, ipAddr, port);
|
|
|
|
} else { /* sockaddr_in was created with INADDR_ANY, use wildcard IP */
|
|
|
|
constr = (*jenv)->GetMethodID(jenv, isa, "<init>",
|
|
"(I)V");
|
|
if (!constr) {
|
|
if ((*jenv)->ExceptionOccurred(jenv))
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't find InetSocketAddress(port)");
|
|
return NULL;
|
|
}
|
|
|
|
return (*jenv)->NewObject(jenv, isa, constr, port);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sessionReused
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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 sessionReused()");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_session_reused((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getPeerCertificate
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
#ifdef KEEP_PEER_CERT
|
|
WOLFSSL_X509* x509 = NULL;
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
if (ssl == 0) {
|
|
return (jlong)0;
|
|
}
|
|
|
|
x509 = wolfSSL_get_peer_certificate((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
return (jlong)(uintptr_t)x509;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
return (jlong)0;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPeerX509Issuer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong x509)
|
|
{
|
|
|
|
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
|
|
jclass excClass;
|
|
char* issuer;
|
|
jstring retString;
|
|
|
|
(void)jcl;
|
|
|
|
if (!x509)
|
|
return NULL;
|
|
|
|
if (!ssl) {
|
|
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 "
|
|
"getPeerX509Issuer");
|
|
return NULL;
|
|
}
|
|
|
|
issuer = wolfSSL_X509_NAME_oneline(
|
|
wolfSSL_X509_get_issuer_name((WOLFSSL_X509*)(uintptr_t)x509), 0, 0);
|
|
|
|
retString = (*jenv)->NewStringUTF(jenv, issuer);
|
|
XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL);
|
|
|
|
return retString;
|
|
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)x509;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPeerX509Subject
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong x509)
|
|
{
|
|
|
|
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
|
|
jclass excClass;
|
|
char* subject;
|
|
jstring retString;
|
|
|
|
(void)jcl;
|
|
|
|
if (!x509)
|
|
return NULL;
|
|
|
|
if (!ssl) {
|
|
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 "
|
|
"getPeerX509Subject");
|
|
return NULL;
|
|
}
|
|
|
|
subject = wolfSSL_X509_NAME_oneline(
|
|
wolfSSL_X509_get_subject_name(
|
|
(WOLFSSL_X509*)(uintptr_t)x509), 0, 0);
|
|
|
|
retString = (*jenv)->NewStringUTF(jenv, subject);
|
|
XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
|
|
|
|
return retString;
|
|
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)x509;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPeerX509AltName
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong x509)
|
|
{
|
|
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
|
|
jclass excClass;
|
|
char* altname;
|
|
jstring retString;
|
|
|
|
(void)jcl;
|
|
|
|
if (!x509)
|
|
return NULL;
|
|
|
|
if (!ssl) {
|
|
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 "
|
|
"getPeerX509AltName");
|
|
return NULL;
|
|
}
|
|
|
|
altname = wolfSSL_X509_get_next_altname((WOLFSSL_X509*)(uintptr_t)x509);
|
|
|
|
retString = (*jenv)->NewStringUTF(jenv, altname);
|
|
return retString;
|
|
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)x509;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getVersion
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return NULL;
|
|
}
|
|
|
|
return (*jenv)->NewStringUTF(jenv,
|
|
wolfSSL_get_version((WOLFSSL*)(uintptr_t)ssl));
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getCurrentCipher
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return (jlong)(uintptr_t)wolfSSL_get_current_cipher(
|
|
(WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_checkDomainName
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring dn)
|
|
{
|
|
int ret;
|
|
const char* dname;
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if(!dn)
|
|
return SSL_FAILURE;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
dname = (*jenv)->GetStringUTFChars(jenv, dn, 0);
|
|
|
|
ret = wolfSSL_check_domain_name((WOLFSSL*)(uintptr_t)ssl, dname);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, dn, dname);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDH
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray p, jint pSz, jbyteArray g,
|
|
jint gSz)
|
|
{
|
|
#ifndef NO_DH
|
|
unsigned char pBuf[pSz];
|
|
unsigned char gBuf[gSz];
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !p || !g) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, p, 0, pSz, (jbyte*)pBuf);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, g, 0, gSz, (jbyte*)gBuf);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_SetTmpDH((WOLFSSL*)(uintptr_t)ssl, pBuf, pSz, gBuf, gSz);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)p;
|
|
(void)pSz;
|
|
(void)g;
|
|
(void)gSz;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTmpDHFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring file, jint format)
|
|
{
|
|
#ifndef NO_DH
|
|
int ret;
|
|
const char* fname;
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!file)
|
|
return SSL_BAD_FILE;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
fname = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = wolfSSL_SetTmpDH_file((WOLFSSL*)(uintptr_t)ssl, fname, format);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, fname);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)file;
|
|
(void)format;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray in, jlong sz, jint format)
|
|
{
|
|
unsigned char buff[sz];
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !in)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_use_certificate_buffer((WOLFSSL*)(uintptr_t)ssl, buff, sz,
|
|
format);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_usePrivateKeyBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray in, jlong sz, jint format)
|
|
{
|
|
unsigned char buff[sz];
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !in)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_use_PrivateKey_buffer((WOLFSSL*)(uintptr_t)ssl, buff, sz,
|
|
format);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useCertificateChainBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray in, jlong sz)
|
|
{
|
|
unsigned char buff[sz];
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !in)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_use_certificate_chain_buffer((WOLFSSL*)(uintptr_t)ssl, buff,
|
|
sz);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setGroupMessages
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
return wolfSSL_set_group_messages((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_enableCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jint options)
|
|
{
|
|
#ifdef HAVE_CRL
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_EnableCRL((WOLFSSL*)(uintptr_t)ssl, options);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)options;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_disableCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
#ifdef HAVE_CRL
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_DisableCRL((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_loadCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jstring path, jint type, jint monitor)
|
|
{
|
|
#ifdef HAVE_CRL
|
|
int ret;
|
|
const char* crlPath;
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || !path)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (!ssl) {
|
|
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");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
crlPath = (*jenv)->GetStringUTFChars(jenv, path, 0);
|
|
|
|
ret = wolfSSL_LoadCRL((WOLFSSL*)(uintptr_t)ssl, crlPath, type, monitor);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, path, crlPath);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)path;
|
|
(void)type;
|
|
(void)monitor;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setCRLCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jobject cb)
|
|
{
|
|
#ifdef HAVE_CRL
|
|
int ret = 0;
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL) {
|
|
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 == 0) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setCRLCb");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* release global CRL callback ref if already registered */
|
|
if (g_crlCbIfaceObj != NULL) {
|
|
(*jenv)->DeleteGlobalRef(jenv, g_crlCbIfaceObj);
|
|
g_crlCbIfaceObj = NULL;
|
|
}
|
|
|
|
if (cb != NULL) {
|
|
/* 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");
|
|
}
|
|
|
|
ret = wolfSSL_SetCRL_Cb((WOLFSSL*)(uintptr_t)ssl,
|
|
NativeMissingCRLCallback);
|
|
}
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)jcl;
|
|
(void)ssl;
|
|
(void)cb;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_CRL
|
|
|
|
void NativeMissingCRLCallback(const char* url)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint vmret = 0;
|
|
jclass excClass;
|
|
jmethodID crlMethod;
|
|
jobjectRefType refcheck;
|
|
|
|
/* get JNIEnv from JavaVM */
|
|
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
|
|
if (vmret == JNI_EDETACHED) {
|
|
#ifdef __ANDROID__
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
|
|
#else
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
|
|
#endif
|
|
if (vmret) {
|
|
printf("Failed to attach JNIEnv to thread\n");
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
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) {
|
|
|
|
/* lookup WolfSSLMissingCRLCallback class from global object ref */
|
|
jclass crlClass = (*jenv)->GetObjectClass(jenv, g_crlCbIfaceObj);
|
|
if (!crlClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLMissingCRLCallback class reference");
|
|
return;
|
|
}
|
|
|
|
crlMethod = (*jenv)->GetMethodID(jenv, crlClass,
|
|
"missingCRLCallback",
|
|
"(Ljava/lang/String;)V");
|
|
if (crlMethod == 0) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting missingCRLCallback method from JNI");
|
|
return;
|
|
}
|
|
|
|
/* create jstring from char* */
|
|
jstring missingUrl = (*jenv)->NewStringUTF(jenv, url);
|
|
|
|
(*jenv)->CallVoidMethod(jenv, g_crlCbIfaceObj, crlMethod, missingUrl);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeMissingCRLCallback");
|
|
}
|
|
}
|
|
|
|
#endif /* HAVE_CRL */
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_cipherGetName
|
|
(JNIEnv* jenv, jclass jcl, jlong ssl)
|
|
{
|
|
const char* cipherName;
|
|
WOLFSSL_CIPHER* cipher;
|
|
jclass excClass;
|
|
|
|
(void)jcl;
|
|
|
|
if (!ssl) {
|
|
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 "
|
|
"cipherGetName");
|
|
return NULL;
|
|
}
|
|
|
|
cipher = wolfSSL_get_current_cipher((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
if (cipher != NULL) {
|
|
cipherName = wolfSSL_CIPHER_get_name(cipher);
|
|
return (*jenv)->NewStringUTF(jenv, cipherName);
|
|
} else {
|
|
return (*jenv)->NewStringUTF(jenv, "NONE");
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getMacSecret
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jint verify)
|
|
{
|
|
jclass excClass;
|
|
#ifdef ATOMIC_USER
|
|
int macLength;
|
|
jbyteArray retSecret;
|
|
const unsigned char* secret;
|
|
#endif
|
|
|
|
(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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"getMacSecret");
|
|
return NULL;
|
|
}
|
|
|
|
secret = wolfSSL_GetMacSecret((WOLFSSL*)(uintptr_t)ssl, (int)verify);
|
|
|
|
if (secret != NULL) {
|
|
|
|
/* get mac size */
|
|
macLength = wolfSSL_GetHmacSize((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* create byte array to return */
|
|
retSecret = (*jenv)->NewByteArray(jenv, macLength);
|
|
if (!retSecret) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create byte array in native getMacSecret");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, retSecret, 0, macLength,
|
|
(jbyte*)secret);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return retSecret;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with ATOMIC_USER");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteKey
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#ifdef ATOMIC_USER
|
|
int keyLength;
|
|
jbyteArray retKey;
|
|
const unsigned char* key;
|
|
#endif
|
|
|
|
(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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"getClientWriteKey");
|
|
return NULL;
|
|
}
|
|
|
|
key = wolfSSL_GetClientWriteKey((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
if (key != NULL) {
|
|
|
|
/* get key size */
|
|
keyLength = wolfSSL_GetKeySize((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* create byte array to return */
|
|
retKey = (*jenv)->NewByteArray(jenv, keyLength);
|
|
if (!retKey) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create byte array in native getClientWriteKey");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, retKey, 0, keyLength,
|
|
(jbyte*)key);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return retKey;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with ATOMIC_USER");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientWriteIV
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#ifdef ATOMIC_USER
|
|
jbyteArray retIV;
|
|
const unsigned char* iv;
|
|
int ivLength;
|
|
#endif
|
|
|
|
(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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"getClientWriteIV");
|
|
return NULL;
|
|
}
|
|
|
|
iv = wolfSSL_GetClientWriteIV((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
if (iv != NULL) {
|
|
|
|
/* get iv size, is block size for what wolfSSL supports */
|
|
ivLength = wolfSSL_GetCipherBlockSize((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* create byte array to return */
|
|
retIV = (*jenv)->NewByteArray(jenv, ivLength);
|
|
if (!retIV) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create byte array in native getClientWriteIV");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, retIV, 0, ivLength,
|
|
(jbyte*)iv);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return retIV;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with ATOMIC_USER");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteKey
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#ifdef ATOMIC_USER
|
|
jbyteArray retKey;
|
|
const unsigned char* key;
|
|
int keyLength;
|
|
#endif
|
|
|
|
(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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"getServerWriteKey");
|
|
return NULL;
|
|
}
|
|
|
|
key = wolfSSL_GetServerWriteKey((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
if (key != NULL) {
|
|
|
|
/* get key size */
|
|
keyLength = wolfSSL_GetKeySize((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* create byte array to return */
|
|
retKey = (*jenv)->NewByteArray(jenv, keyLength);
|
|
if (!retKey) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create byte array in native getServerWriteKey");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, retKey, 0, keyLength,
|
|
(jbyte*)key);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return retKey;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with ATOMIC_USER");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getServerWriteIV
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#ifdef ATOMIC_USER
|
|
jbyteArray retIV;
|
|
const unsigned char* iv;
|
|
int ivLength;
|
|
#endif
|
|
|
|
(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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"getServerWriteIV");
|
|
return NULL;
|
|
}
|
|
|
|
iv = wolfSSL_GetServerWriteIV((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
if (iv != NULL) {
|
|
|
|
/* get iv size, is block size for what wolfSSL supports */
|
|
ivLength = wolfSSL_GetCipherBlockSize((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* create byte array to return */
|
|
retIV = (*jenv)->NewByteArray(jenv, ivLength);
|
|
if (!retIV) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create byte array in native getServerWriteIV");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, retIV, 0, ivLength,
|
|
(jbyte*)iv);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return retIV;
|
|
|
|
} else {
|
|
return NULL;
|
|
}
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with ATOMIC_USER");
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getKeySize
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetKeySize((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getSide
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetSide((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_isTLSv1_11
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_IsTLSv1_1((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getBulkCipher
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetBulkCipher((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getCipherBlockSize
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetCipherBlockSize((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getAeadMacSize
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetAeadMacSize((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getHmacSize
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetHmacSize((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getHmacType
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetHmacType((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getCipherType
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
#ifdef ATOMIC_USER
|
|
/* wolfSSL checks ssl for NULL */
|
|
return wolfSSL_GetCipherType((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTlsHmacInner
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray inner, jlong sz,
|
|
jint content, jint verify)
|
|
{
|
|
int ret = 0;
|
|
unsigned char hmacInner[WOLFSSL_TLS_HMAC_INNER_SZ];
|
|
|
|
(void)jcl;
|
|
|
|
if (!jenv || inner == NULL || !ssl) {
|
|
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((WOLFSSL*)(uintptr_t)ssl, hmacInner, sz,
|
|
content, verify);
|
|
|
|
/* copy hmacInner back into inner jbyteArray */
|
|
(*jenv)->SetByteArrayRegion(jenv, inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ,
|
|
(jbyte*)hmacInner);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to set byte region in native setTlsHmacInner");
|
|
return -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSignCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
|
|
jclass sslClass;
|
|
|
|
void* eccSignCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setEccSignCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
eccSignCtx = (internCtx*) wolfSSL_GetEccSignCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (eccSignCtx != NULL) {
|
|
myCtx = (internCtx*)eccSignCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (!myCtx) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for ECC sign context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (!myCtx->obj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetEccSignCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or ECC");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccVerifyCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
|
|
jclass sslClass;
|
|
|
|
void* eccVerifyCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setEccVerifyCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
eccVerifyCtx = (internCtx*)wolfSSL_GetEccVerifyCtx(
|
|
(WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (eccVerifyCtx != NULL) {
|
|
myCtx = (internCtx*)eccVerifyCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (!myCtx) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for ECC verify context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetEccVerifyCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or ECC");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setEccSharedSecretCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_ECC)
|
|
jclass sslClass;
|
|
|
|
void* eccSharedSecretCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setEccSharedSecretCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
eccSharedSecretCtx =
|
|
(internCtx*) wolfSSL_GetEccSharedSecretCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (eccSharedSecretCtx != NULL) {
|
|
myCtx = (internCtx*)eccSharedSecretCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (myCtx == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for ECC shared secret context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetEccSharedSecretCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or ECC");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaSignCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
|
|
jclass sslClass;
|
|
|
|
void* rsaSignCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setRsaSignCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
rsaSignCtx = (internCtx*) wolfSSL_GetRsaSignCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (rsaSignCtx != NULL) {
|
|
myCtx = (internCtx*)rsaSignCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (myCtx == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for RSA sign context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetRsaSignCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or RSA support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaVerifyCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
|
|
jclass sslClass;
|
|
|
|
void* rsaVerifyCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setRsaVerifyCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
rsaVerifyCtx = (internCtx*)wolfSSL_GetRsaVerifyCtx(
|
|
(WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (rsaVerifyCtx != NULL) {
|
|
myCtx = (internCtx*)rsaVerifyCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (myCtx == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for RSA verify context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetRsaVerifyCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or RSA support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaEncCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
|
|
jclass sslClass;
|
|
|
|
void* rsaEncCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setRsaEncCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
rsaEncCtx = (internCtx*) wolfSSL_GetRsaEncCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (rsaEncCtx != NULL) {
|
|
myCtx = (internCtx*)rsaEncCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (myCtx == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for RSA encrypt context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetRsaEncCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or RSA support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setRsaDecCtx
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
jclass excClass;
|
|
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
|
|
jclass sslClass;
|
|
|
|
void* rsaDecCtx;
|
|
internCtx* myCtx;
|
|
#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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null in "
|
|
"setRsaDecCtx");
|
|
return;
|
|
}
|
|
|
|
/* get WolfSSLSession class from object ref */
|
|
sslClass = (*jenv)->GetObjectClass(jenv, jcl);
|
|
if (!sslClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLSession object class");
|
|
return;
|
|
}
|
|
|
|
/* free existing memory if it already exists, before we malloc again */
|
|
rsaDecCtx = (internCtx*) wolfSSL_GetRsaDecCtx((WOLFSSL*)(uintptr_t)ssl);
|
|
|
|
/* note: if CTX has not been set up yet, wolfSSL defaults to NULL */
|
|
if (rsaDecCtx != NULL) {
|
|
myCtx = (internCtx*)rsaDecCtx;
|
|
if (myCtx != NULL) {
|
|
if (myCtx->active == 1) {
|
|
(*jenv)->DeleteGlobalRef(jenv, myCtx->obj);
|
|
}
|
|
XFREE(myCtx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
}
|
|
|
|
/* allocate memory for internal JNI object reference */
|
|
myCtx = XMALLOC(sizeof(internCtx), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (myCtx == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to allocate memory for RSA decrypt context\n");
|
|
return;
|
|
}
|
|
|
|
/* set CTX as active */
|
|
myCtx->active = 1;
|
|
|
|
/* store global ref to WolfSSLSession object */
|
|
myCtx->obj = (*jenv)->NewGlobalRef(jenv, jcl);
|
|
if (myCtx->obj == NULL) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Unable to store WolfSSLSession object as global reference");
|
|
return;
|
|
}
|
|
|
|
wolfSSL_SetRsaDecCtx((WOLFSSL*)(uintptr_t)ssl, myCtx);
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PK Callbacks and/or RSA support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setPskClientCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(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) {
|
|
/* set PSK client callback */
|
|
wolfSSL_set_psk_client_callback((WOLFSSL*)(uintptr_t)ssl,
|
|
NativePskClientCb);
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null when setting "
|
|
"NativePskClientCb");
|
|
return;
|
|
}
|
|
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PSK support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setPskServerCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(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) {
|
|
/* set PSK server callback */
|
|
wolfSSL_set_psk_server_callback((WOLFSSL*)(uintptr_t)ssl,
|
|
NativePskServerCb);
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLSession object was null when setting "
|
|
"NativePskServerCb");
|
|
return;
|
|
}
|
|
|
|
#else
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"wolfSSL not compiled with PSK support");
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPskIdentityHint
|
|
(JNIEnv* jenv, jobject obj, jlong ssl)
|
|
{
|
|
(void)obj;
|
|
#ifndef NO_PSK
|
|
if (!jenv || !ssl)
|
|
return NULL;
|
|
|
|
return (*jenv)->NewStringUTF(jenv,
|
|
wolfSSL_get_psk_identity_hint((WOLFSSL*)(uintptr_t)ssl));
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLSession_getPskIdentity
|
|
(JNIEnv* jenv, jobject obj, jlong ssl)
|
|
{
|
|
(void)obj;
|
|
#ifndef NO_PSK
|
|
if (!jenv || !ssl)
|
|
return NULL;
|
|
|
|
return (*jenv)->NewStringUTF(jenv,
|
|
wolfSSL_get_psk_identity((WOLFSSL*)(uintptr_t)ssl));
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_usePskIdentityHint
|
|
(JNIEnv* jenv, jobject obj, jlong ssl, jstring hint)
|
|
{
|
|
#ifndef NO_PSK
|
|
jint ret;
|
|
const char* nativeHint;
|
|
|
|
(void)obj;
|
|
|
|
if (!jenv || !ssl || !hint)
|
|
return SSL_FAILURE;
|
|
|
|
nativeHint = (*jenv)->GetStringUTFChars(jenv, hint, 0);
|
|
|
|
ret = (jint)wolfSSL_use_psk_identity_hint((WOLFSSL*)(uintptr_t)ssl,
|
|
nativeHint);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, hint, nativeHint);
|
|
|
|
return ret;
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
(void)hint;
|
|
return NOT_COMPILED_IN;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSLSession_handshakeDone
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return JNI_FALSE;
|
|
|
|
if (wolfSSL_is_init_finished((WOLFSSL*)(uintptr_t)ssl)) {
|
|
return JNI_TRUE;
|
|
}
|
|
else {
|
|
return JNI_FALSE;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setConnectState
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return;
|
|
|
|
wolfSSL_set_connect_state((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setAcceptState
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return;
|
|
|
|
wolfSSL_set_accept_state((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setVerify
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jint mode, jobject callbackIface)
|
|
{
|
|
(void)jcl;
|
|
jobject* verifyCb;
|
|
SSLAppData* appData;
|
|
|
|
if (!jenv || !ssl)
|
|
return;
|
|
|
|
if (!callbackIface) {
|
|
wolfSSL_set_verify((WOLFSSL*)(uintptr_t)ssl, mode, NULL);
|
|
}
|
|
else {
|
|
/* get app data to store verify callback jobject */
|
|
appData = (SSLAppData*)wolfSSL_get_app_data((WOLFSSL*)(uintptr_t)ssl);
|
|
if (appData == NULL) {
|
|
printf("Error getting app data from WOLFSSL\n");
|
|
}
|
|
|
|
if (appData) {
|
|
verifyCb = (jobject*)XMALLOC(sizeof(jobject), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (verifyCb == NULL) {
|
|
printf("Error allocating memory for verifyCb\n");
|
|
}
|
|
}
|
|
|
|
if (appData && verifyCb) {
|
|
/* store Java verify Interface object */
|
|
*verifyCb = (*jenv)->NewGlobalRef(jenv, callbackIface);
|
|
if (*verifyCb == NULL) {
|
|
printf("error storing global callback interface\n");
|
|
}
|
|
else {
|
|
appData->g_verifySSLCbIfaceObj = verifyCb;
|
|
|
|
/* set verify mode, register Java callback with wolfSSL */
|
|
wolfSSL_set_verify((WOLFSSL*)(uintptr_t)ssl, mode,
|
|
NativeSSLVerifyCallback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_setOptions
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jlong op)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return 0;
|
|
|
|
return wolfSSL_set_options((WOLFSSL*)(uintptr_t)ssl, op);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_getOptions
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
if (!jenv || !ssl)
|
|
return 0;
|
|
|
|
return wolfSSL_get_options((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_getShutdown
|
|
(JNIEnv *jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jenv;
|
|
(void)jcl;
|
|
|
|
return (jint)wolfSSL_get_shutdown((WOLFSSL*)(uintptr_t)ssl);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSNI
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyte type, jbyteArray data)
|
|
{
|
|
int ret = SSL_FAILURE;
|
|
(void)jcl;
|
|
#ifdef HAVE_SNI
|
|
byte* dataBuf = NULL;
|
|
word32 dataSz = 0;
|
|
|
|
if (jenv == NULL || ssl <= 0) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
dataBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, data, NULL);
|
|
dataSz = (*jenv)->GetArrayLength(jenv, data);
|
|
|
|
if (dataBuf != NULL && dataSz > 0) {
|
|
ret = wolfSSL_UseSNI((WOLFSSL*)(uintptr_t)ssl, (byte)type,
|
|
dataBuf, (word16)dataSz);
|
|
}
|
|
|
|
(*jenv)->ReleaseByteArrayElements(jenv, data, (jbyte*)dataBuf, JNI_ABORT);
|
|
|
|
#else
|
|
ret = NOT_COMPILED_IN;
|
|
(void)jenv;
|
|
(void)ssl;
|
|
(void)type;
|
|
(void)data;
|
|
#endif /* HAVE_SNI */
|
|
|
|
return (jint)ret;
|
|
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSessionTicket
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
int ret = SSL_FAILURE;
|
|
(void)jcl;
|
|
#ifdef HAVE_SESSION_TICKET
|
|
if (jenv == NULL || ssl <= 0) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
ret = wolfSSL_UseSessionTicket((WOLFSSL*)(uintptr_t)ssl);
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/* return 1 if last alert received was a close_notify alert, otherwise 0 */
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_gotCloseNotify
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
int ret, gotCloseNotify = 0;
|
|
WOLFSSL_ALERT_HISTORY alert_history;
|
|
(void)jcl;
|
|
|
|
if (jenv == NULL || ssl <= 0) {
|
|
return gotCloseNotify;
|
|
}
|
|
|
|
ret = wolfSSL_get_alert_history((WOLFSSL*)(uintptr_t)ssl, &alert_history);
|
|
if (ret == WOLFSSL_SUCCESS) {
|
|
if (alert_history.last_rx.code == 0) {
|
|
gotCloseNotify = 1;
|
|
}
|
|
}
|
|
|
|
return gotCloseNotify;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_sslSetAlpnProtos
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl, jbyteArray alpnProtos)
|
|
{
|
|
int ret = SSL_FAILURE;
|
|
(void)jcl;
|
|
#ifdef HAVE_ALPN
|
|
byte* buff = NULL;
|
|
word32 buffSz = 0;
|
|
|
|
if (jenv == NULL || ssl <= 0 || alpnProtos == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
buff = (byte*)(*jenv)->GetByteArrayElements(jenv, alpnProtos, NULL);
|
|
buffSz = (*jenv)->GetArrayLength(jenv, alpnProtos);
|
|
|
|
if (buff != NULL && buffSz > 0) {
|
|
ret = wolfSSL_set_alpn_protos((WOLFSSL*)(uintptr_t)ssl, buff, buffSz);
|
|
}
|
|
|
|
(*jenv)->ReleaseByteArrayElements(jenv, alpnProtos,
|
|
(jbyte*)buff, JNI_ABORT);
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
(void)alpnProtos;
|
|
ret = NOT_COMPILED_IN;
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_sslGet0AlpnSelected
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
#ifdef HAVE_ALPN
|
|
int err = 0;
|
|
char* protocol_name = NULL;
|
|
word16 protocol_nameSz = 0;
|
|
jbyteArray alpnArray;
|
|
|
|
if (jenv == NULL || ssl <= 0) {
|
|
return NULL;
|
|
}
|
|
|
|
/* get ALPN protocol received from server:
|
|
* WOLFSSL_SUCCESS - on success
|
|
* WOLFSSL_ALPN_NOT_FOUND - no ALPN received (no match with server)
|
|
* other - error case */
|
|
err = wolfSSL_ALPN_GetProtocol((WOLFSSL*)(uintptr_t)ssl,
|
|
&protocol_name, &protocol_nameSz);
|
|
if (err != WOLFSSL_SUCCESS) {
|
|
return NULL;
|
|
}
|
|
|
|
alpnArray = (*jenv)->NewByteArray(jenv, protocol_nameSz);
|
|
if (alpnArray == NULL) {
|
|
(*jenv)->ThrowNew(jenv, jcl,
|
|
"Failed to create byte array in native sslGet0AlpnSelected");
|
|
return NULL;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, alpnArray, 0, protocol_nameSz,
|
|
(jbyte*)protocol_name);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return NULL;
|
|
}
|
|
|
|
return alpnArray;
|
|
#else
|
|
(void)jenv;
|
|
(void)ssl;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setSSLIORecv
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if (ssl) {
|
|
/* set I/O recv callback */
|
|
wolfSSL_SSLSetIORecv((WOLFSSL*)(uintptr_t)ssl, NativeSSLIORecvCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting IORecv");
|
|
}
|
|
}
|
|
|
|
int NativeSSLIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
|
{
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
|
|
JNIEnv* jenv; /* JNI environment */
|
|
jclass excClass; /* WolfSSLJNIException class */
|
|
int needsDetach = 0; /* Should we explicitly detach? */
|
|
|
|
static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
|
|
jclass sslClass; /* WolfSSLSession class */
|
|
jmethodID recvCbMethodId; /* internalIORecvCallback ID */
|
|
jbyteArray inData;
|
|
|
|
if (!g_vm || !ssl || !buf || !ctx) {
|
|
/* can't throw exception yet, just return error */
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get JavaEnv from JavaVM */
|
|
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
|
|
if (vmret == JNI_EDETACHED) {
|
|
#ifdef __ANDROID__
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
|
|
#else
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
|
|
#endif
|
|
if (vmret) {
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
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((WOLFSSL*)(uintptr_t)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"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;
|
|
}
|
|
|
|
/* 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)->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) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"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);
|
|
|
|
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)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
}
|
|
|
|
/* delete local refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, inData);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_setSSLIOSend
|
|
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
|
{
|
|
(void)jcl;
|
|
|
|
/* find exception class in case we need it */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
if (ssl) {
|
|
/* set I/O send callback */
|
|
wolfSSL_SSLSetIOSend((WOLFSSL*)(uintptr_t)ssl, NativeSSLIOSendCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting IOSend");
|
|
}
|
|
}
|
|
|
|
int NativeSSLIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
|
{
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
|
|
JNIEnv* jenv; /* JNI environment */
|
|
jclass excClass; /* WolfSSLJNIException class */
|
|
int needsDetach = 0; /* Should we explicitly detach? */
|
|
|
|
static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
|
|
jclass sslClass; /* WolfSSLSession class */
|
|
jmethodID sendCbMethodId; /* internalIOSendCallback ID */
|
|
jbyteArray outData; /* jbyteArray for data to send */
|
|
|
|
if (!g_vm || !ssl || !buf || !ctx) {
|
|
/* can't throw exception yet, just return error */
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get JavaEnv from JavaVM */
|
|
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
|
|
if (vmret == JNI_EDETACHED) {
|
|
#ifdef __ANDROID__
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
|
|
#else
|
|
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
|
|
#endif
|
|
if (vmret) {
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
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((WOLFSSL*)(uintptr_t)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeSSLIOSendCb");
|
|
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;
|
|
}
|
|
|
|
/* 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)
|
|
(*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 native ctx since Java
|
|
* handles it */
|
|
retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
sendCbMethodId, (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)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|