Skip to content

Repository files navigation

The OpenSSL JOSTLE Project

.github/workflows/arm.yaml .github/workflows/intel.yaml

OpenSSL Jostle is a Java provider that uses the OpenSSL Library for the cryptographic implementation.

This is a collaboration between the OpenSSL Corporation and the Legion of the Bouncy Castle. This project wraps features of OpenSSL native library into a standard Java JCA/JCE Provider.

The JOSTLE code base is released under the same license as the OpenSSL Library - i.e. Apache License 2.0.

OpenSSL Jostle supports running on Java 1.8 to Java 25, and requires Java 25 to build.

Services

See SERVICES.md

Using Jostle with an AI coding assistant

If you use an AI coding assistant (Claude, GitHub Copilot, OpenAI / Codex, Cursor, …) to write code against Jostle, point it at docs/jostle-ai-guide.md. It is a portable, vendor-neutral Markdown brief — provider setup (including the FIPS provider), the defaults that differ from the JDK, exception contracts, interop traps, and verified snippets — written to be dropped into your repo and referenced from your assistant's instruction file.

Usage

This section will be updated when there are published in maven central or equivalent. For the time being you will need to build OpenSSL Jostle before you can try it out.

Contributing

See CONTRIBUTING.md for details.

Building

In this example we are going to build OpenSSL Jostle on an Intel machine spun up in AWS EC2.

Building Locally + General Information

Building may present complexities.

Building involves generating the interface binaries and then installing those binaries and, potentially, the OpenSSL Library libraries into the src/main/resources directory of the jostle Java project so that they can ultimately be bundled into a single jar file.

The interface libraries are organised by common os name then architecture, eg "osx/arm64". The base directory structure for this is laid out in interface/loading along with appropriately configured dependency "deps.txt" files.

Step 1 Obtain and build OpenSSL Library 3.6

OpenSSL Library 3.6 source bundle can be downloaded from OpenSSL Downloads

After copying the source url, download the source tarball onto a suitable machine and unpack it. For the current LTS release you can use the following commands.

    wget https://github.com/openssl/openssl/releases/download/openssl-3.6.2/openssl-3.6.2.tar.gz
    
    tar -zxvf openssl-3.6.2.tar.gz    

In order to build OpenSSL 3.6 you will need to have also installed the appropriate build tools for the OS that you are building on.

Step 2 Build OpenSSL Library 3.6

Users should specify a prefix when building the OpenSSL Library for this example there is no need to install it on the host for all users so we will use prefix and keep it nearby.

  cd openssl-3.6.2
  
  # Tell OpenSSL to install build products in the same parent as openssl-3.6.2
  ./Configure --prefix=`pwd`/../openssl_3_6
  
  # Build it.
  make clean
  make
  make install_sw  
   
   

When the OpenSSL Library build finishes you should have the build artefacts available in ../openssl_3_6

For example, it should look something like this.


cd ..
ls -al
    
drwxr-xr-x.  4 ec2-user ec2-user    46 Oct  2 08:08 .
drwx------.  4 ec2-user ec2-user   133 Oct  2 07:34 ..
drwxr-xr-x. 28 ec2-user ec2-user 16384 Oct  2 08:08 openssl-3.6.2
drwxr-xr-x.  5 ec2-user ec2-user    45 Oct  2 08:08 openssl_3_6

ls -al openssl_3_6

drwxr-xr-x. 5 ec2-user ec2-user  45 Oct  2 08:08 .
drwxr-xr-x. 4 ec2-user ec2-user  46 Oct  2 08:08 ..
drwxr-xr-x. 2 ec2-user ec2-user  37 Oct  2 08:08 bin
drwxr-xr-x. 3 ec2-user ec2-user  21 Oct  2 08:08 include
drwxr-xr-x. 6 ec2-user ec2-user 186 Oct  2 08:08 lib64

Lastly we need to set the OPENSSL_PREFIX env var, this variable will be used by the OpenSSL Jostle build to locate the OpenSSL libraries.

