4234 lines
144 KiB
C
4234 lines
144 KiB
C
/* com_wolfssl_WolfSSLContext.c
|
|
*
|
|
* Copyright (C) 2006-2015 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 <wolfssl/options.h>
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/error-ssl.h>
|
|
|
|
#include "com_wolfssl_globals.h"
|
|
#include "com_wolfssl_WolfSSLContext.h"
|
|
|
|
/* global object refs for verify, CRL callbacks */
|
|
static jobject g_verifyCbIfaceObj;
|
|
static jobject g_crlCtxCbIfaceObj;
|
|
|
|
/* custom I/O native fn prototypes */
|
|
int NativeIORecvCb(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
|
int NativeIOSendCb(WOLFSSL *ssl, char *buf, int sz, void *ctx);
|
|
int NativeGenCookieCb(WOLFSSL *ssl, unsigned char *buf, int sz, void *ctx);
|
|
int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store);
|
|
void NativeCtxMissingCRLCallback(const char* url);
|
|
int NativeMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut,
|
|
const unsigned char* macIn, unsigned int macInSz, int macContent,
|
|
int macVerify, unsigned char* encOut, const unsigned char* encIn,
|
|
unsigned int encSz, void* ctx);
|
|
int NativeDecryptVerifyCb(WOLFSSL* ssl, unsigned char* decOut,
|
|
const unsigned char* decIn, unsigned int decSz, int content,
|
|
int verify, unsigned int* padSz, void* ctx);
|
|
int NativeEccSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, void* ctx);
|
|
int NativeEccVerifyCb(WOLFSSL* ssl, const unsigned char* sig,
|
|
unsigned int sigSz, const unsigned char* hash, unsigned int hashSz,
|
|
const unsigned char* keyDer, unsigned int keySz, int* result,
|
|
void* ctx);
|
|
int NativeRsaSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, void* ctx);
|
|
int NativeRsaVerifyCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz,
|
|
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
|
|
void* ctx);
|
|
int NativeRsaEncCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, void* ctx);
|
|
int NativeRsaDecCb(WOLFSSL* ssl, unsigned char* in, unsigned int inSz,
|
|
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
|
|
void* ctx);
|
|
|
|
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLContext_newContext(JNIEnv* jenv,
|
|
jclass jcl, jlong method)
|
|
{
|
|
/* wolfSSL checks for NULL method ptr */
|
|
return (jlong)wolfSSL_CTX_new((WOLFSSL_METHOD*)method);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_useCertificateFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring file, jint format)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* certFile;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
if (!file)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input certificate file is NULL");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
certFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_CTX_use_certificate_file((WOLFSSL_CTX*)ctx, certFile,
|
|
(int)format);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, certFile);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_usePrivateKeyFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring file, jint format)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* keyFile;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
if (!file)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input private key file is NULL");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
keyFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_CTX_use_PrivateKey_file((WOLFSSL_CTX*)ctx, keyFile,
|
|
(int)format);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, keyFile);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_loadVerifyLocations
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring file, jstring path)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* caFile;
|
|
const char* caPath;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
if (!file && !path)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input file and path are both NULL");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
if (file) {
|
|
caFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
} else {
|
|
caFile = NULL;
|
|
}
|
|
|
|
if (path) {
|
|
caPath = (*jenv)->GetStringUTFChars(jenv, path, 0);
|
|
} else {
|
|
caPath = NULL;
|
|
}
|
|
|
|
ret = (jint) wolfSSL_CTX_load_verify_locations((WOLFSSL_CTX*)ctx, caFile,
|
|
caPath);
|
|
|
|
if (caFile)
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, caFile);
|
|
if (caPath)
|
|
(*jenv)->ReleaseStringUTFChars(jenv, path, caPath);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_useCertificateChainFile
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring file)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* chainFile;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
/* throw exception if no input file */
|
|
if (!file)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input certificate chain file is NULL");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
chainFile = (*jenv)->GetStringUTFChars(jenv, file, 0);
|
|
|
|
ret = (jint) wolfSSL_CTX_use_certificate_chain_file((WOLFSSL_CTX*)ctx,
|
|
chainFile);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, file, chainFile);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_freeContext
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* wolfSSL checks for null pointer */
|
|
wolfSSL_CTX_free((WOLFSSL_CTX*)ctx);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setVerify(JNIEnv* jenv,
|
|
jobject jcl, jlong ctx, jint mode, jobject callbackIface)
|
|
{
|
|
if (!callbackIface) {
|
|
wolfSSL_CTX_set_verify((WOLFSSL_CTX*)ctx, mode, NULL);
|
|
} else {
|
|
|
|
/* store Java verify Interface object */
|
|
g_verifyCbIfaceObj = (*jenv)->NewGlobalRef(jenv, callbackIface);
|
|
if (!g_verifyCbIfaceObj) {
|
|
printf("error storing global callback interface\n");
|
|
}
|
|
|
|
/* set verify mode, register Java callback with wolfSSL */
|
|
wolfSSL_CTX_set_verify((WOLFSSL_CTX*)ctx, mode, NativeVerifyCallback);
|
|
}
|
|
}
|
|
|
|
int NativeVerifyCallback(int preverify_ok, WOLFSSL_X509_STORE_CTX* store)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint vmret = 0;
|
|
jint retval = -1;
|
|
jclass excClass;
|
|
jmethodID verifyMethod;
|
|
jobjectRefType refcheck;
|
|
|
|
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;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, g_verifyCbIfaceObj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLVerifyCallback class from global object ref */
|
|
jclass verifyClass = (*jenv)->GetObjectClass(jenv, g_verifyCbIfaceObj);
|
|
if (!verifyClass) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLVerifyCallback class reference");
|
|
return -104;
|
|
}
|
|
|
|
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 -105;
|
|
}
|
|
|
|
retval = (*jenv)->CallIntMethod(jenv, g_verifyCbIfaceObj,
|
|
verifyMethod, preverify_ok, (jlong) store);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
/* exception occurred on the Java side during method call */
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return -106;
|
|
}
|
|
|
|
} else {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeVerifyCallback");
|
|
return -1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_memsaveCertCache
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray mem, jint sz,
|
|
jintArray used)
|
|
{
|
|
int ret;
|
|
int usedTmp;
|
|
char memBuf[sz];
|
|
|
|
if (!jenv || !ctx || !mem || (sz <= 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
ret = wolfSSL_CTX_memsave_cert_cache((WOLFSSL_CTX*)ctx, memBuf,
|
|
sz, &usedTmp);
|
|
|
|
/* set used value for return */
|
|
(*jenv)->SetIntArrayRegion(jenv, used, 0, 1, &usedTmp);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to set array region in native memsaveCertCache");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
/* set jbyteArray for return */
|
|
if (usedTmp >= 0) {
|
|
(*jenv)->SetByteArrayRegion(jenv, mem, 0, usedTmp, (jbyte*)memBuf);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to set byte region in native memsaveCertCache");
|
|
return SSL_FAILURE;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_memrestoreCertCache
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray mem, jint sz)
|
|
{
|
|
int ret;
|
|
char memBuf[sz];
|
|
|
|
if (!jenv || !ctx || !mem || (sz <= 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, mem, 0, sz, (jbyte*)memBuf);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to get byte region in native memrestoreCertCache");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
ret = wolfSSL_CTX_memrestore_cert_cache((WOLFSSL_CTX*)ctx, memBuf, sz);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_getCertCacheMemsize
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* wolfSSL checks for null pointer */
|
|
return wolfSSL_CTX_get_cert_cache_memsize((WOLFSSL_CTX*)ctx);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setCipherList
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring list)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* cipherList;
|
|
|
|
if (!jenv)
|
|
return SSL_FAILURE;
|
|
|
|
if (!list)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input cipher list is NULL");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
cipherList = (*jenv)->GetStringUTFChars(jenv, list, 0);
|
|
|
|
ret = (jint) wolfSSL_CTX_set_cipher_list((WOLFSSL_CTX*)ctx,
|
|
cipherList);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, list, cipherList);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_loadVerifyBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray in, jlong sz, jint format)
|
|
{
|
|
unsigned char buff[sz];
|
|
|
|
if (!jenv || !ctx || !in || (sz < 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to get byte region in native loadVerifyBuffer");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_CTX_load_verify_buffer((WOLFSSL_CTX*)ctx, buff, sz, format);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_useCertificateBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray in, jlong sz, jint format)
|
|
{
|
|
unsigned char buff[sz];
|
|
|
|
if (!jenv || !ctx || !in || (sz < 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to get byte region in native useCertificateBuffer");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_CTX_use_certificate_buffer((WOLFSSL_CTX*)ctx, buff, sz,
|
|
format);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_usePrivateKeyBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray in, jlong sz, jint format)
|
|
{
|
|
unsigned char buff[sz];
|
|
|
|
if (!jenv || !ctx || !in || (sz < 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to get byte region in native usePrivateKeyBuffer");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_CTX_use_PrivateKey_buffer((WOLFSSL_CTX*)ctx, buff, sz,
|
|
format);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_useCertificateChainBuffer
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jbyteArray in, jlong sz)
|
|
{
|
|
unsigned char buff[sz];
|
|
|
|
if (!jenv || !ctx || !in || (sz < 0))
|
|
return BAD_FUNC_ARG;
|
|
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
(*jenv)->GetByteArrayRegion(jenv, in, 0, sz, (jbyte*)buff);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to get byte region in native "
|
|
"useCertificateChainBuffer");
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
return wolfSSL_CTX_use_certificate_chain_buffer((WOLFSSL_CTX*)ctx,
|
|
buff, sz);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setGroupMessages
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
if (!jenv || !ctx)
|
|
return BAD_FUNC_ARG;
|
|
|
|
return wolfSSL_CTX_set_group_messages((WOLFSSL_CTX*)ctx);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setIORecv(JNIEnv* jenv,
|
|
jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set I/O recv callback */
|
|
wolfSSL_SetIORecv((WOLFSSL_CTX*)ctx, NativeIORecvCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting IORecv");
|
|
}
|
|
}
|
|
|
|
int NativeIORecvCb(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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext 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*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeIORecvCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeIORecvCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in NativeIORecvCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* find WolfSSLContext.getAssociatedContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativeIORecvCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get WolfSSLContext(ctx) object from Java WolfSSLSession object */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeIORecvCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from object */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativeIORecvCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* call internal I/O recv callback */
|
|
recvCbMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalIORecvCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
|
|
if (!recvCbMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalIORecvCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
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");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
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, ctxRef, recvCbMethodId,
|
|
(jobject)(*g_cachedSSLObj),
|
|
inData, (jint)sz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*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, ctxRef);
|
|
(*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, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, inData);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setIOSend
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* 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 (ctx) {
|
|
/* set I/O send callback */
|
|
wolfSSL_SetIOSend((WOLFSSL_CTX*)ctx, NativeIOSendCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting IOSend");
|
|
}
|
|
}
|
|
|
|
int NativeIOSendCb(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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext 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*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeIOSendCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in NativeIOSendCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* find WolfSSLContext.getAssociatedContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativeIOSendCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get WolfSSLContext(ctx) object from Java WolfSSLSession object */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeIOSendCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativeIOSendCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* call internal I/O recv callback */
|
|
sendCbMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalIOSendCallback",
|
|
"(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");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
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");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
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, ctxRef);
|
|
(*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, ctxRef, sendCbMethodId,
|
|
(jobject)(*g_cachedSSLObj), outData, (jint)sz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outData);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return WOLFSSL_CBIO_ERR_GENERAL;
|
|
}
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, outData);
|
|
}
|
|
|
|
/* delete local refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setGenCookie
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* 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 (ctx) {
|
|
/* set gen cookie callback */
|
|
wolfSSL_CTX_SetGenCookie((WOLFSSL_CTX*)ctx, NativeGenCookieCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"genCookieCb");
|
|
}
|
|
}
|
|
|
|
int NativeGenCookieCb(WOLFSSL *ssl, unsigned 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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID cookieCbMethodId; /* internalGenCookieCallback ID */
|
|
jbyteArray inData; /* jbyteArray to hold cookie data */
|
|
|
|
if (!g_vm || !ssl || !buf) {
|
|
/* can't throw exception yet, just return error */
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* 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 GEN_COOKIE_E;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* find exception class in case we need it */
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeGenCookieCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeGenCookieCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in "
|
|
"NativeGenCookieCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* find WolfSSLSession.getAssociatedContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativeGenCookieCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* get WolfSSLContext(ctx) object from WolfSSLSession object */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeGenCookieCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativeGenCookieCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* call internal gen cookie callback */
|
|
cookieCbMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalGenCookieCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;[BI)I");
|
|
|
|
if (!cookieCbMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalGenCookieCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
if (sz >= 0)
|
|
{
|
|
/* create jbyteArray to hold cookie data */
|
|
inData = (*jenv)->NewByteArray(jenv, sz);
|
|
if (!inData) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalGenCookieCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* call Java cookie callback */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxRef, cookieCbMethodId,
|
|
(jobject)(*g_cachedSSLObj),
|
|
inData, (jint)sz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, inData);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
|
|
/* 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, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, inData);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return GEN_COOKIE_E;
|
|
}
|
|
}
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, inData);
|
|
}
|
|
|
|
/* delete local refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_enableCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jint options)
|
|
{
|
|
if (!jenv || !ctx)
|
|
return BAD_FUNC_ARG;
|
|
|
|
return wolfSSL_CTX_EnableCRL((WOLFSSL_CTX*)ctx, options);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_disableCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
if (!jenv || !ctx)
|
|
return BAD_FUNC_ARG;
|
|
|
|
return wolfSSL_CTX_DisableCRL((WOLFSSL_CTX*)ctx);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_loadCRL
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring path, jint type, jint monitor)
|
|
{
|
|
int ret;
|
|
const char* crlPath;
|
|
|
|
if (!jenv || !ctx || !path)
|
|
return BAD_FUNC_ARG;
|
|
|
|
crlPath = (*jenv)->GetStringUTFChars(jenv, path, 0);
|
|
|
|
ret = wolfSSL_CTX_LoadCRL((WOLFSSL_CTX*)ctx, crlPath, type, monitor);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, path, crlPath);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setCRLCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jobject cb)
|
|
{
|
|
int ret = 0;
|
|
jclass excClass;
|
|
|
|
if (!jenv || !ctx || !cb) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
/* store Java CRL callback Interface object */
|
|
g_crlCtxCbIfaceObj = (*jenv)->NewGlobalRef(jenv, cb);
|
|
|
|
if (!g_crlCtxCbIfaceObj) {
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"error storing global missing CTX CRL callback interface");
|
|
}
|
|
|
|
ret = wolfSSL_CTX_SetCRL_Cb((WOLFSSL_CTX*)ctx, NativeCtxMissingCRLCallback);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void NativeCtxMissingCRLCallback(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/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, g_crlCtxCbIfaceObj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLMissingCRLCallback class from global object ref */
|
|
jclass crlClass = (*jenv)->GetObjectClass(jenv, g_crlCtxCbIfaceObj);
|
|
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_crlCtxCbIfaceObj, 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");
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_enableOCSP
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jlong options)
|
|
{
|
|
/* wolfSSL checks for null pointer */
|
|
return wolfSSL_CTX_EnableOCSP((WOLFSSL_CTX*)ctx, options);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_disableOCSP
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* wolfSSL checks for null pointer */
|
|
return wolfSSL_CTX_DisableOCSP((WOLFSSL_CTX*)ctx);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_setOCSPOverrideUrl
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx, jstring urlString)
|
|
{
|
|
jint ret = 0;
|
|
jclass excClass;
|
|
const char* url;
|
|
|
|
/* wolfSSL checks ctx for NULL */
|
|
if (!jenv)
|
|
return BAD_FUNC_ARG;
|
|
|
|
if (urlString == NULL)
|
|
{
|
|
excClass = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
/* throw NullPointerException */
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input URL is NULL in setOCSPOverrideUrl()");
|
|
|
|
return SSL_FAILURE;
|
|
}
|
|
|
|
url = (*jenv)->GetStringUTFChars(jenv, urlString, 0);
|
|
|
|
ret = (jint) wolfSSL_CTX_SetOCSP_OverrideURL((WOLFSSL_CTX*)ctx, url);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, urlString, url);
|
|
|
|
return ret;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setMacEncryptCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set MAC encrypt callback */
|
|
wolfSSL_CTX_SetMacEncryptCb((WOLFSSL_CTX*)ctx, NativeMacEncryptCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when "
|
|
"setting MacEncrypt");
|
|
}
|
|
}
|
|
|
|
int NativeMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut,
|
|
const unsigned char* macIn, unsigned int macInSz, int macContent,
|
|
int macVerify, unsigned char* encOut, const unsigned char* encIn,
|
|
unsigned int encSz, 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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID macEncryptMethodId; /* internalMacEncryptCallback ID */
|
|
|
|
int hmacSize;
|
|
jbyteArray j_macIn;
|
|
|
|
if (!g_vm || !ssl || !macOut || !macIn || !encOut || !encIn) {
|
|
return -1;
|
|
}
|
|
|
|
/* 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 -1;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return -1;
|
|
}
|
|
|
|
/* find exception class in case we need it */
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv,
|
|
(jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativeMacEncryptCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get ref to internal MAC encrypt callback */
|
|
macEncryptMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalMacEncryptCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"[BJIILjava/nio/ByteBuffer;Ljava/nio/ByteBuffer;J)I");
|
|
|
|
if (!macEncryptMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalMacEncryptCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
hmacSize = wolfSSL_GetHmacSize((WOLFSSL*)ssl);
|
|
|
|
/* create ByteBuffer to wrap macOut */
|
|
jobject macOutBB = (*jenv)->NewDirectByteBuffer(jenv, macOut,
|
|
hmacSize);
|
|
if (!macOutBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create macOut ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create jbyteArray to hold macIn, since macIn is read-only */
|
|
j_macIn = (*jenv)->NewByteArray(jenv, macInSz);
|
|
if (!j_macIn) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create macIn ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, j_macIn, 0, macInSz,
|
|
(jbyte*)macIn);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_macIn);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap encOut */
|
|
jobject encOutBB = (*jenv)->NewDirectByteBuffer(jenv, encOut,
|
|
encSz);
|
|
if (!encOutBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create encOut ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_macIn);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap encIn - use encOut b/c it's not a
|
|
* const, but points to same memory. This will be important
|
|
* in Java-land in order to have an updated encIn array after
|
|
* doing the MAC operation. */
|
|
jobject encInBB = (*jenv)->NewDirectByteBuffer(jenv, encOut,
|
|
encSz);
|
|
if (!encInBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create encIn ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_macIn);
|
|
(*jenv)->DeleteLocalRef(jenv, encOutBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call Java MAC/encrypt callback */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxRef, macEncryptMethodId,
|
|
(jobject)(*g_cachedSSLObj), macOutBB, j_macIn, (jlong)macInSz,
|
|
macContent, macVerify, encOutBB, encInBB, (jlong)encSz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv) || retval != 0) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Call to Java callback failed in NativeMacEncryptCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_macIn);
|
|
(*jenv)->DeleteLocalRef(jenv, encOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, encInBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, macOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_macIn);
|
|
(*jenv)->DeleteLocalRef(jenv, encOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, encInBB);
|
|
}
|
|
|
|
/* detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setDecryptVerifyCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set decrypt/verify callback */
|
|
wolfSSL_CTX_SetDecryptVerifyCb((WOLFSSL_CTX*)ctx,
|
|
NativeDecryptVerifyCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when "
|
|
"setting MacDecrypt");
|
|
}
|
|
}
|
|
|
|
int NativeDecryptVerifyCb(WOLFSSL* ssl, unsigned char* decOut,
|
|
const unsigned char* decIn, unsigned int decSz, int content,
|
|
int verify, unsigned int* padSz, 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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID decryptVerifyMethodId;
|
|
|
|
jbyteArray j_decIn;
|
|
jlongArray j_padSz;
|
|
|
|
if (!g_vm || !ssl || !decOut || !decIn || !padSz) {
|
|
return -1;
|
|
}
|
|
|
|
/* 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 -1;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return -1;
|
|
}
|
|
|
|
/* find exception class in case we need it */
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeMacEncryptCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeDecryptVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeDecryptVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeDecryptVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeDecryptVerifyCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call internal decrypt/verify callback */
|
|
decryptVerifyMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalDecryptVerifyCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;[BJII[J)I");
|
|
|
|
if (!decryptVerifyMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalDecryptVerifyCallback method "
|
|
"from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
/* create ByteBuffer to wrap decOut */
|
|
jobject decOutBB = (*jenv)->NewDirectByteBuffer(jenv, decOut,
|
|
decSz);
|
|
if (!decOutBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create decOut ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create jbyteArray to hold decIn */
|
|
j_decIn = (*jenv)->NewByteArray(jenv, decSz);
|
|
if (!j_decIn) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create decIn ByteArray");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
(*jenv)->SetByteArrayRegion(jenv, j_decIn, 0, decSz, (jbyte*)decIn);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_decIn);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create jlongArray to hold padSz, since we need to use it as
|
|
* an OUTPUT parameter from Java. Only needs to have 1 element */
|
|
j_padSz = (*jenv)->NewLongArray(jenv, 1);
|
|
if (!j_padSz) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create padSz longArray");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_decIn);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call Java decrypt/verify callback, java layer handles
|
|
* adding decrypt/verify CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxRef, decryptVerifyMethodId,
|
|
(jobject)(*g_cachedSSLObj), decOutBB, j_decIn, (jlong)decSz,
|
|
content, verify, j_padSz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_decIn);
|
|
(*jenv)->DeleteLocalRef(jenv, j_padSz);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
if (retval == 0) {
|
|
/* copy j_padSz into padSz */
|
|
jlong tmpVal;
|
|
(*jenv)->GetLongArrayRegion(jenv, j_padSz, 0, 1, &tmpVal);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_decIn);
|
|
(*jenv)->DeleteLocalRef(jenv, j_padSz);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
*padSz = (unsigned int)tmpVal;
|
|
}
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, decOutBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_decIn);
|
|
(*jenv)->DeleteLocalRef(jenv, j_padSz);
|
|
}
|
|
|
|
/* delete local refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setEccSignCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set ECC sign callback */
|
|
wolfSSL_CTX_SetEccSignCb((WOLFSSL_CTX*)ctx, NativeEccSignCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"EccSignCb");
|
|
}
|
|
}
|
|
|
|
int NativeEccSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, 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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID eccSignMethodId;
|
|
|
|
jlongArray j_outSz;
|
|
|
|
if (!g_vm || !ssl || !in || !out || !outSz || !keyDer)
|
|
return -1;
|
|
|
|
/* 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 -1;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return -1;
|
|
}
|
|
|
|
/* find exception class in case we need it */
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeEccSignCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeEccSignCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeEccSignCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeEccSignCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeEccSignCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeEccSignCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call internal decrypt/verify callback */
|
|
eccSignMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalEccSignCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;[JLjava/nio/ByteBuffer;J)I");
|
|
|
|
if (!eccSignMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalEccSignCallback method "
|
|
"from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap out */
|
|
jobject outBB = (*jenv)->NewDirectByteBuffer(jenv, out, *outSz);
|
|
if (!outBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create eccSign out ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap in */
|
|
jobject inBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)in, inSz);
|
|
if (!inBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create eccSign in ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap keyDer */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv,
|
|
(void*)keyDer, keySz);
|
|
if (!keyDerBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create eccSign keyDer ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create jlongArray to hold outSz, since we need to use it as
|
|
* an OUTPUT parameter from Java. Only needs to have 1 element */
|
|
j_outSz = (*jenv)->NewLongArray(jenv, 1);
|
|
if (!j_outSz) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to create outSz longArray");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* copy outSz into j_outSz */
|
|
(*jenv)->SetLongArrayRegion(jenv, j_outSz, 0, 1, (jlong*)outSz);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"failed to set j_outSz longArray");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_outSz);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
}
|
|
|
|
/* call Java ECC sign callback, java layer handles
|
|
* adding decrypt/verify CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxRef, eccSignMethodId,
|
|
(jobject)(*g_cachedSSLObj), inBB, (jlong)inSz, outBB, j_outSz,
|
|
keyDerBB, (jlong)keySz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_outSz);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
if (retval == 0) {
|
|
/* copy j_outSz into outSz */
|
|
jlong tmpVal;
|
|
(*jenv)->GetLongArrayRegion(jenv, j_outSz, 0, 1, &tmpVal);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_outSz);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
*outSz = (unsigned int)tmpVal;
|
|
}
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, outBB);
|
|
(*jenv)->DeleteLocalRef(jenv, inBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_outSz);
|
|
|
|
/* detach JNIEnv from thread */
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setEccVerifyCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set ECC verify callback */
|
|
wolfSSL_CTX_SetEccVerifyCb((WOLFSSL_CTX*)ctx, NativeEccVerifyCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"EccVerifyCb");
|
|
}
|
|
}
|
|
|
|
int NativeEccVerifyCb(WOLFSSL* ssl, const unsigned char* sig,
|
|
unsigned int sigSz, const unsigned char* hash, unsigned int hashSz,
|
|
const unsigned char* keyDer, unsigned int keySz, int* result,
|
|
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 sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx FieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID eccVerifyMethodId;
|
|
jintArray j_result;
|
|
|
|
if (!g_vm || !ssl || !sig || !hash || !keyDer || !result)
|
|
return -1;
|
|
|
|
/* 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 -1;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return -1;
|
|
}
|
|
|
|
/* find exception class in case we need it */
|
|
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativeEccVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativeEccVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeEccVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeEccVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeEccVerifyCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeEccVerifyCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call internal ECC verify callback */
|
|
eccVerifyMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalEccVerifyCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J[I)I");
|
|
|
|
if (!eccVerifyMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalEccVerifyCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'sig' */
|
|
jobject sigBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)sig, sigSz);
|
|
if (!sigBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create eccVerify out ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'hash' */
|
|
jobject hashBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)hash, hashSz);
|
|
if (!hashBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create eccVerify hash ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'keyDer' */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer,
|
|
keySz);
|
|
if (!keyDerBB) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create eccVerify keyDer ByteBuffer");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
(*jenv)->DeleteLocalRef(jenv, hashBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* create jintArray to hold result, since we need to use it as
|
|
* an OUTPUT parameter from Java. Only needs to have 1 element */
|
|
j_result = (*jenv)->NewIntArray(jenv, 1);
|
|
if (!j_result) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Failed to create result intArray in EccVerifyCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
(*jenv)->DeleteLocalRef(jenv, hashBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* call Java ECC verify callback, java layer handles
|
|
* adding CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxRef, eccVerifyMethodId,
|
|
(jobject)(*g_cachedSSLObj), sigBB, (jlong)sigSz, hashBB,
|
|
(jlong)hashSz, keyDerBB, (jlong)keySz, j_result);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
(*jenv)->DeleteLocalRef(jenv, hashBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_result);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
|
|
/* copy j_result into result */
|
|
jint tmpVal;
|
|
(*jenv)->GetIntArrayRegion(jenv, j_result, 0, 1, &tmpVal);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
(*jenv)->DeleteLocalRef(jenv, hashBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_result);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return -1;
|
|
}
|
|
*result = tmpVal;
|
|
|
|
/* delete local refs */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, sigBB);
|
|
(*jenv)->DeleteLocalRef(jenv, hashBB);
|
|
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
|
|
(*jenv)->DeleteLocalRef(jenv, j_result);
|
|
|
|
/* detach JNIEnv from thread */
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaSignCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set RSA sign callback */
|
|
wolfSSL_CTX_SetRsaSignCb((WOLFSSL_CTX*)ctx, NativeRsaSignCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"RsaSignCb");
|
|
}
|
|
}
|
|
|
|
int NativeRsaSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, void* ctx)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
jmethodID rsaSignMethodId;
|
|
jclass excClass;
|
|
|
|
jobjectRefType refcheck;
|
|
internCtx* myCtx = ctx;
|
|
|
|
jintArray j_outSz;
|
|
|
|
if (!g_vm) {
|
|
printf("Global JavaVM reference is null!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 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) {
|
|
printf("Failed to attach JNIEnv to thread\n");
|
|
} else {
|
|
printf("Attached JNIEnv to thread\n");
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
printf("Error getting JNIEnv from JavaVM, ret = %d\n", vmret);
|
|
}
|
|
|
|
/* 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);
|
|
return -1;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, myCtx->obj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLSession class from global object ref */
|
|
jclass sessClass = (*jenv)->GetObjectClass(jenv, myCtx->obj);
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference "
|
|
"in NativeRsaSignCb");
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
jfieldID ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeRsaSignCb");
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
jmethodID getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeRsaSignCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
jobject ctxref = (*jenv)->CallObjectMethod(jenv, myCtx->obj,
|
|
getCtxMethodId);
|
|
if (!ctxref) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeRsaSignCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
jclass innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxref);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeRsaSignCb");
|
|
return -1;
|
|
}
|
|
|
|
/* call internal RSA sign callback */
|
|
rsaSignMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalRsaSignCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;[ILjava/nio/ByteBuffer;J)I");
|
|
|
|
if (!rsaSignMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
printf("Error getting internalRsaSignCallback method "
|
|
"from JNI\n");
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
/* create ByteBuffer to wrap 'in' */
|
|
jobject inBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)in,
|
|
inSz);
|
|
if (!inBB) {
|
|
printf("failed to create rsaSign in ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'out' */
|
|
jobject outBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)out,
|
|
*outSz);
|
|
if (!outBB) {
|
|
printf("failed to create rsaSign out ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'keyDer' */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer,
|
|
keySz);
|
|
if (!keyDerBB) {
|
|
printf("failed to create rsaSign keyDer ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create jintArray to hold outSz, since we need to use it as
|
|
* an OUTPUT parameter from Java. Only needs to have 1 element */
|
|
j_outSz = (*jenv)->NewIntArray(jenv, 1);
|
|
if (!j_outSz) {
|
|
printf("failed to create result intArray\n");
|
|
return -1;
|
|
}
|
|
(*jenv)->SetIntArrayRegion(jenv, j_outSz, 0, 1, (jint*)outSz);
|
|
|
|
/* call Java RSA sign callback, java layer handles
|
|
* adding CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxref, rsaSignMethodId,
|
|
myCtx->obj, inBB, (jlong)inSz, outBB, j_outSz, keyDerBB,
|
|
(jlong)keySz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0) {
|
|
/* copy j_outSz into outSz */
|
|
jint tmpVal;
|
|
(*jenv)->GetIntArrayRegion(jenv, j_outSz, 0, 1, &tmpVal);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
*outSz = tmpVal;
|
|
}
|
|
}
|
|
|
|
/* detach JNIEnv from thread */
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
} else {
|
|
/* clear any existing exception before we throw another */
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeRsaSignCb");
|
|
|
|
return -1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaVerifyCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set RSA verify callback */
|
|
wolfSSL_CTX_SetRsaVerifyCb((WOLFSSL_CTX*)ctx, NativeRsaVerifyCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"RsaVerifyCb");
|
|
}
|
|
}
|
|
|
|
int NativeRsaVerifyCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz,
|
|
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
|
|
void* ctx)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
jmethodID rsaVerifyMethodId;
|
|
jclass excClass;
|
|
|
|
jobjectRefType refcheck;
|
|
internCtx* myCtx = ctx;
|
|
|
|
if (!g_vm) {
|
|
printf("Global JavaVM reference is null!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 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) {
|
|
printf("Failed to attach JNIEnv to thread\n");
|
|
} else {
|
|
printf("Attached JNIEnv to thread\n");
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
printf("Error getting JNIEnv from JavaVM, ret = %d\n", vmret);
|
|
}
|
|
|
|
/* 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);
|
|
return -1;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, myCtx->obj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLSession class from global object ref */
|
|
jclass sessClass = (*jenv)->GetObjectClass(jenv, myCtx->obj);
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference "
|
|
"in NativeRsaVerifyCb");
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
jfieldID ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeRsaVerifyCb");
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
jmethodID getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeRsaVerifyCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
jobject ctxref = (*jenv)->CallObjectMethod(jenv, myCtx->obj,
|
|
getCtxMethodId);
|
|
if (!ctxref) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeRsaVerifyCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
jclass innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxref);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeRsaVerifyCb");
|
|
return -1;
|
|
}
|
|
|
|
/* call internal ECC verify callback */
|
|
rsaVerifyMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalRsaVerifyCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J)I");
|
|
|
|
if (!rsaVerifyMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
printf("Error getting internalRsaVerifyCallback method "
|
|
"from JNI\n");
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
/* create ByteBuffer to wrap 'sig' */
|
|
jobject sigBB = (*jenv)->NewDirectByteBuffer(jenv, sig,
|
|
sigSz);
|
|
if (!sigBB) {
|
|
printf("failed to create rsaVerify sig ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'out', since we're actually
|
|
* doing this inline, outBB points to the same address as
|
|
* sigBB */
|
|
jobject outBB = (*jenv)->NewDirectByteBuffer(jenv, sig,
|
|
sigSz);
|
|
if (!outBB) {
|
|
printf("failed to create rsaVerify out ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'keyDer' */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer,
|
|
keySz);
|
|
if (!keyDerBB) {
|
|
printf("failed to create rsaVerify keyDer ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* call Java RSA verify callback, java layer handles
|
|
* adding CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxref, rsaVerifyMethodId,
|
|
myCtx->obj, sigBB, (jlong)sigSz, outBB, (jlong)sigSz,
|
|
keyDerBB, (jlong)keySz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
}
|
|
|
|
/* detach JNIEnv from thread */
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
} else {
|
|
/* clear any existing exception before we throw another */
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeRsaVerifyCb");
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* point out* to the beginning of our decrypted buffer */
|
|
if (retval > 0)
|
|
*out = sig;
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaEncCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set RSA encrypt callback */
|
|
wolfSSL_CTX_SetRsaEncCb((WOLFSSL_CTX*)ctx, NativeRsaEncCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"RsaEncCb");
|
|
}
|
|
}
|
|
|
|
int NativeRsaEncCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
|
|
unsigned char* out, unsigned int* outSz, const unsigned char* keyDer,
|
|
unsigned int keySz, void* ctx)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
jmethodID rsaEncMethodId;
|
|
jclass excClass;
|
|
|
|
jobjectRefType refcheck;
|
|
internCtx* myCtx = ctx;
|
|
|
|
jintArray j_outSz;
|
|
|
|
if (!g_vm) {
|
|
printf("Global JavaVM reference is null!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 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) {
|
|
printf("Failed to attach JNIEnv to thread\n");
|
|
} else {
|
|
printf("Attached JNIEnv to thread\n");
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
printf("Error getting JNIEnv from JavaVM, ret = %d\n", vmret);
|
|
}
|
|
|
|
/* 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);
|
|
return -1;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, myCtx->obj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLSession class from global object ref */
|
|
jclass sessClass = (*jenv)->GetObjectClass(jenv, myCtx->obj);
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference "
|
|
"in NativeRsaEncCb");
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
jfieldID ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeRsaEncCb");
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
jmethodID getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeRsaEncCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
jobject ctxref = (*jenv)->CallObjectMethod(jenv, myCtx->obj,
|
|
getCtxMethodId);
|
|
if (!ctxref) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeRsaEncCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
jclass innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxref);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeRsaEncCb");
|
|
return -1;
|
|
}
|
|
|
|
/* call internal RSA enc callback */
|
|
rsaEncMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalRsaEncCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;[ILjava/nio/ByteBuffer;J)I");
|
|
|
|
if (!rsaEncMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
printf("Error getting internalRsaEncCallback method "
|
|
"from JNI\n");
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
/* create ByteBuffer to wrap 'in' */
|
|
jobject inBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)in,
|
|
inSz);
|
|
if (!inBB) {
|
|
printf("failed to create rsaEnc in ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'out' */
|
|
jobject outBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)out,
|
|
*outSz);
|
|
if (!outBB) {
|
|
printf("failed to create rsaEnc out ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'keyDer' */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer,
|
|
keySz);
|
|
if (!keyDerBB) {
|
|
printf("failed to create rsaEnc keyDer ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create jintArray to hold outSz, since we need to use it as
|
|
* an OUTPUT parameter from Java. Only needs to have 1 element */
|
|
j_outSz = (*jenv)->NewIntArray(jenv, 1);
|
|
if (!j_outSz) {
|
|
printf("failed to create result intArray\n");
|
|
return -1;
|
|
}
|
|
(*jenv)->SetIntArrayRegion(jenv, j_outSz, 0, 1, (jint*)outSz);
|
|
|
|
/* call Java RSA enc callback, java layer handles
|
|
* adding CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxref, rsaEncMethodId,
|
|
myCtx->obj, inBB, (jlong)inSz, outBB, j_outSz, keyDerBB,
|
|
(jlong)keySz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0) {
|
|
/* copy j_outSz into outSz */
|
|
jint tmpVal;
|
|
(*jenv)->GetIntArrayRegion(jenv, j_outSz, 0, 1, &tmpVal);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
*outSz = tmpVal;
|
|
}
|
|
}
|
|
|
|
/* detach JNIEnv from thread */
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
} else {
|
|
/* clear any existing exception before we throw another */
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeRsaEncCb");
|
|
|
|
return -1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaDecCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if(ctx) {
|
|
/* set RSA encrypt callback */
|
|
wolfSSL_CTX_SetRsaDecCb((WOLFSSL_CTX*)ctx, NativeRsaDecCb);
|
|
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"RsaDecCb");
|
|
}
|
|
}
|
|
|
|
int NativeRsaDecCb(WOLFSSL* ssl, unsigned char* in, unsigned int inSz,
|
|
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
|
|
void* ctx)
|
|
{
|
|
JNIEnv* jenv;
|
|
jint retval = 0;
|
|
jint vmret = 0;
|
|
jmethodID rsaDecMethodId;
|
|
jclass excClass;
|
|
|
|
jobjectRefType refcheck;
|
|
internCtx* myCtx = ctx;
|
|
|
|
if (!g_vm) {
|
|
printf("Global JavaVM reference is null!\n");
|
|
return -1;
|
|
}
|
|
|
|
/* 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) {
|
|
printf("Failed to attach JNIEnv to thread\n");
|
|
} else {
|
|
printf("Attached JNIEnv to thread\n");
|
|
}
|
|
} else if (vmret != JNI_OK) {
|
|
printf("Error getting JNIEnv from JavaVM, ret = %d\n", vmret);
|
|
}
|
|
|
|
/* 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);
|
|
return -1;
|
|
}
|
|
|
|
/* check if our stored object reference is valid */
|
|
refcheck = (*jenv)->GetObjectRefType(jenv, myCtx->obj);
|
|
if (refcheck == 2) {
|
|
|
|
/* lookup WolfSSLSession class from global object ref */
|
|
jclass sessClass = (*jenv)->GetObjectClass(jenv, myCtx->obj);
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference "
|
|
"in NativeRsaDecCb");
|
|
return -1;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
jfieldID ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID "
|
|
"in NativeRsaDecCb");
|
|
return -1;
|
|
}
|
|
|
|
/* find getContextPtr() method */
|
|
jmethodID getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID "
|
|
"in NativeRsaDecCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext ctx object from Java land */
|
|
jobject ctxref = (*jenv)->CallObjectMethod(jenv, myCtx->obj,
|
|
getCtxMethodId);
|
|
if (!ctxref) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativeRsaDecCb");
|
|
return -1;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from Java land */
|
|
jclass innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxref);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference "
|
|
"in NativeRsaDecCb");
|
|
return -1;
|
|
}
|
|
|
|
/* call internal ECC verify callback */
|
|
rsaDecMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalRsaDecCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;"
|
|
"JLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J)I");
|
|
|
|
if (!rsaDecMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
printf("Error getting internalRsaDecCallback method "
|
|
"from JNI\n");
|
|
retval = -1;
|
|
}
|
|
|
|
if (retval == 0)
|
|
{
|
|
/* create ByteBuffer to wrap 'in' */
|
|
jobject inBB = (*jenv)->NewDirectByteBuffer(jenv, in,
|
|
inSz);
|
|
if (!inBB) {
|
|
printf("failed to create rsaDec in ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'out', since we're actually
|
|
* doing this inline, outBB points to the same address as
|
|
* inBB */
|
|
jobject outBB = (*jenv)->NewDirectByteBuffer(jenv, in,
|
|
inSz);
|
|
if (!outBB) {
|
|
printf("failed to create rsaDec out ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* create ByteBuffer to wrap 'keyDer' */
|
|
jobject keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer,
|
|
keySz);
|
|
if (!keyDerBB) {
|
|
printf("failed to create rsaDec keyDer ByteBuffer\n");
|
|
return -1;
|
|
}
|
|
|
|
/* call Java RSA decrypt callback, java layer handles
|
|
* adding CTX reference */
|
|
retval = (*jenv)->CallIntMethod(jenv, ctxref, rsaDecMethodId,
|
|
myCtx->obj, inBB, (jlong)inSz, outBB, (jlong)inSz,
|
|
keyDerBB, (jlong)keySz);
|
|
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
retval = -1;
|
|
}
|
|
}
|
|
|
|
/* detach JNIEnv from thread */
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
} else {
|
|
/* clear any existing exception before we throw another */
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Object reference invalid in NativeRsaDecCb");
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* point out* to the beginning of our decrypted buffer */
|
|
if (retval > 0)
|
|
*out = in;
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setPskClientCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if (ctx) {
|
|
/* set PSK client callback */
|
|
wolfSSL_CTX_set_psk_client_callback((WOLFSSL_CTX*)ctx,
|
|
NativePskClientCb);
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"NativePskClientCb");
|
|
}
|
|
}
|
|
|
|
unsigned int NativePskClientCb(WOLFSSL* ssl, const char* hint, char* identity,
|
|
unsigned int id_max_len, unsigned char* key, unsigned int max_key_len)
|
|
{
|
|
jint vmret = 0;
|
|
jlong retval = 0;
|
|
int usingSSLCallback = 0;
|
|
int needsDetach = 0; /* Should we explicitly detach? */
|
|
|
|
JNIEnv* jenv; /* JNI environment */
|
|
jclass excClass; /* class: WolfSSLJNIException */
|
|
|
|
static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
|
|
jclass sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx fieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jfieldID internPskClientCbFid; /* WolfSSLContext->internPskClientCb ID */
|
|
jobject internPskClientCbObj; /* " ->internPskClientCb object */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID pskClientMethodId; /* internalPskClientCallback ID */
|
|
|
|
jstring hintString; /* String, for 'hint' */
|
|
jclass strBufClass; /* StringBuffer class for 'identity' */
|
|
jmethodID strBufMethodId; /* StringBuffer constructor ID */
|
|
jobject strBufObj; /* StringBuffer object */
|
|
jbyteArray keyArray; /* byte[] for key in/out */
|
|
jmethodID toStringId; /* StringBuffer.toString() ID */
|
|
jstring bufString; /* StringBuffer.toString() result */
|
|
const char* tmpString; /* tmp output char* for String out */
|
|
|
|
/* Note: since this is called from C, not the JVM, we need to explicitly
|
|
* free all object refs with DeleteLocalRef() */
|
|
|
|
if (!g_vm || !ssl || !hint || !identity || !key) {
|
|
/* we can't throw an exception yet, so just return 0 (failure) */
|
|
return 0;
|
|
}
|
|
|
|
/* 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 0;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return 0;
|
|
}
|
|
|
|
/* find exception class */
|
|
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 0;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativePskClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativePskClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in "
|
|
"NativePSKClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* find WolfSSLSession.getAssociatedContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativePSKClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* get WolfSSLContext(ctx) object from Java WolfSSLSession object */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativePskClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from object */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativePskClientCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* figure out if we need to call the CTX or SSL level callback */
|
|
|
|
/* 1. Get internPskClientCb FieldID */
|
|
internPskClientCbFid = (*jenv)->GetFieldID(jenv, innerCtxClass,
|
|
"internPskClientCb",
|
|
"Lcom/wolfssl/WolfSSLPskClientCallback;");
|
|
if (!internPskClientCbFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native internPskClientCb field ID in "
|
|
"NativePSKClientCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* 2. Get WolfSSLPskClientCallback object (or null) */
|
|
internPskClientCbObj = (*jenv)->GetObjectField(jenv, ctxRef,
|
|
internPskClientCbFid);
|
|
if (!internPskClientCbObj) {
|
|
printf("Using SSL level PSK Client callback!!!\n");
|
|
usingSSLCallback = 1;
|
|
}
|
|
|
|
if (usingSSLCallback == 1) {
|
|
/* WolfSSLSession level callback */
|
|
pskClientMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"internalPskClientCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/lang/String;"
|
|
"Ljava/lang/StringBuffer;J[BJ)J");
|
|
} else {
|
|
/* WolfSSLContext level callback */
|
|
pskClientMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalPskClientCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/lang/String;"
|
|
"Ljava/lang/StringBuffer;J[BJ)J");
|
|
}
|
|
|
|
if (!pskClientMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalPskClientCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* create String to wrap 'hint' */
|
|
hintString = (*jenv)->NewStringUTF(jenv, hint);
|
|
if (!hintString) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error creating String for PSK client hint");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* find StringBuffer class to wrap 'identity' */
|
|
strBufClass = (*jenv)->FindClass(jenv, "java/lang/StringBuffer");
|
|
if (!strBufClass) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error finding StringBuffer class for PSK client identity");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* find StringBuffer Constructor */
|
|
strBufMethodId = (*jenv)->GetMethodID(jenv, strBufClass,
|
|
"<init>", "()V");
|
|
if (!strBufMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get StringBuffer constructor method ID "
|
|
"in NativePskClientCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* create new StringBuffer object */
|
|
strBufObj = (*jenv)->NewObject(jenv, strBufClass, strBufMethodId);
|
|
if (!strBufObj) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get StringBuffer object in NativePskClientCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* create jbyteArray to hold received key */
|
|
keyArray = (*jenv)->NewByteArray(jenv, max_key_len);
|
|
if (!keyArray) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error creating jbyteArray for PSK client key");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* call Java PSK client callback */
|
|
if (usingSSLCallback == 1) {
|
|
/* call WolfSSLSession level callback */
|
|
retval = (*jenv)->CallLongMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
pskClientMethodId, (jobject)(*g_cachedSSLObj), hintString,
|
|
strBufObj, (jlong)id_max_len, keyArray, (jlong)max_key_len);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
} else {
|
|
/* call WolfSSLContext level callback */
|
|
retval = (*jenv)->CallLongMethod(jenv, ctxRef, pskClientMethodId,
|
|
(jobject)(*g_cachedSSLObj), hintString, strBufObj,
|
|
(jlong)id_max_len, keyArray, (jlong)max_key_len);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (retval > 0) {
|
|
|
|
/* copy jbyteArray into char key array */
|
|
(*jenv)->GetByteArrayRegion(jenv, keyArray, 0, retval, (jbyte*)key);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* get the String from the StringBuffer */
|
|
toStringId = (*jenv)->GetMethodID(jenv, strBufClass,
|
|
"toString", "()Ljava/lang/String;");
|
|
if (!toStringId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting String ID from StringBuffer in PSK CB");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
bufString = (jstring) (*jenv)->CallObjectMethod(jenv,
|
|
strBufObj, toStringId);
|
|
if (!bufString) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting String from StringBuffer in PSK CB");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* convert string to C string (char*) */
|
|
tmpString = (*jenv)->GetStringUTFChars(jenv, bufString, 0);
|
|
if (!tmpString) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error with GetStringUTFChars in PSK Client CB");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
(*jenv)->DeleteLocalRef(jenv, bufString);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
strcpy(identity, tmpString);
|
|
(*jenv)->ReleaseStringUTFChars(jenv, bufString, tmpString);
|
|
(*jenv)->DeleteLocalRef(jenv, bufString);
|
|
}
|
|
|
|
/* delete local obj refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, hintString);
|
|
(*jenv)->DeleteLocalRef(jenv, strBufObj);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setPskServerCb
|
|
(JNIEnv* jenv, jobject jcl, jlong ctx)
|
|
{
|
|
/* find exception class */
|
|
jclass excClass = (*jenv)->FindClass(jenv,
|
|
"com/wolfssl/WolfSSLJNIException");
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
return;
|
|
}
|
|
|
|
if (ctx) {
|
|
/* set PSK server callback */
|
|
wolfSSL_CTX_set_psk_server_callback((WOLFSSL_CTX*)ctx,
|
|
NativePskServerCb);
|
|
} else {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Input WolfSSLContext object was null when setting "
|
|
"NativePskServerCb");
|
|
}
|
|
}
|
|
|
|
unsigned int NativePskServerCb(WOLFSSL* ssl, const char* identity,
|
|
unsigned char* key, unsigned int max_key_len)
|
|
{
|
|
jint vmret = 0;
|
|
jlong retval = 0;
|
|
int usingSSLCallback = 0;
|
|
int needsDetach = 0; /* Should we explicitly detach? */
|
|
|
|
JNIEnv* jenv; /* JNI environment */
|
|
jclass excClass; /* class: WolfSSLJNIException */
|
|
|
|
static jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
|
|
jclass sessClass; /* WolfSSLSession class */
|
|
jfieldID ctxFid; /* WolfSSLSession->ctx fieldID */
|
|
jmethodID getCtxMethodId; /* WolfSSLSession->getAssCtxPtr() ID */
|
|
|
|
jfieldID internPskServerCbFid; /* WolfSSLContext->internPskServerCb ID */
|
|
jobject internPskServerCbObj; /* " -> internPskServerCb object */
|
|
|
|
jobject ctxRef; /* WolfSSLContext object */
|
|
jclass innerCtxClass; /* WolfSSLContext class */
|
|
jmethodID pskServerMethodId; /* internalPskServerCallback ID */
|
|
|
|
jstring identityString; /* String, for 'hint' */
|
|
jbyteArray keyArray; /* byte[] for key in/out */
|
|
|
|
/* Note: since this is called from C, not the JVM, we need to explicitly
|
|
* free all object refs with DeleteLocalRef() */
|
|
|
|
if (!g_vm || !ssl || !identity || !key) {
|
|
/* we can't throw an exception yet, so just return 0 (failure) */
|
|
return 0;
|
|
}
|
|
|
|
/* 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 0;
|
|
}
|
|
needsDetach = 1;
|
|
} else if (vmret != JNI_OK) {
|
|
return 0;
|
|
}
|
|
|
|
/* find exception class */
|
|
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 0;
|
|
}
|
|
|
|
/* get stored WolfSSLSession jobject */
|
|
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject((WOLFSSL*)ssl);
|
|
if (!g_cachedSSLObj) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession object reference in "
|
|
"NativePskServerCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLSession class from object */
|
|
sessClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
|
if (!sessClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLSession class reference in "
|
|
"NativePskServerCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* lookup WolfSSLContext private member fieldID */
|
|
ctxFid = (*jenv)->GetFieldID(jenv, sessClass, "ctx",
|
|
"Lcom/wolfssl/WolfSSLContext;");
|
|
if (!ctxFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext field ID in "
|
|
"NativePSKClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* find WolfSSLSession.getAssociatedContextPtr() method */
|
|
getCtxMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"getAssociatedContextPtr",
|
|
"()Lcom/wolfssl/WolfSSLContext;");
|
|
if (!getCtxMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get getAssociatedContextPtr() method ID in "
|
|
"NativePSKClientCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* get WolfSSLContext(ctx) object from Java WolfSSLSession object */
|
|
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
getCtxMethodId);
|
|
if (!ctxRef) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get WolfSSLContext object in NativePskServerCb");
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* get WolfSSLContext class reference from object */
|
|
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
|
|
if (!innerCtxClass) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native WolfSSLContext class reference in "
|
|
"NativePskServerCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* figure out if we need to call the CTX or SSL level callback */
|
|
|
|
/* 1. Get the internPskServerCb FieldID */
|
|
internPskServerCbFid = (*jenv)->GetFieldID(jenv, innerCtxClass,
|
|
"internPskServerCb",
|
|
"Lcom/wolfssl/WolfSSLPskServerCallback;");
|
|
if (!internPskServerCbFid) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Can't get native internPskServerCb field ID in "
|
|
"NativePskServerCb");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* 2. Get WolfSSLPskServerCallback object (or null) */
|
|
internPskServerCbObj = (*jenv)->GetObjectField(jenv, ctxRef,
|
|
internPskServerCbFid);
|
|
if (!internPskServerCbObj) {
|
|
printf("Using SSL level PSK Server callback!!!\n");
|
|
usingSSLCallback = 1;
|
|
}
|
|
|
|
if (usingSSLCallback == 1) {
|
|
/* WolfSSLSession level callback */
|
|
pskServerMethodId = (*jenv)->GetMethodID(jenv, sessClass,
|
|
"internalPskServerCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/lang/String;"
|
|
"[BJ)J");
|
|
} else {
|
|
/* WolfSSLContext level callback */
|
|
pskServerMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
|
|
"internalPskServerCallback",
|
|
"(Lcom/wolfssl/WolfSSLSession;Ljava/lang/String;"
|
|
"[BJ)J");
|
|
}
|
|
|
|
if (!pskServerMethodId) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error getting internalPskServerCallback method from JNI");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* create String to wrap 'identity' */
|
|
identityString = (*jenv)->NewStringUTF(jenv, identity);
|
|
if (!identityString) {
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
}
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error creating String for PSK client identity");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* create jbyteArray to hold received key */
|
|
keyArray = (*jenv)->NewByteArray(jenv, max_key_len);
|
|
if (!keyArray) {
|
|
(*jenv)->ThrowNew(jenv, excClass,
|
|
"Error creating jbyteArray for PSK server key");
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, identityString);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
|
|
/* call Java PSK server callback */
|
|
if (usingSSLCallback == 1) {
|
|
retval = (*jenv)->CallLongMethod(jenv, (jobject)(*g_cachedSSLObj),
|
|
pskServerMethodId, (jobject)(*g_cachedSSLObj), identityString,
|
|
keyArray, (jlong)max_key_len);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, identityString);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
} else {
|
|
retval = (*jenv)->CallLongMethod(jenv, ctxRef, pskServerMethodId,
|
|
(jobject)(*g_cachedSSLObj), identityString,
|
|
keyArray, (jlong)max_key_len);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, identityString);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (retval > 0) {
|
|
|
|
/* copy jbyteArray into char key array */
|
|
(*jenv)->GetByteArrayRegion(jenv, keyArray, 0, retval, (jbyte*)key);
|
|
if ((*jenv)->ExceptionOccurred(jenv)) {
|
|
(*jenv)->ExceptionDescribe(jenv);
|
|
(*jenv)->ExceptionClear(jenv);
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, identityString);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* delete local obj refs, detach JNIEnv from thread */
|
|
(*jenv)->DeleteLocalRef(jenv, ctxRef);
|
|
(*jenv)->DeleteLocalRef(jenv, identityString);
|
|
(*jenv)->DeleteLocalRef(jenv, keyArray);
|
|
if (needsDetach)
|
|
(*g_vm)->DetachCurrentThread(g_vm);
|
|
|
|
return retval;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLContext_usePskIdentityHint
|
|
(JNIEnv* jenv, jobject obj, jlong ctx, jstring hint)
|
|
{
|
|
jint ret;
|
|
const char* nativeHint;
|
|
|
|
if (!jenv || !ctx || !hint)
|
|
return SSL_FAILURE;
|
|
|
|
nativeHint = (*jenv)->GetStringUTFChars(jenv, hint, 0);
|
|
|
|
ret = (jint)wolfSSL_CTX_use_psk_identity_hint((WOLFSSL_CTX*)ctx,
|
|
nativeHint);
|
|
|
|
(*jenv)->ReleaseStringUTFChars(jenv, hint, nativeHint);
|
|
|
|
return ret;
|
|
}
|
|
|