JNI/JCE: only run FIPS CASTs once up front, for JCE run once when WolfCryptProvider is created

pull/84/head
Chris Conlon 2024-12-03 10:53:04 -07:00
parent 3b627be193
commit acbad58f17
6 changed files with 255 additions and 146 deletions

View File

@ -49,6 +49,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_setPrivateKeyReadEnable
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_getPrivateKeyReadEnable
(JNIEnv *, jclass, jint);
/*
* Class: com_wolfssl_wolfcrypt_Fips
* Method: wc_runAllCast_fips
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1runAllCast_1fips
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_wolfcrypt_Fips
* Method: getFipsVersion

View File

@ -170,6 +170,177 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_getPrivateKeyReadEnable
return ret;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_wc_1runAllCast_1fips
(JNIEnv* jenv, jclass jcl)
{
#if defined (WC_RNG_SEED_CB) || (defined(HAVE_FIPS) && \
defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 5))
int ret = 0;
#endif
int failCount = 0;
(void)jenv;
(void)jcl;
#ifdef WC_RNG_SEED_CB
ret = wc_SetSeed_Cb(wc_GenerateSeed);
if (ret != 0) {
printf("wc_SetSeed_Cb() failed");
}
#endif
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION >= 7)
failCount = wc_RunAllCast_fips();
if (failCount != 0) {
printf("FIPS CASTs failed to run");
}
#elif defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION == 5)
/* run FIPS 140-3 conditional algorithm self tests early to prevent
* multi threaded issues later on */
#if !defined(NO_AES) && !defined(NO_AES_CBC)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_AES_CBC);
if (ret != 0) {
printf("AES-CBC CAST failed");
failCount++;
}
}
#endif
#ifdef HAVE_AESGCM
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_AES_GCM);
if (ret != 0) {
printf("AES-GCM CAST failed");
failCount++;
}
}
#endif
#ifndef NO_SHA
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA1);
if (ret != 0) {
printf("HMAC-SHA1 CAST failed");
failCount++;
}
}
#endif
/* the only non-optional CAST */
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_256);
if (ret != 0) {
printf("HMAC-SHA2-256 CAST failed");
failCount++;
}
}
#ifdef WOLFSSL_SHA512
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_512);
if (ret != 0) {
printf("HMAC-SHA2-512 CAST failed");
failCount++;
}
}
#endif
#ifdef WOLFSSL_SHA3
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA3_256);
if (ret != 0) {
printf("HMAC-SHA3-256 CAST failed");
failCount++;
}
}
#endif
#ifdef HAVE_HASHDRBG
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_DRBG);
if (ret != 0) {
printf("Hash_DRBG CAST failed");
failCount++;
}
}
#endif
#ifndef NO_RSA
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_RSA_SIGN_PKCS1v15);
if (ret != 0) {
printf("RSA sign CAST failed");
failCount++;
}
}
#endif
#if defined(HAVE_ECC_CDH) && defined(HAVE_ECC_CDH_CAST)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECC_CDH);
if (ret != 0) {
printf("ECC CDH CAST failed");
failCount++;
}
}
#endif
#ifdef HAVE_ECC_DHE
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECC_PRIMITIVE_Z);
if (ret != 0) {
printf("ECC Primitive Z CAST failed");
failCount++;
}
}
#endif
#ifdef HAVE_ECC
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECDSA);
if (ret != 0) {
printf("ECDSA CAST failed");
failCount++;
}
}
#endif
#ifndef NO_DH
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_DH_PRIMITIVE_Z);
if (ret != 0) {
printf("DH Primitive Z CAST failed");
failCount++;
}
}
#endif
#ifdef WOLFSSL_HAVE_PRF
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_TLS12);
if (ret != 0) {
printf("KDF TLSv1.2 CAST failed");
failCount++;
}
}
#endif
#if defined(WOLFSSL_HAVE_PRF) && defined(WOLFSSL_TLS13)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_TLS13);
if (ret != 0) {
printf("KDF TLSv1.3 CAST failed");
failCount++;
}
}
#endif
#ifdef WOLFSSL_WOLFSSH
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_SSH);
if (ret != 0) {
printf("KDF SSHv2.0 CAST failed");
failCount++;
}
}
#endif
#endif /* HAVE_FIPS && HAVE_FIPS_VERSION == 5 */
return failCount;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Fips_getFipsVersion
(JNIEnv* env, jclass this)
{

View File

@ -40,152 +40,13 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfObject_init
(void)jenv;
(void)jcl;
int ret = 0;
#ifdef WC_RNG_SEED_CB
ret = wc_SetSeed_Cb(wc_GenerateSeed);
if (ret != 0) {
printf("wc_SetSeed_Cb() failed");
}
#endif
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION >= 7)
ret = wc_RunAllCast_fips();
if (ret != 0) {
printf("FIPS CASTs failed to run");
}
#elif defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION == 5)
/* run FIPS 140-3 conditional algorithm self tests early to prevent
* multi threaded issues later on */
#if !defined(NO_AES) && !defined(NO_AES_CBC)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_AES_CBC);
if (ret != 0) {
printf("AES-CBC CAST failed");
}
}
#endif
#ifdef HAVE_AESGCM
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_AES_GCM);
if (ret != 0) {
printf("AES-GCM CAST failed");
}
}
#endif
#ifndef NO_SHA
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA1);
if (ret != 0) {
printf("HMAC-SHA1 CAST failed");
}
}
#endif
/* the only non-optional CAST */
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_256);
if (ret != 0) {
printf("HMAC-SHA2-256 CAST failed");
}
}
#ifdef WOLFSSL_SHA512
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA2_512);
if (ret != 0) {
printf("HMAC-SHA2-512 CAST failed");
}
}
#endif
#ifdef WOLFSSL_SHA3
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_HMAC_SHA3_256);
if (ret != 0) {
printf("HMAC-SHA3-256 CAST failed");
}
}
#endif
#ifdef HAVE_HASHDRBG
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_DRBG);
if (ret != 0) {
printf("Hash_DRBG CAST failed");
}
}
#endif
#ifndef NO_RSA
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_RSA_SIGN_PKCS1v15);
if (ret != 0) {
printf("RSA sign CAST failed");
}
}
#endif
#if defined(HAVE_ECC_CDH) && defined(HAVE_ECC_CDH_CAST)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECC_CDH);
if (ret != 0) {
printf("ECC CDH CAST failed");
}
}
#endif
#ifdef HAVE_ECC_DHE
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECC_PRIMITIVE_Z);
if (ret != 0) {
printf("ECC Primitive Z CAST failed");
}
}
#endif
#ifdef HAVE_ECC
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_ECDSA);
if (ret != 0) {
printf("ECDSA CAST failed");
}
}
#endif
#ifndef NO_DH
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_DH_PRIMITIVE_Z);
if (ret != 0) {
printf("DH Primitive Z CAST failed");
}
}
#endif
#ifdef WOLFSSL_HAVE_PRF
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_TLS12);
if (ret != 0) {
printf("KDF TLSv1.2 CAST failed");
}
}
#endif
#if defined(WOLFSSL_HAVE_PRF) && defined(WOLFSSL_TLS13)
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_TLS13);
if (ret != 0) {
printf("KDF TLSv1.3 CAST failed");
}
}
#endif
#ifdef WOLFSSL_WOLFSSH
if (ret == 0) {
ret = wc_RunCast_fips(FIPS_CAST_KDF_SSH);
if (ret != 0) {
printf("KDF SSHv2.0 CAST failed");
}
}
#endif
#endif /* HAVE_FIPS && HAVE_FIPS_VERSION == 5 */
if (ret < 0) {
return ret;
}
/* Code which runs the FIPS CASTs up front has been moved to the
* com.wolfssl.wolfcrypt.Fips.runAllCast_fips() method. runAllCast_fips()
* includes a synchronized check that only runs the CASTs once as long
* as they were successful. Fips.runAllCast_fips() is called at both
* the JNI-only level (WolfObject.init()), and the JCE level
* (WolfCryptProvider constructor). Both of these runAllCast_fips()
* at JNI/JCE levels are called before this wolfCrypt_Init() below. */
return (jint)wolfCrypt_Init();
}