cd openssl_3_6/
export OPENSSL_PREFIX=`pwd`

# Print it out.

echo "${OPENSSL_PREFIX}"
/home/ec2-user/build/openssl_3_6

Step 3. Compile Headers

This step produces the C headers needed to compile the interface between the Java provider and the OpenSSL Library libraries.

3.1 Clone repo

Clone this repository and change into the root directory of that clone.

git clone https://github.com/openssl-projects/openssl-jostle.git
cd openssl-jostle

ls -al

-rw-r--r--. 1 ec2-user ec2-user 11357 Oct  3 01:01 LICENSE
-rw-r--r--. 1 ec2-user ec2-user 14205 Oct  3 01:01 README.md
-rw-r--r--. 1 ec2-user ec2-user   800 Oct  3 01:01 build.gradle
-rw-r--r--. 1 ec2-user ec2-user   368 Oct  3 01:01 settings.gradle
-- etc

Set up Java 25

For this step you will need to have Java 25 on your PATH (aka command line), and you should also set JAVA_HOME appropriately, for example:

#
# This value will be different depending on the machine you are building on
#
export JAVA_HOME=/usr/lib/jvm/java-25-amazon-corretto.x86_64

export PATH=$JAVA_HOME/bin:$PATH


java -version

openjdk version "25" 2025-09-16 LTS
OpenJDK Runtime Environment Corretto-25.0.0.36.2 (build 25+36-LTS)
OpenJDK 64-Bit Server VM Corretto-25.0.0.36.2 (build 25+36-LTS, mixed mode, sharing)

Build headers

Use gradlew to generate the headers, make sure you are in the root of the OpenSSL Jostle repository

./gradlew clean compileJava

.. some output..

BUILD SUCCESSFUL in 2s
2 actionable tasks: 2 executed

Step 4. Compile interface

This step will compile and install the interface layer, both JNI and FFI that connects the Java side of OpenSSL Jostle to the OpenSSL Library libraries.

CMAKE

You will need CMAKE version of at least 3.31

cmake -version

cmake version 3.31.6

CMake suite maintained and supported by Kitware (kitware.com/cmake).

Optional, build with Operations Test support

Skip this step if you do not want to perform Operations Testing!

The interface libraries can be built with support for operations testing which should be left out for normal use.

If you want to do operations testing then set the following:

# This is optional, leave it unset 

export JOSTLE_OPS_TEST=true

# To unset

unset JOSTLE_OPS_TEST

Ensure OPENSSL_PREFIX is set

To build the interface you need to make sure the OPENSSL_PREFIX is set from either Step 2 or points to a directory that has the same structure as what the OpenSSL build would have generated.

You must also ensure that JAVA_HOME is set.

echo $OPENSSL_PREFIX 
/home/ec2-user/build/openssl_3_6

echo $JAVA_HOME
/usr/lib/jvm/java-25-amazon-corretto.x86_64/

Build and install the interface

To build:

    # The following should work for the bulk of users

    ./interface/build.sh
    
    # To build on Windows
    
    ./interface/build.bat

The build step will copy build products into the appropriate locations into jostle/src/main/resources/native

For example:

ls -alR jostle/src/main/resources/native/linux/
jostle/src/main/resources/native/linux/:
total 0
drwxr-xr-x. 4 ec2-user ec2-user 35 Oct  2 10:35 .
drwxr-xr-x. 4 ec2-user ec2-user 53 Oct  2 10:35 ..
drwxr-xr-x. 2 ec2-user ec2-user 22 Oct  2 10:35 aarch64
drwxr-xr-x. 2 ec2-user ec2-user 98 Oct  2 10:43 x86_64

jostle/src/main/resources/native/linux/aarch64:
total 4
drwxr-xr-x. 2 ec2-user ec2-user 22 Oct  2 10:35 .
drwxr-xr-x. 4 ec2-user ec2-user 35 Oct  2 10:35 ..
-rw-r--r--. 1 ec2-user ec2-user 69 Oct  2 10:33 deps.txt

