JNI: wrap wolfSSL_set_tls13_secret_cb() in WolfSSLSession.setTls13SecretCb(), along with example in Client.java

pull/181/head
Chris Conlon 2024-03-27 12:25:15 -06:00
parent ecd67a4596
commit 3dee881dda
11 changed files with 874 additions and 30 deletions

View File

@ -72,6 +72,9 @@ public class Client {
int logCallback = 0; /* use test logging callback */
int usePsk = 0; /* use pre shared keys */
boolean useSecretCallback = false; /* enable TLS 1.3 secret cb */
String keyLogFile = "sslkeylog.log"; /* output keylog file */
long session = 0; /* pointer to WOLFSSL_SESSION */
boolean resumeSession = false; /* try one session resumption */
@ -201,6 +204,16 @@ public class Client {
} else if (arg.equals("-r")) {
resumeSession = true;
} else if (arg.equals("-tls13secretcb")) {
if (!WolfSSL.secretCallbackEnabled()) {
printUsage();
}
if (args.length < i+2) {
printUsage();
}
useSecretCallback = true;
keyLogFile = args[++i];
} else {
printUsage();
}
@ -451,6 +464,16 @@ public class Client {
}
}
/* Set TLS 1.3 secret callback if enabled */
if (useSecretCallback) {
MyTls13SecretCallback tsc =
new MyTls13SecretCallback(keyLogFile);
ssl.keepArrays();
ssl.setTls13SecretCb(tsc, null);
System.out.println("Writing TLS 1.3 secrets to keylog file: " +
keyLogFile);
}
/* open Socket */
if (doDTLS == 1) {
dsock = new DatagramSocket();
@ -757,6 +780,8 @@ public class Client {
System.out.println("-U\t\tEnable Atomic User Record Layer Callbacks");
if (WolfSSL.isEnabledPKCallbacks() == 1)
System.out.println("-P\t\tPublic Key Callbacks");
if (WolfSSL.secretCallbackEnabled())
System.out.println("-tls13secretcb\tEnable TLS 1.3 secret callback");
System.exit(1);
}

View File

@ -0,0 +1,141 @@
/* MyTls13SecretCallback.java
*
* Copyright (C) 2006-2024 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
*/
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLSession;
import com.wolfssl.WolfSSLTls13SecretCallback;
import com.wolfssl.WolfSSLJNIException;
/**
* Example TLS 1.3 secret callback implementation.
*
* This is provided as an example only, and used with the example JNI
* applications provided in this package. Users in production environments
* should write their own implementation to conform to desired goals.
*/
class MyTls13SecretCallback implements WolfSSLTls13SecretCallback
{
/* SSL keylog file to output secrets to */
private String sslKeyLogFile = "sslkeylog.log";
/**
* Create new MyTls13SecretCallback using default "sslkeylog.log" file
* path.
*/
public MyTls13SecretCallback() {
}
/**
* Create new MyTls13SecretCallback object specifying SSL keylog file
* path.
*
* @param keyLogFile path to output file (ex: sslkeylog.log) to use
* for writing TLS 1.3 secrets into.
*/
public MyTls13SecretCallback(String keyLogFile) {
this.sslKeyLogFile = keyLogFile;
}
/**
* Callback method for printing/saving TLS 1.3 secrets, for use
* with Wireshark. Called by native wolfSSL when each secret is available.
*
* @param ssl the current SSL session object from which the
* callback was initiated.
* @param id Identifier specifying what type of secret this callback
* is being called with, one of the following:
* WolfSSL.CLIENT_EARLY_TRAFFIC_SECRET
* WolfSSL.EARLY_EXPORTER_SECRET
* WolfSSL.CLIENT_HANDSHAKE_TRAFFIC_SECRET
* WolfSSL.SERVER_HANDSHAKE_TRAFFIC_SECRET
* WolfSSL.CLIENT_TRAFFIC_SECRET
* WolfSSL.SERVER_TRAFFIC_SECRET
* WolfSSL.EXPORTER_SECRET
* @param secret Current secret as byte array
* @param ctx Optional user context if set
*
* @return 0 on success, otherwise negative if callback encounters
* an error.
*/
public int tls13SecretCallback(WolfSSLSession ssl, int id, byte[] secret,
Object ctx) {
int i;
String str = null;
FileWriter fw = null;
PrintWriter pw = null;
byte[] clientRandom = null;
try {
/* Open FileWriter in append mode */
fw = new FileWriter(sslKeyLogFile, true);
pw = new PrintWriter(fw);
clientRandom = ssl.getClientRandom();
if (clientRandom == null || clientRandom.length == 0) {
System.out.println("Error getting client random");
}
/* Set secret label based on ID */
if (id == WolfSSL.CLIENT_EARLY_TRAFFIC_SECRET) {
str = "CLIENT_EARLY_TRAFFIC_SECRET";
} else if (id == WolfSSL.EARLY_EXPORTER_SECRET) {
str = "EARLY_EXPORTER_SECRET";
} else if (id == WolfSSL.CLIENT_HANDSHAKE_TRAFFIC_SECRET) {
str = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
} else if (id == WolfSSL.SERVER_HANDSHAKE_TRAFFIC_SECRET) {
str = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
} else if (id == WolfSSL.CLIENT_TRAFFIC_SECRET) {
str = "CLIENT_TRAFFIC_SECRET";
} else if (id == WolfSSL.SERVER_TRAFFIC_SECRET) {
str = "SERVER_TRAFFIC_SECRET";
} else if (id == WolfSSL.EXPORTER_SECRET) {
str = "EXPORTER_SECRET";
} else {
pw.close();
return WolfSSL.TLS13_SECRET_CB_E;
}
pw.printf("%s ", str);
for (i = 0; i < clientRandom.length; i++) {
pw.printf("%02x", clientRandom[i]);
}
pw.printf(" ");
for (i = 0; i < clientRandom.length; i++) {
pw.printf("%02x", secret[i]);
}
pw.printf("\n");
pw.close();
return 0;
} catch (IOException | WolfSSLJNIException e) {
e.printStackTrace();
return WolfSSL.TLS13_SECRET_CB_E;
}
}
}

View File

@ -298,6 +298,97 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getBulkCipherAlgorithmEnumCAMELL
return wolfssl_camellia;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1EARLY_1TRAFFIC_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return CLIENT_EARLY_TRAFFIC_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1HANDSHAKE_1TRAFFIC_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return CLIENT_HANDSHAKE_TRAFFIC_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1SERVER_1HANDSHAKE_1TRAFFIC_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return SERVER_HANDSHAKE_TRAFFIC_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1TRAFFIC_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return CLIENT_TRAFFIC_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1SERVER_1TRAFFIC_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return SERVER_TRAFFIC_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1EARLY_1EXPORTER_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return EARLY_EXPORTER_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1EXPORTER_1SECRET
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
return EXPORTER_SECRET;
#else
return NOT_COMPILED_IN;
#endif
}
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_TLSv1Enabled
(JNIEnv* jenv, jclass jcl)
{
@ -519,6 +610,19 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_sessionTicketEnabled
#endif
}
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_secretCallbackEnabled
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#ifdef HAVE_SECRET_CALLBACK
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSL_SSLv3_1ServerMethod
(JNIEnv* jenv, jclass jcl)
{

View File

@ -187,6 +187,8 @@ extern "C" {
#define com_wolfssl_WolfSSL_NOT_COMPILED_IN -174L
#undef com_wolfssl_WolfSSL_NO_PASSWORD
#define com_wolfssl_WolfSSL_NO_PASSWORD -176L
#undef com_wolfssl_WolfSSL_TLS13_SECRET_CB_E
#define com_wolfssl_WolfSSL_TLS13_SECRET_CB_E -438L
#undef com_wolfssl_WolfSSL_MD5
#define com_wolfssl_WolfSSL_MD5 0L
#undef com_wolfssl_WolfSSL_SHA
@ -423,6 +425,62 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getBulkCipherAlgorithmEnumCHACHA
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getBulkCipherAlgorithmEnumCAMELLIA
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_CLIENT_EARLY_TRAFFIC_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1EARLY_1TRAFFIC_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_CLIENT_HANDSHAKE_TRAFFIC_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1HANDSHAKE_1TRAFFIC_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_SERVER_HANDSHAKE_TRAFFIC_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1SERVER_1HANDSHAKE_1TRAFFIC_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_CLIENT_TRAFFIC_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1CLIENT_1TRAFFIC_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_SERVER_TRAFFIC_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1SERVER_1TRAFFIC_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_EARLY_EXPORTER_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1EARLY_1EXPORTER_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getTls13SecretEnum_EXPORTER_SECRET
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getTls13SecretEnum_1EXPORTER_1SECRET
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: getEnabledCipherSuites
@ -599,6 +657,14 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_trustPeerCertEnabled
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_sessionTicketEnabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: secretCallbackEnabled
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_secretCallbackEnabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: SSLv3_ServerMethod

View File

@ -54,6 +54,10 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg);
/* TLS 1.3 secret native callback prototype */
int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret,
int secretSz, void* ctx);
#ifdef HAVE_CRL
/* global object refs for CRL callback */
static jobject g_crlCbIfaceObj;
@ -4546,6 +4550,234 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out,
#endif /* HAVE_ALPN */
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_keepArrays
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
(void)jenv;
(void)jcl;
#ifndef WOLFCRYPT_ONLY
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
/* Checks ssl for null internally */
wolfSSL_KeepArrays(ssl);
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientRandom
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
#if !defined(WOLFCRYPT_ONLY) && (defined(OPENSSL_EXTRA) || \
defined(WOLFSSL_WPAS_SMALL) || defined(HAVE_SECRET_CALLBACK)) && \
!defined(NO_WOLFSSL_CLIENT)
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
int clientRandomSz;
byte clientRandom[32];
jbyteArray randomArr = NULL;
(void)jcl;
if (jenv == NULL || ssl == NULL) {
return NULL;
}
clientRandomSz = (int)wolfSSL_get_client_random(ssl, clientRandom,
sizeof(clientRandom));
if (clientRandomSz <= 0) {
return NULL;
}
randomArr = (*jenv)->NewByteArray(jenv, clientRandomSz);
if (randomArr == NULL) {
(*jenv)->ThrowNew(jenv, jcl,
"Failed to create byte array in native getClientRandom()");
return NULL;
}
(*jenv)->SetByteArrayRegion(jenv, randomArr, 0, clientRandomSz,
(jbyte*)clientRandom);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
return NULL;
}
return randomArr;
#else
(void)jenv;
(void)jcl;
(void)sslPtr;
return NULL;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTls13SecretCb
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
#if defined(WOLFSSL_TLS13) && !defined(WOLFCRYPT_ONLY) && \
defined(HAVE_SECRET_CALLBACK)
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
int ret = SSL_SUCCESS;
(void)jcl;
if (jenv == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
/* Java layer handles setting and giving back user CTX */
ret = wolfSSL_set_tls13_secret_cb(ssl, NativeTls13SecretCb, NULL);
return ret;
#else
(void)jenv;
(void)jcl;
(void)sslPtr;
return NOT_COMPILED_IN;
#endif
}
#if defined(WOLFSSL_TLS13) && !defined(WOLFCRYPT_ONLY) && \
defined(HAVE_SECRET_CALLBACK)
int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret,
int secretSz, void* ctx)
{
JNIEnv* jenv; /* JNI environment */
jclass excClass; /* WolfSSLJNIException class */
int needsDetach = 0; /* Should we explicitly detach? */
jint retval = 0;
jint vmret = 0;
jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
jclass sslClass; /* WolfSSLSession class */
jmethodID tls13SecretMethodId; /* internalTls13SecretCallback ID */
jbyteArray secretArr = NULL;
if (g_vm == NULL || ssl == NULL) {
return BAD_FUNC_ARG;
}
/* 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 TLS13_SECRET_CB_E;
}
needsDetach = 1;
}
else if (vmret != JNI_OK) {
return TLS13_SECRET_CB_E;
}
/* Find exception class in case we need it */
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
/* Get stored WolfSSLSession object */
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl);
if (!g_cachedSSLObj) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get native WolfSSLSession object reference in "
"NativeTls13SecretCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
/* Lookup WolfSSLSession class from object */
sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
if (sslClass == NULL) {
(*jenv)->ThrowNew(jenv, excClass,
"Can't get native WolfSSLSession class reference in "
"NativeTls13SecretCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
/* Call internal TLS 1.3 secret callback */
tls13SecretMethodId = (*jenv)->GetMethodID(jenv, sslClass,
"internalTls13SecretCallback", "(Lcom/wolfssl/WolfSSLSession;I[B)I");
if (tls13SecretMethodId == NULL) {
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
}
(*jenv)->ThrowNew(jenv, excClass,
"Error getting internalTls13SecretCallback method from JNI");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
if (secretSz > 0) {
/* Create jbyteArray to hold secret data */
secretArr = (*jenv)->NewByteArray(jenv, secretSz);
if (secretArr == NULL) {
(*jenv)->ThrowNew(jenv, excClass,
"Error creating new jbyteArray in NativeTls13SecretCb");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
(*jenv)->SetByteArrayRegion(jenv, secretArr, 0, secretSz,
(jbyte*)secret);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
/* Call Java TLS 1.3 secret callback, ignore native CTX since Java
* handles it */
retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj),
tls13SecretMethodId, (jobject)(*g_cachedSSLObj), (jint)id,
secretArr);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->ThrowNew(jenv, excClass,
"Exception while calling internalTls13SecretCallback()");
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return TLS13_SECRET_CB_E;
}
/* Delete local refs */
(*jenv)->DeleteLocalRef(jenv, secretArr);
}
/* Detach JNIEnv from thread */
if (needsDetach) {
(*g_vm)->DetachCurrentThread(g_vm);
}
return (int)retval;
}
#endif /* WOLFSSL_TLS13 && !WOLFCRYPT_ONLY && HAVE_SECRET_CALLBACK */
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSecureRenegotiation
(JNIEnv* jenv, jobject jcl, jlong ssl)
{

View File

@ -775,6 +775,30 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useALPN
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setALPNSelectCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: setTls13SecretCb
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTls13SecretCb
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: keepArrays
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_keepArrays
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: getClientRandom
* Signature: (J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLSession_getClientRandom
(JNIEnv *, jobject, jlong);
/*
* Class: com_wolfssl_WolfSSLSession
* Method: useSecureRenegotiation

View File

@ -42,6 +42,7 @@ infer run -- javac \
src/java/com/wolfssl/WolfSSLRsaSignCallback.java \
src/java/com/wolfssl/WolfSSLRsaVerifyCallback.java \
src/java/com/wolfssl/WolfSSLSession.java \
src/java/com/wolfssl/WolfSSLTls13SecretCallback.java \
src/java/com/wolfssl/WolfSSLVerifyCallback.java \
src/java/com/wolfssl/WolfSSLX509StoreCtx.java \
src/java/com/wolfssl/wolfcrypt/ECC.java \

View File

@ -313,6 +313,28 @@ public class WolfSSL {
/** ALPN ERR FATAL, ALPN callback no match and fatal */
public static final int SSL_TLSEXT_ERR_ALERT_FATAL = 2;
/* ----------------- TLS 1.3 secret callback IDs -------------------- */
/** TLS 1.3 secret ID: client early traffic secret */
public static int CLIENT_EARLY_TRAFFIC_SECRET;
/** TLS 1.3 secret ID: client handshake traffic secret */
public static int CLIENT_HANDSHAKE_TRAFFIC_SECRET;
/** TLS 1.3 secret ID: server handshake traffic secret */
public static int SERVER_HANDSHAKE_TRAFFIC_SECRET;
/** TLS 1.3 secret ID: client traffic secret */
public static int CLIENT_TRAFFIC_SECRET;
/** TLS 1.3 secret ID: server traffic secret */
public static int SERVER_TRAFFIC_SECRET;
/** TLS 1.3 secret ID: early exporter secret */
public static int EARLY_EXPORTER_SECRET;
/** TLS 1.3 secret ID: exporter secret */
public static int EXPORTER_SECRET;
/* ---------------------- wolfCrypt codes ---------------------------- */
/** Out of memory error */
@ -333,6 +355,9 @@ public class WolfSSL {
/** No password provided by user */
public static final int NO_PASSWORD = -176;
/** TLS 1.3 secret callback function failure */
public static final int TLS13_SECRET_CB_E = -438;
/* hmac codes, from wolfssl/wolfcrypt/hmac.h */
/** Md5 HMAC type */
public static final int MD5 = 0;
@ -519,6 +544,22 @@ public class WolfSSL {
wolfssl_aes_gcm = getBulkCipherAlgorithmEnumAESGCM();
wolfssl_aes_ccm = getBulkCipherAlgorithmEnumAESCCM();
/* initialize TLS 1.3 secret callback ID enums */
CLIENT_EARLY_TRAFFIC_SECRET =
getTls13SecretEnum_CLIENT_EARLY_TRAFFIC_SECRET();
CLIENT_HANDSHAKE_TRAFFIC_SECRET =
getTls13SecretEnum_CLIENT_HANDSHAKE_TRAFFIC_SECRET();
SERVER_HANDSHAKE_TRAFFIC_SECRET =
getTls13SecretEnum_SERVER_HANDSHAKE_TRAFFIC_SECRET();
CLIENT_TRAFFIC_SECRET =
getTls13SecretEnum_CLIENT_TRAFFIC_SECRET();
SERVER_TRAFFIC_SECRET =
getTls13SecretEnum_SERVER_TRAFFIC_SECRET();
EARLY_EXPORTER_SECRET =
getTls13SecretEnum_EARLY_EXPORTER_SECRET();
EXPORTER_SECRET =
getTls13SecretEnum_EXPORTER_SECRET();
this.active = true;
}
@ -544,6 +585,14 @@ public class WolfSSL {
static native int getBulkCipherAlgorithmEnumCHACHA();
static native int getBulkCipherAlgorithmEnumCAMELLIA();
static native int getTls13SecretEnum_CLIENT_EARLY_TRAFFIC_SECRET();
static native int getTls13SecretEnum_CLIENT_HANDSHAKE_TRAFFIC_SECRET();
static native int getTls13SecretEnum_SERVER_HANDSHAKE_TRAFFIC_SECRET();
static native int getTls13SecretEnum_CLIENT_TRAFFIC_SECRET();
static native int getTls13SecretEnum_SERVER_TRAFFIC_SECRET();
static native int getTls13SecretEnum_EARLY_EXPORTER_SECRET();
static native int getTls13SecretEnum_EXPORTER_SECRET();
static native String getEnabledCipherSuites();
static native String getEnabledCipherSuitesIana();
static native String getAvailableCipherSuitesIana(int version);
@ -759,6 +808,16 @@ public class WolfSSL {
*/
public static native boolean sessionTicketEnabled();
/**
* Tests if native wolfSSL has been compiled with HAVE_SECRET_CALLBACK
* default. If defined, will compile in APIs to support SSL/TLS secret
* callback support.
*
* @return true if enabled, otherwise false if HAVE_SECRET_CALLBACK
* has not been defind.
*/
public static native boolean secretCallbackEnabled();
/* ---------------- native SSL/TLS version functions ---------------- */
/**

View File

@ -56,6 +56,7 @@ public class WolfSSLSession {
private Object rsaEncCtx;
private Object rsaDecCtx;
private Object alpnSelectArg;
private Object tls13SecretCtx;
/* reference to the associated WolfSSLContext */
private WolfSSLContext ctx = null;
@ -74,6 +75,10 @@ public class WolfSSLSession {
* ALPN select callback */
private WolfSSLALPNSelectCallback internAlpnSelectCb;
/* user-registered TLS 1.3 secret callbcak, called by internal
* WolfSSLSession TLS 1.3 secret callback */
private WolfSSLTls13SecretCallback internTls13SecretCb;
/* have session tickets been enabled for this session? Default to false. */
private boolean sessionTicketsEnabled = false;
@ -169,66 +174,54 @@ public class WolfSSLSession {
return this.rsaDecCtx;
}
/* these callbacks will be registered with native wolfSSL library */
/* These callbacks will be registered with native wolfSSL library */
private int internalIOSSLRecvCallback(WolfSSLSession ssl, byte[] buf,
int sz)
{
int ret;
/* call user-registered recv method */
ret = internRecvSSLCb.receiveCallback(ssl, buf, sz,
ssl.getIOReadCtx());
return ret;
return internRecvSSLCb.receiveCallback(ssl, buf, sz,
ssl.getIOReadCtx());
}
private int internalIOSSLSendCallback(WolfSSLSession ssl, byte[] buf,
int sz)
{
int ret;
/* call user-registered recv method */
ret = internSendSSLCb.sendCallback(ssl, buf, sz,
ssl.getIOWriteCtx());
return ret;
return internSendSSLCb.sendCallback(ssl, buf, sz,
ssl.getIOWriteCtx());
}
private long internalPskClientCallback(WolfSSLSession ssl, String hint,
StringBuffer identity, long idMaxLen, byte[] key,
long keyMaxLen)
{
long ret;
/* call user-registered PSK client callback method */
ret = internPskClientCb.pskClientCallback(ssl, hint, identity,
idMaxLen, key, keyMaxLen);
return ret;
return internPskClientCb.pskClientCallback(ssl, hint, identity,
idMaxLen, key, keyMaxLen);
}
private long internalPskServerCallback(WolfSSLSession ssl,
String identity, byte[] key, long keyMaxLen)
{
long ret;
/* call user-registered PSK server callback method */
ret = internPskServerCb.pskServerCallback(ssl, identity,
key, keyMaxLen);
return ret;
return internPskServerCb.pskServerCallback(ssl, identity,
key, keyMaxLen);
}
private int internalAlpnSelectCallback(WolfSSLSession ssl, String[] out,
String[] in)
{
int ret;
/* call user-registered ALPN select callback */
ret = internAlpnSelectCb.alpnSelectCallback(ssl, out, in,
this.alpnSelectArg);
return internAlpnSelectCb.alpnSelectCallback(ssl, out, in,
this.alpnSelectArg);
}
return ret;
private int internalTls13SecretCallback(WolfSSLSession ssl, int id,
byte[] secret)
{
/* call user-registered TLS 1.3 secret callback */
return internTls13SecretCb.tls13SecretCallback(ssl, id, secret,
this.tls13SecretCtx);
}
/**
@ -350,6 +343,9 @@ public class WolfSSLSession {
private native byte[] sslGet0AlpnSelected(long ssl);
private native int useALPN(long ssl, String protocols, int options);
private native int setALPNSelectCb(long ssl);
private native int setTls13SecretCb(long ssl);
private native void keepArrays(long ssl);
private native byte[] getClientRandom(long ssl);
private native int useSecureRenegotiation(long ssl);
private native int rehandshake(long ssl);
private native int set1SigAlgsList(long ssl, String list);
@ -3437,10 +3433,12 @@ public class WolfSSLSession {
*
* @param cb callback to be registered with SSL session
* @param arg Object that will be passed back to user inside callback
*
* @return <code>SSL_SUCCESS</code> upon success. <code>
* NOT_COMPILED_IN</code> if wolfSSL was not compiled with
* ALPN support, and other negative value representing other
* error scenarios.
*
* @throws IllegalStateException WolfSSLSession has been freed
* @throws WolfSSLJNIException Internal JNI error
*/
@ -3465,6 +3463,83 @@ public class WolfSSLSession {
return ret;
}
/**
* Register TLS 1.3 secret callback.
*
* The callback registered by this method is called by native wolfSSL
* during TLS 1.3 connection to retrieve the secrets used in those
* connections. These can be printed to a log file for consumption by
* Wireshark.
*
* @param cb callback to be registered with this SSL session
* @param ctx Object that will be passed back to user inside callback
*
* @return <code>SSL_SUCCESS</code> on success. <code>
* NOT_COMPILED_IN</code> if wolfSSL was not compiled with
* TLS 1.3 and HAVE_SECERT_CALLBACK defined, and other
* negative value on error.
*
* @throws IllegalStateException WolfSSLSession has been freed
* @throws WolfSSLJNIException Internal JNI error
*/
public int setTls13SecretCb(WolfSSLTls13SecretCallback cb, Object ctx)
throws IllegalStateException, WolfSSLJNIException {
int ret = 0;
confirmObjectIsActive();
synchronized (sslLock) {
ret = setTls13SecretCb(getSessionPtr());
if (ret == WolfSSL.SSL_SUCCESS) {
/* Set TLS 1.3 secret callback */
internTls13SecretCb = cb;
/* Set TLS 1.3 secret ctx Object, returned to user in cb */
this.tls13SecretCtx = ctx;
}
}
return ret;
}
/**
* Do not free temporary arrays at end of handshake.
*
* This needs to be called if using the TLS 1.3 secret callback, and
* should be called after the WolfSSLSession object has been created.
*
* @throws IllegalStateException WolfSSLSession has been freed
* @throws WolfSSLJNIException Internal JNI error
*/
public void keepArrays()
throws IllegalStateException, WolfSSLJNIException {
confirmObjectIsActive();
synchronized (sslLock) {
keepArrays(getSessionPtr());
}
}
/**
* Get the client random value used in this SSL/TLS session.
*
* @return client random byte array on success, or null if not available
*
* @throws IllegalStateException WolfSSLSession has been freed
* @throws WolfSSLJNIException Internal JNI error
*/
public byte[] getClientRandom()
throws IllegalStateException, WolfSSLJNIException {
confirmObjectIsActive();
synchronized (sslLock) {
return getClientRandom(getSessionPtr());
}
}
/**
* Enable use of secure renegotiation on this session. Calling this
* API does not initiate secure renegotiation, but enables it. If enabled,

View File

@ -0,0 +1,66 @@
/* WolfSSLTls13SecretCallback.java
*
* Copyright (C) 2006-2024 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 TLS 1.3 Secret Callback Interface.
* This interface specifies how applications should implement the TLS 1.3
* secret callback class, to be used by wolfSSL when logging TLS 1.3 secrets.
* <p>
* To use this interface, native wolfSSL must be compiled with
* HAVE_SECRET_CALLBACK defined.
* <p>
* After implementing this interface, it should be passed as a parameter
* to the
* {@link WolfSSLSession#setTls13SecretCb(WolfSSLTls13SecretCallback, Object)
* WolfSSLSession.setTls13SecretCb()} method to be registered with the native
* wolfSSL library.
*/
public interface WolfSSLTls13SecretCallback {
/**
* Callback method for printing/saving TLS 1.3 secrets, for use
* with Wireshark.
*
* @param ssl the current SSL session object from which the
* callback was initiated.
* @param id Identifier specifying what type of secret this callback
* is being called with, one of the following:
* WolfSSL.CLIENT_EARLY_TRAFFIC_SECRET
* WolfSSL.EARLY_EXPORTER_SECRET
* WolfSSL.CLIENT_HANDSHAKE_TRAFFIC_SECRET
* WolfSSL.SERVER_HANDSHAKE_TRAFFIC_SECRET
* WolfSSL.CLIENT_TRAFFIC_SECRET
* WolfSSL.SERVER_TRAFFIC_SECRET
* WolfSSL.EXPORTER_SECRET
* @param secret Current secret as byte array
* @param ctx Optional user context if set
*
* @return 0 on success, otherwise negative if callback encounters
* an error.
*/
public int tls13SecretCallback(WolfSSLSession ssl, int id,
byte[] secret, Object ctx);
}

View File

@ -39,6 +39,7 @@ import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
import com.wolfssl.WolfSSLPskClientCallback;
import com.wolfssl.WolfSSLPskServerCallback;
import com.wolfssl.WolfSSLTls13SecretCallback;
import com.wolfssl.WolfSSLSession;
public class WolfSSLSessionTest {
@ -95,6 +96,7 @@ public class WolfSSLSessionTest {
test_WolfSSLSession_UseAfterFree();
test_WolfSSLSession_getSessionID();
test_WolfSSLSession_useSecureRenegotiation();
test_WolfSSLSession_setTls13SecretCb();
}
public void test_WolfSSLSession_new() {
@ -663,5 +665,54 @@ public class WolfSSLSessionTest {
System.out.println("... passed");
}
class TestTls13SecretCb implements WolfSSLTls13SecretCallback
{
public int tls13SecretCallback(WolfSSLSession ssl, int id,
byte[] secret, Object ctx)
{
return 0;
}
}
public void test_WolfSSLSession_setTls13SecretCb() {
int ret;
WolfSSL sslLib = null;
WolfSSLContext sslCtx = null;
WolfSSLSession ssl = null;
TestTls13SecretCb cb = null;
System.out.print("\tTesting setTls13SecretCb()");
if (!WolfSSL.secretCallbackEnabled()) {
System.out.println("\t... skipped");
return;
}
try {
/* setup library, context, session, socket */
sslLib = new WolfSSL();
sslCtx = new WolfSSLContext(WolfSSL.TLSv1_3_ClientMethod());
sslCtx.setVerify(WolfSSL.SSL_VERIFY_NONE, null);
ssl = new WolfSSLSession(sslCtx);
/* setting with null should pass */
ssl.setTls13SecretCb(null, null);
/* set with test callback */
cb = new TestTls13SecretCb();
ssl.setTls13SecretCb(cb, null);
} catch (Exception e) {
System.out.println("\t... failed");
e.printStackTrace();
fail("failed setTls13SecretCb() test");
return;
}
System.out.println("\t... passed");
}
}