From 3ca22fba6bcf0ddeb8a54bc8dc5d77d67728ad7c Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 10:10:43 -0600 Subject: [PATCH 01/11] F-3769: log the written output region in AesCtr ByteBuffer update debug output --- jni/jni_aesctr.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/jni/jni_aesctr.c b/jni/jni_aesctr.c index 6300d75b..2773e401 100644 --- a/jni/jni_aesctr.c +++ b/jni/jni_aesctr.c @@ -146,10 +146,12 @@ Java_com_wolfssl_wolfcrypt_AesCtr_native_1update_1internal___3BII_3BI( LogStr("wc_AesCtrEncrypt(aes=%p, out, in, inSz) = %d\n", aes, ret); } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, ret); @@ -218,10 +220,12 @@ Java_com_wolfssl_wolfcrypt_AesCtr_native_1update_1internal__Ljava_nio_ByteBuffer ret = length; } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output); - LogHex((byte*) output, 0, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } #else throwNotCompiledInException(env); #endif From 5a0be9de599997628299863d04e6750a3966d32a Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 12:33:40 -0600 Subject: [PATCH 02/11] F-3996: reject IV shorter than one AES block in AesCts key setup --- jni/jni_aescts.c | 5 +++++ .../com/wolfssl/wolfcrypt/test/AesCtsTest.java | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/jni/jni_aescts.c b/jni/jni_aescts.c index 7ffd2a72..7d58392e 100644 --- a/jni/jni_aescts.c +++ b/jni/jni_aescts.c @@ -116,6 +116,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCts_native_1set_1key_1inter byte* key = NULL; byte* iv = NULL; word32 keySz = 0; + word32 ivSz = 0; ctx = (AesCtsCtx*) getNativeStruct(env, this); if ((*env)->ExceptionOccurred(env)) { @@ -126,10 +127,14 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCts_native_1set_1key_1inter key = getByteArray(env, key_object); iv = getByteArray(env, iv_object); keySz = getByteArrayLength(env, key_object); + ivSz = getByteArrayLength(env, iv_object); if (ctx == NULL || key == NULL || iv == NULL) { ret = BAD_FUNC_ARG; } + else if (ivSz != AES_BLOCK_SIZE) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { /* Initialize AES_KEY structure using OpenSSL-compatible functions. diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/AesCtsTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/AesCtsTest.java index 16e0a065..4aeead91 100644 --- a/src/test/java/com/wolfssl/wolfcrypt/test/AesCtsTest.java +++ b/src/test/java/com/wolfssl/wolfcrypt/test/AesCtsTest.java @@ -123,6 +123,20 @@ public void checkSetKeyParams() { /* test must throw */ } + try { + aesCts.setKey(KEY_128, new byte[8], AesCts.ENCRYPT_MODE); + fail("iv shorter than one AES block should be rejected."); + } catch (WolfCryptException e) { + /* test must throw */ + } + + try { + aesCts.setKey(KEY_128, new byte[24], AesCts.ENCRYPT_MODE); + fail("iv longer than one AES block should be rejected."); + } catch (WolfCryptException e) { + /* test must throw */ + } + aesCts.setKey(KEY_128, IV, AesCts.ENCRYPT_MODE); aesCts.releaseNativeStruct(); From a89f7877e65972251e32989b41e4baaa853e641d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 12:52:54 -0600 Subject: [PATCH 03/11] F-6156: avoid XMALLOC(0) on AAD-only AES-GCM/CCM paths --- jni/jni_aesccm.c | 18 ++++++++++++++---- jni/jni_aesgcm.c | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/jni/jni_aesccm.c b/jni/jni_aesccm.c index dbada278..98d09c9c 100644 --- a/jni/jni_aesccm.c +++ b/jni/jni_aesccm.c @@ -204,12 +204,17 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesCcm_wc_1AesCcmEncrypt /* Allocate new buffer to hold ciphertext */ if (ret == 0) { - out = (byte*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + word32 outSz = inLen; + if (outSz == 0) { + /* AAD-only case, allocate 1 byte to avoid XMALLOC(0) */ + outSz = 1; + } + out = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) { ret = MEMORY_E; } else { - XMEMSET(out, 0, inLen); + XMEMSET(out, 0, outSz); } } @@ -336,12 +341,17 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesCcm_wc_1AesCcmDecrypt } if (ret == 0) { - out = (byte*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + word32 outSz = inLen; + if (outSz == 0) { + /* AAD-only case, allocate 1 byte to avoid XMALLOC(0) */ + outSz = 1; + } + out = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) { ret = MEMORY_E; } else { - XMEMSET(out, 0, inLen); + XMEMSET(out, 0, outSz); } } diff --git a/jni/jni_aesgcm.c b/jni/jni_aesgcm.c index a434f548..e92e9966 100644 --- a/jni/jni_aesgcm.c +++ b/jni/jni_aesgcm.c @@ -211,12 +211,17 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesGcm_wc_1AesGcmEncrypt /* Allocate new buffer to hold ciphertext */ if (ret == 0) { - out = (byte*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + word32 outSz = inLen; + if (outSz == 0) { + /* AAD-only case, allocate 1 byte to avoid XMALLOC(0) */ + outSz = 1; + } + out = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) { ret = MEMORY_E; } else { - XMEMSET(out, 0, inLen); + XMEMSET(out, 0, outSz); } } @@ -362,12 +367,17 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_AesGcm_wc_1AesGcmDecrypt } if (ret == 0) { - out = (byte*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + word32 outSz = inLen; + if (outSz == 0) { + /* AAD-only case, allocate 1 byte to avoid XMALLOC(0) */ + outSz = 1; + } + out = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) { ret = MEMORY_E; } else { - XMEMSET(out, 0, inLen); + XMEMSET(out, 0, outSz); } } From efe1cf855e321dd10ceebb32faf13902ea24b4fa Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 12:59:14 -0600 Subject: [PATCH 04/11] F-9997: add explicit non-blinding arm to wc_RsaSetRNG JNI wrapper --- jni/jni_rsa.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jni/jni_rsa.c b/jni/jni_rsa.c index 976ba99c..bc08e6bd 100644 --- a/jni/jni_rsa.c +++ b/jni/jni_rsa.c @@ -742,6 +742,10 @@ Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaSetRNG( else { return JNI_TRUE; } +#else + (void)env; + (void)this; + (void)rng_object; #endif #else From fa2e99a46bc245e8384962ad784415819963a053 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 13:04:32 -0600 Subject: [PATCH 05/11] F-11207: log the processed region in MD5 ByteBuffer update/final debug output --- jni/jni_md5.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/jni/jni_md5.c b/jni/jni_md5.c index 483061aa..05682daa 100644 --- a/jni/jni_md5.c +++ b/jni/jni_md5.c @@ -163,8 +163,8 @@ Java_com_wolfssl_wolfcrypt_Md5_native_1update_1internal__Ljava_nio_ByteBuffer_2I LogStr("wc_Md5Update(md5=%p, data, len)\n", md5); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else throwNotCompiledInException(env); @@ -240,8 +240,10 @@ Java_com_wolfssl_wolfcrypt_Md5_native_1final_1internal__Ljava_nio_ByteBuffer_2I( } LogStr("wc_Md5Final(md5=%p, hash)\n", md5); - LogStr("hash[%u]: [%p]\n", (word32)MD5_DIGEST_SIZE, hash); - LogHex(hash, 0, MD5_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)MD5_DIGEST_SIZE, hash + position); + LogHex(hash, position, MD5_DIGEST_SIZE); + } #else throwNotCompiledInException(env); #endif @@ -274,8 +276,10 @@ Java_com_wolfssl_wolfcrypt_Md5_native_1final_1internal___3B( } LogStr("wc_Md5Final(md5=%p, hash)\n", md5); - LogStr("hash[%u]: [%p]\n", (word32)MD5_DIGEST_SIZE, hash); - LogHex(hash, 0, MD5_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)MD5_DIGEST_SIZE, hash); + LogHex(hash, 0, MD5_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, 0); #else From f7124112893dd871a4d0345176c288baa30ecbc4 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 13:10:56 -0600 Subject: [PATCH 06/11] F-11208: log the processed region in SHA ByteBuffer update/final debug output --- jni/jni_sha.c | 96 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/jni/jni_sha.c b/jni/jni_sha.c index b2a0d802..feedb1a1 100644 --- a/jni/jni_sha.c +++ b/jni/jni_sha.c @@ -291,8 +291,8 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1update_1internal__Ljava_nio_ByteBuffer_2I LogStr("wc_ShaUpdate(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else throwNotCompiledInException(env); @@ -331,7 +331,7 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1update_1internal___3BII( LogStr("wc_ShaUpdate_fips(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); + LogStr("data[%u]: [%p]\n", (word32)len, data + offset); LogHex(data, offset, len); } @@ -366,8 +366,10 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1final_1internal__Ljava_nio_ByteBuffer_2I( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_ShaFinal(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA_DIGEST_SIZE, hash + position); + LogHex(hash, position, SHA_DIGEST_SIZE); + } #else throwNotCompiledInException(env); #endif @@ -398,8 +400,10 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1final_1internal___3B( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_ShaFinal(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA_DIGEST_SIZE, hash); + LogHex(hash, 0, SHA_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, ret); #else @@ -504,8 +508,8 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1interna LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else (void)env; @@ -592,8 +596,11 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal } LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA224_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, + hash + position); + LogHex(hash, position, SHA224_DIGEST_SIZE); + } #else (void)env; (void)this; @@ -631,8 +638,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal } LogStr("wc_Sha224Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA224_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash); + LogHex(hash, 0, SHA224_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, ret); #else @@ -734,8 +743,8 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1update_1internal__Ljava_nio_ByteBuffer LogStr("wc_Sha256Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else throwNotCompiledInException(env); @@ -776,8 +785,8 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1update_1internal___3BII( LogStr("wc_Sha256Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + offset); + LogHex(data, offset, len); } releaseByteArray(env, data_buffer, data, JNI_ABORT); @@ -811,8 +820,11 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1final_1internal__Ljava_nio_ByteBuffer_ throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha256Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA256_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA256_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA256_DIGEST_SIZE, + hash + position); + LogHex(hash, position, SHA256_DIGEST_SIZE); + } #else throwNotCompiledInException(env); #endif @@ -843,8 +855,10 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1final_1internal___3B( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha256Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA256_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA256_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA256_DIGEST_SIZE, hash); + LogHex(hash, 0, SHA256_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, ret); #else @@ -941,8 +955,8 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1update_1internal__Ljava_nio_ByteBuffer LogStr("wc_Sha384Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else throwNotCompiledInException(env); @@ -1017,8 +1031,11 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1final_1internal__Ljava_nio_ByteBuffer_ throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha384Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA384_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA384_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA384_DIGEST_SIZE, + hash + position); + LogHex(hash, position, SHA384_DIGEST_SIZE); + } #else throwNotCompiledInException(env); #endif @@ -1049,8 +1066,10 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1final_1internal___3B( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha384Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA384_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA384_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA384_DIGEST_SIZE, hash); + LogHex(hash, 0, SHA384_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, ret); #else @@ -1147,8 +1166,8 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1update_1internal__Ljava_nio_ByteBuffer LogStr("wc_Sha512Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + position); + LogHex(data, position, len); } #else throwNotCompiledInException(env); @@ -1224,8 +1243,11 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1final_1internal__Ljava_nio_ByteBuffer_ throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha512Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA512_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA512_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA512_DIGEST_SIZE, + hash + position); + LogHex(hash, position, SHA512_DIGEST_SIZE); + } #else throwNotCompiledInException(env); #endif @@ -1256,8 +1278,10 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1final_1internal___3B( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_Sha512Final(sha=%p, hash) = %d\n", sha, ret); - LogStr("hash[%u]: [%p]\n", (word32)SHA512_DIGEST_SIZE, hash); - LogHex(hash, 0, SHA512_DIGEST_SIZE); + if (hash != NULL) { + LogStr("hash[%u]: [%p]\n", (word32)SHA512_DIGEST_SIZE, hash); + LogHex(hash, 0, SHA512_DIGEST_SIZE); + } releaseByteArray(env, hash_buffer, hash, ret); #else @@ -1438,8 +1462,8 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal_ LogStr("wc_Sha3_Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); - LogHex(data, 0, len); + LogStr("data[%u]: [%p]\n", (word32)len, data + offset); + LogHex(data, offset, len); } #else (void)env; @@ -1501,7 +1525,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1update_1internal_ LogStr("wc_Sha3_Update(sha=%p, data, len) = %d\n", sha, ret); if (ret == 0) { - LogStr("data[%u]: [%p]\n", (word32)len, data); + LogStr("data[%u]: [%p]\n", (word32)len, data + offset); LogHex(data, offset, len); } From 998f8f91a4b28e76321836493e771afefcba1210 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 13:12:36 -0600 Subject: [PATCH 07/11] F-11209: log the generated region in RNG debug output --- jni/jni_rng.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jni/jni_rng.c b/jni/jni_rng.c index ef48ee32..c0f24b1f 100644 --- a/jni/jni_rng.c +++ b/jni/jni_rng.c @@ -148,8 +148,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rng_rngGenerateBlock__Ljava_ni } LogStr("wc_RNG_GenerateBlock(rng=%p, buffer, size) = %d\n", rng, ret); - LogStr("output[%u]: [%p]\n", (word32)size, buffer); - LogHex(buffer, 0, size); + if (buffer != NULL) { + LogStr("output[%u]: [%p]\n", (word32)size, buffer + position); + LogHex(buffer, position, size); + } #else throwNotCompiledInException(env); #endif @@ -189,8 +191,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Rng_rngGenerateBlock___3BII( } LogStr("wc_RNG_GenerateBlock(rng=%p, buffer, length) = %d\n", rng, ret); - LogStr("output[%u]: [%p]\n", (word32)length, buffer); - LogHex(buffer, 0, length); + if (buffer != NULL) { + LogStr("output[%u]: [%p]\n", (word32)length, buffer + offset); + LogHex(buffer, offset, length); + } releaseByteArray(env, buffer_buffer, buffer, ret); #else From eb33338caef722a513280678db04283bed0932c2 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 13:14:13 -0600 Subject: [PATCH 08/11] F-9327: correct wcSHA3_224 class javadoc label to SHA3-224 --- .../com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java index 97655e61..6430b5b6 100644 --- a/src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java +++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java @@ -138,7 +138,7 @@ protected void finalize() throws Throwable { } /** - * wolfJCE SHA1wECDSA message digest class + * wolfJCE SHA3-224 message digest class */ public static final class wcSHA3_224 extends WolfCryptMessageDigestSha3 { /** From 114338bb0cc1d937d8266dff8b089e57a29fa0fd Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 13:20:13 -0600 Subject: [PATCH 09/11] F-9328: fix stale testConvertWksToWks comment claiming stream identity --- .../java/com/wolfssl/provider/jce/test/WolfCryptUtilTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptUtilTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptUtilTest.java index c406c526..758341fe 100644 --- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptUtilTest.java +++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptUtilTest.java @@ -508,7 +508,8 @@ public void testConvertP12ToWksWithMapping() throws Exception { } /** - * Test converting WKS to WKS (should return same InputStream) + * Test converting WKS to a newly serialized WKS InputStream while + * preserving all entries */ @Test public void testConvertWksToWks() throws Exception { From 4f5131953c483a304e78c6044a0b435fa1f31d41 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 14:35:28 -0600 Subject: [PATCH 10/11] F-3563: zeroize Hmac and ChaCha native structs on release --- jni/include/com_wolfssl_wolfcrypt_Chacha.h | 8 ++++ jni/include/com_wolfssl_wolfcrypt_Hmac.h | 8 ++++ jni/jni_chacha.c | 26 +++++++++++++ jni/jni_hmac.c | 28 ++++++++++++++ .../java/com/wolfssl/wolfcrypt/Chacha.java | 7 +++- src/main/java/com/wolfssl/wolfcrypt/Hmac.java | 5 +++ .../com/wolfssl/wolfcrypt/test/HmacTest.java | 37 +++++++++++++++++++ 7 files changed, 117 insertions(+), 2 deletions(-) diff --git a/jni/include/com_wolfssl_wolfcrypt_Chacha.h b/jni/include/com_wolfssl_wolfcrypt_Chacha.h index 30fe4db8..80383544 100644 --- a/jni/include/com_wolfssl_wolfcrypt_Chacha.h +++ b/jni/include/com_wolfssl_wolfcrypt_Chacha.h @@ -41,6 +41,14 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setKey JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV (JNIEnv *, jobject, jbyteArray); +/* + * Class: com_wolfssl_wolfcrypt_Chacha + * Method: native_free + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_native_1free + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif diff --git a/jni/include/com_wolfssl_wolfcrypt_Hmac.h b/jni/include/com_wolfssl_wolfcrypt_Hmac.h index 34db2745..30e796e5 100644 --- a/jni/include/com_wolfssl_wolfcrypt_Hmac.h +++ b/jni/include/com_wolfssl_wolfcrypt_Hmac.h @@ -153,6 +153,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Hmac_getCodeSha3_1512 JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Hmac_mallocNativeStruct (JNIEnv *, jobject); +/* + * Class: com_wolfssl_wolfcrypt_Hmac + * Method: native_free + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_native_1free + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif diff --git a/jni/jni_chacha.c b/jni/jni_chacha.c index 614b2233..ab11d012 100644 --- a/jni/jni_chacha.c +++ b/jni/jni_chacha.c @@ -65,6 +65,32 @@ Java_com_wolfssl_wolfcrypt_Chacha_mallocNativeStruct( #endif } +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_native_1free + (JNIEnv* env, jobject this) +{ +#ifdef HAVE_CHACHA + ChaCha* chacha = (ChaCha*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + LogStr("free ChaCha %p\n", chacha); + + if (chacha) { + /* Zeroize ChaCha key/state, NativeStruct.xfree() frees memory */ + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(chacha, sizeof(ChaCha)); + #else + XMEMSET(chacha, 0, sizeof(ChaCha)); + #endif + } +#else + throwNotCompiledInException(env); +#endif +} + JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Chacha_wc_1Chacha_1setIV (JNIEnv* env, jobject this, jbyteArray iv_object) { diff --git a/jni/jni_hmac.c b/jni/jni_hmac.c index f7366e31..69c20518 100644 --- a/jni/jni_hmac.c +++ b/jni/jni_hmac.c @@ -148,6 +148,34 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Hmac_mallocNativeStruct #endif } +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_native_1free + (JNIEnv* env, jobject this) +{ +#ifndef NO_HMAC + Hmac* hmac = (Hmac*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + LogStr("free Hmac %p\n", hmac); + + if (hmac) { + /* Free device/async/inner-hash resources, then zeroize key-derived + * ipad/opad. NativeStruct.xfree() frees the memory. */ + wc_HmacFree(hmac); + #if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \ + !defined(WOLFSSL_NO_FORCE_ZERO) + wc_ForceZero(hmac, sizeof(Hmac)); + #else + XMEMSET(hmac, 0, sizeof(Hmac)); + #endif + } +#else + throwNotCompiledInException(env); +#endif +} + JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacSetKey (JNIEnv* env, jobject this, jint type, jbyteArray key_object) { diff --git a/src/main/java/com/wolfssl/wolfcrypt/Chacha.java b/src/main/java/com/wolfssl/wolfcrypt/Chacha.java index a5ff1e05..74c120a6 100644 --- a/src/main/java/com/wolfssl/wolfcrypt/Chacha.java +++ b/src/main/java/com/wolfssl/wolfcrypt/Chacha.java @@ -57,14 +57,17 @@ public Chacha() { private native byte[] wc_Chacha_process(byte in[]); private native void wc_Chacha_setKey(byte[] Key); private native void wc_Chacha_setIV(byte[] IV); + private native void native_free(); @Override public synchronized void releaseNativeStruct() { - /* No native ChaCha free API, so just release NativeStruct */ synchronized (stateLock) { if ((state != WolfCryptState.UNINITIALIZED) && (state != WolfCryptState.RELEASED)) { - super.releaseNativeStruct(); + synchronized (pointerLock) { + native_free(); + super.releaseNativeStruct(); + } state = WolfCryptState.RELEASED; } } diff --git a/src/main/java/com/wolfssl/wolfcrypt/Hmac.java b/src/main/java/com/wolfssl/wolfcrypt/Hmac.java index 45da8fe1..065db59b 100644 --- a/src/main/java/com/wolfssl/wolfcrypt/Hmac.java +++ b/src/main/java/com/wolfssl/wolfcrypt/Hmac.java @@ -126,6 +126,8 @@ public Hmac(int type, byte[] key) { */ protected native long mallocNativeStruct() throws OutOfMemoryError; + private native void native_free(); + /** * Check if type is -1, if so that type is not compiled in at native * wolfSSL level. @@ -220,6 +222,9 @@ public synchronized void reset() @Override public synchronized void releaseNativeStruct() { synchronized (pointerLock) { + if (getNativeStruct() != NativeStruct.NULL) { + native_free(); + } super.releaseNativeStruct(); } } diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/HmacTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/HmacTest.java index fb4ec42e..da99d3de 100644 --- a/src/test/java/com/wolfssl/wolfcrypt/test/HmacTest.java +++ b/src/test/java/com/wolfssl/wolfcrypt/test/HmacTest.java @@ -70,6 +70,43 @@ public void constructorShouldNotInitializeNativeStruct() { assertEquals(NativeStruct.NULL, new Hmac().getNativeStruct()); } + @Test + public void hmacReleaseLifecycle() { + byte[] key = new byte[32]; + byte[] data = new byte[64]; + + try { + /* Release before any setKey() must be a safe no-op */ + Hmac unused = new Hmac(); + unused.releaseNativeStruct(); + + /* Release after use, then re-key and produce the same MAC */ + Hmac hmac = new Hmac(); + hmac.setKey(Hmac.SHA256, key); + hmac.update(data); + byte[] mac1 = hmac.doFinal(); + + hmac.releaseNativeStruct(); + + hmac.setKey(Hmac.SHA256, key); + hmac.update(data); + byte[] mac2 = hmac.doFinal(); + assertArrayEquals("MAC after release and re-key must match", + mac1, mac2); + + /* Double release must not crash */ + hmac.releaseNativeStruct(); + hmac.releaseNativeStruct(); + } catch (WolfCryptException e) { + if (e.getError() == WolfCryptError.NOT_COMPILED_IN) { + System.out.println("Hmac release test skipped: " + + e.getError()); + } else { + throw e; + } + } + } + @Test public void shaHmacShouldMatch() { String[] keyVector = new String[] { From 1e0c9212ed9ef94d9278ffbe1ff1ec0b978e13f7 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 27 Aug 2026 16:11:07 -0600 Subject: [PATCH 11/11] JNI: guard cipher and MAC debug logging against NULL caller buffers --- jni/jni_aes.c | 20 ++++++++++++-------- jni/jni_aescmac.c | 12 ++++++++---- jni/jni_aescts.c | 10 ++++++---- jni/jni_aesecb.c | 20 ++++++++++++-------- jni/jni_aesofb.c | 20 ++++++++++++-------- jni/jni_des3.c | 20 ++++++++++++-------- jni/jni_hmac.c | 12 ++++++++---- 7 files changed, 70 insertions(+), 44 deletions(-) diff --git a/jni/jni_aes.c b/jni/jni_aes.c index 4b501e32..eee27a1c 100644 --- a/jni/jni_aes.c +++ b/jni/jni_aes.c @@ -145,10 +145,12 @@ Java_com_wolfssl_wolfcrypt_Aes_native_1update_1internal__I_3BII_3BI( LogStr("wc_AesCbcDecrypt(aes=%p, out, in, inSz) = %d\n", aes, ret); } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, ret); @@ -223,10 +225,12 @@ Java_com_wolfssl_wolfcrypt_Aes_native_1update_1internal__ILjava_nio_ByteBuffer_2 ret = length; } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } #else throwNotCompiledInException(env); ret = NOT_COMPILED_IN; diff --git a/jni/jni_aescmac.c b/jni/jni_aescmac.c index 4109b99a..3f8ccc2e 100644 --- a/jni/jni_aescmac.c +++ b/jni/jni_aescmac.c @@ -197,8 +197,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCmac_wc_1CmacUpdate___3BII( throwWolfCryptExceptionFromError(env, ret); LogStr("wc_CmacUpdate(cmac=%p, data, length) = %d\n", cmac, ret); - LogStr("data[%u]: [%p]\n", (word32)length, data + offset); - LogHex((byte*) data, offset, length); + if (data != NULL) { + LogStr("data[%u]: [%p]\n", (word32)length, data + offset); + LogHex((byte*) data, offset, length); + } releaseByteArray(env, data_object, data, JNI_ABORT); #else @@ -236,8 +238,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesCmac_wc_1CmacUpdate__Ljava_ throwWolfCryptExceptionFromError(env, ret); LogStr("wc_CmacUpdate(cmac=%p, data, length) = %d\n", cmac, ret); - LogStr("data[%u]: [%p]\n", (word32)length, data + offset); - LogHex((byte*) data, offset, length); + if (data != NULL) { + LogStr("data[%u]: [%p]\n", (word32)length, data + offset); + LogHex((byte*) data, offset, length); + } #else throwNotCompiledInException(env); #endif diff --git a/jni/jni_aescts.c b/jni/jni_aescts.c index 7d58392e..4719ce9c 100644 --- a/jni/jni_aescts.c +++ b/jni/jni_aescts.c @@ -259,10 +259,12 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_AesCts_native_1update_1interna ctx, opmode, length, ret); } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, diff --git a/jni/jni_aesecb.c b/jni/jni_aesecb.c index 88847988..4988379f 100644 --- a/jni/jni_aesecb.c +++ b/jni/jni_aesecb.c @@ -151,10 +151,12 @@ Java_com_wolfssl_wolfcrypt_AesEcb_native_1update_1internal__I_3BII_3BI( LogStr("wc_AesEcbDecrypt(aes=%p, out, in, inSz) = %d\n", aes, ret); } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, ret); @@ -232,10 +234,12 @@ Java_com_wolfssl_wolfcrypt_AesEcb_native_1update_1internal__ILjava_nio_ByteBuffe ret = length; } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } #else throwNotCompiledInException(env); ret = NOT_COMPILED_IN; diff --git a/jni/jni_aesofb.c b/jni/jni_aesofb.c index cccf429c..49947ca2 100644 --- a/jni/jni_aesofb.c +++ b/jni/jni_aesofb.c @@ -159,10 +159,12 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1update_1internal__I_3BII_3BI( #endif } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, ret); @@ -246,10 +248,12 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1update_1internal__ILjava_nio_ByteBuffe ret = length; } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } #else throwNotCompiledInException(env); ret = NOT_COMPILED_IN; diff --git a/jni/jni_des3.c b/jni/jni_des3.c index 20626a36..eb4e13be 100644 --- a/jni/jni_des3.c +++ b/jni/jni_des3.c @@ -144,10 +144,12 @@ Java_com_wolfssl_wolfcrypt_Des3_native_1update_1internal__I_3BII_3BI( LogStr("wc_Des3CbcDecrypt(des=%p, out, in, inSz) = %d\n", des, ret); } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } releaseByteArray(env, input_object, input, JNI_ABORT); releaseByteArray(env, output_object, output, ret); @@ -221,10 +223,12 @@ Java_com_wolfssl_wolfcrypt_Des3_native_1update_1internal__ILjava_nio_ByteBuffer_ ret = length; } - LogStr("input[%u]: [%p]\n", (word32)length, input + offset); - LogHex((byte*) input, offset, length); - LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); - LogHex((byte*) output, outputOffset, length); + if (input != NULL && output != NULL) { + LogStr("input[%u]: [%p]\n", (word32)length, input + offset); + LogHex((byte*) input, offset, length); + LogStr("output[%u]: [%p]\n", (word32)length, output + outputOffset); + LogHex((byte*) output, outputOffset, length); + } #else throwNotCompiledInException(env); #endif diff --git a/jni/jni_hmac.c b/jni/jni_hmac.c index 69c20518..6651b2f9 100644 --- a/jni/jni_hmac.c +++ b/jni/jni_hmac.c @@ -287,8 +287,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate___3BII throwWolfCryptExceptionFromError(env, ret); LogStr("wc_HmacUpdate(hmac=%p, data, length) = %d\n", hmac, ret); - LogStr("data[%u]: [%p]\n", (word32)length, data + offset); - LogHex((byte*) data, offset, length); + if (data != NULL) { + LogStr("data[%u]: [%p]\n", (word32)length, data + offset); + LogHex((byte*) data, offset, length); + } releaseByteArray(env, data_object, data, JNI_ABORT); #else @@ -326,8 +328,10 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Hmac_wc_1HmacUpdate__Ljava_nio throwWolfCryptExceptionFromError(env, ret); LogStr("wc_HmacUpdate(hmac=%p, data, length) = %d\n", hmac, ret); - LogStr("data[%u]: [%p]\n", (word32)length, data + offset); - LogHex((byte*) data, offset, length); + if (data != NULL) { + LogStr("data[%u]: [%p]\n", (word32)length, data + offset); + LogHex((byte*) data, offset, length); + } #else throwNotCompiledInException(env); #endif