F-3561: zeroize AES and 3DES key material in releaseNativeStruct

pull/257/head
Chris Conlon 2026-08-14 12:14:24 -06:00
parent 3590c2af6d
commit 65adee1049
16 changed files with 226 additions and 7 deletions

View File

@ -29,6 +29,14 @@ extern "C" {
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Aes_mallocNativeStruct_1internal
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_Aes
* Method: wc_AesFree
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Aes_wc_1AesFree
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_Aes
* Method: native_set_key_internal

View File

@ -25,6 +25,14 @@ extern "C" {
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_mallocNativeStruct_1internal
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesCtr
* Method: wc_AesFree
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_wc_1AesFree
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesCtr
* Method: native_set_key_internal

View File

@ -29,6 +29,14 @@ extern "C" {
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_mallocNativeStruct_1internal
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesEcb
* Method: wc_AesFree
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_wc_1AesFree
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesEcb
* Method: native_set_key_internal

View File

@ -29,6 +29,14 @@ extern "C" {
JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_mallocNativeStruct_1internal
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesOfb
* Method: wc_AesFree
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_wc_1AesFree
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_AesOfb
* Method: native_set_key_internal

View File

@ -17,6 +17,14 @@ extern "C" {
#define com_wolfssl_wolfcrypt_Des3_ENCRYPT_MODE 0L
#undef com_wolfssl_wolfcrypt_Des3_DECRYPT_MODE
#define com_wolfssl_wolfcrypt_Des3_DECRYPT_MODE 1L
/*
* Class: com_wolfssl_wolfcrypt_Des3
* Method: wc_Des3Free
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Des3_wc_1Des3Free
(JNIEnv *, jobject);
/*
* Class: com_wolfssl_wolfcrypt_Des3
* Method: native_set_key_internal

View File

@ -40,6 +40,7 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Aes_mallocNativeStruct_1inter
{
#ifndef NO_AES
Aes* aes = NULL;
int ret = 0;
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (aes == NULL) {
@ -47,6 +48,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Aes_mallocNativeStruct_1inter
}
else {
XMEMSET(aes, 0, sizeof(Aes));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0) {
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
aes = NULL;
throwWolfCryptExceptionFromError(env, ret);
}
}
LogStr("new Aes() = %p\n", aes);
@ -60,6 +67,27 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Aes_mallocNativeStruct_1inter
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Aes_wc_1AesFree
(JNIEnv* env, jobject this)
{
#ifndef NO_AES
Aes* aes = NULL;
aes = (Aes*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, if so stop and return */
return;
}
wc_AesFree(aes);
LogStr("wc_AesFree(aes=%p)\n", aes);
#else
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Aes_native_1set_1key_1internal(
JNIEnv* env, jobject this, jbyteArray key_object, jbyteArray iv_object,

View File

@ -40,6 +40,7 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_mallocNativeStruct_1in
{
#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
Aes* aes = NULL;
int ret = 0;
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (aes == NULL) {
@ -47,6 +48,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_mallocNativeStruct_1in
}
else {
XMEMSET(aes, 0, sizeof(Aes));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0) {
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
aes = NULL;
throwWolfCryptExceptionFromError(env, ret);
}
}
LogStr("new AesCtr() = %p\n", aes);
@ -60,6 +67,27 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_mallocNativeStruct_1in
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCtr_wc_1AesFree
(JNIEnv* env, jobject this)
{
#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
Aes* aes = NULL;
aes = (Aes*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, if so stop and return */
return;
}
wc_AesFree(aes);
LogStr("wc_AesFree(aes=%p)\n", aes);
#else
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_AesCtr_native_1set_1key_1internal(
JNIEnv* env, jobject this, jbyteArray key_object, jbyteArray iv_object)

View File

@ -40,6 +40,7 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_mallocNativeStruct_1in
{
#if !defined(NO_AES) && defined(HAVE_AES_ECB)
Aes* aes = NULL;
int ret = 0;
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (aes == NULL) {
@ -47,6 +48,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_mallocNativeStruct_1in
}
else {
XMEMSET(aes, 0, sizeof(Aes));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0) {
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
aes = NULL;
throwWolfCryptExceptionFromError(env, ret);
}
}
LogStr("new AesEcb() = %p\n", aes);
@ -60,6 +67,27 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_mallocNativeStruct_1in
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesEcb_wc_1AesFree
(JNIEnv* env, jobject this)
{
#if !defined(NO_AES) && defined(HAVE_AES_ECB)
Aes* aes = NULL;
aes = (Aes*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, if so stop and return */
return;
}
wc_AesFree(aes);
LogStr("wc_AesFree(aes=%p)\n", aes);
#else
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_AesEcb_native_1set_1key_1internal(
JNIEnv* env, jobject this, jbyteArray key_object, jbyteArray iv_object, jint opmode)

View File

@ -40,6 +40,7 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_mallocNativeStruct_1in
{
#if !defined(NO_AES) && defined(WOLFSSL_AES_OFB)
Aes* aes = NULL;
int ret = 0;
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (aes == NULL) {
@ -47,6 +48,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_mallocNativeStruct_1in
}
else {
XMEMSET(aes, 0, sizeof(Aes));
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
if (ret != 0) {
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
aes = NULL;
throwWolfCryptExceptionFromError(env, ret);
}
}
LogStr("new AesOfb() = %p\n", aes);
@ -60,6 +67,27 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_mallocNativeStruct_1in
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesOfb_wc_1AesFree
(JNIEnv* env, jobject this)
{
#if !defined(NO_AES) && defined(WOLFSSL_AES_OFB)
Aes* aes = NULL;
aes = (Aes*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, if so stop and return */
return;
}
wc_AesFree(aes);
LogStr("wc_AesFree(aes=%p)\n", aes);
#else
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_AesOfb_native_1set_1key_1internal(
JNIEnv* env, jobject this, jbyteArray key_object, jbyteArray iv_object,

View File

@ -40,6 +40,7 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Des3_mallocNativeStruct(
{
#ifndef NO_DES3
Des3* des = NULL;
int ret = 0;
des = (Des3*) XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (des == NULL) {
@ -47,6 +48,12 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Des3_mallocNativeStruct(
}
else {
XMEMSET(des, 0, sizeof(Des3));
ret = wc_Des3Init(des, NULL, INVALID_DEVID);
if (ret != 0) {
XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER);
des = NULL;
throwWolfCryptExceptionFromError(env, ret);
}
}
LogStr("new Des3() = %p\n", des);
@ -59,6 +66,27 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Des3_mallocNativeStruct(
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Des3_wc_1Des3Free
(JNIEnv* env, jobject this)
{
#ifndef NO_DES3
Des3* des3 = NULL;
des3 = (Des3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, if so stop and return */
return;
}
wc_Des3Free(des3);
LogStr("wc_Des3Free(des3=%p)\n", des3);
#else
(void)this;
throwNotCompiledInException(env);
#endif
}
JNIEXPORT void JNICALL
Java_com_wolfssl_wolfcrypt_Des3_native_1set_1key_1internal(
JNIEnv* env, jobject this, jbyteArray key_object, jbyteArray iv_object,

View File

@ -51,6 +51,7 @@ public class Aes extends BlockCipher {
* NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native long mallocNativeStruct_internal() throws OutOfMemoryError;
private native void wc_AesFree();
private native void native_set_key_internal(byte[] key, byte[] iv,
int opmode);
private native int native_update_internal(int opmode, byte[] input,
@ -58,6 +59,11 @@ public class Aes extends BlockCipher {
private native int native_update_internal(int opmode, ByteBuffer input,
int offset, int length, ByteBuffer output, int outputOffset);
@Override
protected void nativeFree() {
wc_AesFree();
}
/**
* Malloc native JNI AES structure
*

View File

@ -51,6 +51,7 @@ public class AesCtr extends NativeStruct {
* NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native long mallocNativeStruct_internal() throws OutOfMemoryError;
private native void wc_AesFree();
private native void native_set_key_internal(byte[] key, byte[] iv);
private native int native_update_internal(byte[] input,
int offset, int length, byte[] output, int outputOffset);
@ -315,10 +316,14 @@ public class AesCtr extends NativeStruct {
@Override
public synchronized void releaseNativeStruct() {
synchronized (stateLock) {
if (state != WolfCryptState.RELEASED) {
super.releaseNativeStruct();
state = WolfCryptState.RELEASED;
if ((state != WolfCryptState.UNINITIALIZED) &&
(state != WolfCryptState.RELEASED)) {
synchronized (pointerLock) {
wc_AesFree();
super.releaseNativeStruct();
}
}
state = WolfCryptState.RELEASED;
}
}
}

View File

@ -52,6 +52,7 @@ public class AesEcb extends BlockCipher {
* NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native long mallocNativeStruct_internal() throws OutOfMemoryError;
private native void wc_AesFree();
private native void native_set_key_internal(byte[] key, byte[] iv,
int opmode);
private native int native_update_internal(int opmode, byte[] input,
@ -59,6 +60,11 @@ public class AesEcb extends BlockCipher {
private native int native_update_internal(int opmode, ByteBuffer input,
int offset, int length, ByteBuffer output, int outputOffset);
@Override
protected void nativeFree() {
wc_AesFree();
}
/**
* Malloc native AesEcb structure
*

View File

@ -57,6 +57,7 @@ public class AesOfb extends NativeStruct {
* NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native long mallocNativeStruct_internal() throws OutOfMemoryError;
private native void wc_AesFree();
private native void native_set_key_internal(byte[] key, byte[] iv,
int opmode);
private native int native_update_internal(int opmode, byte[] input,
@ -664,10 +665,14 @@ public class AesOfb extends NativeStruct {
@Override
public synchronized void releaseNativeStruct() {
synchronized (stateLock) {
if (state != WolfCryptState.RELEASED) {
super.releaseNativeStruct();
state = WolfCryptState.RELEASED;
if ((state != WolfCryptState.UNINITIALIZED) &&
(state != WolfCryptState.RELEASED)) {
synchronized (pointerLock) {
wc_AesFree();
super.releaseNativeStruct();
}
}
state = WolfCryptState.RELEASED;
}
}
}

View File

@ -262,12 +262,23 @@ public abstract class BlockCipher extends NativeStruct {
return ret;
}
/**
* Zeroize contents of the native structure. Called by releaseNativeStruct()
* before the native structure memory is freed, subclasses override to
* wipe key material.
*/
protected void nativeFree() {
}
@Override
public synchronized void releaseNativeStruct() {
synchronized (stateLock) {
if ((state != WolfCryptState.UNINITIALIZED) &&
(state != WolfCryptState.RELEASED)) {
super.releaseNativeStruct();
synchronized (pointerLock) {
nativeFree();
super.releaseNativeStruct();
}
state = WolfCryptState.RELEASED;
}
}

View File

@ -43,6 +43,7 @@ public class Des3 extends BlockCipher {
/* native JNI methods, internally reach back and grab/use pointer from
* NativeStruct.java. We wrap calls to these below in order to
* synchronize access to native pointer between threads */
private native void wc_Des3Free();
private native void native_set_key_internal(byte[] key, byte[] iv,
int opmode);
private native int native_update_internal(int opmode, byte[] input,
@ -59,6 +60,11 @@ public class Des3 extends BlockCipher {
*/
protected native long mallocNativeStruct() throws OutOfMemoryError;
@Override
protected void nativeFree() {
wc_Des3Free();
}
/**
* Set native Des3 key
*