jostle/src/main/resources/native/linux/x86_64:
total 7352
drwxr-xr-x. 2 ec2-user ec2-user      98 Oct  2 10:43 .
drwxr-xr-x. 4 ec2-user ec2-user      35 Oct  2 10:35 ..
-rw-r--r--. 1 ec2-user ec2-user      69 Oct  2 10:33 deps.txt
-rw-r--r--. 1 ec2-user ec2-user 7186360 Oct  2 08:08 libcrypto.so.3
-rwxr-xr-x. 1 ec2-user ec2-user   82680 Oct  2 10:43 libinterface_ffi.so
-rwxr-xr-x. 1 ec2-user ec2-user  102352 Oct  2 10:43 libinterface_jni.so

Step 5. Building the Jar

To build the jar with the libraries baked in. Note that the tests will be automatically run unless you use provide "-x test" on the command line.

    # Ensure Java 25
    
    java -version
    
    openjdk version "25" 2025-09-16 LTS
    .. etc

    ./gradlew clean build
    
    # to skip testing
    
    ./gradlew clean build -x test
    

The Jostle jars can be found in:

    <repo>/jostle/build/libs/

Step 6. Running DumpInfo

DumpInfo reports the loaded provider, OS/arch, JVM, the resolved native interface (JNI or FFI), and the extracted native libraries. Two optional arguments may be appended to the command:

  1. --fine — emit FINE-level loader logs.
  2. --services — also list every algorithm the provider registers, grouped by service type (KeyFactory, Cipher, Signature, KeyStore, Mac, MessageDigest, ...), with a count per type.

With modules

java --module-path jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar \
--enable-native-access=org.openssl.jostle.prov \
--module org.openssl.jostle.prov/org.openssl.jostle.util.DumpInfo
-------------------------------------------------------------------------------
DumpInfo

Provider:
  Info: Jostle Provider for OpenSSL v1.0.0-SNAPSHOT
  Name: JSL
  OS: Linux
  Version: 6.1.153-175.280.amzn2023.x86_64
  Arch: amd64
  Java Version: 25
  Java Vendor: Amazon.com Inc.

Loader:
  Load Attempted: true
  Load Successful: true
  Loader Message: Loader Finished Successfully
  Loader Interface Resolution Strategy: auto
  Loader Interface: FFI
  Loaded Native Libraries:
    Extracted: /native/linux/x86_64/libcrypto.so.3
    Extracted: /native/linux/x86_64/libinterface_ffi.so

Native Status:
  Native Available: true
  OpenSSL Version: 3.6.2
.END
Use: --fine to emit FINE level logs, --services to list provider services grouped by type
-------------------------------------------------------------------------------

Without modules

-------------------------------------------------------------------------------
DumpInfo

Provider:
  Info: Jostle Provider for OpenSSL v1.0.0-SNAPSHOT
  Name: JSL
  OS: Linux
  Version: 6.1.153-175.280.amzn2023.x86_64
  Arch: amd64
  Java Version: 25
  Java Vendor: Amazon.com Inc.

Loader:
  Load Attempted: true
  Load Successful: true
  Loader Message: Loader Finished Successfully
  Loader Interface Resolution Strategy: auto
  Loader Interface: FFI
  Loaded Native Libraries:
    Extracted: /native/linux/x86_64/libcrypto.so.3
    Extracted: /native/linux/x86_64/libinterface_ffi.so

Native Status:
  Native Available: true
  OpenSSL Version: 3.6.2
.END
Use: --fine to emit FINE level logs, --services to list provider services grouped by type
-------------------------------------------------------------------------------