View File

@ -60,6 +60,11 @@ public final class WolfCryptProvider extends Provider {
String mapJksToWks = null;
String mapPkcs12ToWks = null;
/* Run FIPS algorithm self tests (CASTs) if needed */
if (Fips.enabled) {
Fips.runAllCast_fips();
}
/* MessageDigest */
if (FeatureDetect.Md5Enabled()) {
put("MessageDigest.MD5",

View File

@ -52,6 +52,13 @@ public class Fips extends WolfObject {
/** Native wolfCrypt FIPS version (HAVE_FIPS_VERSION) */
public static final int fipsVersion = Fips.getFipsVersion();
/* Internal flag to keep track of if FIPS CAST has already been run and
* passed successfully. */
private static volatile boolean fipsCastRunSuccessfully = false;
/* Lock around fipsCastRunSuccessfully */
private static final Object fipsCastLock = new Object();
private Fips() {
}
@ -119,6 +126,55 @@ public class Fips extends WolfObject {
*/
public static native int getPrivateKeyReadEnable(int keyType);
/**
* Native JNI wrapper around running FIPS CASTs.
*
* Called by public runAllCast_fips() in this class.
*
* @return 0 on success, otherwise greater than zero if some algorithm
* self tests have failed. The count of tests failed will be
* returned on error.
*/
private static native int wc_runAllCast_fips();
/**
* Run all FIPS Conditional Algorithm Self Tests (CAST).
*
* In wolfCrypt FIPS 140-3, the algorithm self tests are Conditional (CAST),
* meaning they will run on-demand per algorithm the first time that
* algorithm is used. This can be convienent for startup time if on a
* single threaded application, but can introduce potentially unwanted
* errors at runtime if operating in a multi threaded environment where
* multiple threads will be using wolfCrypt cryptography in parallel. If
* one thread is actively running an algorithm CAST and another thread
* tries to use the algorithm, it may return a FIPS not allowed error.
*
* To avoid multi threaded errors at runtime due to the above, this method
* can be called once up front when an application starts. It will run
* all algorithm CASTS, and if run before threaded operations start will
* avoid the FIPS not allowed errors which may occur otherwise.
*
* @return 0 on success, otherwise greater than zero if some algorithm
* self tests have failed. The count of tests failed will be
* returned on error.
*/
public static int runAllCast_fips() {
int ret = 0;
synchronized (fipsCastLock) {
if (!fipsCastRunSuccessfully) {
ret = wc_runAllCast_fips();
if (ret == 0) {
/* Only forcefully run FIPS CAST once */
fipsCastRunSuccessfully = true;
}
}
}
return ret;
}
private static native int getFipsVersion();
/*

View File

@ -21,6 +21,8 @@
package com.wolfssl.wolfcrypt;
import com.wolfssl.wolfcrypt.Fips;
/**
* Loader for the native WolfCrypt implementation.
* All classes in this package must inherit from it.
@ -62,6 +64,12 @@ public class WolfObject {
/* Load wolfcryptjni library */
System.loadLibrary("wolfcryptjni");
/* Run FIPS CAST if we are in FIPS mode. Will only forcefully
* be run once - Fips class keeps track of a successful run. */
if (Fips.enabled) {
Fips.runAllCast_fips();
}
/* initialize native wolfCrypt library */
init();
}