Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions jni/jni_fips.c
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f

RNG* rng = NULL;
byte* buf = NULL;
jlong bufCap = 0;

rng = (RNG*) getNativeStruct(env, rng_object);
if ((*env)->ExceptionOccurred(env)) {
Expand All @@ -1936,9 +1937,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}

buf = getDirectBufferAddress(env, buf_buffer);
bufCap = (*env)->GetDirectBufferCapacity(env, buf_buffer);

if (!rng || !buf)
/* reject NULL, negative, or bufSz beyond the buffer capacity, the
* capacity ceiling also keeps the word32 cast from wrapping */
if (rng == NULL || buf == NULL || bufSz < 0 || bufSz > bufCap) {
return BAD_FUNC_ARG;
}

#if FIPS_VERSION_GT(5,0)
ret = wc_RNG_GenerateBlock_fips(rng, buf, (word32)bufSz);
Expand All @@ -1948,7 +1953,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f

LogStr("RNG_GenerateBlock_fips(rng=%p, buf, bufSz) = %d\n", rng, ret);
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, bufSz);
LogHex(buf, 0, (word32)bufSz);

#endif

Expand All @@ -1965,6 +1970,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f

RNG* rng = NULL;
byte* buf = NULL;
word32 bufLen = 0;

rng = (RNG*) getNativeStruct(env, rng_object);
if ((*env)->ExceptionOccurred(env)) {
Expand All @@ -1973,8 +1979,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}

buf = getByteArray(env, buf_buffer);
bufLen = getByteArrayLength(env, buf_buffer);

if (rng == NULL || buf == NULL) {
/* reject NULL, negative, or bufSz beyond the backing array */
if (rng == NULL || buf == NULL || bufSz < 0 || bufSz > (jlong)bufLen) {
ret = BAD_FUNC_ARG;
}
else {
Expand All @@ -1986,8 +1994,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1GenerateBlock_1f
}

LogStr("RNG_GenerateBlock_fips(rng=%p, buf, bufSz) = %d\n", rng, ret);
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, bufSz);
if (buf != NULL && ret == 0) {
LogStr("output[%u]: [%p]\n", (word32)bufSz, buf);
LogHex(buf, 0, (word32)bufSz);
}

releaseByteArray(env, buf_buffer, buf, ret);

Expand Down
103 changes: 76 additions & 27 deletions jni/jni_sha.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,16 +390,22 @@ Java_com_wolfssl_wolfcrypt_Sha_native_1final_1internal___3B(

hash = getByteArray(env, hash_buffer);

ret = (!sha || !hash)
? BAD_FUNC_ARG
: wc_ShaFinal(sha, hash);
if (sha == NULL || hash == NULL ||
getByteArrayLength(env, hash_buffer) < SHA_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_ShaFinal(sha, hash);
}

if (ret != 0)
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 (ret == 0) {
LogStr("hash[%u]: [%p]\n", (word32)SHA_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA_DIGEST_SIZE);
}

releaseByteArray(env, hash_buffer, hash, ret);
#else
Expand Down Expand Up @@ -619,7 +625,8 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal

hash = getByteArray(env, hash_buffer);

if (sha == NULL || hash == NULL) {
if (sha == NULL || hash == NULL ||
getByteArrayLength(env, hash_buffer) < SHA224_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
Expand All @@ -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 (ret == 0) {
LogStr("hash[%u]: [%p]\n", (word32)SHA224_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA224_DIGEST_SIZE);
}

releaseByteArray(env, hash_buffer, hash, ret);
#else
Expand Down Expand Up @@ -835,16 +844,22 @@ Java_com_wolfssl_wolfcrypt_Sha256_native_1final_1internal___3B(

hash = getByteArray(env, hash_buffer);

ret = (!sha || !hash)
? BAD_FUNC_ARG
: wc_Sha256Final(sha, hash);
if (sha == NULL || hash == NULL ||
getByteArrayLength(env, hash_buffer) < SHA256_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha256Final(sha, hash);
}

if (ret != 0)
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 (ret == 0) {
LogStr("hash[%u]: [%p]\n", (word32)SHA256_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA256_DIGEST_SIZE);
}

releaseByteArray(env, hash_buffer, hash, ret);
#else
Expand Down Expand Up @@ -1041,16 +1056,22 @@ Java_com_wolfssl_wolfcrypt_Sha384_native_1final_1internal___3B(

hash = getByteArray(env, hash_buffer);

ret = (!sha || !hash)
? BAD_FUNC_ARG
: wc_Sha384Final(sha, hash);
if (sha == NULL || hash == NULL ||
getByteArrayLength(env, hash_buffer) < SHA384_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha384Final(sha, hash);
}

if (ret != 0)
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 (ret == 0) {
LogStr("hash[%u]: [%p]\n", (word32)SHA384_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA384_DIGEST_SIZE);
}

releaseByteArray(env, hash_buffer, hash, ret);
#else
Expand Down Expand Up @@ -1248,16 +1269,22 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1final_1internal___3B(

hash = getByteArray(env, hash_buffer);

ret = (!sha || !hash)
? BAD_FUNC_ARG
: wc_Sha512Final(sha, hash);
if (sha == NULL || hash == NULL ||
getByteArrayLength(env, hash_buffer) < SHA512_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha512Final(sha, hash);
}

if (ret != 0)
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 (ret == 0) {
LogStr("hash[%u]: [%p]\n", (word32)SHA512_DIGEST_SIZE, hash);
LogHex(hash, 0, SHA512_DIGEST_SIZE);
}

releaseByteArray(env, hash_buffer, hash, ret);
#else
Expand Down Expand Up @@ -1579,6 +1606,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal__
int ret = 0;
wc_Sha3* sha = NULL;
byte* hash = NULL;
word32 hashSz = 0;

sha = (wc_Sha3*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
Expand All @@ -1593,18 +1621,39 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha3_native_1final_1internal__
}

if (ret == 0) {
hashSz = getByteArrayLength(env, hash_buffer);
switch(hashType) {
case WC_HASH_TYPE_SHA3_224:
ret = wc_Sha3_224_Final(sha, hash);
if (hashSz < WC_SHA3_224_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha3_224_Final(sha, hash);
}
break;
case WC_HASH_TYPE_SHA3_256:
ret = wc_Sha3_256_Final(sha, hash);
if (hashSz < WC_SHA3_256_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha3_256_Final(sha, hash);
}
break;
case WC_HASH_TYPE_SHA3_384:
ret = wc_Sha3_384_Final(sha, hash);
if (hashSz < WC_SHA3_384_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha3_384_Final(sha, hash);
}
break;
case WC_HASH_TYPE_SHA3_512:
ret = wc_Sha3_512_Final(sha, hash);
if (hashSz < WC_SHA3_512_DIGEST_SIZE) {
ret = BAD_FUNC_ARG;
}
else {
ret = wc_Sha3_512_Final(sha, hash);
}
break;
default:
ret = BAD_FUNC_ARG;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/wolfssl/wolfcrypt/AesCmac.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ public synchronized void setKey(byte[] key)
wc_CmacSetKey(key);
}

/* Store key for reset functionality */
/* Store key for reset, zeroize any prior key clone */
zeroizeKey();
this.key = new byte[key.length];
System.arraycopy(key, 0, this.key, 0, key.length);

Expand Down
43 changes: 43 additions & 0 deletions src/test/java/com/wolfssl/wolfcrypt/test/AesCmacTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.junit.Assert.*;

import java.nio.ByteBuffer;
import java.lang.reflect.Field;

import org.junit.Assume;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -574,6 +575,48 @@ public void aesCmacShouldHandleObjectReuse() {
}
}

@Test
public void aesCmacShouldZeroizePriorKeyOnReKey() throws Exception {

String key1 = "2b7e151628aed2a6abf7158809cf4f3c";
String key2 = "603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4";

byte[] key1Bytes = Util.h2b(key1);
byte[] key2Bytes = Util.h2b(key2);

AesCmac cmac;
try {
cmac = new AesCmac();
cmac.setKey(key1Bytes);
} catch (WolfCryptException e) {
if (e.getError() == WolfCryptError.NOT_COMPILED_IN) {
System.out.println("AesCmac re-key zeroize test skipped: " +
e.getError());
return;
}
throw e;
}

/* Capture reference to the internal key clone stored by setKey.
* Zeroization has no public observable, so this deliberately couples
* to the private AesCmac.key field name and must be updated if that
* field is renamed. */
Field keyField = AesCmac.class.getDeclaredField("key");
keyField.setAccessible(true);
byte[] priorClone = (byte[]) keyField.get(cmac);

assertNotNull("Internal key clone should be stored", priorClone);
assertFalse("Internal key clone should be non-zero before re-key",
Arrays.equals(priorClone, new byte[priorClone.length]));

/* Re-keying must zeroize the prior clone before replacing it */
cmac.setKey(key2Bytes);

assertArrayEquals("Prior key clone should be zeroized after re-key",
new byte[priorClone.length], priorClone);
}

@Test
public void aesCmacStaticMethodsShouldHandleEdgeCases() {
try {
Expand Down
Loading
Loading