NB: Java25 will emit a warning about access to restricted methods in java.lang.System.

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.openssl.jostle.Loader in an unnamed module (file:/home/ec2-user/build/jostle/jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Java 8

java -cp jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar org.openssl.jostle.util.DumpInfo


-------------------------------------------------------------------------------
DumpInfo

Provider:
  Info: Jostle Provider for OpenSSL v1.0.0-SNAPSHOT
  Name: JSL
  OS: Linux
  Version: 6.1.153-175.280.amzn2023.x86_64
  Arch: amd64
  Java Version: 1.8.0_462
  Java Vendor: Amazon.com Inc.

Loader:
  Load Attempted: true
  Load Successful: true
  Loader Message: Loader Finished Successfully
  Loader Interface Resolution Strategy: auto
  Loader Interface: JNI
  Loaded Native Libraries:
    Extracted: /native/linux/x86_64/libcrypto.so.3
    Extracted: /native/linux/x86_64/libinterface_jni.so

Native Status:
  Native Available: true
  OpenSSL Version: 3.6.2
.END
Use: --fine to emit FINE level logs, --services to list provider services grouped by type

java 25 -- default will use FFI

java --module-path jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar \
--enable-native-access=org.openssl.jostle.prov \
--module org.openssl.jostle.prov/org.openssl.jostle.util.DumpInfo

-------------------------------------------------------------------------------
DumpInfo

Provider:
Info: Jostle Provider for OpenSSL v1.0.0-SNAPSHOT

-- snipped

Loader:
Load Attempted: true
Load Successful: true
Loader Message: Loader Finished Successfully
Loader Interface Resolution Strategy: auto
Loader Interface: FFI  <-----
Loaded Native Libraries:
Extracted: /native/linux/x86_64/libcrypto.so.3
Extracted: /native/linux/x86_64/libinterface_ffi.so

-- snipped

Forcing use of JNI

Jostle will default to FFI when available, it can be forced to use JNI.

-Dorg.openssl.jostle.loader.interface=JNI

For example, with module loading

java -Dorg.openssl.jostle.loader.interface=JNI \
--module-path jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar \
--enable-native-access=org.openssl.jostle.prov \
--module  org.openssl.jostle.prov/org.openssl.jostle.util.DumpInfo


-------------------------------------------------------------------------------
DumpInfo

Provider:
Info: Jostle Provider for OpenSSL v1.0.0-SNAPSHOT

-- snipped

Loader:
Load Attempted: true
Load Successful: true
Loader Message: Loader Finished Successfully
Loader Interface Resolution Strategy: jni
Loader Interface: JNI <----
Loaded Native Libraries:
Extracted: /native/linux/x86_64/libcrypto.so.3
Extracted: /native/linux/x86_64/libinterface_jni.so

-- snipped

Unsuccessful loading example

java -cp jostle/build/libs/openssl-jostle-1.0-SNAPSHOT.jar org.openssl.jostle.util.DumpInfo

java -cp openssl-jostle-1.0-SNAPSHOT.jar org.openssl.jostle.util.DumpInfo
Oct 02, 2025 10:02:41 PM org.openssl.jostle.Loader load
WARNING: extraction file '/native/osx/arm64/libcrypto.3.dylib' not found
java.io.IOException: extraction file '/native/osx/arm64/libcrypto.3.dylib' not found
	at org.openssl.jostle.Loader.extractAndLoad(Loader.java:389)
	at org.openssl.jostle.Loader.loadImpl(Loader.java:308)
	at org.openssl.jostle.Loader.load(Loader.java:104)
	at org.openssl.jostle.CryptoServicesRegistrar.<clinit>(CryptoServicesRegistrar.java:21)
	at org.openssl.jostle.jcajce.provider.JostleProvider.<init>(JostleProvider.java:54)
	at org.openssl.jostle.jcajce.provider.JostleProvider.<init>(JostleProvider.java:42)
	at org.openssl.jostle.util.DumpInfo.main(DumpInfo.java:41)

Exception in thread "main" java.lang.IllegalStateException: no access to native library
	at org.openssl.jostle.CryptoServicesRegistrar.assertNativeAvailable(CryptoServicesRegistrar.java:34)
	at org.openssl.jostle.jcajce.provider.JostleProvider.<init>(JostleProvider.java:54)
	at org.openssl.jostle.jcajce.provider.JostleProvider.<init>(JostleProvider.java:42)
	at org.openssl.jostle.util.DumpInfo.main(DumpInfo.java:41)

Testing on multiple JVMs specifically

The build can execute tests on specific JVMs, the enable these tests users must set one or more of the following environmental variables to the relevant JAVA_HOME for that JVM.

BC_JDK8= .. jdk8
BC_JDK11= .. jdk11
BC_JDK17= .. jdk17
BC_JDK21= .. jdk21
BC_JDK25= .. jdk25

For example, setting:

export BC_JDK17=/usr/lib/jvm/java-17-amazon-corretto.x86_64
export BC_JDK8=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64
export BC_JDK11=/usr/lib/jvm/java-11.12.34-amazon-corretto.x86_64
export BC_JDK21=/usr/lib/jvm/java-21-amazon-corretto.x86_64
export BC_JDK25=/usr/lib/jvm/java-25-amazon-corretto.x86_64

Will get picked up by the gradle build and will the trigger the addition of extra JVM specific tests tasks to the main test task.

jostle: Adding test8 as dependency for test task because BC_JDK8 is defined
jostle: Adding test11 as dependency for test task because BC_JDK11 is defined
jostle: Adding test17 as dependency for test task because BC_JDK17 is defined
jostle: Adding test21 as dependency for test task because BC_JDK21 is defined
jostle: Adding test25 as dependency for test task because BC_JDK25 is defined

Secure Random

From 6-Apr-2026 Jostle will honor any passed in SecureRandom. It does this by implementing an internal OpenSSL provider that supplies RAND implementation that can draw its source of random data via upcalls to the JVM.

If no SecureRandom is supplied the default from CryptoServicesRegistrar will be used.

The handling of SecureRandom in CryptoServicesRegistrar is exactly the same as Bouncy Castle's handling.

Random strength for post-quantum key generation

The higher-strength post-quantum parameter sets require entropy of matching security strength; keying them from a weaker SecureRandom would cap their effective strength, so Jostle enforces a minimum at key-pair generation:

Required strength Parameter sets
128-bit ML-KEM-512, ML-DSA-44, SLH-DSA-*-128
192-bit ML-KEM-768, ML-DSA-65, SLH-DSA-*-192
256-bit ML-KEM-1024, ML-DSA-87, SLH-DSA-*-256

The simplest and most portable approach is to omit the SecureRandom and let Jostle pick a strength-appropriate DRBG for you:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM-1024", "JSL");
kpg.initialize(MLKEMParameterSpec.ml_kem_1024);   // no SecureRandom — works on every platform
KeyPair kp = kpg.generateKeyPair();

If you pass a SecureRandom explicitly, KeyPairGenerator.initialize throws InvalidAlgorithmParameterException when it reports a strength below the requirement.

Windows note. new SecureRandom() is not portable for this. On Linux and macOS the JDK default (NativePRNG) reports an unknown strength and is accepted; on Windows (JDK 9+) the default is a 128-bit DRBG that reports 128, so initialize(spec, new SecureRandom()) is rejected for the 192- and 256-bit parameter sets above. Either omit the SecureRandom (recommended) or pass an explicitly strength-typed DRBG:

SecureRandom drbg = SecureRandom.getInstance(
        "DRBG", DrbgParameters.instantiation(256, DrbgParameters.Capability.RESEED_ONLY, null));
kpg.initialize(MLKEMParameterSpec.ml_kem_1024, drbg);

FIPS support (JSLFIPS)

Alongside the standard JostleProvider ("JSL"), Jostle ships JostleFIPSProvider ("JSLFIPS") which backs its services with an externally supplied OpenSSL FIPS provider module (for example the FIPS-validated OpenSSL 3.1.2 fips.dylib / fips.so / fips.dll). The module is loaded by libcrypto itself — its integrity MAC is verified against the fipsinstall-generated configuration and its self-tests run before any service is available. The JVM never System.loads the module.

The two providers coexist in the same JVM: each runs on its own native interface library with its own OSSL_LIB_CTX, so JSL continues to serve its full algorithm set while JSLFIPS serves only what the FIPS module provides as approved (the lib ctx is pinned to fips=yes default properties).

Configuring

The provider needs to know where the FIPS module lives. The configuration string is a comma-separated key=value list (values may be quoted with ", ' or a backtick, and resolve via the file:, prop:, env: and str: schemes):

  1. fips_module — REQUIRED. Path to the FIPS provider module. The module search path is its parent directory and the OpenSSL provider name is the file name minus its extension.
  2. fips_config — OPTIONAL. Path to the fipsinstall-generated configuration carrying the module MAC. Defaults to fipsmodule.cnf in the module's directory.
Security.addProvider(new JostleFIPSProvider("fips_module='/opt/openssl-fips/lib/ossl-modules/fips.so'"));

// or via java.security static registration / Provider.configure:
Provider p = new JostleFIPSProvider().configure("fips_module=env:MY_FIPS_MODULE");

The no-arg constructor consults the org.openssl.jostle.fips.config property (java.security property, thread-local override, then system property); with no configuration it stays unconfigured and registers no services. Initialisation is one-shot per JVM: constructing another provider with the identical configuration is a no-op, a different configuration throws IllegalStateException.

What JSLFIPS serves

MessageDigest (SHA-1/SHA-2/SHA-3/SHAKE), Cipher AES (modes via the module, key wrap RFC 3394/5649, CCM), Mac (HMAC over the approved digests, AES-CMAC), SecureRandom (SP 800-90A DRBGs over the FIPS 140-3 approved digest set), KeyGenerator AES (keyed from the module's DRBG), RSA (key generation ≥ 2048, KeyFactory, PKCS#1 v1.5 and PSS signatures, OAEP encryption), EC (ECDSA, ECDH — the module gates curve approval), DSA, DH, and SecretKeyFactory PBKDF2/HKDF.

Deliberately absent because the module does not serve them (or does not serve them as approved): MD5, SM3, RIPEMD, BLAKE2, ChaCha20, Camellia, ARIA, SM4, DESede, Poly1305, scrypt, Ed25519/Ed448, and the post-quantum families (ML-KEM, ML-DSA, SLH-DSA). Also absent per the module's FIPS 140-3 certification (certificate #4985): X25519/X448 key agreement and the raw NoneWithECDSA verification component (security policy Tables 8/13); and RSA PKCS#1 v1.5 encryption (RSA/ECB/PKCS1Padding) — the security policy approves RSA key transport via OAEP only (KTS-4, SP 800-56Br2), so PKCS#1 v1.5 encryption is non-approved, and the 3.1.2 module additionally does not honour the implicit-rejection Bleichenbacher mitigation for it. The module serves these under fips=yes, but using them places it in the non-approved mode of operation, so JSLFIPS does not register them (RSA PKCS#1 v1.5 remains available for signatures, which the policy approves). Requests for any of these through JSLFIPS fail with NoSuchAlgorithmException while JSL continues to serve them in the same JVM. To restrict either provider's surface further, use the JVM's own mechanisms (e.g. the jdk.security.providers.filter security property).

Behavioural differences under the FIPS module

Beyond the absent registrations, three registered services behave differently under JSLFIPS because the FIPS module either lacks a capability or silently substitutes behaviour. In each case Jostle fails loud with a typed exception rather than running degraded or returning something other than what was asked for:

  1. RSA PKCS#1 v1.5 decryption is refused at the native layer too. The transformation is not registered (see above), and independently of registration the native interface refuses to initialise a PKCS#1 v1.5 DECRYPT session against any provider that does not support the implicit-rejection Bleichenbacher mitigation (the parameter entered OpenSSL 3.2; the validated 3.1.2 module silently ignores it). The capability is probed at init and the refusal surfaces as InvalidKeyException; encryption and wrapping are unaffected. Use RSA/ECB/OAEPPadding for key transport — it is the approved mechanism and needs no implicit rejection.
  2. DH parameter generation refuses rather than returning constants. AlgorithmParameterGenerator.getInstance("DH", "JSLFIPS").generateParameters() throws ProviderException: the FIPS module does not run the PKCS#3 safe-prime search — it silently returns the RFC 7919 named-group constants matching the requested size (and hard-fails other sizes), which is not what "generate parameters" promises. Use named-group DH key generation instead (KeyPairGenerator.getInstance("DH", "JSLFIPS") with a standard size); the named groups are the FIPS-approved domain parameters anyway. Under JSL (mainline OpenSSL), parameter generation performs a genuine safe-prime search as before.
  3. DH key agreement requires the subgroup order q. The module's SP 800-56A key check rejects keys that carry no q at derive-init, so private keys built from PKCS#3 component specs (DHParameterSpec / DHPrivateKeySpec — p, g, x only) fail KeyAgreement.init with an InvalidKeyException naming the cause. Keys from named-group generation (or any source that carries q) work as normal. Under JSL, q-less keys continue to work.

Key isolation

Jostle keys are bound to the interface library (and OSSL_LIB_CTX) that created them. Public keys carry no secret material and may be used freely with either provider's services (OpenSSL imports the public components into the operating lib ctx). PRIVATE keys are isolated: the operational services — Signature, Cipher, KeyAgreement — of one provider reject a private key created by the other with InvalidKeyException. To move a private key between JSL and JSLFIPS, encode it (getEncoded()) and decode it through the target provider's KeyFactory; the boundary crossing then happens explicitly in your code. SecretKeys (raw bytes, no native residency) are unaffected.

Entropy

The FIPS lib ctx does not install the java rand bridge: all entropy — DRBG seeding, key generation, signature randomness — is drawn inside the FIPS boundary from the module's own approved DRBGs. SecureRandom instances from JSLFIPS chain to the module's primary DRBG.

A consequence is that a caller-supplied SecureRandom is ignored by every operation that executes inside the FIPS module — key pair generation, signing (ECDSA nonces, PSS salts) and encryption (OAEP seeds). This is OpenSSL architecture, not a Jostle policy: the FIPS module runs on its own internal library context whose DRBG chain seeds directly from the operating system's entropy sources, and nothing installed on the host context — including a SecureRandom passed through the JCE API — is ever consulted by module-internal operations. (SunPKCS11 behaves the same way for operations performed inside a token.) Passing a SecureRandom to initialize(...) / init(...) on a JSLFIPS service is therefore harmless but has no effect on the randomness those operations use.

The one exception is the AES KeyGenerator, whose key bytes are drawn in Java. To keep those bytes inside the FIPS boundary the generator does not blindly honour a caller-supplied SecureRandom: by default it uses the caller's random only when that random is backed by the FIPS provider (checked via SecureRandom.getProvider()), and otherwise falls back to the module's own DRBG. This closes the KeyGenerator.init(int) case — where the JCE injects the JVM's default SecureRandom, indistinguishable from an explicit caller choice — so init(int) no longer silently pulls key bytes from a non-module RNG. Consequently: generateKey() with no init(...), init(int), and init(int, r) where r is a JSLFIPS DRBG (e.g. SecureRandom.getInstance("CTR-DRBG", "JSLFIPS")) all keep the bytes inside the module; init(int, r) where r is a non-FIPS random has r overridden by the module DRBG.

The check recognises only JSLFIPS's own DRBG — it cannot identify an arbitrary FIPS-validated SecureRandom from another provider (there is no portable "is this SecureRandom FIPS?" query), so a DRBG from BCFIPS or SunPKCS11 would also be overridden. If you must drive the AES KeyGenerator with a third-party FIPS DRBG, set -Dorg.openssl.jostle.fips.enforce_provider_random=false at JVM start-up (the property is read once at class initialisation); the generator then reverts to the standard JCE contract of honouring the supplied SecureRandom verbatim, and the FIPS status of the resulting keys rests on the entropy source you supply.

Testing

Running the FIPS tests requires an OpenSSL FIPS module to test against. Set the TEST_FIPS_LIB environment variable to the full path of the FIPS module library (fips.dylib / fips.so / fips.dll), with its fipsinstall-generated fipsmodule.cnf sitting in the same directory:

export TEST_FIPS_LIB=/opt/openssl-fips/lib/ossl-modules/fips.so

The test helpers TestUtil.addFipsProvider() and TestUtil.skipFipsTests() read this variable: when it is unset (or empty) the FIPS tests skip; when it is set they register the JSLFIPS provider against that module. A set-but-invalid path fails loudly rather than skipping. This is the same value the provider's fips_module configuration key expects.

Operations-test fault injection (JOSTLE_OPS_TEST) is intentionally not compiled into the FIPS interface libraries.

Provider startup

During the construction, new JostleProvider(...) an optional provider can be named.

The constructor will trigger the creation of a global OSSL_LIB_CTX with an internal provider that supplies the java rand bridge and then the named provider will loaded second. While you are free to call new JostleProvider(...) with the same module you will be unable to change module after the first call.

Options

This section will cover property setting that effect usage and also includes a few common problems that may arise for some usage scenarios.

Available properties

Properties may be set in a security policy file or on the command line via -Dxxx

Property: "org.openssl.jostle.loader.install_dir"

Directly specify an installation directory rather than use one derived from the default temporary directory provided by the JVM.

This is very useful if your host system is configured to deny execution from any binary file (this also includes libraries) that are installed in a temp drive.

Property: "org.openssl.jostle.loader.single_install"

This property will cause the loader to use a fixed install location, if "org.openssl.jostle.loader.install_dir" is defined it will use that otherwise it will the default temp dir defined by the JVM.

This property is useful on systems with multiple instances running that would otherwise create multiple copies of the same libraries.

It is advisable to use this with: "org.openssl.jostle.loader.install_dir"

Property: "org.openssl.jostle.loader.load_lib_NN"

This property allows you to override the list of native libraries loaded that are not interface libraries, for example:

   org.openssl.jostle.loader.load_lib_00=/path/to/library
   org.openssl.jostle.loader.load_lib_01=/path/to/library1
   etc
   

The paths must be absolute paths and the loader will count from _00 to _99 it will stop when it cannot find a property.

Please see:

https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#load-java.lang.String-

Property: "org.openssl.jostle.loader.load_name_NN"

This property allows you to override the list of native libraries loaded that are not interface libraries, example except it allows the specification of the library name rather than path. The JVM will use whatever library lookup mechanism it has access to.

   org.openssl.jostle.loader.load_name_00=openssl
   org.openssl.jostle.loader.load_name_01=mymodule
   etc
  

The name must be compatible with System.loadLibrary(name);. The loader will count from _00 to _99 and, it will stop when it cannot find a property.

Please review:

https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#loadLibrary-java.lang.String- https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#mapLibraryName-java.lang.String-

Property: "org.openssl.jostle.loader.interface"

This property can be one of the following values:

Setting Description
auto Loader will detect FFI / JNI interface automatically
jni Force the extraction and use of the JNI interface only
ffi Force the extraction and use of the FFI interface only
none Do not extract an interface library

If "none" is selected then the name or path to the interface library must be defined by either:

  1. org.openssl.jostle.loader.load_name_NN, or
  2. org.openssl.jostle.loader.load_lib_NN

"org.openssl.jostle.ossl_prov"

Use this property to set the name of the OpenSSL provider module after loading.

About

OpenSSL Jostle - Java Interface to the OpenSSL Library

Resources

Contributing

Stars

23 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages