JNI: add RSA-PSS sign/verify and RSA sign check PK callbacks

pull/338/head
Chris Conlon 2026-02-25 14:17:29 -07:00
parent b937eec507
commit 1aec153270
10 changed files with 1872 additions and 21 deletions

View File

@ -26,6 +26,8 @@
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include "com_wolfssl_WolfCryptRSA.h"
@ -214,6 +216,189 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc
return ret;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssSign
(JNIEnv* jenv, jobject jcl, jobject in, jlong inSz, jobject out, jintArray outSz, jint hash, jint mgf, jobject keyDer, jlong keySz)
{
#ifdef WC_RSA_PSS
int ret;
WC_RNG rng;
RsaKey myKey;
int rngInit = 0;
int keyInit = 0;
unsigned int idx = 0;
unsigned int tmpOut;
unsigned char* inBuf = NULL;
unsigned char* outBuf = NULL;
unsigned char* keyBuf = NULL;
enum wc_HashType hashType;
(void)jcl;
if ((inSz < 0) || (keySz < 0)) {
return -1;
}
inBuf = (*jenv)->GetDirectBufferAddress(jenv, in);
if (inBuf == NULL) {
printf("problem getting in buffer address\n");
return -1;
}
outBuf = (*jenv)->GetDirectBufferAddress(jenv, out);
if (outBuf == NULL) {
printf("problem getting out buffer address\n");
return -1;
}
keyBuf = (*jenv)->GetDirectBufferAddress(jenv, keyDer);
if (keyBuf == NULL) {
printf("problem getting key buffer address\n");
return -1;
}
hashType = wc_OidGetHash(hash);
if (hashType == WC_HASH_TYPE_NONE) {
printf("doPssSign: unsupported hash OID %d\n", hash);
return -1;
}
/* get output buffer size */
(*jenv)->GetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
ret = wc_InitRng(&rng);
if (ret != 0) {
printf("wc_InitRng failed, ret = %d\n", ret);
return ret;
}
rngInit = 1;
ret = wc_InitRsaKey(&myKey, NULL);
if (ret != 0) {
printf("wc_InitRsaKey failed, ret = %d\n", ret);
wc_FreeRng(&rng);
return ret;
}
keyInit = 1;
ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, (unsigned int)keySz);
if (ret == 0) {
ret = wc_RsaPSS_Sign(inBuf, (unsigned int)inSz, outBuf, tmpOut,
hashType, mgf, &myKey, &rng);
if (ret > 0) {
tmpOut = ret;
(*jenv)->SetIntArrayRegion(jenv, outSz, 0, 1, (jint*)&tmpOut);
ret = 0;
}
} else {
printf("wc_RsaPrivateKeyDecode failed, ret = %d\n", ret);
}
if (keyInit) {
wc_FreeRsaKey(&myKey);
}
if (rngInit) {
wc_FreeRng(&rng);
}
return ret;
#else
(void)jenv;
(void)jcl;
(void)in;
(void)inSz;
(void)out;
(void)outSz;
(void)hash;
(void)mgf;
(void)keyDer;
(void)keySz;
return (jint)NOT_COMPILED_IN;
#endif /* WC_RSA_PSS */
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssVerify
(JNIEnv* jenv, jobject jcl, jobject sig, jlong sigSz, jobject out, jlong outSz, jint hash, jint mgf, jobject keyDer, jlong keySz)
{
#ifdef WC_RSA_PSS
int ret;
RsaKey myKey;
unsigned int idx = 0;
unsigned char* sigBuf = NULL;
unsigned char* outBuf = NULL;
unsigned char* keyBuf = NULL;
enum wc_HashType hashType;
(void)jcl;
if ((sigSz < 0) || (keySz < 0) || (outSz < 0)) {
return -1;
}
sigBuf = (*jenv)->GetDirectBufferAddress(jenv, sig);
if (sigBuf == NULL) {
printf("problem getting sig buffer address\n");
return -1;
}
outBuf = (*jenv)->GetDirectBufferAddress(jenv, out);
if (outBuf == NULL) {
printf("problem getting out buffer address\n");
return -1;
}
keyBuf = (*jenv)->GetDirectBufferAddress(jenv, keyDer);
if (keyBuf == NULL) {
printf("problem getting key buffer address\n");
return -1;
}
hashType = wc_OidGetHash(hash);
if (hashType == WC_HASH_TYPE_NONE) {
printf("doPssVerify: unsupported hash OID %d\n", hash);
return -1;
}
ret = wc_InitRsaKey(&myKey, NULL);
if (ret != 0) {
printf("wc_InitRsaKey failed, ret = %d\n", ret);
return ret;
}
/* Try private key decode first (sign check receives the server private),
* fall back to public key decode (verify receives the peer public) */
ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, (unsigned int)keySz);
if (ret != 0) {
idx = 0;
ret = wc_RsaPublicKeyDecode(keyBuf, &idx, &myKey, (unsigned int)keySz);
}
if (ret == 0) {
ret = wc_RsaPSS_Verify(sigBuf, (unsigned int)sigSz, outBuf,
(unsigned int)outSz, hashType, mgf, &myKey);
if (ret < 0) {
printf("wc_RsaPSS_Verify failed, ret = %d\n", ret);
}
} else {
printf("RSA key decode failed, ret = %d\n", ret);
}
wc_FreeRsaKey(&myKey);
return ret;
#else
(void)jenv;
(void)jcl;
(void)sig;
(void)sigSz;
(void)out;
(void)outSz;
(void)hash;
(void)mgf;
(void)keyDer;
(void)keySz;
return (jint)NOT_COMPILED_IN;
#endif /* WC_RSA_PSS */
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doDec
(JNIEnv* jenv, jobject jcl, jobject in, jlong inSz, jobject out,
jlong outSz, jobject keyDer, jlong keySz)

View File

