wolfSSL Java JSSE Provider User Manual | wolfSSL Documentation

 

The Java Secure Socket Extension (JSSE) framework supports the installation of security providers. These providers can implement a subset of the functionality used by the Java JSSE security APIs, including SSL/TLS.

This document describes wolfSSL’s JSSE provider implementation, named “wolfJSSE”. wolfJSSE wraps the native wolfSSL SSL/TLS library, providing Java users the opportunity to take advantage of wolfSSL’s progressive features, performance, and resource optimizations. wolfJSSE supports up to the newest SSL/TLS protocol, TLS 1.3!

wolfJSSE is distributed as part of the “wolfssljni” package. This package includes both a thin JNI wrapper for wolfSSL and the wolfJSSE provider.


Requirements

A. Java / JDK

wolfJSSE requires Java to be installed on the host system.  There are several JDK variants available to users and developers - including the Oracle JDK, OpenJDK, Zulu JDK, and Android.

B. JUnit

In order to run the unit tests, JUnit is required to be installed on the development system.  JUnit can be downloaded from the project website at www.junit.org.

To install JUnit on a Unix/Linux/OSX system:

  • Download “junit-4.13.jar” and “hamcrest-all-1.3.jar” from junit.org/junit4/.  At the time of writing, the above mentioned .jar files could be downloaded from the following links:

LINK:  junit-4.13.jar
LINK:  hamcrest-all-1.3.jar

  • Place these JAR files on your system and set JUNIT_HOME to point to that location.  Ex:

$ export JUNIT_HOME=/path/to/jar/files

C. gcc and ant

Both “gcc” and “ant” are used to compile native C code and Java code, respectively.  Please ensure that these are installed on your development machine.

D. wolfSSL Library

As a wrapper around the native wolfSSL library, the wolfSSL C library must be installed on the host platform and placed on the include and library search paths.

Compiling wolfSSL and wolfCrypt C Library

To compile and install wolfSSL in a Unix/Linux environment for use with wolfJSSE, please follow build instructions in the wolfSSL Manual.  The most common way to compile wolfSSL is with the Autoconf system.  

When using Autoconf to configure wolfSSL, the “--enable-jni” option will need to be used:

$ cd wolfssl-X.X.X
$ ./configure --enable-jni
$ make

Verify “make check” passes successfully, then install the library:

$ make check
$ sudo make install

This will install the wolfSSL library to your system default installation location.  On many platforms this is:

/usr/local/lib
/usr/local/include

If wolfSSL has installed to a non-standard library installation location, you may need to update LD_LIBRARY_PATH (Unix/Linux) or DYLD_LIBRARY_PATH (OSX):

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/wolfssl/install

Return to top of page


wolfSSL JNI and wolfJSSE Compilation

There are three ways to compile wolfJSSE listed in this section, including:

1. Unix Command Line
2. Android Studio Build
3. Generic IDE Build

1. Unix Command Line

Before following steps in this section, please ensure that the dependencies in Section 1 above are installed.

The “java.sh” script in the root package directory is used to compile the native JNI C source files into a shared library for either Unix/Linux or Mac. This script tries to auto-detect between OSX (Darwin) and Linux to set up include paths and shared library extension type. This script directly calls gcc on the JNI C source files, producing “./lib/libwolfssljni.so” or “./lib/libwolfssljni.dylib”

$ ./java.sh

Compiling Native JNI library:
    WOLFSSL_INSTALL_DIR = /usr/local
    Detected Linux host OS
    Generated ./lib/libwolfssljni.so

To compile the Java sources, “ant” is used:

$ ant

This will build the wolfJSSE jar and native code necessary to use wolfJSSE in a project.

To compile and run tests the the command “ant test” is used:

$ ant test

This will compile tests and the main wolfJSSE code and an output with the results of the tests will be displayed along with a summary of total tests that passed at the end of the wolfJSSE testsuite and wolfSSL JNI testsuite. A successful build will display the message “BUILD SUCCESSFUL” at the end.

    [junit] WolfSSLTrustX509 Class
    [junit]         Testing parse all_mixed.jks        ... passed
    [junit]         Testing loading default certs        ... passed
    [junit]         Testing parse all.jks                ... passed
    [junit]         Testing verify                        ... passed
…
…
…




build:


BUILD SUCCESSFUL        
Total time: 18 seconds

To compile and run examples bundled with wolfJSSE the the command “ant examples” is used:

$ ant examples

2. Android Studio Build

An example Android Studio project is located in the directory IDE/Android. To run the example Android Studio project use the following steps;

1. On an Android device, BKS format key stores are expected. To convert the JKS example bundles to BKS use the following commands:

cd examples/provider
./convert-to-bks.sh <path/to/provider>

Example:

cd examples/provider
./convert-to-bks.sh ~/Downloads/bcprov-jdk15on-161.jar

2. Push BKS bundles up to the device along with certificates. To do this, start up the emulator/device and use "adb push". An example of this would be the following commands from root wolfssljni directory:

adb shell
cd sdcard
mkdir examples
mkdir examples/provider
mkdir examples/certs
exit
adb push ./examples/provider/*.bks /sdcard/examples/provider/
adb push ./examples/certs/ /sdcard/examples/

3. Add wolfSSL source code for compiling

The project looks for the directory wolfssljni/IDE/Android/app/src/main/cpp/wolfssl for wolfSSL source code. This can be done multiple ways one being to download the latest release from wolfSSL's website, unzip it, rename it to wolfssl, and place it in the directory wolfssljni/IDE/Android/app/src/main/cpp/. Alternatively GitHub can be used with "cd /IDE/Android/app/src/main/cpp/ && git clone https://github.com/wolfssl/wolfssl". And the final method to be mentioned in this document is by creating a symbolic link to a wolfssl directory on the system by using "cd /IDE/Android/app/src/main/cpp/ && ln -s /path/to/local/wolfssl ./wolfssl".

4. Open the Android studio project by double clicking on the Android folder in wolfssljni/IDE/

5. Compile the project and run MainActivity from app -> java -> com -> example.wolfssl. This will ask for permissions to access the certificates in the /sdcard/ directory and then print out the server certificate information on success.

6. OPTIONAL : The androidTests can then be run after permissions have been given. app->java->com.wolfssl->provider.jsse.test->WolfSSLJSSETestSuite and app->java->com.wolfssl->test->WolfSSLTestSuite

7. OPTIONAL : To build with TLS 1.3 enabled macros need added to IDE/Android/app/src/main/cpp/CMakeLists.txt. The macros needed to be defined are; HAVE_HKDF, WC_RSA_PSS, HAVE_FFDHE_2048, HAVE_SUPPORTED_CURVES, WOLFSSL_TLS13 and HAVE_TLS_EXTENSION. Each of those should be added to the “add_definitions” list in the CMakeLists.txt file.

3. Generic IDE Build

For generic IDE builds create a new project in the IDE, then add source files from src/java. This will be the following packages:

com.wolfssl
com.wolfssl.provider.jsse
com.wolfssl.wolfcrypt

Run java.sh from the command line or have the IDE execute java.sh to generate the native shim layer linking against wolfSSL.

Add native library reference to the project. It should look in the lib directory for libwolfssl.jnilib (i.e. wolfssljni/lib/).

To compile test cases add the packages com.wolfssl.provider.jsse.test and com.wolfssl.test from the directory src/test. The project will also need JUNIT5 to run the tests.

If adding in optional examples then the source code in examples/provider/ can be added to the project. Optionally the IDE can execute examples/provider/ClientJSSE.sh. One of the difficult parts to adding in the examples is making sure the path to keystores is known to the IDE when it runs the examples, if trying to use the default keystores.

Return to top of page


Installation

There are two ways that wolfJSSE can be installed and used, either at runtime or globally at the system level.

1. Installation at Runtime

To install and use wolfJSSE at runtime, first make sure that “libwolfssljni.so” is on your system’s library search path. On Linux, you can modify this path with:

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/add

Next, place the wolfSSL JNI / wolfJSSE JAR file(s) (wolfssl.jar, wolfssl-jsse.jar) on your Java classpath. You can do this by adjusting your system classpath settings, or at compile time and runtime like so:

$ javac -classpath <path/to/jar> …
$ java -classpath <path/to/jar> …

Finally, in your Java application, add the provider at runtime by importing the provider class and calling Security.addProvider():

import com.wolfssl.provider.jsse.WolfSSLProvider;

public class TestClass {
        public static void main(String args[]) {
                …
                Security.addProvider(new WolfSSLProvider());
                …
}
}

To print a list of all installed providers for verification, you can do:

Provider[] providers = Security.getProviders()
for (Provider prov:providers) {
        System.out.println(prov);
}

2. Installation at OS / System Level

I. Unix/Linux

To install the wolfJSSE provider at the system level, copy the wolfssl.jar and/or wolfssl-jsse.jar files into the correct Java installation directory for your OS and verify the libwolfssljni.so or libwolfssljni.dylib shared library is on your library search path.

Add the JAR files (wolfssl.jar, wolfssl-jsse.jar) and shared library (libwolfssljni.so) to the following directory:

$JAVA_HOME/jre/lib/ext

For example, on Ubuntu with OpenJDK this may be similar to:

/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext

Next, add an entry to the java.security file that looks similar to the following:

security.provider.N=com.wolfssl.provider.jce.WolfSSLProvider

The java.security file will be located at:

$JAVA_HOME/jre/lib/security/java.security

Replacing “N” with the order of precedence you would like the WolfSSLProvider to have in comparison to other providers in the file. For example, to place the WolfSSLProvider as the top priority provider, the following line would be added to the providers list in the java.security file. You will also need to re-number the priority numbers on the other providers listed in the java.security file.

security.provider.1=com.wolfssl.provider.jce.WolfSSLProvider

II. Android OSP (AOSP)

For instructions on installing wolfJSSE as a system security provider in the Android OSP (AOSP) source tree, please reference the separate document titled “Installing a JSSE Provider in Android OSP”.

Return to top of page


Package Design

wolfJSSE is bundled together with the wolfSSL JNI wrapper in the “wolfssljni” package. Since wolfJSSE depends on the underlying JNI bindings for wolfSSL, it is compiled into the same native library file as the JNI wrapper.

wolfJSSE / wolfSSL JNI package structure:

wolfssljni/
      build.xml             ant build script
      COPYING
      docs/                 Javadocs
      examples/             Example apps
      java.sh               Script to build native C JNI sources
      lib/                  output directory for compiled library
      LICENSING
      native/               native C JNI binding source files
      README_JSSE.md
      README.md
      src/
          java/             Java source files                        
          test/             Test source files

The wolfJSSE provider source code is located in the “src/java/com/wolfssl/provider/jsse” directory, and is part of the “com.wolfssl.provider.jsse” Java package.

The wolfSSL JNI wrapper is located in the “src/java/com/wolfssl” directory and is part of the “com.wolfssl” Java package. Users of JSSE will not need to use this package directly, as it will be consumed by the wolfJSSE classes.

Once wolfSSL JNI and wolfJSSE have been compiled, there are two JAR files and one native shared library that have been generated. These are located in the “./lib” directory.

lib/
      libwolfSSL.so       (native C JNI wrapper shared library)
      wolfssl.jar         (JAR with ONLY wolfSSL JNI Java classes)
      wolfssl-jsse.jar    (JAR with BOTH wolfSSL JNI and wolfJSSE classes)

Return to top of page


Supported Algorithms and Classes

wolfJCE currently provides implementations of the following JSSE classes:

SSLContext (TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3)
SSLEngine
SSLSession
SSLSocket / SSLServerSocket
SSLSocketFactory / SSLServerSocketFactory
KeyManagerFactory
X509KeyManager
TrustManagerFactory
X509TrustManager
X509Certificate

Return to top of page


Usage

For usage, please follow the Oracle/OpenJDK Javadocs for the classes specified in Section 5 above. Note that you will need to explicitly request the “wolfJCE” provider if it has been set lower in precedence than other providers that offer the same algorithm in the java.security file.

For example, to use the wolfJSSE provider with the SSLContext class for TLS 1.2 you would create a SSLContext object like so:

SSLContext ctx = SSLContext.getInstance(“TLSv1.2”, “wolfJCE”);

Examples

An example server and example client are bundled with the wolfJSSE provider. They are located in wolfssljni/examples/provider/ directory and are implemented in the files ClientJSSE.java and ServerJSSE.java. After compiling the library with “ant” they can be invoked by use of their corresponding .sh files. An example of this would be “./examples/provider/ClientJSSE.sh”. This .sh file sets up the pathing for the example to use the recently created wolfssl-jsse.jar. Both examples take a “-h” input to display a help message showing available options. An example of displaying the help message would be

./examples/provider/ClientJSSE.sh -h

Both ClientJSSE.java and ServerJSSE.java will choose ECC certs/keys over RSA ones from their default keystores if ECC has been enabled in native wolfSSL. For example, you can see that these two example connect with an ECDHE_ECDSA cipher suite by default when ECC is compiled at the native level:

$ ./examples/provider/ServerJSSE.sh 
Using SSLContext provider wolfJSSE
Started server at 127.0.1.1, port 11111

waiting for client connection...
SSL version is TLSv1.2
SSL cipher suite is TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
Client message : Too legit to quit


$ ./examples/provider/ClientJSSE.sh 
Using SSLContext provider wolfJSSE
SSL version is TLSv1.2
SSL cipher suite is TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
Server message : I hear you fa shizzle, from Java!

If you are connecting the native wolfSSL examples to one of these JSSE examples, you may need to explicitly set the CA file on the native wolfSSL examples in order to authenticate the JSSE example correctly.

For example, connecting the native wolfSSL client to ServerJSSE.java, you may need to start the native client with:

$ ./examples/client/client -A ./certs/ca-ecc-cert.pem

And, when connecting the ClientJSSE to the native wolfSSL example server, you may need to start the native example server with:

$ ./examples/server/server -A ./certs/client-ecc-cert.pem

Return to top of page


Support

For support and feature requests please contact the wolfSSL support team at support@wolfssl.com.

Return to top of page