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
8 changes: 8 additions & 0 deletions jni/include/com_wolfssl_wolfcrypt_FeatureDetect.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions jni/jni_feature_detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <wolfssl/version.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/dh.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfcrypt_jni_debug.h>

JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_Md5Enabled
Expand Down Expand Up @@ -904,3 +905,16 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_XmssEnabled
return JNI_FALSE;
#endif
}

JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_RngHealthTestEnabled
(JNIEnv* env, jclass jcl)
{
(void)env;
(void)jcl;
#if defined(HAVE_FIPS) && \
(!defined(WC_FIPS_LOCAL_API) || defined(WOLFSSL_FIPS_EXPORT_LOCAL_APIS))
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
15 changes: 13 additions & 2 deletions jni/jni_fips.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@
/* #define WOLFCRYPT_JNI_DEBUG_ON */
#include <wolfcrypt_jni_debug.h>

/* Native wolfSSL marks the wc_RNG_HealthTest*() family WOLFSSL_LOCAL in FIPS
* builds so applications cannot run the DRBG health test with arbitrary seeds
* (FIPS 140-3 IG 9.3.A). They are only exported from FIPS builds that define
* WOLFSSL_FIPS_EXPORT_LOCAL_APIS. wolfSSL versions with this behavior define
* WC_FIPS_LOCAL_API in random.h, older versions always export the health
* test. */
#if defined(HAVE_FIPS) && \
(!defined(WC_FIPS_LOCAL_API) || defined(WOLFSSL_FIPS_EXPORT_LOCAL_APIS))
#define WOLFCRYPT_JNI_FIPS_RNG_HEALTHTEST
#endif

#ifdef HAVE_FIPS
extern JavaVM* g_vm;
static jobject g_errCb;
Expand Down Expand Up @@ -2211,7 +2222,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1HealthTest_1fips
{
jint ret = NOT_COMPILED_IN;

#if defined(HAVE_FIPS)
#if defined(WOLFCRYPT_JNI_FIPS_RNG_HEALTHTEST)

const byte* entropyA = getDirectBufferAddress(env, entropyA_object);
const byte* entropyB = getDirectBufferAddress(env, entropyB_object);
Expand Down Expand Up @@ -2251,7 +2262,7 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1RNG_1HealthTest_1fips
{
jint ret = NOT_COMPILED_IN;

#if defined(HAVE_FIPS)
#if defined(WOLFCRYPT_JNI_FIPS_RNG_HEALTHTEST)

jboolean entropyAIsCopy = JNI_FALSE;
jboolean entropyBIsCopy = JNI_FALSE;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/wolfssl/wolfcrypt/FeatureDetect.java
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,18 @@ public class FeatureDetect {
*/
public static native boolean XmssEnabled();

/**
* Tests if the wolfCrypt FIPS Hash_DRBG health test is available through
* Fips.RNG_HealthTest_fips().
*
* Always false in non-FIPS builds. Native wolfSSL FIPS builds do not
* export the DRBG health test unless compiled with
* WOLFSSL_FIPS_EXPORT_LOCAL_APIS.
*
* @return true if Fips.RNG_HealthTest_fips() is available, otherwise false.
*/
public static native boolean RngHealthTestEnabled();

/**
* Loads JNI library.
*
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/com/wolfssl/wolfcrypt/Fips.java
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,10 @@ public static int RNG_GenerateBlock_fips(Rng rng, byte[] buf, long bufSz) {
* bytes entropyBSz and then tests the RNG against the expected output of
* size in bytes outputSz.
*
* Native wolfSSL FIPS builds do not export the DRBG health test unless
* compiled with WOLFSSL_FIPS_EXPORT_LOCAL_APIS (FIPS 140-3 IG 9.3.A). Use
* FeatureDetect.RngHealthTestEnabled() to check availability.
*
* @param reseed the reseed flag.
* @param entropyA the entropyA buffer.
* @param entropyASz the entropyA length.
Expand All @@ -1029,7 +1033,8 @@ public static int RNG_GenerateBlock_fips(Rng rng, byte[] buf, long bufSz) {
* @param output the output buffer.
* @param outputSz the output length.
*
* @return 0 on success, {@literal <} 0 on error.
* @return 0 on success, {@literal <} 0 on error, NOT_COMPILED_IN if the
* native DRBG health test is not available.
*/
public static int RNG_HealthTest_fips(int reseed, ByteBuffer entropyA,
long entropyASz, ByteBuffer entropyB, long entropyBSz,
Expand All @@ -1050,6 +1055,10 @@ public static int RNG_HealthTest_fips(int reseed, ByteBuffer entropyA,
* bytes entropyBSz and then tests the RNG against the expected output of
* size in bytes outputSz.
*
* Native wolfSSL FIPS builds do not export the DRBG health test unless
* compiled with WOLFSSL_FIPS_EXPORT_LOCAL_APIS (FIPS 140-3 IG 9.3.A). Use
* FeatureDetect.RngHealthTestEnabled() to check availability.
*
* @param reseed the reseed flag.
* @param entropyA the entropyA buffer.
* @param entropyASz the entropyA length.
Expand All @@ -1058,7 +1067,8 @@ public static int RNG_HealthTest_fips(int reseed, ByteBuffer entropyA,
* @param output the output buffer.
* @param outputSz the output length.
*
* @return 0 on success, {@literal <} 0 on error.
* @return 0 on success, {@literal <} 0 on error, NOT_COMPILED_IN if the
* native DRBG health test is not available.
*/
public static int RNG_HealthTest_fips(int reseed, byte[] entropyA,
long entropyASz, byte[] entropyB, long entropyBSz, byte[] output,
Expand Down
16 changes: 16 additions & 0 deletions src/test/java/com/wolfssl/wolfcrypt/test/RngTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import static org.junit.Assert.*;

import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Rule;
Expand All @@ -39,6 +40,9 @@
import java.util.concurrent.LinkedBlockingQueue;

import com.wolfssl.wolfcrypt.Rng;
import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.wolfcrypt.FeatureDetect;
import com.wolfssl.wolfcrypt.WolfCryptError;
import com.wolfssl.wolfcrypt.NativeStruct;
import com.wolfssl.wolfcrypt.WolfCryptException;
import com.wolfssl.wolfcrypt.test.TimedTestWatcher;
Expand All @@ -58,6 +62,18 @@ public void constructorShouldNotInitializeNativeStruct() {
assertEquals(NativeStruct.NULL, new Rng().getNativeStruct());
}

@Test
public void rngHealthTestNotDetectedInNonFipsBuild() {
/* Fips.RNG_HealthTest_fips() only exists in FIPS builds, so
* FeatureDetect must not report it as available otherwise */
Assume.assumeFalse("FIPS enabled", Fips.enabled);

assertFalse(FeatureDetect.RngHealthTestEnabled());
assertEquals(WolfCryptError.NOT_COMPILED_IN.getCode(),
Fips.RNG_HealthTest_fips(0, new byte[48], 48, null, 0,
new byte[128], 128));
}

@Test
public void testInitFree() {
Rng wcRng = new Rng();
Expand Down
31 changes: 31 additions & 0 deletions src/test/java/com/wolfssl/wolfcrypt/test/fips/RngFipsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.nio.ByteBuffer;
import java.util.Arrays;

import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Rule;
Expand All @@ -37,6 +38,7 @@
import com.wolfssl.wolfcrypt.WolfCrypt;
import com.wolfssl.wolfcrypt.WolfCryptError;
import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.wolfcrypt.FeatureDetect;

import com.wolfssl.wolfcrypt.test.Util;
import com.wolfssl.wolfcrypt.test.TimedTestWatcher;
Expand All @@ -54,6 +56,11 @@ public static void setupClass() {
System.out.println("JNI FIPS RNG Tests");
}

private static void assumeRngHealthTestEnabled() {
Assume.assumeTrue("RNG health test not exported by native wolfSSL",
FeatureDetect.RngHealthTestEnabled());
}

@Test
public void initShouldReturnZero() {
Rng rng = new Rng();
Expand Down Expand Up @@ -123,6 +130,8 @@ public void GenerateBlockShouldRejectBadBufSzUsingByteArray() {

@Test
public void HeathTestShouldReturnZeroUsingByteBuffer() {
assumeRngHealthTestEnabled();

String[] inputA = new String[] {
"1734476fa80d0c74ee6c77c760223ccbbbebaac8d4f59fe3a1aba7be35a7d8ef5acd22db2cbbac88009c04776f99da06",
"5eb3049f0b85b3a3a2bfd775ee10b68c4ff232e9695601f7f1b175643960f93f86418d771c91ca3b718aad20160c6bc2",
Expand Down Expand Up @@ -155,6 +164,8 @@ public void HeathTestShouldReturnZeroUsingByteBuffer() {

@Test
public void HeathTestShouldReturnZeroUsingByteArray() {
assumeRngHealthTestEnabled();

String[] inputA = new String[] {
"1734476fa80d0c74ee6c77c760223ccbbbebaac8d4f59fe3a1aba7be35a7d8ef5acd22db2cbbac88009c04776f99da06",
"5eb3049f0b85b3a3a2bfd775ee10b68c4ff232e9695601f7f1b175643960f93f86418d771c91ca3b718aad20160c6bc2",
Expand Down Expand Up @@ -187,6 +198,8 @@ public void HeathTestShouldReturnZeroUsingByteArray() {

@Test
public void healthTestShouldRejectUndersizedOutputUsingByteArray() {
assumeRngHealthTestEnabled();

/* outputSz claims 256 bytes but the array is only 1 byte */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_HealthTest_fips(0, new byte[48], 48, null, 0,
Expand All @@ -195,6 +208,8 @@ public void healthTestShouldRejectUndersizedOutputUsingByteArray() {

@Test
public void healthTestShouldRejectUndersizedEntropyBUsingByteArray() {
assumeRngHealthTestEnabled();

/* with reseed set, entropyB must hold entropyBSz bytes */
assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_HealthTest_fips(1, new byte[48], 48, new byte[1], 32,
Expand All @@ -203,13 +218,29 @@ public void healthTestShouldRejectUndersizedEntropyBUsingByteArray() {

@Test
public void healthTestShouldRejectUndersizedOutputUsingByteBuffer() {
assumeRngHealthTestEnabled();

ByteBuffer entropyA = ByteBuffer.allocateDirect(48);
ByteBuffer output = ByteBuffer.allocateDirect(1);

assertEquals(WolfCryptError.BAD_FUNC_ARG.getCode(),
Fips.RNG_HealthTest_fips(0, entropyA, 48, null, 0, output, 256));
}

@Test
public void healthTestShouldReturnNotCompiledInWhenUnavailable() {
Assume.assumeFalse("RNG health test exported by native wolfSSL",
FeatureDetect.RngHealthTestEnabled());

/* must return NOT_COMPILED_IN, not call a missing native symbol */
assertEquals(WolfCryptError.NOT_COMPILED_IN.getCode(),
Fips.RNG_HealthTest_fips(0, new byte[48], 48, null, 0,
new byte[128], 128));
assertEquals(WolfCryptError.NOT_COMPILED_IN.getCode(),
Fips.RNG_HealthTest_fips(0, ByteBuffer.allocateDirect(48), 48,
null, 0, ByteBuffer.allocateDirect(128), 128));
}

@Test
public void generateBlockShouldRejectUndersizedBufferUsingByteArray() {
Rng rng = new Rng();
Expand Down
Loading