diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
index 00000000..90c7d2e4
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,155 @@
+### wolfCrypt JNI Release 1.6.0 (4/17/2024)
+
+Release 1.6.0 of wolfCrypt JNI and JCE has bug fixes and new features including:
+
+**New JCE Functionality:**
+- Add RSA support to `KeyPairGenerator` class (PR 49)
+- Add `AES/CBC/PKCS5Padding` support to `Cipher` class (PR 51)
+- Add `RSA` support to `Cipher` class (PR 51)
+- Add `PKIX` implementation of `CertPathValidator` class (PR 60, 66)
+- Add `SHA1` alias for `MessageDigest` `SHA-1` for interop compatibility (PR 61)
+- Add `AES/GCM/NoPadding` support to `Cipher` class (PR 62)
+- Add `SecretKeyFactory` implementation supporting `PBKDF2` (PR 70)
+- Add `DEFAULT` support to `SecureRandom` class (PR 72)
+
+**New JNI Wrapped APIs and Functionality:**
+- Add `AES-GCM` support to `com.wolfssl.wolfcrypt.AesGcm` class (PR 62)
+
+**JNI and JCE Changes:**
+- Add synchronization to `com.wolfssl.wolfcrypt.Rng` class (PR 44)
+- Correct preprocessor guards for 3DES with wolfCrypt FIPS (PR 47)
+- Correct order of operations in `wc_CreatePKCS8Key()` JNI wrapper API (PR 50)
+- Add synchronization around native structure pointer use (PR 53)
+- Remove inclusion of CyaSSL header includes, switch to wolfSSL (PR 56)
+- Call `PRIVATE_KEY_LOCK/UNLOCK()` for wolfCrypt FIPS 140-3 compatibility (PR 57)
+- Improve native HMAC feature detection (PR 58)
+- Prepend zero byte to DH shared secret if less than prime length (PR 69)
+- Add synchronization to protected methods in `WolfCryptSignature` (PR 68)
+- Add synchronization to public methods of `WolfCryptKeyPairGenerator` (PR 73)
+- Only allocate one `Rng` object per `WolfCryptSignature`, not per sign operation (PR 73)
+- Reduce extra `WolfCryptRng` object creation in `Signature` and `KeyPairGenerator` (PR 73)
+
+**New Platform Support:**
+- Add Windows support with Visual Studio, see IDE/WIN/README.md (PR 46)
+
+**Build System Changes:**
+- Support custom wolfSSL library prefix and name in `makefile.linux` (PR 45)
+- Standardize JNI library name on OSX to .dylib (PR 54)
+- Update Maven build support (PR 55)
+
+**Example Changes:**
+- Print provider of `SecureRandom` from `ProviderTest.java` (PR 43)
+- Add Windows batch script to run `ProviderTest` example (PR 52)
+
+**Testing Changes:**
+- Add extended threading test for `WolfCryptRandom` class (PR 44)
+- Add Facebook Infer test script, make fixes (PR 48, 63)
+- Add GitHub Actions tests for Oracle/Zulu/Coretto/Temurin/Microsoft JDKs on Linux and OS X (PR 65)
+
+**Documentation Changes:**
+- Remove build instructions from `README.md` for FIPS historical cert #2425 (PR 56)
+- Fix Javadoc warnings for Java 21 and 22 (PR 71)
+
+The wolfCrypt JNI/JCE Manual is available at:
+https://www.wolfssl.com/documentation/manuals/wolfcryptjni/. For build
+instructions and more details comments, please check the manual.
+
+### wolfCrypt JNI Release 1.5.0 (11/14/2022)
+
+Release 1.5.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- Add build compatibility for Java 7 (PR 38)
+- Add support for "SHA" algorithm string in wolfJCE (PR 39)
+- Add rpm package support (PR 40)
+- Add wolfJCE MessageDigest.clone() support (PR 41)
+- Improve error checking of native Md5 API calls (PR 41)
+- Add unit tests for com.wolfssl.wolfcrypt.Md5 (PR 41)
+
+### wolfCrypt JNI Release 1.4.0 (08/11/2022)
+
+Release 1.4.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- Add example directory with one simple ProviderTest example (PR 32)
+- Fix double free of ChaCha pointer (PR 34)
+- Add test cases for ChaCha.java (PR 34)
+- Skip WolfCryptMacTest for HMAC-MD5 when using wolfCrypt FIPS 140-3 (PR 35)
+- Use new hash struct names (wc\_Md5/wc\_Sha/etc) in native code (PR 35)
+- Fix potential build error with non-ASCII apostrophes in Fips.java (PR 36)
+
+### wolfCrypt JNI Release 1.3.0 (05/13/2022)
+
+Release 1.3.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- Run FIPS tests on `ant test` when linked against a wolfCrypt FIPS library (PR 24)
+- Wrap native AesGcmSetExtIV\_fips() API (PR 24)
+- Fix releaseByteArray() usage in Fips.RsaSSL\_Sign() (PR 24)
+- Fix AES-GCM FIPS test cases (PR 24)
+- Keep existing JAVA\_HOME in makefiles if already set (PR 25)
+- Add JCE support for MessageDigestSpi.engineGetDigestLength() (PR 27)
+- Update junit to 4.13.2 (PR 28)
+- Update missing Javadocs, fixes warnings on newer Java versions (PR 29)
+
+### wolfCrypt JNI Release 1.2.0 (11/16/2021)
+
+Release 1.2.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- Add **FIPS 140-3** compatibility when using wolfCrypt FIPS or FIPS Ready
+- Increase junit version from 4.12 to 4.13 in pom.xml
+- Add local `./lib` directory to `java.library.path` in pom.xml
+- Fix builds with `WOLFCRYPT_JNI_DEBUG_ON` defined
+- Fix compatibility with wolfCrypt `NO_OLD_*` defines
+- Fix compatibility with wolfSSL `./configure --enable-all` and ECC tests
+
+### wolfCrypt JNI Release 1.1.0 (08/26/2020)
+
+Release 1.1.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- New JNI-level wrappers for ChaCha, Curve25519, and Ed25519
+- Maven pom.xml build file
+- Runtime detection of hash type enum values for broader wolfSSL support
+- Updated wolfSSL error codes to match native wolfSSL updates
+- Native HMAC wrapper fixes for building with wolfCrypt FIPSv2
+- Native wrapper to return `HAVE_FIPS_VERSION` value to Java
+- Remove Blake2b from HMAC types, to match native wolfSSL changes
+- Better native wolfSSL feature detection
+- Increase Junit version to 4.13
+- Use nativeheaderdir on supported platforms instead of javah
+- Use hamcrest-all-1.3.jar in build.xml
+- Add call to `wc_ecc_set_rng()` when needed
+
+### wolfCrypt JNI Release 1.0.0 (7/10/2017)
+
+Release 1.0.0 of wolfCrypt JNI has bug fixes and new features including:
+
+- Bug fixes to JCE classes: Cipher, KeyAgreement (DH), Signature
+- JCE debug logging with wolfjce.debug system property
+- Additional unit tests for JCE provider
+- Conditional ant build for JNI and/or JCE
+- New ant targets with choice of debug or release builds
+
+### wolfCrypt JNI Release 0.3 BETA
+
+Release 0.3 BETA of wolfCrypt JNI includes:
+
+- Support for ECC and DH key generation
+- Bug fixes regarding key import/export
+- Better argument sanitization at JNI level
+
+### wolfCrypt JNI Release 0.2 BETA
+
+Release 0.2 BETA of wolfCrypt JNI includes:
+
+- Support for Android
+- Support for Oracle JDK/JVM
+- Support for code signing wolfcrypt-jni.jar file
+- Compatibility with non-FIPS wolfSSL and wolfCrypt builds
+- Bug fixes regarding releasing native resources
+- Test package changed to (com.wolfssl.provider.jce.test)
+
+### wolfCrypt JNI Release 0.1 BETA
+
+Release 0.1 BETA of wolfCrypt JNI includes:
+
+- Initial JCE package
+- Support for OpenJDK
+
diff --git a/IDE/WIN/README.md b/IDE/WIN/README.md
index 818bf067..1bba6bee 100644
--- a/IDE/WIN/README.md
+++ b/IDE/WIN/README.md
@@ -136,6 +136,7 @@ section titled `/* Configuration */`:
```
#define WOLFSSL_KEY_GEN
+#define HAVE_CRL
```
After editing and saving the `user_settings.h` file, select one of the following
@@ -202,6 +203,7 @@ and set the values for `HAVE_FIPS`, `HAVE_FIPS_VERSION`, and
```
#define WOLFSSL_KEY_GEN
+#define HAVE_CRL
```
6. Build the `wolfssl-fips` project, which will create a DLL in one of the
@@ -258,6 +260,7 @@ The following additional defines will also need to be added to
```
#define WOLFSSL_KEY_GEN
+#define HAVE_CRL
```
For additional help, contact support@wolfssl.com.
diff --git a/IDE/WIN/wolfcryptjni.vcxproj b/IDE/WIN/wolfcryptjni.vcxproj
index 0d67b3a2..f748ee4b 100644
--- a/IDE/WIN/wolfcryptjni.vcxproj
+++ b/IDE/WIN/wolfcryptjni.vcxproj
@@ -66,6 +66,7 @@
+
@@ -80,10 +81,13 @@
+
+
+
16.0
@@ -97,52 +101,52 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
diff --git a/IDE/WIN/wolfcryptjni.vcxproj.filters b/IDE/WIN/wolfcryptjni.vcxproj.filters
index 0c193f56..f4bcc94c 100644
--- a/IDE/WIN/wolfcryptjni.vcxproj.filters
+++ b/IDE/WIN/wolfcryptjni.vcxproj.filters
@@ -158,5 +158,17 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 24eb17cb..70d92435 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
## wolfCrypt JCE Provider and JNI Wrapper
-This package provides a Java, JNI-based interface to the native wolfCrypt
-(and wolfCrypt FIPS API, if using with a FIPS version of wolfCrypt). It also
-includes a JCE provider for wolfCrypt.
+This packages includes both a JNI wrapper and JCE provider around the native
+wolfCrypt cryptography library. It supports both normal and FIPS validated
+versions of wolfCrypt.
-For instructions and notes on the JNI wrapper, please reference this README.md,
-or the wolfSSL online documentation.
+For instructions and notes on the **JNI wrapper**, please reference this
+README.md, or the wolfSSL online user manual.
-For instructions and notes on the JCE provider, please reference the
-[README_JCE.md](./README_JCE.md) file, or online instructions.
+For instructions and notes on the **JCE provider**, please reference the
+[README_JCE.md](./README_JCE.md) file, or online user manual.
### Compiling Native wolfSSL (Dependency)
---------
@@ -18,14 +18,19 @@ To compile the wolfCrypt JNI wrapper and JCE provider, first the native (C)
wolfSSL library must be compiled and installed.
Compile and install a wolfSSL (wolfssl-x.x.x), wolfSSL FIPS
-release (wolfssl-x.x.x-commercial-fips), or wolfSSL FIPS Ready release:
+release (wolfssl-x.x.x-commercial-fips), or wolfSSL FIPS Ready release.
-In any of these cases, you will need the `--enable-keygen` ./configure option.
+In any of these cases, you will need the `--enable-jni` ./configure option.
+The `--enable-jni` option includes all native wolfSSL features needed by
+both wolfCrypt JNI/JCE (this package) as well as wolfSSL JNI/JSSE (a
+separate package and repo). If you want the minimal set of requirements needed
+for only wolfJCE, you can use `--enable-keygen --enable-crl`, where
+CRL support is needed to support JCE `CertPathValidator(PKIX)` CRL support.
**wolfSSL Standard Build**:
```
$ cd wolfssl-x.x.x
-$ ./configure --enable-keygen
+$ ./configure --enable-jni
$ make check
$ sudo make install
```
@@ -34,7 +39,7 @@ $ sudo make install
```
$ cd wolfssl-x.x.x-commercial-fips
-$ ./configure --enable-fips=v2 --enable-keygen
+$ ./configure --enable-fips=v2 --enable-jni
$ make check
$ sudo make install
```
@@ -43,7 +48,7 @@ $ sudo make install
```
$ cd wolfssl-x.x.x-commercial-fips
-$ ./configure --enable-fips=ready --enable-keygen
+$ ./configure --enable-fips=ready --enable-jni
$ make check
$ sudo make install
```
@@ -203,7 +208,7 @@ on the current release):
com.wolfssl
wolfcrypt-jni
- 1.5.0-SNAPSHOT
+ 1.6.0-SNAPSHOT
...
@@ -248,105 +253,8 @@ Signing the JAR is important especially if using the JCE Provider with a JDK
that requires JCE provider JAR's to be authenticated. Please see
[README_JCE.md](./README_JCE.md) for more details.
-### Revision History
+### Release Notes
---------
-#### wolfCrypt JNI Release 1.5.0 (11/14/2022)
-
-Release 1.5.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- Add build compatibility for Java 7 (PR 38)
-- Add support for "SHA" algorithm string in wolfJCE (PR 39)
-- Add rpm package support (PR 40)
-- Add wolfJCE MessageDigest.clone() support (PR 41)
-- Improve error checking of native Md5 API calls (PR 41)
-- Add unit tests for com.wolfssl.wolfcrypt.Md5 (PR 41)
-
-#### wolfCrypt JNI Release 1.4.0 (08/11/2022)
-
-Release 1.4.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- Add example directory with one simple ProviderTest example (PR 32)
-- Fix double free of ChaCha pointer (PR 34)
-- Add test cases for ChaCha.java (PR 34)
-- Skip WolfCryptMacTest for HMAC-MD5 when using wolfCrypt FIPS 140-3 (PR 35)
-- Use new hash struct names (wc\_Md5/wc\_Sha/etc) in native code (PR 35)
-- Fix potential build error with non-ASCII apostrophes in Fips.java (PR 36)
-
-#### wolfCrypt JNI Release 1.3.0 (05/13/2022)
-
-Release 1.3.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- Run FIPS tests on `ant test` when linked against a wolfCrypt FIPS library (PR 24)
-- Wrap native AesGcmSetExtIV\_fips() API (PR 24)
-- Fix releaseByteArray() usage in Fips.RsaSSL\_Sign() (PR 24)
-- Fix AES-GCM FIPS test cases (PR 24)
-- Keep existing JAVA\_HOME in makefiles if already set (PR 25)
-- Add JCE support for MessageDigestSpi.engineGetDigestLength() (PR 27)
-- Update junit to 4.13.2 (PR 28)
-- Update missing Javadocs, fixes warnings on newer Java versions (PR 29)
-
-#### wolfCrypt JNI Release 1.2.0 (11/16/2021)
-
-Release 1.2.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- Add **FIPS 140-3** compatibility when using wolfCrypt FIPS or FIPS Ready
-- Increase junit version from 4.12 to 4.13 in pom.xml
-- Add local `./lib` directory to `java.library.path` in pom.xml
-- Fix builds with `WOLFCRYPT_JNI_DEBUG_ON` defined
-- Fix compatibility with wolfCrypt `NO_OLD_*` defines
-- Fix compatibility with wolfSSL `./configure --enable-all` and ECC tests
-
-#### wolfCrypt JNI Release 1.1.0 (08/26/2020)
-
-Release 1.1.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- New JNI-level wrappers for ChaCha, Curve25519, and Ed25519
-- Maven pom.xml build file
-- Runtime detection of hash type enum values for broader wolfSSL support
-- Updated wolfSSL error codes to match native wolfSSL updates
-- Native HMAC wrapper fixes for building with wolfCrypt FIPSv2
-- Native wrapper to return `HAVE_FIPS_VERSION` value to Java
-- Remove Blake2b from HMAC types, to match native wolfSSL changes
-- Better native wolfSSL feature detection
-- Increase Junit version to 4.13
-- Use nativeheaderdir on supported platforms instead of javah
-- Use hamcrest-all-1.3.jar in build.xml
-- Add call to `wc_ecc_set_rng()` when needed
-
-#### wolfCrypt JNI Release 1.0.0 (7/10/2017)
-
-Release 1.0.0 of wolfCrypt JNI has bug fixes and new features including:
-
-- Bug fixes to JCE classes: Cipher, KeyAgreement (DH), Signature
-- JCE debug logging with wolfjce.debug system property
-- Additional unit tests for JCE provider
-- Conditional ant build for JNI and/or JCE
-- New ant targets with choice of debug or release builds
-
-#### wolfCrypt JNI Release 0.3 BETA
-
-Release 0.3 BETA of wolfCrypt JNI includes:
-
-- Support for ECC and DH key generation
-- Bug fixes regarding key import/export
-- Better argument sanitization at JNI level
-
-#### wolfCrypt JNI Release 0.2 BETA
-
-Release 0.2 BETA of wolfCrypt JNI includes:
-
-- Support for Android
-- Support for Oracle JDK/JVM
-- Support for code signing wolfcrypt-jni.jar file
-- Compatibility with non-FIPS wolfSSL and wolfCrypt builds
-- Bug fixes regarding releasing native resources
-- Test package changed to (com.wolfssl.provider.jce.test)
-
-#### wolfCrypt JNI Release 0.1 BETA
-
-Release 0.1 BETA of wolfCrypt JNI includes:
-
-- Initial JCE package
-- Support for OpenJDK
+Release notes can be found in [ChangeLog.md](./ChangeLog.md).
diff --git a/build.xml b/build.xml
index b4e4dc19..d8a1ee26 100644
--- a/build.xml
+++ b/build.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/jni/jni_ecc.c b/jni/jni_ecc.c
index 3ae35d30..81115e50 100644
--- a/jni/jni_ecc.c
+++ b/jni/jni_ecc.c
@@ -821,7 +821,9 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1sign_1hash(
RNG* rng = NULL;
byte* hash = NULL;
byte* signature = NULL;
- word32 hashSz = 0, signatureSz = 0;
+ word32 hashSz = 0;
+ word32 expectedSigSz = 0;
+ word32 signatureSz = 0;
word32 signatureBufSz = 0;
ecc = (ecc_key*) getNativeStruct(env, this);
@@ -844,7 +846,8 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1sign_1hash(
}
if (ret == 0) {
- signatureSz = wc_ecc_sig_size(ecc);
+ expectedSigSz = wc_ecc_sig_size(ecc);
+ signatureSz = expectedSigSz;
signatureBufSz = signatureSz;
signature = (byte*)XMALLOC(signatureSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -860,25 +863,39 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1sign_1hash(
ret = wc_ecc_sign_hash(hash, hashSz, signature, &signatureSz, rng, ecc);
}
+ if (ret == 0) {
+ /* Sanity check on wc_ecc_sig_size() and actual length */
+ if (expectedSigSz < signatureSz) {
+ ret = BUFFER_E;
+ throwWolfCryptException(env,
+ "wc_ecc_sig_size() less than actual sig size");
+ }
+ }
+
if (ret == 0) {
result = (*env)->NewByteArray(env, signatureSz);
- if (result) {
+ if (result != NULL) {
(*env)->SetByteArrayRegion(env, result, 0, signatureSz,
(const jbyte*)signature);
} else {
+ releaseByteArray(env, hash_object, hash, JNI_ABORT);
throwWolfCryptException(env, "Failed to allocate signature");
+ return NULL;
}
} else {
+ releaseByteArray(env, hash_object, hash, JNI_ABORT);
throwWolfCryptExceptionFromError(env, ret);
+ return NULL;
}
LogStr("wc_ecc_sign_hash(input, inSz, output, &outSz, rng, ecc) = %d\n",
ret);
- LogStr("signature[%u]: [%p]\n", (word32)signatureSz, signature);
- LogHex((byte*) signature, 0, signatureSz);
if (signature != NULL) {
+ LogStr("signature[%u]: [%p]\n", (word32)signatureSz, signature);
+ LogHex((byte*) signature, 0, signatureSz);
+
XMEMSET(signature, 0, signatureBufSz);
XFREE(signature, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
@@ -896,8 +913,8 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1verify_1hash(
JNIEnv* env, jobject this, jbyteArray hash_object,
jbyteArray signature_object)
{
- int ret = 0;
#ifdef HAVE_ECC_VERIFY
+ int ret = 0;
int status = 0;
ecc_key* ecc = NULL;
byte* hash = NULL;
@@ -907,7 +924,7 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1verify_1hash(
ecc = (ecc_key*) getNativeStruct(env, this);
if ((*env)->ExceptionOccurred(env)) {
/* getNativeStruct may throw exception, prevent throwing another */
- return 0;
+ return JNI_FALSE;
}
hash = getByteArray(env, hash_object);
@@ -921,26 +938,29 @@ Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1verify_1hash(
}
else {
ret = wc_ecc_verify_hash(signature, signatureSz, hash,
- hashSz, &status, ecc);
+ hashSz, &status, ecc);
}
- if (ret == 0) {
- ret = status;
- } else {
- throwWolfCryptExceptionFromError(env, ret);
- }
+ releaseByteArray(env, hash_object, hash, JNI_ABORT);
+ releaseByteArray(env, signature_object, signature, JNI_ABORT);
LogStr(
"wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &status, ecc); = %d\n",
ret);
- releaseByteArray(env, hash_object, hash, JNI_ABORT);
- releaseByteArray(env, signature_object, signature, JNI_ABORT);
+ if (ret != 0) {
+ throwWolfCryptExceptionFromError(env, ret);
+ }
+
+ if (status == 1) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
#else
throwNotCompiledInException(env);
+ return JNI_FALSE;
#endif
-
- return ret;
}
JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1get_1curve_1size_1from_1name
diff --git a/jni/jni_feature_detect.c b/jni/jni_feature_detect.c
index 1fdfc510..54cc6f9d 100644
--- a/jni/jni_feature_detect.c
+++ b/jni/jni_feature_detect.c
@@ -213,7 +213,7 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_HmacSha224En
{
(void)env;
(void)jcl;
-#if !defined(NO_HMAC) && !defined(WOLFSSL_SHA224)
+#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224)
return JNI_TRUE;
#else
return JNI_FALSE;
diff --git a/jni/jni_native_struct.c b/jni/jni_native_struct.c
index 247d3dcf..c6574af1 100644
--- a/jni/jni_native_struct.c
+++ b/jni/jni_native_struct.c
@@ -151,9 +151,10 @@ byte* getByteArray(JNIEnv* env, jbyteArray array)
void releaseByteArray(JNIEnv* env, jbyteArray array, byte* elements, jint abort)
{
- if (elements)
+ if ((env != NULL) && (array != NULL) && (elements != NULL)) {
(*env)->ReleaseByteArrayElements(env, array, (jbyte*) elements,
abort ? JNI_ABORT : 0);
+ }
}
word32 getByteArrayLength(JNIEnv* env, jbyteArray array)
diff --git a/jni/jni_wolfobject.c b/jni/jni_wolfobject.c
index 52a33ada..48b7460f 100644
--- a/jni/jni_wolfobject.c
+++ b/jni/jni_wolfobject.c
@@ -49,7 +49,17 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfObject_init
}
#endif
-#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 5)
+#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)
diff --git a/pom.xml b/pom.xml
index acf13a2f..bf969207 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.wolfssl
wolfcrypt-jni
- 1.5.0-SNAPSHOT
+ 1.6.0-SNAPSHOT
jar
wolfcrypt-jni
https://www.wolfssl.com
diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java
index 5032ef57..b2c96273 100644
--- a/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java
+++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptKeyPairGenerator.java
@@ -80,6 +80,9 @@ enum KeyType {
private Rng rng = null;
+ /* Lock around Rng access */
+ private final Object rngLock = new Object();
+
/* for debug logging */
private WolfCryptDebug debug;
private String algString;
@@ -88,15 +91,12 @@ private WolfCryptKeyPairGenerator(KeyType type) {
this.type = type;
- rng = new Rng();
- rng.init();
-
if (debug.DEBUG)
algString = typeToString(type);
}
@Override
- public void initialize(int keysize, SecureRandom random) {
+ public synchronized void initialize(int keysize, SecureRandom random) {
if (type == KeyType.WC_DH) {
throw new RuntimeException(
@@ -111,19 +111,33 @@ public void initialize(int keysize, SecureRandom random) {
this.publicExponent = Rsa.getDefaultRsaExponent();
}
+ synchronized (rngLock) {
+ if (this.rng == null) {
+ this.rng = new Rng();
+ this.rng.init();
+ }
+ }
+
if (debug.DEBUG)
log("init with keysize: " + keysize);
}
@Override
- public void initialize(AlgorithmParameterSpec params,
- SecureRandom random) throws InvalidAlgorithmParameterException {
+ public synchronized void initialize(AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidAlgorithmParameterException {
if (params == null) {
throw new InvalidAlgorithmParameterException(
"AlgorithmParameterSpec must not be null");
}
+ synchronized (rngLock) {
+ if (this.rng == null) {
+ this.rng = new Rng();
+ this.rng.init();
+ }
+ }
+
switch (type) {
case WC_RSA:
@@ -206,7 +220,7 @@ public void initialize(AlgorithmParameterSpec params,
}
@Override
- public KeyPair generateKeyPair() {
+ public synchronized KeyPair generateKeyPair() {
KeyPair pair = null;
@@ -232,7 +246,10 @@ public KeyPair generateKeyPair() {
Rsa rsa = new Rsa();
try {
- rsa.makeKey(this.keysize, this.publicExponent, rng);
+ synchronized (rngLock) {
+ rsa.makeKey(this.keysize, this.publicExponent,
+ this.rng);
+ }
/* private key */
privDer = rsa.privateKeyEncodePKCS8();
@@ -280,13 +297,16 @@ public KeyPair generateKeyPair() {
ECPrivateKey eccPriv = null;
ECPublicKey eccPub = null;
+ Ecc ecc = null;
- Ecc ecc = new Ecc();
+ synchronized (rngLock) {
+ ecc = new Ecc(this.rng);
- if (this.curve == null) {
- ecc.makeKey(rng, this.keysize);
- } else {
- ecc.makeKeyOnCurve(rng, this.keysize, this.curve);
+ if (this.curve == null) {
+ ecc.makeKey(this.rng, this.keysize);
+ } else {
+ ecc.makeKeyOnCurve(this.rng, this.keysize, this.curve);
+ }
}
/* private key */
@@ -343,7 +363,9 @@ public KeyPair generateKeyPair() {
dh.setParams(dhP, dhG);
/* make key */
- dh.makeKey(rng);
+ synchronized (rngLock) {
+ dh.makeKey(this.rng);
+ }
privSpec = new DHPrivateKeySpec(
new BigInteger(dh.getPrivateKey()),
@@ -401,11 +423,13 @@ private void log(String msg) {
@SuppressWarnings("deprecation")
@Override
- protected void finalize() throws Throwable {
+ protected synchronized void finalize() throws Throwable {
try {
- if (this.rng != null) {
- rng.free();
- rng.releaseNativeStruct();
+ synchronized (rngLock) {
+ if (this.rng != null) {
+ this.rng.free();
+ this.rng.releaseNativeStruct();
+ }
}
} finally {
super.finalize();
diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java
index c38f9cad..142b0099 100644
--- a/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java
+++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java
@@ -34,7 +34,7 @@ public final class WolfCryptProvider extends Provider {
* Create new WolfCryptProvider object
*/
public WolfCryptProvider() {
- super("wolfJCE", 1.5, "wolfCrypt JCE Provider");
+ super("wolfJCE", 1.6, "wolfCrypt JCE Provider");
/* MessageDigest */
if (FeatureDetect.Md5Enabled()) {
@@ -181,41 +181,43 @@ public WolfCryptProvider() {
"com.wolfssl.provider.jce.WolfCryptPKIXCertPathValidator");
/* SecretKeyFactory */
- if (FeatureDetect.HmacShaEnabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA1",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA1");
- }
- if (FeatureDetect.HmacSha224Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA224",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA224");
- }
- if (FeatureDetect.HmacSha256Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA256",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA256");
- }
- if (FeatureDetect.HmacSha384Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA384",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA384");
- }
- if (FeatureDetect.HmacSha512Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA512",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA512");
- }
- if (FeatureDetect.HmacSha3_224Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA3-224",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_224");
- }
- if (FeatureDetect.HmacSha3_256Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA3-256",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_256");
- }
- if (FeatureDetect.HmacSha3_384Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA3-384",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_384");
- }
- if (FeatureDetect.HmacSha3_512Enabled()) {
- put("SecretKeyFactory.PBKDF2WithHmacSHA3-512",
- "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_512");
+ if (FeatureDetect.Pbkdf2Enabled()) {
+ if (FeatureDetect.HmacShaEnabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA1",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA1");
+ }
+ if (FeatureDetect.HmacSha224Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA224",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA224");
+ }
+ if (FeatureDetect.HmacSha256Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA256",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA256");
+ }
+ if (FeatureDetect.HmacSha384Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA384",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA384");
+ }
+ if (FeatureDetect.HmacSha512Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA512",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA512");
+ }
+ if (FeatureDetect.HmacSha3_224Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA3-224",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_224");
+ }
+ if (FeatureDetect.HmacSha3_256Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA3-256",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_256");
+ }
+ if (FeatureDetect.HmacSha3_384Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA3-384",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_384");
+ }
+ if (FeatureDetect.HmacSha3_512Enabled()) {
+ put("SecretKeyFactory.PBKDF2WithHmacSHA3-512",
+ "com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_512");
+ }
}
/* If using a FIPS version of wolfCrypt, allow private key to be
diff --git a/src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java b/src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java
index c071ee76..60561ab2 100644
--- a/src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java
+++ b/src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java
@@ -101,21 +101,30 @@ enum DigestType {
private String keyString;
private String digestString;
+ /* Class-wide RNG to be used for padding during sign operations */
+ private Rng rng = null;
+ private final Object rngLock = new Object();
+
private WolfCryptSignature(KeyType ktype, DigestType dtype)
throws NoSuchAlgorithmException {
this.keyType = ktype;
this.digestType = dtype;
- /* init asn object */
- asn = new Asn();
-
if ((ktype != KeyType.WC_RSA) &&
(ktype != KeyType.WC_ECDSA)) {
throw new NoSuchAlgorithmException(
"Signature algorithm key type must be RSA or ECC");
}
+ synchronized (rngLock) {
+ this.rng = new Rng();
+ this.rng.init();
+ }
+
+ /* init asn object */
+ asn = new Asn();
+
/* init hash type */
switch (dtype) {
case WC_MD5:
@@ -238,14 +247,18 @@ protected synchronized void engineInitSign(PrivateKey privateKey)
/* initialize native struct */
switch (keyType) {
case WC_RSA:
- if (this.rsa != null)
+ if (this.rsa != null) {
this.rsa.releaseNativeStruct();
+ }
this.rsa = new Rsa();
break;
case WC_ECDSA:
- if (this.ecc != null)
+ if (this.ecc != null) {
this.ecc.releaseNativeStruct();
- this.ecc = new Ecc();
+ }
+ synchronized (this.rngLock) {
+ this.ecc = new Ecc(this.rng);
+ }
break;
}
@@ -303,14 +316,18 @@ protected synchronized void engineInitVerify(PublicKey publicKey)
/* initialize native struct */
switch (keyType) {
case WC_RSA:
- if (this.rsa != null)
+ if (this.rsa != null) {
this.rsa.releaseNativeStruct();
+ }
this.rsa = new Rsa();
break;
case WC_ECDSA:
- if (this.ecc != null)
+ if (this.ecc != null) {
this.ecc.releaseNativeStruct();
- this.ecc = new Ecc();
+ }
+ synchronized (this.rngLock) {
+ this.ecc = new Ecc(this.rng);
+ }
break;
}
@@ -390,10 +407,6 @@ protected synchronized byte[] engineSign() throws SignatureException {
throw new SignatureException(e.getMessage());
}
- /* init RNG for padding */
- Rng rng = new Rng();
- rng.init();
-
/* sign digest */
switch (this.keyType) {
case WC_RSA:
@@ -409,7 +422,9 @@ protected synchronized byte[] engineSign() throws SignatureException {
byte[] tmp = new byte[encodedSz];
System.arraycopy(encDigest, 0, tmp, 0, encodedSz);
- signature = this.rsa.sign(tmp, rng);
+ synchronized (rngLock) {
+ signature = this.rsa.sign(tmp, this.rng);
+ }
zeroArray(tmp);
break;
@@ -417,7 +432,9 @@ protected synchronized byte[] engineSign() throws SignatureException {
case WC_ECDSA:
/* ECC sign */
- signature = this.ecc.sign(digest, rng);
+ synchronized (rngLock) {
+ signature = this.ecc.sign(digest, this.rng);
+ }
break;
@@ -426,10 +443,6 @@ protected synchronized byte[] engineSign() throws SignatureException {
"Invalid signature algorithm type");
}
- /* release RNG */
- rng.free();
- rng.releaseNativeStruct();
-
if (debug.DEBUG) {
if (signature != null) {
log("generated signature, len: " + signature.length);
@@ -617,7 +630,7 @@ private void log(String msg) {
@SuppressWarnings("deprecation")
@Override
- protected void finalize() throws Throwable {
+ protected synchronized void finalize() throws Throwable {
try {
/* free native digest objects */
if (this.md5 != null)
@@ -642,6 +655,15 @@ protected void finalize() throws Throwable {
if (this.ecc != null)
this.ecc.releaseNativeStruct(); /* frees internally */
+ synchronized (rngLock) {
+ if (this.rng != null) {
+ /* release RNG */
+ this.rng.free();
+ this.rng.releaseNativeStruct();
+ this.rng = null;
+ }
+ }
+
} finally {
super.finalize();
}
diff --git a/src/main/java/com/wolfssl/wolfcrypt/Ecc.java b/src/main/java/com/wolfssl/wolfcrypt/Ecc.java
index 3f908d9a..7c875757 100644
--- a/src/main/java/com/wolfssl/wolfcrypt/Ecc.java
+++ b/src/main/java/com/wolfssl/wolfcrypt/Ecc.java
@@ -38,9 +38,17 @@ public class Ecc extends NativeStruct {
/* used with native wc_ecc_set_rng() */
private Rng rng = null;
+ /* Do we own the Rng struct, or has that been passed in? Used
+ * during Rng cleanup. */
+ private boolean weOwnRng = true;
+
+ /** Lock around Rng object access */
+ private final Object rngLock = new Object();
+
/** Lock around object state */
protected final Object stateLock = new Object();
+
/**
* Create new Ecc object
*/
@@ -48,6 +56,18 @@ public Ecc() {
init();
}
+ /**
+ * Create new Ecc object with existing Rng object.
+ *
+ * @param rng initialized com.wolfssl.wolfcrypt.Rng object
+ */
+ public Ecc(Rng rng) {
+ this.rng = rng;
+ weOwnRng = false;
+
+ init();
+ }
+
@Override
public synchronized void releaseNativeStruct() {
free();
@@ -100,9 +120,12 @@ protected void init() {
}
/* used with native wc_ecc_set_rng() */
- if (rng == null) {
- rng = new Rng();
- rng.init();
+ synchronized (rngLock) {
+ if (rng == null) {
+ rng = new Rng();
+ rng.init();
+ weOwnRng = true;
+ }
}
state = WolfCryptState.INITIALIZED;
@@ -124,9 +147,11 @@ protected void free() {
wc_ecc_free();
}
- if (this.rng != null) {
- rng.free();
- rng.releaseNativeStruct();
+ synchronized (rngLock) {
+ if (this.weOwnRng && this.rng != null) {
+ rng.free();
+ rng.releaseNativeStruct();
+ }
}
state = WolfCryptState.UNINITIALIZED;
@@ -445,7 +470,9 @@ public synchronized byte[] makeSharedSecret(Ecc pubKey)
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
- return wc_ecc_shared_secret(pubKey, this.rng);
+ synchronized (rngLock) {
+ return wc_ecc_shared_secret(pubKey, this.rng);
+ }
}
} else {
throw new IllegalStateException(
@@ -473,7 +500,9 @@ public synchronized byte[] sign(byte[] hash, Rng rng)
synchronized (stateLock) {
if (state == WolfCryptState.READY) {
synchronized (pointerLock) {
- signature = wc_ecc_sign_hash(hash, rng);
+ synchronized (rngLock) {
+ signature = wc_ecc_sign_hash(hash, rng);
+ }
}
} else {
throw new IllegalStateException(
diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyAgreementTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyAgreementTest.java
index 4d316f8e..c6c366f7 100644
--- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyAgreementTest.java
+++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyAgreementTest.java
@@ -29,10 +29,11 @@
import java.util.ArrayList;
import java.util.Random;
import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicIntegerArray;
import javax.crypto.KeyAgreement;
import javax.crypto.ShortBufferException;
@@ -537,9 +538,18 @@ private void threadRunnerKeyAgreeTest(String algo)
int numThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numThreads);
final CountDownLatch latch = new CountDownLatch(numThreads);
- final LinkedBlockingQueue results = new LinkedBlockingQueue<>();
final String currentAlgo = algo;
+ /* Used to detect timeout of CountDownLatch, don't run indefinitely
+ * if threads are stalled out or deadlocked */
+ boolean returnWithoutTimeout = true;
+
+ /* Keep track of failure and success count */
+ final AtomicIntegerArray failures = new AtomicIntegerArray(1);
+ final AtomicIntegerArray success = new AtomicIntegerArray(1);
+ failures.set(0, 0);
+ success.set(0, 0);
+
/* DH Tests */
AlgorithmParameterGenerator paramGen =
AlgorithmParameterGenerator.getInstance("DH");
@@ -552,7 +562,6 @@ private void threadRunnerKeyAgreeTest(String algo)
service.submit(new Runnable() {
@Override public void run() {
- int failed = 0;
KeyPairGenerator keyGen = null;
KeyAgreement aKeyAgree = null;
KeyAgreement bKeyAgree = null;
@@ -603,53 +612,56 @@ private void threadRunnerKeyAgreeTest(String algo)
byte secretB[] = bKeyAgree.generateSecret();
if (!Arrays.equals(secretA, secretB)) {
- failed = 1;
+ throw new Exception(
+ "Secrets A and B to not match");
}
- if (failed == 0) {
- cKeyAgree = KeyAgreement.getInstance(
- currentAlgo, "wolfJCE");
- cPair = keyGen.generateKeyPair();
- cKeyAgree.init(cPair.getPrivate());
+ cKeyAgree = KeyAgreement.getInstance(
+ currentAlgo, "wolfJCE");
+ cPair = keyGen.generateKeyPair();
+ cKeyAgree.init(cPair.getPrivate());
- aKeyAgree.doPhase(cPair.getPublic(), true);
- cKeyAgree.doPhase(aPair.getPublic(), true);
+ aKeyAgree.doPhase(cPair.getPublic(), true);
+ cKeyAgree.doPhase(aPair.getPublic(), true);
- byte secretA2[] = aKeyAgree.generateSecret();
- byte secretC[] = cKeyAgree.generateSecret();
+ byte secretA2[] = aKeyAgree.generateSecret();
+ byte secretC[] = cKeyAgree.generateSecret();
- if (!Arrays.equals(secretA2, secretC)) {
- failed = 1;
- }
+ if (!Arrays.equals(secretA2, secretC)) {
+ throw new Exception(
+ "Secrets A2 and C do not match");
}
+ /* Log success */
+ success.incrementAndGet(0);
+
} catch (Exception e) {
e.printStackTrace();
- failed = 1;
+
+ /* Log failure */
+ failures.incrementAndGet(0);
} finally {
latch.countDown();
}
-
- if (failed == 1) {
- results.add(1);
- }
- else {
- results.add(0);
- }
}
});
}
/* wait for all threads to complete */
- latch.await();
-
- /* Look for any failures that happened */
- Iterator listIterator = results.iterator();
- while (listIterator.hasNext()) {
- Integer cur = listIterator.next();
- if (cur == 1) {
- fail("Threading error in KeyAgreement thread test");
+ returnWithoutTimeout = latch.await(10, TimeUnit.SECONDS);
+ service.shutdown();
+
+ /* Check failure count and success count against thread count */
+ if ((failures.get(0) != 0) ||
+ (success.get(0) != numThreads)) {
+ if (returnWithoutTimeout == true) {
+ fail("KeyAgreement test threading error: " +
+ failures.get(0) + " failures, " +
+ success.get(0) + " success, " +
+ numThreads + " num threads total");
+ } else {
+ fail("KeyAgreement test threading error, threads timed out");
}
}
}
diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java
index e6d06133..b7b9255a 100644
--- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java
+++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptKeyPairGeneratorTest.java
@@ -55,6 +55,7 @@
import com.wolfssl.wolfcrypt.Rsa;
import com.wolfssl.wolfcrypt.Ecc;
+import com.wolfssl.wolfcrypt.Fips;
import com.wolfssl.wolfcrypt.test.Util;
import com.wolfssl.wolfcrypt.WolfCryptException;
import com.wolfssl.provider.jce.WolfCryptProvider;
@@ -93,6 +94,16 @@ public class WolfCryptKeyPairGeneratorTest {
"brainpoolp512r1"
};
+ private static String supportedCurvesFIPS1403[] = {
+ "secp224r1",
+ "secp256r1",
+ "secp384r1",
+ "secp521r1",
+
+ "secp224k1",
+ "secp256k1",
+ };
+
private static ArrayList enabledCurves =
new ArrayList();
@@ -100,9 +111,7 @@ public class WolfCryptKeyPairGeneratorTest {
new ArrayList();
/* Test generation of these RSA key sizes */
- private static int testedRSAKeySizes[] = {
- 1024, 2048, 3072, 4096
- };
+ private static int testedRSAKeySizes[] = null;
/* DH test params */
private static byte[] prime = Util.h2b(
@@ -127,16 +136,35 @@ public static void testProviderInstallationAtRuntime() {
Provider p = Security.getProvider("wolfJCE");
assertNotNull(p);
+ if (Fips.enabled && Fips.fipsVersion >= 5) {
+ /* FIPS after 2425 doesn't allow 1024-bit RSA key gen */
+ testedRSAKeySizes = new int[] {
+ 2048, 3072, 4096
+ };
+ }
+ else {
+ testedRSAKeySizes = new int[] {
+ 1024, 2048, 3072, 4096
+ };
+ }
+
/* build list of enabled curves and key sizes,
* getCurveSizeFromName() will return 0 if curve not found */
Ecc tmp = new Ecc();
- for (int i = 0; i < supportedCurves.length; i++) {
+ String[] curves = null;
+
+ if (Fips.enabled && Fips.fipsVersion >= 5) {
+ curves = supportedCurvesFIPS1403;
+ } else {
+ curves = supportedCurves;
+ }
+
+ for (int i = 0; i < curves.length; i++) {
- int size = tmp.getCurveSizeFromName(
- supportedCurves[i].toUpperCase());
+ int size = tmp.getCurveSizeFromName(curves[i].toUpperCase());
if (size > 0) {
- enabledCurves.add(supportedCurves[i]);
+ enabledCurves.add(curves[i]);
if (!enabledEccKeySizes.contains(Integer.valueOf(size))) {
enabledEccKeySizes.add(Integer.valueOf(size));
diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptPKIXCertPathValidatorTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptPKIXCertPathValidatorTest.java
index 6ec089dc..24a4e41b 100644
--- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptPKIXCertPathValidatorTest.java
+++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptPKIXCertPathValidatorTest.java
@@ -63,6 +63,7 @@
import java.security.cert.CollectionCertStoreParameters;
import java.lang.IllegalArgumentException;
+import com.wolfssl.wolfcrypt.WolfCrypt;
import com.wolfssl.provider.jce.WolfCryptProvider;
public class WolfCryptPKIXCertPathValidatorTest {
@@ -388,6 +389,13 @@ public void testSingleCertValidateRSAWithCRL()
Collection crls = null;
List certStores = null;
+ if (!WolfCrypt.CrlEnabled()) {
+ /* Native CRL not enabled, skip CRL test */
+ System.out.println("CertPathValidator CRL test skipped, " +
+ "CRL not compiled in");
+ return;
+ }
+
/* Use example KeyStore that verifies server-cert.der */
store = createKeyStoreFromFile(jksCaServerRSA2048, keyStorePass);
if (store == null || store.size() != 1) {
diff --git a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptSignatureTest.java b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptSignatureTest.java
index 4cd273b2..87bcfc45 100644
--- a/src/test/java/com/wolfssl/provider/jce/test/WolfCryptSignatureTest.java
+++ b/src/test/java/com/wolfssl/provider/jce/test/WolfCryptSignatureTest.java
@@ -29,10 +29,12 @@
import java.util.ArrayList;
import java.util.Random;
import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicIntegerArray;
import java.security.Security;
import java.security.Provider;
@@ -343,15 +345,48 @@ private KeyPair generateKeyPair(String algo, SecureRandom rand)
return pair;
}
- private void threadRunnerSignVerify(byte[] inBuf, String algo)
- throws InterruptedException {
+ private void threadRunnerSignVerify(byte[] inBuf, String algo,
+ final AtomicIntegerArray failures, final AtomicIntegerArray success,
+ ExecutorService service, final CountDownLatch latch, int numThreads)
+ throws InterruptedException, Exception {
- int numThreads = 10;
- ExecutorService service = Executors.newFixedThreadPool(numThreads);
- final CountDownLatch latch = new CountDownLatch(numThreads);
- final LinkedBlockingQueue results = new LinkedBlockingQueue<>();
- final String currentAlgo = algo;
+ final String currentAlg = algo;
final byte[] toSignBuf = inBuf;
+ KeyPair pair = null;
+ KeyPairGenerator keyGen = null;
+ final PrivateKey priv;
+ final PublicKey pub;
+
+ /* Generate key pairs once up front to minimize use of entropy from
+ * RNG. We also are just interested in testing sign/verify across
+ * multiple threads, not key gen in this test. */
+ if (currentAlg.contains("RSA")) {
+ keyGen = KeyPairGenerator.getInstance("RSA");
+ keyGen.initialize(2048, secureRandom);
+ pair = keyGen.generateKeyPair();
+
+ } else if (currentAlg.contains("ECDSA")) {
+ keyGen = KeyPairGenerator.getInstance("EC",
+ "wolfJCE");
+ ECGenParameterSpec ecSpec =
+ new ECGenParameterSpec("secp521r1");
+ keyGen.initialize(ecSpec);
+ pair = keyGen.generateKeyPair();
+ }
+
+ if (pair == null) {
+ throw new Exception("KeyPair from generateKeyPair() is null");
+ }
+ else {
+ priv = pair.getPrivate();
+ if (priv == null) {
+ throw new Exception("KeyPair.getPrivate() returned null");
+ }
+ pub = pair.getPublic();
+ if (pub == null) {
+ throw new Exception("KeyPair.getPublic() returned null");
+ }
+ }
/* Do encrypt/decrypt and sign/verify in parallel across numThreads
* threads, all operations should pass */
@@ -359,107 +394,115 @@ private void threadRunnerSignVerify(byte[] inBuf, String algo)
service.submit(new Runnable() {
@Override public void run() {
- int failed = 0;
- KeyPair pair = null;
- KeyPairGenerator keyGen = null;
- PrivateKey priv = null;
- PublicKey pub = null;
+ byte[] signature = null;
Signature signer = null;
Signature verifier = null;
- byte[] signature = null;
try {
- signer = Signature.getInstance(
- currentAlgo, "wolfJCE");
- verifier = Signature.getInstance(
- currentAlgo, "wolfJCE");
+ signer = Signature.getInstance(currentAlg, "wolfJCE");
+ verifier = Signature.getInstance(currentAlg, "wolfJCE");
if (signer == null || verifier == null) {
- failed = 1;
+ throw new Exception(
+ "signer or verifier Signature object null");
}
- /* generate key pair */
- if (failed == 0) {
- if (currentAlgo.contains("RSA")) {
- keyGen = KeyPairGenerator.getInstance("RSA");
- keyGen.initialize(2048, secureRandom);
- pair = keyGen.generateKeyPair();
-
- } else if (currentAlgo.contains("ECDSA")) {
- keyGen = KeyPairGenerator.getInstance("EC",
- "wolfJCE");
- ECGenParameterSpec ecSpec =
- new ECGenParameterSpec("secp521r1");
- keyGen.initialize(ecSpec);
- pair = keyGen.generateKeyPair();
- }
-
- if (pair == null) {
- failed = 1;
- }
- else {
- priv = pair.getPrivate();
- pub = pair.getPublic();
- }
+ /* generate signature */
+ signer.initSign(priv);
+ signer.update(toSignBuf, 0, toSignBuf.length);
+ signature = signer.sign();
+ if (signature == null || signature.length == 0) {
+ throw new Exception(
+ "signer.sign() returned null or zero " +
+ "length array");
}
- if (failed == 0) {
- /* generate signature */
- signer.initSign(priv);
- signer.update(toSignBuf, 0, toSignBuf.length);
- signature = signer.sign();
-
- /* verify signature */
- verifier.initVerify(pub);
- verifier.update(toSignBuf, 0, toSignBuf.length);
- boolean verified = verifier.verify(signature);
-
- if (verified == false) {
- failed = 1;
- }
+ /* verify signature */
+ verifier.initVerify(pub);
+ verifier.update(toSignBuf, 0, toSignBuf.length);
+ boolean verified = verifier.verify(signature);
+
+ if (verified == false) {
+ throw new Exception(
+ "verifier.verify() returned false:\n" +
+ "algo: " + currentAlg + "\n" +
+ "signature (" + signature.length + " bytes): " +
+ arrayToHex(signature) + "\n" +
+ "private (" + priv.getEncoded().length +
+ " bytes): " + arrayToHex(priv.getEncoded()) +
+ "\npublic (" + pub.getEncoded().length +
+ " bytes): " + arrayToHex(pub.getEncoded()));
}
+ /* Log success */
+ success.incrementAndGet(0);
+
} catch (Exception e) {
e.printStackTrace();
- failed = 1;
+
+ /* Log failure */
+ failures.incrementAndGet(0);
} finally {
latch.countDown();
}
-
- if (failed == 1) {
- results.add(1);
- }
- else {
- results.add(0);
- }
}
});
}
+ }
- /* wait for all threads to complete */
- latch.await();
-
- /* Look for any failures that happened */
- Iterator listIterator = results.iterator();
- while (listIterator.hasNext()) {
- Integer cur = listIterator.next();
- if (cur == 1) {
- fail("Threading error in RSA sign/verify thread test");
- }
+ private synchronized String arrayToHex(byte[] in) {
+ StringBuilder builder = new StringBuilder();
+ for (byte b: in) {
+ builder.append(String.format("%02X", b));
}
+
+ return builder.toString();
}
@Test
- public void testThreadedWolfSignWolfVerify() throws InterruptedException {
-
+ public void testThreadedWolfSignWolfVerify() throws Exception {
final String toSign = "Hello World";
final byte[] toSignBuf = toSign.getBytes();
+ int numThreads = 10;
+ int numAlgos = enabledAlgos.size();
+ ExecutorService service =
+ Executors.newFixedThreadPool(numAlgos * numThreads);
+ final CountDownLatch latch = new CountDownLatch(numAlgos * numThreads);
+
+ /* Used to detect timeout of CountDownLatch, don't run indefinitely
+ * if threads are stalled out or deadlocked */
+ boolean returnWithoutTimeout = true;
+
+ /* Keep track of failure and success count */
+ final AtomicIntegerArray failures = new AtomicIntegerArray(1);
+ final AtomicIntegerArray success = new AtomicIntegerArray(1);
+ failures.set(0, 0);
+ success.set(0, 0);
+
/* run threaded test for each enabled Signature algorithm */
- for (int i = 0; i < enabledAlgos.size(); i++) {
- threadRunnerSignVerify(toSignBuf, enabledAlgos.get(i));
+ for (int i = 0; i < numAlgos; i++) {
+ threadRunnerSignVerify(toSignBuf, enabledAlgos.get(i),
+ failures, success, service, latch, numThreads);
+ }
+
+ /* wait for all threads to complete */
+ returnWithoutTimeout = latch.await(10, TimeUnit.SECONDS);
+ service.shutdown();
+
+ /* Check failure count and success count against thread count */
+ if ((failures.get(0) != 0) ||
+ (success.get(0) != (enabledAlgos.size() * numThreads))) {
+ if (returnWithoutTimeout == true) {
+ fail("Signature test threading error: " +
+ failures.get(0) + " failures, " +
+ success.get(0) + " success, " +
+ (numThreads * enabledAlgos.size()) + " num threads total");
+ } else {
+ fail("Signature test threading error, threads timed out");
+ }
}
}
}
diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/DhTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/DhTest.java
index d738bdef..13d516c9 100644
--- a/src/test/java/com/wolfssl/wolfcrypt/test/DhTest.java
+++ b/src/test/java/com/wolfssl/wolfcrypt/test/DhTest.java
@@ -30,10 +30,11 @@
import java.util.Arrays;
import java.util.Random;
import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicIntegerArray;
import com.wolfssl.wolfcrypt.Dh;
import com.wolfssl.wolfcrypt.Rng;
@@ -105,7 +106,16 @@ public void threadedDhSharedSecretTest() throws InterruptedException {
int numThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numThreads);
final CountDownLatch latch = new CountDownLatch(numThreads);
- final LinkedBlockingQueue results = new LinkedBlockingQueue<>();
+
+ /* Used to detect timeout of CountDownLatch, don't run indefinitely
+ * if threads are stalled out or deadlocked */
+ boolean returnWithoutTimeout = true;
+
+ /* Keep track of failure and success count */
+ final AtomicIntegerArray failures = new AtomicIntegerArray(1);
+ final AtomicIntegerArray success = new AtomicIntegerArray(1);
+ failures.set(0, 0);
+ success.set(0, 0);
final byte[] p = Util.h2b(
"E6969D3D495BE32C7CF180C3BDD4798E91B7818251BB055E"
@@ -121,7 +131,6 @@ public void threadedDhSharedSecretTest() throws InterruptedException {
service.submit(new Runnable() {
@Override public void run() {
- int failed = 0;
Dh alice = null;
Dh bob = null;
@@ -134,65 +143,65 @@ public void threadedDhSharedSecretTest() throws InterruptedException {
/* keys should be null before generation */
if (alice.getPublicKey() != null ||
bob.getPublicKey() != null) {
- failed = 1;
+ throw new Exception(
+ "keys not null before generation");
}
/* generate Dh keys */
- if (failed == 0) {
- synchronized (rngLock) {
- alice.makeKey(rng);
- bob.makeKey(rng);
- }
+ synchronized (rngLock) {
+ alice.makeKey(rng);
+ bob.makeKey(rng);
}
/* keys should not be null after generation */
- if (failed == 0) {
- if (alice.getPublicKey() == null ||
- bob.getPublicKey() == null) {
- failed = 1;
- }
+ if (alice.getPublicKey() == null ||
+ bob.getPublicKey() == null) {
+ throw new Exception(
+ "keys null after generation");
}
- if (failed == 0) {
- byte[] sharedSecretA = alice.makeSharedSecret(bob);
- byte[] sharedSecretB = bob.makeSharedSecret(alice);
+ byte[] sharedSecretA = alice.makeSharedSecret(bob);
+ byte[] sharedSecretB = bob.makeSharedSecret(alice);
- if (sharedSecretA == null ||
- sharedSecretB == null ||
- !Arrays.equals(sharedSecretA, sharedSecretB)) {
- failed = 1;
- }
+ if (sharedSecretA == null ||
+ sharedSecretB == null ||
+ !Arrays.equals(sharedSecretA, sharedSecretB)) {
+ throw new Exception(
+ "shared secrets null or not equal");
}
+ /* Log success */
+ success.incrementAndGet(0);
+
} catch (Exception e) {
e.printStackTrace();
- failed = 1;
+
+ /* Log failure */
+ failures.incrementAndGet(0);
} finally {
alice.releaseNativeStruct();
bob.releaseNativeStruct();
latch.countDown();
}
-
- if (failed == 1) {
- results.add(1);
- }
- else {
- results.add(0);
- }
}
});
}
/* wait for all threads to complete */
- latch.await();
-
- /* Look for any failures that happened */
- Iterator listIterator = results.iterator();
- while (listIterator.hasNext()) {
- Integer cur = listIterator.next();
- if (cur == 1) {
- fail("Threading error in DH shared secret thread test");
+ returnWithoutTimeout = latch.await(10, TimeUnit.SECONDS);
+ service.shutdown();
+
+ /* Check failure count and success count against thread count */
+ if ((failures.get(0) != 0) ||
+ (success.get(0) != numThreads)) {
+ if (returnWithoutTimeout == true) {
+ fail("DH shared secret test threading error: " +
+ failures.get(0) + " failures, " +
+ success.get(0) + " success, " +
+ numThreads + " num threads total");
+ } else {
+ fail("DH shared secret test error, threads timed out");
}
}
}
diff --git a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java
index a0b086f1..d0bd2b6c 100644
--- a/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java
+++ b/src/test/java/com/wolfssl/wolfcrypt/test/RsaTest.java
@@ -71,9 +71,14 @@ public void constructorShouldInitializeNativeStruct() {
@Test
public void testMakeKey() {
- Rsa key = new Rsa();
- key.makeKey(1024, 65537, rng);
- key.releaseNativeStruct();
+ Rsa key = null;
+
+ /* FIPS after 2425 doesn't allow 1024-bit RSA key gen */
+ if (Fips.enabled && Fips.fipsVersion < 5) {
+ key = new Rsa();
+ key.makeKey(1024, 65537, rng);
+ key.releaseNativeStruct();
+ }
key = new Rsa();
key.makeKey(2048, 65537, rng);
@@ -219,6 +224,12 @@ public void rsaPrivateToPkcs8() {
+ "4e8c3a458fe69640eb63f919863a51dd894bb0f3f99f5d289538"
+ "be35abca5ce7935334a1455d1339654246a19fcdf5bf");
+ /* FIPS after 2425 doesn't allow 1024-bit RSA key gen */
+ if (Fips.enabled && Fips.fipsVersion >= 5) {
+ /* skip */
+ return;
+ }
+
/* Test that exception is thrown without private key available */
try {
pkcs8 = key.privateKeyEncodePKCS8();