@ -39,6 +39,22 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doEnc
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doDec
(JNIEnv *, jobject, jobject, jlong, jobject, jlong, jobject, jlong);
/*
* Class: com_wolfssl_WolfCryptRSA
* Method: doPssSign
* Signature: (Ljava/nio/ByteBuffer;JLjava/nio/ByteBuffer;[IIILjava/nio/ByteBuffer;J)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssSign
(JNIEnv *, jobject, jobject, jlong, jobject, jintArray, jint, jint, jobject, jlong);
/*
* Class: com_wolfssl_WolfCryptRSA
* Method: doPssVerify
* Signature: (Ljava/nio/ByteBuffer;JLjava/nio/ByteBuffer;JIILjava/nio/ByteBuffer;J)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfCryptRSA_doPssVerify
(JNIEnv *, jobject, jobject, jlong, jobject, jlong, jint, jint, jobject, jlong);
#ifdef __cplusplus
}
#endif

View File

@ -70,9 +70,19 @@ int NativeEccSharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey,
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 NativeRsaPssSignCb(WOLFSSL* ssl,
const unsigned char* in, unsigned int inSz, unsigned char* out,
unsigned int* outSz, int hash, int mgf, 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 NativeRsaSignCheckCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz,
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
void* ctx);
int NativeRsaPssSignCheckCb(WOLFSSL* ssl, unsigned char* sig,
unsigned int sigSz, unsigned char** out, int hash, int mgf,
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);
@ -4152,6 +4162,324 @@ int NativeRsaSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
#endif /* HAVE_PK_CALLBACKS */
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaPssSignCb
(JNIEnv* jenv, jobject jcl, jlong ctxPtr)
{
WOLFSSL_CTX* ctx = (WOLFSSL_CTX*)(uintptr_t)ctxPtr;
jclass excClass = NULL;
(void)jcl;
/* find exception class */
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
return;
}
#if defined(HAVE_PK_CALLBACKS) && defined(WC_RSA_PSS) && !defined(NO_RSA)
if (ctx != NULL) {
wolfSSL_CTX_SetRsaPssSignCb(ctx, NativeRsaPssSignCb);
} else {
(*jenv)->ThrowNew(jenv, excClass,
"Input WolfSSLContext object was null when setting RsaPssSignCb");
}
#else
(void)ctx;
(*jenv)->ThrowNew(jenv, excClass,
"wolfSSL not compiled with PK Callback support and/or RSA-PSS support");
#endif
}
#if defined(HAVE_PK_CALLBACKS) && defined(WC_RSA_PSS) && !defined(NO_RSA)
int NativeRsaPssSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
unsigned char* out, unsigned int* outSz, int hash, int mgf,
const unsigned char* keyDer, unsigned int keySz, void* ctx)
{
jint retval = 0;
jint vmret = 0;
JNIEnv* jenv;
jclass excClass;
int needsDetach = 0;
static jobject* g_cachedSSLObj;
jclass sessClass;
jfieldID ctxFid;
jmethodID getCtxMethodId;
jobject ctxRef;
jclass innerCtxClass;
jmethodID rsaPssSignMethodId;
jintArray j_outSz;
jobject inBB = NULL;
jobject outBB = NULL;
jobject keyDerBB = NULL;
jint tmpVal = 0;
(void)ctx;
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 NativeRsaPssSignCb");
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 NativeRsaPssSignCb");
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 NativeRsaPssSignCb");
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 NativeRsaPssSignCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* get WolfSSLContext ctx object from Java land */
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
getCtxMethodId);
CheckException(jenv);
if (!ctxRef) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get WolfSSLContext object in NativeRsaPssSignCb");
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 NativeRsaPssSignCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call internal RSA-PSS sign callback */
rsaPssSignMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
"internalRsaPssSignCallback", "(Lcom/wolfssl/WolfSSLSession;"
"Ljava/nio/ByteBuffer;J" "Ljava/nio/ByteBuffer;[III"
"Ljava/nio/ByteBuffer;J)I");
if (!rsaPssSignMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting internalRsaPssSignCallback method from JNI");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'in' */
inBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)in, inSz);
if (!inBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSign in ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'out' */
outBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)out, *outSz);
if (!outBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSign out ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'keyDer' */
keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer, keySz);
if (!keyDerBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSign keyDer ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create jintArray to hold outSz, used as an output parameter from Java,
* only needs to have 1 element */
j_outSz = (*jenv)->NewIntArray(jenv, 1);
if (!j_outSz) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create result intArray in RsaPssSignCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* copy outSz into j_outSz */
(*jenv)->SetIntArrayRegion(jenv, j_outSz, 0, 1, (jint*)outSz);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set j_outSz intArray in RsaPssSignCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
(*jenv)->DeleteLocalRef(jenv, j_outSz);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call Java callback, java layer handles adding CTX ref */
retval = (*jenv)->CallIntMethod(jenv, ctxRef, rsaPssSignMethodId,
(jobject)(*g_cachedSSLObj), inBB, (jlong)inSz, outBB, j_outSz, hash,
mgf, keyDerBB, (jlong)keySz);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*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 */
(*jenv)->GetIntArrayRegion(jenv, j_outSz, 0, 1, &tmpVal);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
(*jenv)->DeleteLocalRef(jenv, j_outSz);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
*outSz = tmpVal;
}
/* delete local refs */
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, inBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
(*jenv)->DeleteLocalRef(jenv, j_outSz);
/* detach JNIEnv from thread */
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return retval;
}
#endif /* HAVE_PK_CALLBACKS && WC_RSA_PSS && !NO_RSA */
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaVerifyCb
(JNIEnv* jenv, jobject jcl, jlong ctxPtr)
{
@ -4399,13 +4727,533 @@ int NativeRsaVerifyCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz,
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
/* detach JNIEnv from thread */
(*g_vm)->DetachCurrentThread(g_vm);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return retval;
}
#endif /* HAVE_PK_CALLBACKS */
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaSignCheckCb
(JNIEnv* jenv, jobject jcl, jlong ctxPtr)
{
WOLFSSL_CTX* ctx = (WOLFSSL_CTX*)(uintptr_t)ctxPtr;
jclass excClass = NULL;
(void)jcl;
/* find exception class */
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
return;
}
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
if (ctx != NULL) {
/* set RSA sign check callback */
wolfSSL_CTX_SetRsaSignCheckCb(ctx, NativeRsaSignCheckCb);
} else {
(*jenv)->ThrowNew(jenv, excClass,
"Input WolfSSLContext object was null when setting RsaSignCheckCb");
}
#else
(void)ctx;
(*jenv)->ThrowNew(jenv, excClass,
"wolfSSL not compiled with PK Callback and/or RSA support");
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaPssSignCheckCb
(JNIEnv* jenv, jobject jcl, jlong ctxPtr)
{
WOLFSSL_CTX* ctx = (WOLFSSL_CTX*)(uintptr_t)ctxPtr;
jclass excClass = NULL;
(void)jcl;
/* find exception class */
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
return;
}
#if defined(HAVE_PK_CALLBACKS) && defined(WC_RSA_PSS) && !defined(NO_RSA)
if (ctx != NULL) {
/* set RSA-PSS sign check callback */
wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, NativeRsaPssSignCheckCb);
} else {
(*jenv)->ThrowNew(jenv, excClass, "Input WolfSSLContext object was "
"null when setting RsaPssSignCheckCb");
}
#else
(void)ctx;
(*jenv)->ThrowNew(jenv, excClass,
"wolfSSL not compiled with PK Callback and/or RSA-PSS support");
#endif
}
#if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA)
int NativeRsaSignCheckCb(WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz,
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
void* ctx)
{
jint retval = 0;
jint vmret = 0;
JNIEnv* jenv;
jclass excClass;
int needsDetach = 0;
static jobject* g_cachedSSLObj;
jclass sessClass;
jfieldID ctxFid;
jmethodID getCtxMethodId;
jobject ctxRef;
jclass innerCtxClass;
jmethodID rsaSignCheckMethodId;
jobject sigBB = NULL;
jobject outBB = NULL;
jobject keyDerBB = NULL;
(void)ctx;
if (!g_vm || !ssl || !sig || !out || !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 NativeRsaSignCheckCb");
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 NativeRsaSignCheckCb");
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 NativeRsaSignCheckCb");
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 NativeRsaSignCheckCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* get WolfSSLContext ctx object from Java land */
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
getCtxMethodId);
CheckException(jenv);
if (!ctxRef) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get WolfSSLContext object in NativeRsaSignCheckCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* get WolfSSLContext class reference */
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
if (!innerCtxClass) {
(*jenv)->ThrowNew(jenv, excClass, "Can't get native WolfSSLContext "
"class reference in NativeRsaSignCheckCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call internal RSA sign check callback */
rsaSignCheckMethodId = (*jenv)->GetMethodID(jenv, innerCtxClass,
"internalRsaSignCheckCallback", "(Lcom/wolfssl/WolfSSLSession;"
"Ljava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J"
"Ljava/nio/ByteBuffer;J)I");
if (!rsaSignCheckMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting internalRsaSignCheckCallback method from JNI");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'sig' */
sigBB = (*jenv)->NewDirectByteBuffer(jenv, sig, sigSz);
if (!sigBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaSignCheck sig ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'out', since doing this inline, outBB points
* to the same address as sigBB */
outBB = (*jenv)->NewDirectByteBuffer(jenv, sig, sigSz);
if (!outBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaSignCheck out ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'keyDer' */
keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer, keySz);
if (!keyDerBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaSignCheck keyDer ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call Java callback, java layer handles adding CTX ref */
retval = (*jenv)->CallIntMethod(jenv, ctxRef, rsaSignCheckMethodId,
(jobject)(*g_cachedSSLObj), sigBB, (jlong)sigSz, outBB, (jlong)sigSz,
keyDerBB, (jlong)keySz);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
/* point out* to the beginning of decrypted buffer */
if (retval > 0) {
*out = sig;
}
/* delete local refs */
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
/* detach JNIEnv from thread */
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return retval;
}
#endif /* HAVE_PK_CALLBACKS && !NO_RSA */
#if defined(HAVE_PK_CALLBACKS) && defined(WC_RSA_PSS) && !defined(NO_RSA)
int NativeRsaPssSignCheckCb(WOLFSSL* ssl, unsigned char* sig,
unsigned int sigSz, unsigned char** out, int hash, int mgf,
const unsigned char* keyDer, unsigned int keySz, void* ctx)
{
jint retval = 0;
jint vmret = 0;
JNIEnv* jenv;
jclass excClass;
int needsDetach = 0;
static jobject* g_cachedSSLObj;
jclass sessClass;
jfieldID ctxFid;
jmethodID getCtxMethodId;
jobject ctxRef;
jclass innerCtxClass;
jmethodID rsaPssSignCheckMethodId;
jobject sigBB = NULL;
jobject outBB = NULL;
jobject keyDerBB = NULL;
(void)ctx;
if (!g_vm || !ssl || !sig || !out || !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 NativeRsaPssSignCheckCb");
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 NativeRsaPssSignCheckCb");
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 NativeRsaPssSignCheckCb");
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 NativeRsaPssSignCheckCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* get WolfSSLContext ctx object from Java land */
ctxRef = (*jenv)->CallObjectMethod(jenv, (jobject)(*g_cachedSSLObj),
getCtxMethodId);
CheckException(jenv);
if (!ctxRef) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get WolfSSLContext object in NativeRsaPssSignCheckCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* get WolfSSLContext class reference */
innerCtxClass = (*jenv)->GetObjectClass(jenv, ctxRef);
if (!innerCtxClass) {
(*jenv)->ThrowNew(jenv, excClass, "Can't get native WolfSSLContext "
"class reference in NativeRsaPssSignCheckCb");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call internal RSA-PSS sign check callback */
rsaPssSignCheckMethodId = (*jenv)->GetMethodID(jenv,
innerCtxClass, "internalRsaPssSignCheckCallback",
"(Lcom/wolfssl/WolfSSLSession;Ljava/nio/ByteBuffer;J"
"Ljava/nio/ByteBuffer;JIILjava/nio/ByteBuffer;J)I");
if (!rsaPssSignCheckMethodId) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting internalRsaPssSignCheckCallback method from JNI");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'sig' */
sigBB = (*jenv)->NewDirectByteBuffer(jenv, sig, sigSz);
if (!sigBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSignCheck sig ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'out', since doing inline, outBB points to
* the same address as sigBB */
outBB = (*jenv)->NewDirectByteBuffer(jenv, sig, sigSz);
if (!outBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSignCheck out ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* create ByteBuffer to wrap 'keyDer' */
keyDerBB = (*jenv)->NewDirectByteBuffer(jenv, (void*)keyDer, keySz);
if (!keyDerBB) {
(*jenv)->ThrowNew(jenv, excClass,
"Failed to create rsaPssSignCheck keyDer ByteBuffer");
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return -1;
}
/* call Java callback, java layer handles adding CTX ref */
retval = (*jenv)->CallIntMethod(jenv, ctxRef, rsaPssSignCheckMethodId,
(jobject)(*g_cachedSSLObj), sigBB, (jlong)sigSz, outBB, (jlong)sigSz,
hash, mgf, keyDerBB, (jlong)keySz);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
/* point out* to the beginning of decrypted buffer */
if (retval > 0) {
*out = sig;
}
/* delete local refs */
(*jenv)->DeleteLocalRef(jenv, ctxRef);
(*jenv)->DeleteLocalRef(jenv, sigBB);
(*jenv)->DeleteLocalRef(jenv, outBB);
(*jenv)->DeleteLocalRef(jenv, keyDerBB);
/* detach JNIEnv from thread */
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return retval;
}
#endif /* HAVE_PK_CALLBACKS && WC_RSA_PSS && !NO_RSA */
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaEncCb
(JNIEnv* jenv, jobject jcl, jlong ctxPtr)
{

View File

@ -327,6 +327,14 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setEccSharedSecretCb
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaSignCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLContext
* Method: setRsaPssSignCb
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaPssSignCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLContext
* Method: setRsaVerifyCb
@ -335,6 +343,22 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaSignCb
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaVerifyCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLContext
* Method: setRsaSignCheckCb
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaSignCheckCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLContext
* Method: setRsaPssSignCheckCb
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLContext_setRsaPssSignCheckCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLContext
* Method: setRsaEncCb

View File

@ -64,6 +64,8 @@ infer --fail-on-issue run -- javac \
src/java/com/wolfssl/WolfSSLPskServerCallback.java \
src/java/com/wolfssl/WolfSSLRsaDecCallback.java \
src/java/com/wolfssl/WolfSSLRsaEncCallback.java \
src/java/com/wolfssl/WolfSSLRsaPssSignCallback.java \
src/java/com/wolfssl/WolfSSLRsaPssVerifyCallback.java \
src/java/com/wolfssl/WolfSSLRsaSignCallback.java \
src/java/com/wolfssl/WolfSSLRsaVerifyCallback.java \
src/java/com/wolfssl/WolfSSLSession.java \

View File

@ -102,5 +102,42 @@ public class WolfCryptRSA {
*/
public native int doDec(ByteBuffer in, long inSz, ByteBuffer out,
long outSz, ByteBuffer keyDer, long keySz);
/**
* RSA-PSS sign, wraps native wolfCrypt operation.
*
* @param in input buffer to be signed
* @param inSz size of input buffer, bytes
* @param out output for generated signature
* @param outSz [IN/OUT] size of output buffer on input, size of
* generated signature on output
* @param hash hash algorithm type
* @param mgf mask generation function identifier
* @param key DER formatted RSA key to be used for signing
* @param keySz size of key, bytes
*
* @return 0 on success, negative on error.
*/
public native int doPssSign(ByteBuffer in, long inSz,
ByteBuffer out, int[] outSz, int hash, int mgf,
ByteBuffer key, long keySz);
/**
* RSA-PSS verify, wraps native wolfCrypt operation.
*
* @param sig input signature to verify
* @param sigSz size of input signature, bytes
* @param out output buffer to place verified data
* @param outSz size of output buffer, bytes
* @param hash hash algorithm type
* @param mgf mask generation function identifier
* @param keyDer public key used for verify, DER formatted
* @param keySz size of public key, bytes
*
* @return size of returned data on success, negative on error.
*/
public native int doPssVerify(ByteBuffer sig, long sigSz,
ByteBuffer out, long outSz, int hash, int mgf,
ByteBuffer keyDer, long keySz);
}

View File

@ -59,6 +59,11 @@ public class WolfSSLContext {
/* user-registered RSA sign/verify callbacks */
private WolfSSLRsaSignCallback internRsaSignCb = null;
private WolfSSLRsaVerifyCallback internRsaVerifyCb = null;
private WolfSSLRsaVerifyCallback internRsaSignCheckCb = null;
/* user-registered RSA-PSS sign/verify callbacks */
private WolfSSLRsaPssSignCallback internRsaPssSignCb = null;
private WolfSSLRsaPssVerifyCallback internRsaPssSignCheckCb = null;
/* user-registered RSA enc/dec callbacks */
private WolfSSLRsaEncCallback internRsaEncCb = null;
@ -280,14 +285,53 @@ public class WolfSSLContext {
}
private int internalRsaVerifyCallback(WolfSSLSession ssl, ByteBuffer sig,
long sigSz, ByteBuffer out, long outSz, ByteBuffer keyDer,
long keySz)
long sigSz, ByteBuffer out, long outSz, ByteBuffer keyDer,
long keySz)
{
int ret;
/* call user-registered rsa verify method */
ret = internRsaVerifyCb.rsaVerifyCallback(ssl, sig, sigSz, out,
outSz, keyDer, keySz, ssl.getRsaVerifyCtx());
ret = internRsaVerifyCb.rsaVerifyCallback(ssl, sig, sigSz, out, outSz,
keyDer, keySz, ssl.getRsaVerifyCtx());
return ret;
}
private int internalRsaSignCheckCallback(WolfSSLSession ssl, ByteBuffer sig,
long sigSz, ByteBuffer out, long outSz, ByteBuffer keyDer,
long keySz)
{
int ret;
/* call user-registered rsa sign check method */
ret = internRsaSignCheckCb.rsaVerifyCallback(ssl, sig, sigSz, out,
outSz, keyDer, keySz, ssl.getRsaVerifyCtx());
return ret;
}
private int internalRsaPssSignCallback(WolfSSLSession ssl, ByteBuffer in,
long inSz, ByteBuffer out, int[] outSz, int hash, int mgf,
ByteBuffer keyDer, long keySz)
{
int ret;
/* call user-registered rsa pss sign method */
ret = internRsaPssSignCb.rsaPssSignCallback(ssl, in, inSz, out, outSz,
hash, mgf, keyDer, keySz, ssl.getRsaSignCtx());
return ret;
}
private int internalRsaPssSignCheckCallback(WolfSSLSession ssl,
ByteBuffer sig, long sigSz, ByteBuffer out, long outSz, int hash,
int mgf, ByteBuffer keyDer, long keySz)
{
int ret;
/* call user-registered rsa pss verify method */
ret = internRsaPssSignCheckCb.rsaPssVerifyCallback(ssl, sig, sigSz,
out, outSz, hash, mgf, keyDer, keySz, ssl.getRsaVerifyCtx());
return ret;
}
@ -406,7 +450,10 @@ public class WolfSSLContext {
private native void setEccVerifyCb(long ctx);
private native void setEccSharedSecretCb(long ctx);
private native void setRsaSignCb(long ctx);
private native void setRsaPssSignCb(long ctx);
private native void setRsaVerifyCb(long ctx);
private native void setRsaSignCheckCb(long ctx);
private native void setRsaPssSignCheckCb(long ctx);
private native void setRsaEncCb(long ctx);
private native void setRsaDecCb(long ctx);
private native void setPskClientCb(long ctx);
@ -1933,23 +1980,128 @@ public class WolfSSLContext {
}
/**
* Allows caller to set the Public Key Callback for RSA Public Encrypt.
* The callback should return 0 for success or negative value for an
* error. The <b>ssl</b> and <b>ctx</b> objects are available for
* the users convenience. <b>in</b> is the input buffer to encrypt while
* <b>inSz</b> denotes the length of the input. <b>out</b> is the output
* buffer where the result of the encryption should be stored. <b>outSz</b>
* is an input/output variable that specifies the size of the output
* buffer upon invocation and the actual size of the encryption should be
* stored there before returning. <b>keyDer</b> is the RSA Public key in
* ASN1 format and <b>keySz</b> is the length of the key in bytes. An
* example callback can be found in examples/MyRsaEncCallback.java.
* Allows caller to set the Public Key Callback for RSA Sign Check (verify
* a signature that was just created). Uses the same callback signature as
* RSA Verify. The callback should return the number of plaintext bytes
* for success or a negative value for an error.
*
* @param callback object to be registered as the RSA public encrypt
* callback for the WolfSSL context. The signature of
* this object and corresponding method must match that
* as shown in WolfSSLRsaEncCallback.java, inside
* rsaEncCallback().
* @param callback object to be registered as the RSA sign check callback
* for the WolfSSL context. The signature of this object
* and corresponding method must match that as shown in
* WolfSSLRsaVerifyCallback.java, inside
* rsaVerifyCallback().
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
* @see WolfSSLSession#setRsaVerifyCtx(Object)
*/
public synchronized void setRsaSignCheckCb(
WolfSSLRsaVerifyCallback callback) throws IllegalStateException,
WolfSSLJNIException {
confirmObjectIsActive();
synchronized (ctxLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, getContextPtr(),
() -> "entered setRsaSignCheckCb(" + callback + ")");
/* set rsa sign check callback */
internRsaSignCheckCb = callback;
/* register internal callback with native lib */
setRsaSignCheckCb(getContextPtr());
}
}
/**
* Allows caller to set the Public Key Callback for RSA-PSS Signing. The
* callback should return 0 for success or a negative value for an error.
* <b>in</b> is the input buffer to sign and <b>inSz</b> denotes the length
* of the input. <b>out</b> is the output buffer where the result of the
* signature should be stored. <b>outSz</b> is an input/output variable that
* specifies the size of the output buffer upon invocation. <b>hash</b> and
* <b>mgf</b> specify the hash algorithm and mask generation function.
* <b>keyDer</b> is the RSA Private key in ASN1 format and <b>keySz</b> is
* the length of the key in bytes.
*
* @param callback object to be registered as the RSA-PSS sign callback for
* the WolfSSL context. The signature of this object and
* corresponding method must match that as shown in
* WolfSSLRsaPssSignCallback.java.
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
* @see WolfSSLSession#setRsaSignCtx(Object)
*/
public synchronized void setRsaPssSignCb(WolfSSLRsaPssSignCallback callback)
throws IllegalStateException, WolfSSLJNIException {
confirmObjectIsActive();
synchronized (ctxLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, getContextPtr(),
() -> "entered setRsaPssSignCb(" + callback + ")");
/* set rsa pss sign callback */
internRsaPssSignCb = callback;
/* register internal callback with native lib */
setRsaPssSignCb(getContextPtr());
}
}
/**
* Allows caller to set the Public Key Callback for RSA-PSS Sign Check
* (verify a PSS signature that was just created). The callback should
* return the number of plaintext bytes for success or a negative value
* for an error. <b>hash</b> and <b>mgf</b> specify the hash algorithm and
* mask generation function.
*
* @param callback object to be registered as the RSA-PSS sign check
* callback for the WolfSSL context. The signature of
* this object and corresponding method must match that as
* shown in WolfSSLRsaPssVerifyCallback.java.
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI error
* @see WolfSSLSession#setRsaVerifyCtx(Object)
*/
public synchronized void setRsaPssSignCheckCb(
WolfSSLRsaPssVerifyCallback callback) throws IllegalStateException,
WolfSSLJNIException {
confirmObjectIsActive();
synchronized (ctxLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, getContextPtr(),
() -> "entered setRsaPssSignCheckCb(" + callback + ")");
/* set rsa pss sign check callback */
internRsaPssSignCheckCb = callback;
/* register internal callback with native lib */
setRsaPssSignCheckCb(getContextPtr());
}
}
/**
* Allows caller to set the Public Key Callback for RSA Public Encrypt.
* The callback should return 0 for success or negative value for an error.
* The <b>ssl</b> and <b>ctx</b> objects are available for the users
* convenience. <b>in</b> is the input buffer to encrypt while <b>inSz</b>
* denotes the length of the input. <b>out</b> is the output buffer where
* the result of the encryption should be stored. <b>outSz</b> is an
* input/output variable that specifies the size of the output buffer upon
* invocation and the actual size of the encryption should be stored there
* before returning. <b>keyDer</b> is the RSA Public key in ASN1 format
* and <b>keySz</b> is the length of the key in bytes. An example callback
* can be found in examples/MyRsaEncCallback.java.
*
* @param callback object to be registered as the RSA public encrypt
* callback for the WolfSSL context. The signature of
* this object and corresponding method must match that as
* shown in WolfSSLRsaEncCallback.java, inside
* rsaEncCallback().
* @throws IllegalStateException WolfSSLContext has been freed
* @throws WolfSSLJNIException Internal JNI exception
* @see WolfSSLSession#setRsaEncCtx(Object)

View File

@ -0,0 +1,66 @@
/* WolfSSLRsaPssSignCallback.java
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
package com.wolfssl;
import java.nio.ByteBuffer;
/**
* wolfSSL RSA-PSS Signing Callback Interface.
* This interface specifies how applications should implement the RSA-PSS
* signing callback class to be used by wolfSSL.
* <p>
* After implementing this interface, it should be passed as a parameter to the
* {@link WolfSSLContext#setRsaPssSignCb(WolfSSLRsaPssSignCallback)
* WolfSSLContext.setRsaPssSignCb()} method to be registered with the native
* wolfSSL library.
*
* @author wolfSSL
*/
public interface WolfSSLRsaPssSignCallback {
/**
* RSA-PSS signing callback method.
* This method acts as RSA-PSS signing callback.
*
* @param ssl the current SSL session object from which the callback was
* initiated.
* @param in input buffer to sign
* @param inSz length of the input, <b>in</b>
* @param out output buffer where the result of the signature should be
* stored.
* @param outSz input/output variable that specifies the size of the output
* buffer upon invocation. The actual size of the signature
* should be stored there before returning. Use the first
* element of the array for storage.
* @param hash hash algorithm type
* @param mgf mask generation function
* @param keyDer RSA Private key in ASN1 format
* @param keySz length of the key, <b>keyDer</b>, in bytes
* @param ctx custom user-registered RSA-PSS signing context
* @return <b><code>0</code></b> upon success, otherwise a negative
* value on error.
*/
public int rsaPssSignCallback(WolfSSLSession ssl, ByteBuffer in, long inSz,
ByteBuffer out, int[] outSz, int hash, int mgf, ByteBuffer keyDer,
long keySz, Object ctx);
}

View File

@ -0,0 +1,63 @@
/* WolfSSLRsaPssVerifyCallback.java
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
package com.wolfssl;
import java.nio.ByteBuffer;
/**
* wolfSSL RSA-PSS Verification Callback Interface.
* This interface specifies how applications should implement the RSA-PSS
* verification callback class to be used by wolfSSL.
* <p>
* After implementing this interface, it should be passed as a parameter to the
* {@link WolfSSLContext#setRsaPssSignCheckCb(WolfSSLRsaPssVerifyCallback)
* WolfSSLContext.setRsaPssSignCheckCb()} method to be registered with the
* native wolfSSL library.
*
* @author wolfSSL
*/
public interface WolfSSLRsaPssVerifyCallback {
/**
* RSA-PSS verification callback method.
* This method acts as RSA-PSS verification callback.
*
* @param ssl the current SSL session object from which the callback
* was initiated.
* @param sig the signature to verify
* @param sigSz length of the signature, <b>sig</b>
* @param out the verification/output buffer after the decryption
* process and padding.
* @param outSz size of the output buffer, <b>out</b>
* @param hash hash algorithm type
* @param mgf mask generation function
* @param keyDer the RSA Public key in ASN1 format
* @param keySz the length of the key, <b>keyDer</b>, in bytes
* @param ctx custom user-registered RSA-PSS verify context
* @return the number of plaintext bytes on success, otherwise a
* negative value on error.
*/
public int rsaPssVerifyCallback(WolfSSLSession ssl, ByteBuffer sig,
long sigSz, ByteBuffer out, long outSz, int hash, int mgf,
ByteBuffer keyDer, long keySz, Object ctx);
}

View File

@ -25,6 +25,18 @@ import org.junit.Test;
import org.junit.BeforeClass;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLContext;
import com.wolfssl.WolfSSLException;
@ -32,6 +44,11 @@ import com.wolfssl.WolfSSLJNIException;
import com.wolfssl.WolfSSLPskClientCallback;
import com.wolfssl.WolfSSLPskServerCallback;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLRsaSignCallback;
import com.wolfssl.WolfSSLRsaVerifyCallback;
import com.wolfssl.WolfSSLRsaPssSignCallback;
import com.wolfssl.WolfSSLRsaPssVerifyCallback;
import com.wolfssl.WolfCryptRSA;
public class WolfSSLContextTest {
@ -40,6 +57,8 @@ public class WolfSSLContextTest {
public static String cliCert = "examples/certs/client-cert.pem";
public static String cliKey = "examples/certs/client-key.pem";
public static String svrCert = "examples/certs/server-cert.pem";
public static String svrKey = "examples/certs/server-key.pem";
public static String svrCertEcc = "examples/certs/server-ecc.pem";
public static String caCert = "examples/certs/ca-cert.pem";
public static String dhParams = "examples/certs/dh2048.pem";
@ -63,6 +82,8 @@ public class WolfSSLContextTest {
cliCert = WolfSSLTestCommon.getPath(cliCert);
cliKey = WolfSSLTestCommon.getPath(cliKey);
svrCert = WolfSSLTestCommon.getPath(svrCert);
svrKey = WolfSSLTestCommon.getPath(svrKey);
svrCertEcc = WolfSSLTestCommon.getPath(svrCertEcc);
caCert = WolfSSLTestCommon.getPath(caCert);
dhParams = WolfSSLTestCommon.getPath(dhParams);
@ -80,6 +101,7 @@ public class WolfSSLContextTest {
test_WolfSSLContext_set1SigAlgsList();
test_WolfSSLContext_setMinRSAKeySize();
test_WolfSSLContext_setMinECCKeySize();
test_WolfSSLContext_rsaCbHandshake();
test_WolfSSLContext_free();
}
@ -735,6 +757,442 @@ public class WolfSSLContextTest {
System.out.println("\t\t... passed");
}
/* Context object shared between RSA sign/verify callbacks, tracks whether
* callback was invoked during handshake */
class TestRsaCbCtx
{
public boolean called = false;
}
class TestRsaSignCb implements WolfSSLRsaSignCallback
{
public int rsaSignCallback(WolfSSLSession ssl, ByteBuffer in, long inSz,
ByteBuffer out, int[] outSz, ByteBuffer keyDer, long keySz,
Object ctx) {
TestRsaCbCtx myCtx = (TestRsaCbCtx)ctx;
myCtx.called = true;
WolfCryptRSA rsa = new WolfCryptRSA();
return rsa.doSign(in, inSz, out, outSz, keyDer, keySz);
}
}
class TestRsaVerifyCb implements WolfSSLRsaVerifyCallback
{
public int rsaVerifyCallback(WolfSSLSession ssl, ByteBuffer sig,
long sigSz, ByteBuffer out, long outSz, ByteBuffer keyDer,
long keySz, Object ctx) {
TestRsaCbCtx myCtx = (TestRsaCbCtx)ctx;
myCtx.called = true;
WolfCryptRSA rsa = new WolfCryptRSA();
return rsa.doVerify(sig, sigSz, out, outSz, keyDer, keySz);
}
}
class TestRsaPssSignCb implements WolfSSLRsaPssSignCallback
{
public int rsaPssSignCallback(WolfSSLSession ssl, ByteBuffer in,
long inSz, ByteBuffer out, int[] outSz, int hash, int mgf,
ByteBuffer keyDer, long keySz, Object ctx) {
TestRsaCbCtx myCtx = (TestRsaCbCtx)ctx;
myCtx.called = true;
WolfCryptRSA rsa = new WolfCryptRSA();
return rsa.doPssSign(in, inSz, out, outSz, hash, mgf, keyDer,
keySz);
}
}
class TestRsaPssVerifyCb implements WolfSSLRsaPssVerifyCallback
{
public int rsaPssVerifyCallback(WolfSSLSession ssl, ByteBuffer sig,
long sigSz, ByteBuffer out, long outSz, int hash, int mgf,
ByteBuffer keyDer, long keySz, Object ctx) {
TestRsaCbCtx myCtx = (TestRsaCbCtx)ctx;
myCtx.called = true;
WolfCryptRSA rsa = new WolfCryptRSA();
return rsa.doPssVerify(sig, sigSz, out, outSz, hash, mgf, keyDer,
keySz);
}
}
/**
* Helper to create and configure a WolfSSLContext with cert, key, and CA
* for handshake tests.
*/
private WolfSSLContext createCtx(String certPath, String keyPath,
String caPath, long method) throws Exception {
int ret;
WolfSSLContext c = new WolfSSLContext(method);
ret = c.useCertificateChainFile(certPath);
if (ret != WolfSSL.SSL_SUCCESS) {
c.free();
throw new Exception("Failed to load cert: " + certPath);
}
ret = c.usePrivateKeyFile(keyPath, WolfSSL.SSL_FILETYPE_PEM);
if (ret != WolfSSL.SSL_SUCCESS) {
c.free();
throw new Exception("Failed to load key: " + keyPath);
}
ret = c.loadVerifyLocations(caPath, null);
if (ret != WolfSSL.SSL_SUCCESS) {
c.free();
throw new Exception("Failed to load CA: " + caPath);
}
return c;
}
public void test_WolfSSLContext_rsaCbHandshake() {
System.out.print("\trsaCbHandshake()");
if (!WolfSSL.RsaEnabled() || !WolfSSL.FileSystemEnabled()) {
System.out.println("\t\t... skipped");
return;
}
/* TLS 1.2 handshake with RSA PK callbacks */
rsaCbHandshakeTls12();
/* TLS 1.3 handshake with RSA-PSS PK callbacks */
if (WolfSSL.TLSv13Enabled() && WolfSSL.RsaPssEnabled()) {
rsaCbHandshakeTls13();
}
System.out.println("\t\t... passed");
}
private void rsaCbHandshakeTls12() {
WolfSSLContext srvCtx = null;
WolfSSLContext cliCtx = null;
ServerSocket srvSocket = null;
ExecutorService es = null;
Socket cliSock = null;
WolfSSLSession cliSes = null;
try {
srvCtx = createCtx(svrCert, svrKey, caCert,
WolfSSL.TLSv1_2_ServerMethod());
cliCtx = createCtx(cliCert, cliKey, caCert,
WolfSSL.TLSv1_2_ClientMethod());
/* Register server-side RSA sign + sign check */
TestRsaSignCb signCb = new TestRsaSignCb();
TestRsaVerifyCb signCheckCb = new TestRsaVerifyCb();
srvCtx.setRsaSignCb(signCb);
srvCtx.setRsaSignCheckCb(signCheckCb);
/* Register client-side RSA verify */
TestRsaVerifyCb verifyCb = new TestRsaVerifyCb();
cliCtx.setRsaVerifyCb(verifyCb);
/* Register RSA-PSS callbacks in case rsa_pss_sa_algo is used
* as sig algo in TLS 1.2 */
if (WolfSSL.RsaPssEnabled()) {
TestRsaPssSignCb pssSignCb = new TestRsaPssSignCb();
TestRsaPssVerifyCb pssSrvChk = new TestRsaPssVerifyCb();
TestRsaPssVerifyCb pssCliChk = new TestRsaPssVerifyCb();
srvCtx.setRsaPssSignCb(pssSignCb);
srvCtx.setRsaPssSignCheckCb(pssSrvChk);
cliCtx.setRsaPssSignCheckCb(pssCliChk);
}
/* Context objects to track invocation */
final TestRsaCbCtx srvSignCtx = new TestRsaCbCtx();
final TestRsaCbCtx srvVerifyCtx = new TestRsaCbCtx();
final TestRsaCbCtx cliVerifyCtx = new TestRsaCbCtx();
srvSocket = new ServerSocket(0);
srvSocket.setSoTimeout(10000);
final int port = srvSocket.getLocalPort();
final ServerSocket fSrvSock = srvSocket;
final WolfSSLContext fSrvCtx = srvCtx;
final CountDownLatch ready = new CountDownLatch(1);
es = Executors.newSingleThreadExecutor();
Future<Void> srvFuture = es.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
int ret;
int err;
Socket srv = null;
WolfSSLSession srvSes = null;
try {
ready.countDown();
srv = fSrvSock.accept();
srvSes = new WolfSSLSession(fSrvCtx);
srvSes.setRsaSignCtx(srvSignCtx);
srvSes.setRsaVerifyCtx(srvVerifyCtx);
ret = srvSes.setFd(srv);
if (ret != WolfSSL.SSL_SUCCESS) {
throw new Exception("srv setFd fail: " + ret);
}
do {
ret = srvSes.accept();
err = srvSes.getError(ret);
} while (
ret != WolfSSL.SSL_SUCCESS &&
(err == WolfSSL.SSL_ERROR_WANT_READ ||
err == WolfSSL.SSL_ERROR_WANT_WRITE));
if (ret != WolfSSL.SSL_SUCCESS) {
throw new Exception("srv accept fail: " + ret);
}
srvSes.shutdownSSL();
} finally {
if (srvSes != null) {
srvSes.freeSSL();
}
if (srv != null) {
srv.close();
}
fSrvSock.close();
}
return null;
}
});
if (!ready.await(2, TimeUnit.SECONDS)) {
fail("Server did not become ready within timeout");
}
cliSock = new Socket("localhost", port);
cliSes = new WolfSSLSession(cliCtx);
cliSes.setRsaVerifyCtx(cliVerifyCtx);
int ret = cliSes.setFd(cliSock);
if (ret != WolfSSL.SSL_SUCCESS) {
fail("cli setFd fail: " + ret);
}
int err;
do {
ret = cliSes.connect();
err = cliSes.getError(ret);
} while (ret != WolfSSL.SSL_SUCCESS &&
(err == WolfSSL.SSL_ERROR_WANT_READ ||
err == WolfSSL.SSL_ERROR_WANT_WRITE));
if (ret != WolfSSL.SSL_SUCCESS) {
fail("TLS 1.2 RSA CB connect fail: " + ret);
}
cliSes.shutdownSSL();
cliSes.freeSSL();
cliSock.close();
/* Check server thread for errors */
es.shutdown();
srvFuture.get(5, TimeUnit.SECONDS);
/* Verify callbacks were invoked */
assertTrue("RSA sign cb not called", srvSignCtx.called);
assertTrue("RSA sign check cb not called", srvVerifyCtx.called);
if (!WolfSSL.RsaPssEnabled()) {
assertTrue("RSA verify (cli) cb not called",
cliVerifyCtx.called);
}
} catch (WolfSSLJNIException e) {
/* PK callbacks may not be compiled in */
if (e.getMessage() != null &&
e.getMessage().contains("PK Callback")) {
return;
}
System.out.println("\t\t... failed");
fail("TLS 1.2 RSA CB handshake: " + e.getMessage());
} catch (ExecutionException e) {
System.out.println("\t\t... failed");
fail("TLS 1.2 RSA CB server: " + e.getCause().getMessage());
} catch (Exception e) {
System.out.println("\t\t... failed");
fail("TLS 1.2 RSA CB handshake: " + e.getMessage());
} finally {
if (cliSes != null) {
try { cliSes.freeSSL(); }
catch (Exception e) { /* ignore */ }
}
if (cliSock != null) {
try { cliSock.close(); }
catch (IOException e) { /* ignore */ }
}
if (srvSocket != null && !srvSocket.isClosed()) {
try { srvSocket.close(); }
catch (IOException e) { /* ignore */ }
}
if (cliCtx != null) cliCtx.free();
if (srvCtx != null) srvCtx.free();
if (es != null) {
es.shutdownNow();
}
}
}
private void rsaCbHandshakeTls13() {
WolfSSLContext srvCtx = null;
WolfSSLContext cliCtx = null;
ServerSocket srvSocket = null;
ExecutorService es = null;
Socket cliSock = null;
WolfSSLSession cliSes = null;
try {
srvCtx = createCtx(svrCert, svrKey, caCert,
WolfSSL.TLSv1_3_ServerMethod());
cliCtx = createCtx(cliCert, cliKey, caCert,
WolfSSL.TLSv1_3_ClientMethod());
/* Server: RSA-PSS sign + sign check */
TestRsaPssSignCb pssSignCb = new TestRsaPssSignCb();
TestRsaPssVerifyCb pssSrvChkCb = new TestRsaPssVerifyCb();
srvCtx.setRsaPssSignCb(pssSignCb);
srvCtx.setRsaPssSignCheckCb(pssSrvChkCb);
/* Context objects to track invocation */
final TestRsaCbCtx srvSignCtx = new TestRsaCbCtx();
final TestRsaCbCtx srvVerifyCtx = new TestRsaCbCtx();
srvSocket = new ServerSocket(0);
srvSocket.setSoTimeout(10000);
final int port = srvSocket.getLocalPort();
final ServerSocket fSrvSock = srvSocket;
final WolfSSLContext fSrvCtx = srvCtx;
final CountDownLatch ready = new CountDownLatch(1);
es = Executors.newSingleThreadExecutor();
Future<Void> srvFuture = es.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
int ret;
int err;
Socket srv = null;
WolfSSLSession srvSes = null;
try {
ready.countDown();
srv = fSrvSock.accept();
srvSes = new WolfSSLSession(fSrvCtx);
srvSes.setRsaSignCtx(srvSignCtx);
srvSes.setRsaVerifyCtx(srvVerifyCtx);
ret = srvSes.setFd(srv);
if (ret != WolfSSL.SSL_SUCCESS) {
throw new Exception("srv setFd fail: " + ret);
}
do {
ret = srvSes.accept();
err = srvSes.getError(ret);
} while (ret != WolfSSL.SSL_SUCCESS &&
(err == WolfSSL.SSL_ERROR_WANT_READ ||
err == WolfSSL.SSL_ERROR_WANT_WRITE));
if (ret != WolfSSL.SSL_SUCCESS) {
throw new Exception("srv accept fail: " + ret);
}
srvSes.shutdownSSL();
} finally {
if (srvSes != null) {
srvSes.freeSSL();
}
if (srv != null) {
srv.close();
}
fSrvSock.close();
}
return null;
}
});
if (!ready.await(2, TimeUnit.SECONDS)) {
fail("Server did not become ready within timeout");
}
cliSock = new Socket("localhost", port);
cliSes = new WolfSSLSession(cliCtx);
int ret = cliSes.setFd(cliSock);
if (ret != WolfSSL.SSL_SUCCESS) {
fail("cli setFd fail: " + ret);
}
int err;
do {
ret = cliSes.connect();
err = cliSes.getError(ret);
} while (ret != WolfSSL.SSL_SUCCESS &&
(err == WolfSSL.SSL_ERROR_WANT_READ ||
err == WolfSSL.SSL_ERROR_WANT_WRITE));
if (ret != WolfSSL.SSL_SUCCESS) {
fail("TLS 1.3 PSS CB connect fail: " + ret);
}
cliSes.shutdownSSL();
cliSes.freeSSL();
cliSock.close();
/* Check server thread for errors */
es.shutdown();
srvFuture.get(5, TimeUnit.SECONDS);
/* Verify server-side callbacks were invoked. Client-side PSS peer
* verify uses internal wolfSSL code (no setRsaPssVerifyCb in
* JNI yet). */
assertTrue("PSS sign cb not called", srvSignCtx.called);
assertTrue("PSS sign check cb not called", srvVerifyCtx.called);
} catch (WolfSSLJNIException e) {
/* PK callbacks may not be compiled in */
if (e.getMessage() != null &&
e.getMessage().contains("PK Callback")) {
return;
}
System.out.println("\t\t... failed");
fail("TLS 1.3 PSS CB handshake: " + e.getMessage());
} catch (ExecutionException e) {
System.out.println("\t\t... failed");
fail("TLS 1.3 PSS CB server: " + e.getCause().getMessage());
} catch (Exception e) {
System.out.println("\t\t... failed");
fail("TLS 1.3 PSS CB handshake: " + e.getMessage());
} finally {
if (cliSes != null) {
try { cliSes.freeSSL(); }
catch (Exception e) { /* ignore */ }
}
if (cliSock != null) {
try { cliSock.close(); }
catch (IOException e) { /* ignore */ }
}
if (srvSocket != null && !srvSocket.isClosed()) {
try { srvSocket.close(); }
catch (IOException e) { /* ignore */ }
}
if (cliCtx != null) cliCtx.free();
if (srvCtx != null) srvCtx.free();
if (es != null) {
es.shutdownNow();
}
}
}
public void test_WolfSSLContext_free() {
System.out.print("\tfree()");