diff --git a/jni/include/com_wolfssl_wolfcrypt_Sha224.h b/jni/include/com_wolfssl_wolfcrypt_Sha224.h new file mode 100644 index 0000000..8f3deee --- /dev/null +++ b/jni/include/com_wolfssl_wolfcrypt_Sha224.h @@ -0,0 +1,75 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_wolfssl_wolfcrypt_Sha224 */ + +#ifndef _Included_com_wolfssl_wolfcrypt_Sha224 +#define _Included_com_wolfssl_wolfcrypt_Sha224 +#ifdef __cplusplus +extern "C" { +#endif +#undef com_wolfssl_wolfcrypt_Sha224_NULL +#define com_wolfssl_wolfcrypt_Sha224_NULL 0LL +#undef com_wolfssl_wolfcrypt_Sha224_TYPE +#define com_wolfssl_wolfcrypt_Sha224_TYPE 5L +#undef com_wolfssl_wolfcrypt_Sha224_DIGEST_SIZE +#define com_wolfssl_wolfcrypt_Sha224_DIGEST_SIZE 28L +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: mallocNativeStruct_internal + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Sha224_mallocNativeStruct_1internal + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_init_internal + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1init_1internal + (JNIEnv *, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_copy_internal + * Signature: (Lcom/wolfssl/wolfcrypt/Sha224;)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1copy_1internal + (JNIEnv *, jobject, jobject); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_update_internal + * Signature: (Ljava/nio/ByteBuffer;II)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal__Ljava_nio_ByteBuffer_2II + (JNIEnv *, jobject, jobject, jint, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_update_internal + * Signature: ([BII)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal___3BII + (JNIEnv *, jobject, jbyteArray, jint, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_final_internal + * Signature: (Ljava/nio/ByteBuffer;I)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal__Ljava_nio_ByteBuffer_2I + (JNIEnv *, jobject, jobject, jint); + +/* + * Class: com_wolfssl_wolfcrypt_Sha224 + * Method: native_final_internal + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal___3B + (JNIEnv *, jobject, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/jni_sha.c b/jni/jni_sha.c index 79655c9..b9011fa 100644 --- a/jni/jni_sha.c +++ b/jni/jni_sha.c @@ -32,6 +32,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -45,6 +49,12 @@ #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE #define SHA_PAD_SIZE WC_SHA_PAD_SIZE #endif + #ifndef NO_SHA224 + #define Sha224 wc_Sha224 + #define SHA224_BLOCK_SIZE WC_SHA224_BLOCK_SIZE + #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define SHA224_PAD_SIZE WC_SHA224_PAD_SIZE + #endif #ifndef NO_SHA256 #define Sha256 wc_Sha256 #define SHA256_BLOCK_SIZE WC_SHA256_BLOCK_SIZE @@ -90,6 +100,32 @@ Java_com_wolfssl_wolfcrypt_Sha_mallocNativeStruct_1internal( #endif } +JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Sha224_mallocNativeStruct_1internal + (JNIEnv* env, jobject this) +{ +#ifdef WOLFSSL_SHA224 + Sha224* sha = NULL; + + sha = (Sha224*) XMALLOC(sizeof(Sha224), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) { + throwOutOfMemoryException(env, "Failed to allocate Sha224 object"); + } + else { + XMEMSET(sha, 0, sizeof(Sha224)); + } + + LogStr("new Sha224() = %p\n", sha); + + return (jlong)(uintptr_t)sha; +#else + (void)env; + (void)this; + throwNotCompiledInException(env); + + return (jlong)0; +#endif +} + JNIEXPORT jlong JNICALL Java_com_wolfssl_wolfcrypt_Sha256_mallocNativeStruct_1internal( JNIEnv* env, jobject this) @@ -946,3 +982,231 @@ Java_com_wolfssl_wolfcrypt_Sha512_native_1final_1internal___3B( #endif } +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1init_1internal + (JNIEnv* env, jobject this) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + if (sha == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_InitSha224(sha); + } + + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } +#else + (void)env; + (void)this; + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1copy_1internal + (JNIEnv* env, jobject this, jobject toBeCopied) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = NULL; + Sha224* tbc = NULL; /* tbc = to be copied */ + + if (this == NULL || toBeCopied == NULL) { + throwWolfCryptExceptionFromError(env, BAD_FUNC_ARG); + return; + } + + sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + tbc = (Sha224*) getNativeStruct(env, toBeCopied); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + ret = wc_Sha224Copy(tbc, sha); + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } +#else + (void)env; + (void)this; + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal__Ljava_nio_ByteBuffer_2II + (JNIEnv* env, jobject this, jobject data_buffer, jint position, jint len) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = NULL; + byte* data = NULL; + + sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + data = getDirectBufferAddress(env, data_buffer); + + if (sha == NULL || data == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_Sha224Update(sha, data + position, len); + } + + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret); + LogStr("data[%u]: [%p]\n", (word32)len, data); + LogHex(data, 0, len); +#else + (void)env; + (void)this; + (void)data_buffer; + (void)position; + (void)len; + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1update_1internal___3BII + (JNIEnv* env, jobject this, jbyteArray data_buffer, jint offset, jint len) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = NULL; + byte* data = NULL; + word32 dataSz = 0; + + sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + data = getByteArray(env, data_buffer); + dataSz = getByteArrayLength(env, data_buffer); + + if (sha == NULL || data == NULL || + (word32)(offset + len) > dataSz) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_Sha224Update(sha, data + offset, len); + } + + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } + + LogStr("wc_Sha224Update(sha=%p, data, len) = %d\n", sha, ret); + LogStr("data[%u]: [%p]\n", (word32)len, data + offset); + LogHex(data, offset, len); + + releaseByteArray(env, data_buffer, data, JNI_ABORT); +#else + (void)env; + (void)this; + (void)data_buffer; + (void)offset; + (void)len; + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal__Ljava_nio_ByteBuffer_2I + (JNIEnv* env, jobject this, jobject hash_buffer, jint position) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = NULL; + byte* hash = NULL; + + sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + hash = getDirectBufferAddress(env, hash_buffer); + + if (sha == NULL || hash == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_Sha224Final(sha, hash + position); + } + + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } + + 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); +#else + (void)env; + (void)this; + (void)hash_buffer; + (void)position; + throwNotCompiledInException(env); +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Sha224_native_1final_1internal___3B + (JNIEnv* env, jobject this, jbyteArray hash_buffer) +{ +#ifdef WOLFSSL_SHA224 + int ret = 0; + Sha224* sha = NULL; + byte* hash = NULL; + + sha = (Sha224*) getNativeStruct(env, this); + if ((*env)->ExceptionOccurred(env)) { + /* getNativeStruct may throw exception, prevent throwing another */ + return; + } + + hash = getByteArray(env, hash_buffer); + + if (sha == NULL || hash == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = wc_Sha224Final(sha, hash); + } + + if (ret != 0) { + throwWolfCryptExceptionFromError(env, ret); + } + + 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); + + releaseByteArray(env, hash_buffer, hash, ret); +#else + (void)env; + (void)this; + (void)hash_buffer; + throwNotCompiledInException(env); +#endif +} + diff --git a/scripts/infer.sh b/scripts/infer.sh index 11720f6..fb6d325 100755 --- a/scripts/infer.sh +++ b/scripts/infer.sh @@ -53,6 +53,7 @@ infer --fail-on-issue run -- javac \ src/main/java/com/wolfssl/wolfcrypt/Rng.java \ src/main/java/com/wolfssl/wolfcrypt/Rsa.java \ src/main/java/com/wolfssl/wolfcrypt/Sha.java \ + src/main/java/com/wolfssl/wolfcrypt/Sha224.java \ src/main/java/com/wolfssl/wolfcrypt/Sha256.java \ src/main/java/com/wolfssl/wolfcrypt/Sha384.java \ src/main/java/com/wolfssl/wolfcrypt/Sha512.java \ diff --git a/src/main/java/com/wolfssl/wolfcrypt/Sha224.java b/src/main/java/com/wolfssl/wolfcrypt/Sha224.java new file mode 100644 index 0000000..f32c74f --- /dev/null +++ b/src/main/java/com/wolfssl/wolfcrypt/Sha224.java @@ -0,0 +1,239 @@ +/* Sha224.java + * + * Copyright (C) 2006-2025 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.wolfcrypt; + +import java.nio.ByteBuffer; + +/** + * Wrapper for the native WolfCrypt SHA2-224 implementation + */ +public class Sha224 extends MessageDigest implements Cloneable { + + /** SHA2-224 hash type */ + public static final int TYPE = 5; /* hash type unique */ + /** SHA2-224 digest size */ + public static final int DIGEST_SIZE = 28; + + /** Array to init Sha224 with, will be reset to null once initialized */ + private byte[] initialData = null; + + /* 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 long mallocNativeStruct_internal() throws OutOfMemoryError; + private native void native_init_internal(); + private native void native_copy_internal(Sha224 toBeCopied); + private native void native_update_internal(ByteBuffer data, int offset, + int len); + private native void native_update_internal(byte[] data, int offset, + int len); + private native void native_final_internal(ByteBuffer hash, int offset); + private native void native_final_internal(byte[] hash); + + /** + * Malloc native JNI Sha224 structure + * + * @return native allocated pointer + * + * @throws OutOfMemoryError when malloc fails with memory error + */ + protected long mallocNativeStruct() + throws OutOfMemoryError { + + synchronized (pointerLock) { + return mallocNativeStruct_internal(); + } + } + + /** + * Initialize Sha224 object + * + * @throws WolfCryptException if native operation fails + */ + protected void native_init() + throws WolfCryptException { + + synchronized (pointerLock) { + native_init_internal(); + + /* Check if we need to init with passed in data */ + if (this.initialData != null) { + update(this.initialData); + this.initialData = null; + } + } + } + + /** + * Copy existing native WC_SHA224 struct (Sha224 object) into this one. + * Copies structure state using wc_Sha224Copy(). + * + * @param toBeCopied initialized Sha224 object to be copied. + * + * @throws WolfCryptException if native operation fails + */ + protected void native_copy(Sha224 toBeCopied) + throws WolfCryptException { + + synchronized (pointerLock) { + native_copy_internal(toBeCopied); + } + } + + /** + * Native SHA2-224 update + * + * @param data input data + * @param offset offset into input data + * @param len length of input data + * + * @throws WolfCryptException if native operation fails + */ + protected void native_update(ByteBuffer data, int offset, int len) + throws WolfCryptException { + + synchronized (pointerLock) { + native_update_internal(data, offset, len); + } + } + + /** + * Native SHA2-224 update + * + * @param data input data + * @param offset offset into input data + * @param len length of input data + * + * @throws WolfCryptException if native operation fails + */ + protected void native_update(byte[] data, int offset, int len) + throws WolfCryptException { + + synchronized (pointerLock) { + native_update_internal(data, offset, len); + } + } + + /** + * Native SHA2-224 final, calculate final digest + * + * @param hash output buffer to place digest + * @param offset offset into output buffer to write digest + * + * @throws WolfCryptException if native operation fails + */ + protected void native_final(ByteBuffer hash, int offset) + throws WolfCryptException { + + synchronized (pointerLock) { + native_final_internal(hash, offset); + } + } + + /** + * Native SHA2-224 final, calculate final digest + * + * @param hash output buffer to place digest + * + * @throws WolfCryptException if native operation fails + */ + protected void native_final(byte[] hash) + throws WolfCryptException { + + synchronized (pointerLock) { + native_final_internal(hash); + } + } + + /** + * Create new SHA2-224 object. + * + * @throws WolfCryptException if SHA-224 has not been compiled into native + * wolfCrypt library. + */ + public Sha224() { + if (!FeatureDetect.Sha224Enabled()) { + throw new WolfCryptException( + WolfCryptError.NOT_COMPILED_IN.getCode()); + } + /* Internal state is initialized on first use */ + } + + /** + * Create new SHA2-224 object by making a copy of the one given. + * + * @param sha224 Initialized/created Sha224 object to be copied + * + * @throws WolfCryptException to indicate this constructor has been + * deprecated, along with instructions on what API to call + * + * @deprecated This constructor has been deprecated to avoid storage + * of a second Sha224 object inside this Sha224 object, and to + * avoid potential incomplete object creation issues between + * subclass/superclasses. Please refactor existing code to + * call Sha224.clone() to get a copy of an existing Sha224 + * object. + */ + @Deprecated + public Sha224(Sha224 sha224) { + throw new WolfCryptException( + "Constructor deprecated, use Sha224.clone() to duplicate " + + "Sha224 object"); + } + + /** + * Create new SHA2-224 object. + * + * @param data input data to hash + * + * @throws WolfCryptException if SHA-224 has not been compiled into native + * wolfCrypt library. + */ + public Sha224(byte[] data) { + if (!FeatureDetect.Sha224Enabled()) { + throw new WolfCryptException( + WolfCryptError.NOT_COMPILED_IN.getCode()); + } + /* Internal state is initialized on first use */ + this.initialData = data.clone(); + } + + /** + * Get SHA2-224 digest size + * + * @return SHA2-224 digest size + */ + public int digestSize() { + return DIGEST_SIZE; + } + + @Override + public Object clone() { + + Sha224 shaCopy = new Sha224(); + /* Initialize NativeStruct, since is done on first use */ + shaCopy.checkStateAndInitialize(); + shaCopy.native_copy(this); + + return shaCopy; + } +} diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/Sha224Test.java b/src/test/java/com/wolfssl/wolfcrypt/test/Sha224Test.java new file mode 100644 index 0000000..df49811 --- /dev/null +++ b/src/test/java/com/wolfssl/wolfcrypt/test/Sha224Test.java @@ -0,0 +1,244 @@ +/* Sha224Test.java + * + * Copyright (C) 2006-2025 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.wolfcrypt.test; + +import static org.junit.Assert.*; + +import java.nio.ByteBuffer; +import java.util.Random; +import java.util.Arrays; +import java.util.Iterator; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; +import javax.crypto.ShortBufferException; + +import org.junit.Test; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +import com.wolfssl.wolfcrypt.Sha224; +import com.wolfssl.wolfcrypt.NativeStruct; +import com.wolfssl.wolfcrypt.WolfCryptException; +import com.wolfssl.wolfcrypt.WolfCryptError; + +public class Sha224Test { + private ByteBuffer data = ByteBuffer.allocateDirect(64); + private ByteBuffer result = ByteBuffer.allocateDirect(Sha224.DIGEST_SIZE); + private ByteBuffer expected = ByteBuffer.allocateDirect(Sha224.DIGEST_SIZE); + + static String[] dataVector = new String[] { + "", + "abc", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + }; + static String[] hashVector = new String[] { + "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" + }; + + @Rule(order = Integer.MIN_VALUE) + public TestRule testWatcher = new TestWatcher() { + protected void starting(Description desc) { + System.out.println("\t" + desc.getMethodName()); + } + }; + + @BeforeClass + public static void checkSha224IsAvailable() { + try { + Sha224 sha = new Sha224(); + System.out.println("JNI Sha224 Class"); + } catch (WolfCryptException e) { + if (e.getError() == WolfCryptError.NOT_COMPILED_IN) { + System.out.println("Sha224Test skipped: " + e.getError()); + Assume.assumeTrue(false); + } + } + } + + @Test + public void constructorShouldNotInitializeNativeStruct() { + assertEquals(NativeStruct.NULL, new Sha224().getNativeStruct()); + } + + @Test + public void hashShouldMatchUsingByteBuffer() throws ShortBufferException { + + for (int i = 0; i < dataVector.length; i++) { + Sha224 sha = new Sha224(); + byte[] input = dataVector[i].getBytes(); + + data.put(input).rewind(); + expected.put(Util.h2b(hashVector[i])).rewind(); + + sha.update(data, input.length); + sha.digest(result); + data.rewind(); + result.rewind(); + + assertEquals(expected, result); + } + } + + @Test + public void hashShouldMatchUsingByteArray() { + + for (int i = 0; i < dataVector.length; i++) { + Sha224 sha = new Sha224(); + + byte[] data = dataVector[i].getBytes(); + byte[] expected = Util.h2b(hashVector[i]); + + sha.update(data); + byte[] result = sha.digest(); + + assertArrayEquals(expected, result); + } + } + + @Test + public void releaseAndReInitObject() { + + Sha224 sha = new Sha224(); + byte[] data = dataVector[0].getBytes(); + byte[] expected = Util.h2b(hashVector[0]); + byte[] result = null; + + sha.update(data); + result = sha.digest(); + assertArrayEquals(expected, result); + sha.releaseNativeStruct(); + + /* test re-initializing object */ + sha = new Sha224(); + result = null; + sha.update(data); + result = sha.digest(); + sha.releaseNativeStruct(); + } + + @Test + public void reuseObject() { + + Sha224 sha = new Sha224(); + byte[] data = dataVector[0].getBytes(); + byte[] data2 = dataVector[1].getBytes(); + byte[] expected = Util.h2b(hashVector[0]); + byte[] expected2 = Util.h2b(hashVector[1]); + byte[] result = null; + byte[] result2 = null; + + sha.update(data); + result = sha.digest(); + assertArrayEquals(expected, result); + + /* test reusing existing object after a call to digest() */ + sha.update(data2); + result2 = sha.digest(); + assertArrayEquals(expected2, result2); + + sha.releaseNativeStruct(); + } + + @Test + public void copyObject() { + + Sha224 sha = null; + Sha224 shaCopy = null; + byte[] data = dataVector[0].getBytes(); + byte[] expected = Util.h2b(hashVector[0]); + byte[] result = null; + byte[] result2 = null; + + sha = new Sha224(); + sha.update(data); + + /* test making copy of Sha224, should retain same state */ + shaCopy = (Sha224)sha.clone(); + + result = sha.digest(); + result2 = shaCopy.digest(); + + assertArrayEquals(expected, result); + assertArrayEquals(expected, result2); + + sha.releaseNativeStruct(); + shaCopy.releaseNativeStruct(); + } + + @Test + public void threadedHashTest() throws InterruptedException { + + int numThreads = 100; + ExecutorService service = Executors.newFixedThreadPool(numThreads); + final CountDownLatch latch = new CountDownLatch(numThreads); + final LinkedBlockingQueue results = new LinkedBlockingQueue<>(); + final byte[] rand10kBuf = new byte[10240]; + + /* fill large input buffer with random bytes */ + new Random().nextBytes(rand10kBuf); + + /* generate hash over input data concurrently across numThreads */ + for (int i = 0; i < numThreads; i++) { + service.submit(new Runnable() { + @Override public void run() { + Sha224 sha = new Sha224(); + + /* process/update in 1024-byte chunks */ + for (int j = 0; j < rand10kBuf.length; j+= 1024) { + sha.update(rand10kBuf, j, 1024); + } + + /* get final hash */ + byte[] hash = sha.digest(); + results.add(hash.clone()); + + sha.releaseNativeStruct(); + latch.countDown(); + } + }); + } + + /* wait for all threads to complete */ + latch.await(); + + /* compare all digests, all should be the same across threads */ + Iterator listIterator = results.iterator(); + byte[] current = listIterator.next(); + while (listIterator.hasNext()) { + byte[] next = listIterator.next(); + if (!Arrays.equals(current, next)) { + fail("Found two non-identical digests in thread test"); + } + if (listIterator.hasNext()) { + current = listIterator.next(); + } + } + } +} \ No newline at end of file diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/WolfCryptTestSuite.java b/src/test/java/com/wolfssl/wolfcrypt/test/WolfCryptTestSuite.java index 044fe48..4430d9b 100644 --- a/src/test/java/com/wolfssl/wolfcrypt/test/WolfCryptTestSuite.java +++ b/src/test/java/com/wolfssl/wolfcrypt/test/WolfCryptTestSuite.java @@ -33,6 +33,7 @@ import org.junit.runners.Suite.SuiteClasses; ChachaTest.class, Md5Test.class, ShaTest.class, + Sha224Test.class, Sha256Test.class, Sha384Test.class, Sha512Test.class,