diff --git a/wolfSSL-JNI/src/chapter01.md b/wolfSSL-JNI/src/chapter01.md
index 3bd4df1d..b6693b41 100644
--- a/wolfSSL-JNI/src/chapter01.md
+++ b/wolfSSL-JNI/src/chapter01.md
@@ -4,6 +4,6 @@ wolfSSL JNI/JSSE is a provider implementation of the Java Secure Socket Extensio
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 / wolfSSLProvider**”. wolfJSSE wraps the native wolfSSL SSL/TLS library. This interface gives Java applications access to all the benefits of using wolfSSL, including current SSL/TLS standards up to [TLS 1.3](https://www.wolfssl.com/tls13), [DTLS 1.3](https://www.wolfssl.com/wolfssl-java-jsse-provider-supports-dtls-1-3/), and [FIPS 140-2 and 140-3](https://www.wolfssl.com/license/fips/) support, performance optimizations, hardware cryptography support, [commercial support](https://www.wolfssl.com/products/support-and-maintenance/), and more!
+This document describes wolfSSL’s JSSE provider implementation, named “**wolfJSSE / wolfSSLProvider**”. wolfJSSE wraps the native wolfSSL SSL/TLS library. This interface gives Java applications access to all the benefits of using wolfSSL, including current SSL/TLS standards up to [TLS 1.3](https://www.wolfssl.com/tls13), [DTLS 1.3](https://www.wolfssl.com/wolfssl-java-jsse-provider-supports-dtls-1-3/), post-quantum ML-KEM key exchange and ML-DSA certificates, and [FIPS 140-2 and 140-3](https://www.wolfssl.com/license/fips/) support, performance optimizations, hardware cryptography support, [commercial support](https://www.wolfssl.com/products/support-and-maintenance/), and more!
wolfJSSE is distributed as part of the “ **wolfssljni** ”package.
diff --git a/wolfSSL-JNI/src/chapter02.md b/wolfSSL-JNI/src/chapter02.md
index 357b1b7c..8cbdb621 100644
--- a/wolfSSL-JNI/src/chapter02.md
+++ b/wolfSSL-JNI/src/chapter02.md
@@ -12,6 +12,7 @@ on the following:
+ Zulu JDK
+ Amazon Corretto
+ Eclipse Temurin
+ + Microsoft Build of OpenJDK
- Mac OSX
- Windows (Visual Studio)
- Android Studio
@@ -36,9 +37,9 @@ To install JUnit4 on a Unix/Linux/OSX system:
$ export JUNIT_HOME=/path/to/jar/files
```
-## System Dependencies (gcc and ant)
+## System Dependencies (make, gcc, and ant)
-**gcc** and **ant** are used to compile native C code and Java code, respectively. Please ensure that these are installed on your development machine. Alternatively, you can choose to compile with **maven** instead of **ant**.
+**gcc** and **ant** are used to compile native C code and Java code, respectively. The included `Makefile` drives both of these, so **make** is also required. Please ensure that these are installed on your development machine. Alternatively, you can choose to compile the Java code with **maven** instead of **ant**.
## wolfSSL SSL/TLS Library
@@ -75,3 +76,26 @@ If wolfSSL has been installed to a non-standard library installation location, y
```
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/wolfssl/install
```
+
+If building a wolfSSL FIPS or FIPS Ready release bundle, additional configure
+options may be required. Reference the wolfSSL Manual and FIPS build
+documentation for exact build instructions.
+
+### Optional Native wolfSSL Features
+
+Some wolfJSSE features depend on additional native wolfSSL configure options:
+
+| Feature | wolfSSL `./configure` Option |
+| --- | --- |
+| Pre-Shared Key (PSK) cipher suites | Enabled by `--enable-jni` |
+| Secure renegotiation | `--enable-secure-renegotiation` |
+| ML-KEM (FIPS 203) TLS 1.3 key exchange | `--enable-mlkem` |
+| ML-DSA (FIPS 204) certificates | `--enable-mldsa` |
+| Pure (non-hybrid) ML-KEM named groups | `--enable-tls-mlkem-standalone` |
+| Native debug logging | `--enable-debug` |
+
+For example, to build wolfSSL with post-quantum support for use with wolfJSSE:
+
+```
+$ ./configure --enable-jni --enable-mlkem --enable-mldsa
+```
diff --git a/wolfSSL-JNI/src/chapter03.md b/wolfSSL-JNI/src/chapter03.md
index d061c297..52518d53 100644
--- a/wolfSSL-JNI/src/chapter03.md
+++ b/wolfSSL-JNI/src/chapter03.md
@@ -1,29 +1,84 @@
# wolfSSL JNI and wolfJSSE Compilation
-There are three ways to compile wolfJSSE listed in this chapter, including
-using the Unix Command Line, Android Studio Build and Generic IDE Build.
+This chapter describes several ways to compile wolfJSSE, including using the
+Unix command line (make, ant, or Maven), Windows Visual Studio, Android Studio,
+and a generic IDE build.
## Unix Command Line
Before following steps in this section, please ensure that the dependencies
listed in Chapter 2 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 OSX.
-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`.
+### Building with make
+
+The `Makefile` in the root package directory compiles the native JNI C sources
+into a shared library (`./lib/libwolfssljni.so` or `./lib/libwolfssljni.dylib`)
+and then invokes `ant` to build the Java sources and JAR files. The Makefile
+auto-detects between OSX (Darwin) and Linux to set up include paths and the
+shared library extension type. It will also auto-detect `JAVA_HOME` if not
+already set. To explicitly specify a Java installation, set the `JAVA_HOME`
+environment variable before running `make`.
+
+To build and test wolfJSSE:
```
-$ ./java.sh
+$ cd wolfssljni
+$ export JUNIT_HOME=/path/to/junit/jars
+$ make
+$ make check
+```
+
+Available `make` targets are:
+
+- `make` / `make build` (compiles the native JNI library and Java sources/JARs)
+- `make check` (builds, then runs JUnit tests, requires `JUNIT_HOME`)
+- `make native` (compiles only the native JNI shared library)
+- `make clean` (cleans all Java and native artifacts)
+- `make clean-native` (cleans only native artifacts)
+- `make install` (installs the shared library and JAR files to `/usr/local/lib`,
+ or `$PREFIX/lib` if `PREFIX` is set)
+- `make uninstall` (removes installed files)
+
+If linking against a native wolfSSL library not installed to `/usr/local`, or
+a wolfSSL library with a custom name (for example when wolfSSL was compiled
+with `--with-libsuffix`), these can be passed to `make`:
+
+```
+$ make WOLFSSL_INSTALL_DIR=/path/to/wolfssl/install WOLFSSL_LIBNAME=wolfssljsse
+```
+
+Preset `CFLAGS` can be passed to `make`:
+
+```
+$ make CFLAGS="-DWOLFJNI_USE_IO_SELECT"
+```
-Compiling Native JNI library:
- WOLFSSL_INSTALL_DIR = /usr/local
- Detected Linux host OS
- Linux x86_64
- Java Home = /usr/lib/jvm/java-8-openjdk-amd64
- Generated ./lib/libwolfssljni.so
+On x86_64 and Aarch64 Linux hosts, `-fPIC` is automatically added to CFLAGS.
+
+Set `V=1` to see the full compiler commands:
+
+```
+$ make V=1
+```
+
+Set `ENABLE_PATCHES=1` to automatically detect and enable JNI code that depends
+on native wolfSSL pull request patches (`WOLFSSL_PR*_PATCH_APPLIED` defines).
+This requires a recent build of native wolfSSL that includes those patches,
+often newer than the latest tagged wolfSSL release.
+
+```
+$ make ENABLE_PATCHES=1
+```
+
+### java.sh Script
+
+The `java.sh` script in the root package directory is a convenience wrapper
+around the Makefile. It compiles only the native JNI shared library by running
+`make clean-native` followed by `make native`, doing a clean rebuild of the
+native library each time.
+
+```
+$ ./java.sh
```
If linking against a native wolfSSL library not installed to `/usr/local`, one
@@ -41,21 +96,16 @@ against. This is useful when wolfSSL was compiled with `--with-libsuffix`:
$ ./java.sh /usr/local wolfssljsse
```
-The script will attempt to auto-detect `JAVA_HOME` if not set. To explicitly
-specify a Java installation, set the `JAVA_HOME` environment variable before
-running.
-
-Preset `CFLAGS` can be passed to the script via the environment:
+`CFLAGS` can be set in the environment prior to running the script:
```
$ CFLAGS="-DWOLFJNI_USE_IO_SELECT" ./java.sh
```
-On x86_64 and Aarch64 Linux hosts, `-fPIC` is automatically added to CFLAGS.
-
## Building with ant
-To compile the Java sources, `ant` is used:
+The Java sources can also be compiled by calling `ant` directly, after the
+native JNI library has been compiled with `make native` or `java.sh`:
```
$ ant
@@ -69,31 +119,37 @@ Available build targets for `ant` are :
- `ant clean` (cleans all Java artifacts)
- `ant cleanjni` (cleans native artifacts)
-These two commands will build the wolfJSSE jar and native code necessary to use
-wolfJSSE in a project. To compile and run JUnit tests the command `ant test`
-is used:
+To compile and run JUnit tests the command `ant test` (or `make check`) is
+used:
```
$ ant test
```
-This will compile tests and the main wolfJSSE code and 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
+This will compile the tests and main wolfJSSE code, then run the wolfSSL JNI
+and wolfJSSE test suites. Results are grouped by test class, with each test
+method listed along with the time it took to run in milliseconds. Tests that
+are skipped, for example because a feature is not compiled into native wolfSSL,
+are labeled `SKIP` instead of showing a time. After each test suite finishes,
+a summary line shows the number of tests run, failures, errors, and skipped
+tests. A successful build will display the message “BUILD SUCCESSFUL” at the
+end.
+
+```
+ [junit] WolfSSLContext Class
+ [junit] 465.26 ms testInit
+ [junit] 577.66 ms testWolfJSSEEnabledCipherSuites
+ [junit] 1135.56 ms testJdkTlsDisabledAlgorithms
+ [junit] 218.36 ms testGetSessionContext
+ [junit] 0.21 ms testGetSSLContextFromProvider
+ [junit] 205.77 ms testGetDefaultSSLParameters
+ [junit] 78.93 ms testContextDefaultParamsExcludeAnon
+ [junit] 0.18 ms testGetSessionContextBeforeInit
+ [junit] 211.86 ms testGetSupportedSSLParameters
+ [junit] 3.70 ms testGetSocketFactory
...
-build:
-
BUILD SUCCESSFUL
-Total time: 18 seconds
```
To compile and run examples bundled with wolfJSSE the command `ant examples`
@@ -108,11 +164,11 @@ $ ant examples
wolfJSSE supports building and packaging with Maven for projects that consume
Maven packages.
-First, compile the native JNI shared library using `java.sh` as described above.
+First, compile the native JNI shared library as described above.
This creates the native library under `./lib`:
```
-$ ./java.sh
+$ make native
```
Compile the Java sources (output to `./target/classes`):
@@ -161,10 +217,61 @@ Applications can include wolfJSSE as a Maven dependency:
com.wolfssl
wolfssl-jsse
- 1.16.0-SNAPSHOT
+ 1.19.0-SNAPSHOT
```
+## Java Module System (JPMS) Build
+
+wolfSSL JNI/JSSE supports the Java Platform Module System (JPMS) introduced in
+Java 9. When built with Java 9 or later, the JAR produced is a modular JAR that
+works on both the classpath and module path. When built with Java 8,
+`module-info.java` is automatically excluded and a standard classpath JAR is
+produced.
+
+| JDK Used to Build | Resulting JAR |
+| --- | --- |
+| Java 8 | Standard JAR (classpath only) |
+| Java 9+ | Modular JAR (classpath and module path) |
+
+The modular JAR declares the module `com.wolfssl`, exports the `com.wolfssl`
+and `com.wolfssl.provider.jsse` packages, and registers `WolfSSLProvider` as a
+`java.security.Provider` service.
+
+To build a modular JAR, use a JDK 9 or newer when building with either ant or
+Maven. Maven uses a profile (`java9-module`) that activates automatically on
+Java 9+:
+
+```
+$ export JAVA_HOME=/path/to/jdk11
+$ make
+```
+
+Module support can be verified with `jar --describe-module`, which should
+print output similar to:
+
+```
+$ jar --describe-module --file=lib/wolfssl-jsse.jar
+com.wolfssl jar:file:///path/to/lib/wolfssl-jsse.jar!/module-info.class
+exports com.wolfssl
+exports com.wolfssl.provider.jsse
+requires java.logging
+uses java.security.Provider
+provides java.security.Provider with com.wolfssl.provider.jsse.WolfSSLProvider
+```
+
+The modular JAR can be used with `jlink` to create a custom Java runtime that
+includes wolfJSSE:
+
+```
+$ jlink \
+ --module-path lib/wolfssl-jsse.jar \
+ --add-modules com.wolfssl \
+ --output custom-runtime \
+ --no-header-files \
+ --no-man-pages
+```
+
## Windows Visual Studio Build
wolfJSSE can be compiled on Windows using Visual Studio. For detailed
@@ -176,8 +283,10 @@ An example Android Studio project is located in the directory `IDE/Android`.
This is an example Android Studio project file for wolfssljni / wolfJSSE.
This project should be used for reference only.
-More details on tool and version information used when testing can be found in
-the `wolfssljni/IDE/Android/README.md`. The following steps outline what is
+The example project uses Android Gradle Plugin 8.3.1 (Android Studio Iguana
+2023.2.1 or newer), Gradle 8.4, and JDK 17 or newer, with compileSdk/targetSdk
+33 and minSdk 24. More details on tool and version information can be found in
+`wolfssljni/IDE/Android/README.md`. The following steps outline what is
required to run this example on an Android device or emulator.
### 1. Add Native wolfSSL Library Source Code to Project
@@ -205,6 +314,8 @@ $ mv wolfssl-X.X.X wolfssljni/IDE/Android/app/src/main/cpp/wolfssl
```
$ cd /IDE/Android/app/src/main/cpp/
$ git clone https://github.com/wolfssl/wolfssl
+$ cd wolfssl
+$ ./autogen.sh
$ cp wolfssl/options.h.in wolfssl/options.h
```
@@ -267,15 +378,10 @@ after the starting Android Studio and compiling the project, but must be done
before running the app or test cases.
```
-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/
-adb push ./examples/certs/intermediate/* /sdcard/examples/certs/intermediate/
+adb shell mkdir -p /data/local/tmp/examples/provider
+adb shell mkdir -p /data/local/tmp/examples/certs/intermediate
+adb push ./examples/provider/*.bks /data/local/tmp/examples/provider/
+adb push ./examples/certs/ /data/local/tmp/examples/
```
### 5. Import and Build the Example Project with Android Studio
@@ -285,13 +391,25 @@ in wolfssljni/IDE/. Or, from inside Android Studio, open the `Android` project
located in the wolfssljni/IDE directory.
2) Build 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.
+This will print out the server certificate information on success.
-3) OPTIONAL: The androidTests can be run after permissions has been given.
+3) OPTIONAL: The androidTests can be run to verify functionality.
app->java->com.wolfssl->provider.jsse.test->WolfSSLJSSETestSuite and
app->java->com.wolfssl->test->WolfSSLTestSuite
+### Additional Android Build Notes
+
+The example project's `CMakeLists.txt` links native shared libraries with
+16 KB ELF segment alignment (`-Wl,-z,max-page-size=16384`), required for
+devices using 16 KB memory pages (Android 15+). NDK r28 and later do this by
+default, but older NDKs need it set explicitly. Applications integrating
+wolfSSL JNI/JSSE into their own Android build should do the same.
+
+The example project also enables Gradle dependency verification, using
+SHA-256 checksums stored in `gradle/verification-metadata.xml`. If dependency
+or plugin versions are changed, this file needs to be regenerated. See
+`IDE/Android/README.md` for instructions.
+
## Generic IDE Build
For generic IDE builds create a new project in the IDE, then add source files
diff --git a/wolfSSL-JNI/src/chapter04.md b/wolfSSL-JNI/src/chapter04.md
index 7c3cfb6d..4462f7c9 100644
--- a/wolfSSL-JNI/src/chapter04.md
+++ b/wolfSSL-JNI/src/chapter04.md
@@ -52,7 +52,7 @@ for (Provider prov:providers) {
wolfJSSE includes Java ServiceLoader support for compatibility with the Java
Module System (JPMS). This allows the wolfJSSE provider to be automatically
-discovered and loaded when the JAR is on the module path.
+discovered and loaded when the JAR is on the classpath or module path.
The wolfJSSE JAR contains a `META-INF/services/java.security.Provider` file
that registers `com.wolfssl.provider.jsse.WolfSSLProvider` for automatic
@@ -73,8 +73,15 @@ for (Provider provider : loader) {
}
```
-For modular applications, wolfJSSE can be used as an automatic module or
-included as a dependency in your `module-info.java`.
+When built with Java 9 or later, the wolfJSSE JAR is a modular JAR named
+`com.wolfssl` (see Chapter 3). Modular applications can depend on it from
+their own `module-info.java`:
+
+```
+module com.example.app {
+ requires com.wolfssl;
+}
+```
**Note:** ServiceLoader-based provider discovery relies on the
`META-INF/services` mechanism which is a JAR/module system feature. On Android,
diff --git a/wolfSSL-JNI/src/chapter05.md b/wolfSSL-JNI/src/chapter05.md
index 1bf10a53..d5a1e74c 100644
--- a/wolfSSL-JNI/src/chapter05.md
+++ b/wolfSSL-JNI/src/chapter05.md
@@ -11,22 +11,26 @@ wolfJSSE / wolfSSL JNI package structure:
wolfssljni/
build.xml ant build script
pom.xml Maven build configuration
+ ChangeLog.md Release notes
COPYING
docs/ Javadocs
examples/ Example apps
+ provider/ wolfJSSE provider examples
IDE/ IDE projects
Android/ Android Studio
WIN/ Windows Visual Studio
java.sh Script to build native C JNI sources
LICENSING
- Makefile
+ Makefile Builds native JNI library and invokes ant
lib/ Output directory for compiled library
native/ Native C JNI binding source files
platform/ Android AOSP build files
README.md
rpm/ rpm spec files
+ scripts/ Helper and CI check scripts
src/
java/ Java source files
+ java9/ module-info.java for Java 9+ (JPMS) builds
test/ Test source files
```
diff --git a/wolfSSL-JNI/src/chapter06.md b/wolfSSL-JNI/src/chapter06.md
index 0f4581e7..cc3b6503 100644
--- a/wolfSSL-JNI/src/chapter06.md
+++ b/wolfSSL-JNI/src/chapter06.md
@@ -24,6 +24,45 @@ wolfJSSE extends or implements the following JSSE classes:
DTLSv1.0 and DTLSv1.2 are available through the lower-level wolfSSL JNI API
but are not currently registered as JSSE SSLContext types.
+The wolfJSSE `TrustManagerFactory` can be initialized with a `KeyStore` or
+with `ManagerFactoryParameters`. Supported parameter types are
+`CertPathTrustManagerParameters` (trust anchors are taken from the wrapped
+`PKIXParameters`) and `KeyStoreBuilderParameters` (the first
+`KeyStore.Builder` is used).
+
+## Post-Quantum Cryptography
+
+wolfJSSE supports post-quantum TLS 1.3 key exchange using ML-KEM (FIPS 203)
+and post-quantum certificate authentication using ML-DSA (FIPS 204). Native
+wolfSSL must be compiled with `--enable-mlkem` and `--enable-mldsa` (see
+Chapter 2).
+
+Supported ML-KEM TLS 1.3 named groups include:
+
+| Group Type | Named Groups | Native wolfSSL Requirement |
+| --- | --- | --- |
+| PQ/T hybrid (IETF) | `X25519MLKEM768`, `SECP256R1MLKEM768`, `SECP384R1MLKEM1024` | `--enable-mlkem` |
+| Pure ML-KEM | `ML-KEM-512`, `ML-KEM-768`, `ML-KEM-1024` | `--enable-tls-mlkem-standalone` |
+| PQ/T hybrid (OQS, experimental) | `SECP256R1MLKEM512`, `SECP384R1MLKEM768`, `SECP521R1MLKEM1024`, `X25519MLKEM512`, `X448MLKEM768` | `--enable-experimental --enable-extra-pqc-hybrids` |
+
+Named groups can be configured with `SSLParameters.setNamedGroups()` (JDK 20+),
+the `jdk.tls.namedGroups` System property, or the
+`wolfjsse.enabledSupportedCurves` Security property. See Chapter 7 for details
+and precedence. wolfJSSE pre-generates the TLS 1.3 client key share for the
+first configured group, avoiding a HelloRetryRequest when the server supports
+that group.
+
+ML-DSA certificate authentication requires a native wolfSSL release newer than
+5.9.1. Loading ML-DSA private keys from a JKS KeyStore requires JDK 24 or newer
+(JEP 497).
+
+## Pre-Shared Key (PSK)
+
+wolfJSSE supports TLS Pre-Shared Key (PSK) cipher suites through both
+`SSLSocket` and `SSLEngine`. PSK callbacks and identity hints are configured
+using the wolfJSSE `WolfSSLParameters` class, which extends `SSLParameters`.
+See Chapter 7 for usage.
+
## Secure Renegotiation
wolfJSSE supports secure renegotiation when the underlying native wolfSSL
diff --git a/wolfSSL-JNI/src/chapter07.md b/wolfSSL-JNI/src/chapter07.md
index fb43f022..cae79691 100644
--- a/wolfSSL-JNI/src/chapter07.md
+++ b/wolfSSL-JNI/src/chapter07.md
@@ -26,7 +26,10 @@ The following standard Java Security properties are supported by wolfJSSE:
| `keystore.type` | JKS | Default KeyStore type |
| `jdk.tls.disabledAlgorithms` | | Disable algorithms, protocols, key lengths (partial support) |
-Example `jdk.tls.disabledAlgorithms` usage:
+wolfJSSE supports the following entries in `jdk.tls.disabledAlgorithms`:
+SSL/TLS protocol versions (ex: `TLSv1.1`) and minimum RSA, EC, and DH key
+sizes (ex: `RSA keySize < 2048`). The DH minimum is enforced against the
+Diffie-Hellman group negotiated during the handshake. Example usage:
```
jdk.tls.disabledAlgorithms=SSLv3, TLSv1.1, DH keySize < 1024, EC keySize < 224, RSA keySize < 1024
@@ -37,16 +40,17 @@ jdk.tls.disabledAlgorithms=SSLv3, TLSv1.1, DH keySize < 1024, EC keySize < 224,
The following Security properties are specific to wolfJSSE:
| Property | Default | Description |
-| --- | --- | --- |
+| ------------------------------------------------------------ | ---------- | ------------------------------ |
| `wolfjsse.enabledCipherSuites` | | Restrict enabled cipher suites |
-| `wolfjsse.enabledSupportedCurves` | | Restrict enabled ECC curves |
+| `wolfjsse.enabledSupportedCurves` | | Restrict enabled named groups (ECC curves and PQC/hybrid groups) |
| `wolfjsse.enabledSignatureAlgorithms` | | Restrict enabled signature algorithms |
| `wolfjsse.keystore.type.required` | | Require specific KeyStore type |
| `wolfjsse.clientSessionCache.disabled` | "false" | Disable client session cache |
| `wolfjsse.X509KeyManager.disableCache` | "false" | Disable X509KeyManager caching |
+| `wolfjsse.skipFIPSCAST` | "false" | Skip FIPS CASTs during wolfJSSE init |
| `wolfssl.readWriteByteBufferPool.disabled` | "false" | Disable direct ByteBuffer pool for read/write |
-| `wolfssl.readWriteByteBufferPool.size` | | Set max number of ByteBuffers in per-thread pool |
-| `wolfssl.readWriteByteBufferPool.bufferSize` | | Set size of individual ByteBuffers in pool |
+| `wolfssl.readWriteByteBufferPool.size` | 16 | Set max number of ByteBuffers in per-thread pool |
+| `wolfssl.readWriteByteBufferPool.bufferSize` | 17408 | Set size of individual ByteBuffers in pool |
Example cipher suite restriction:
@@ -54,29 +58,51 @@ Example cipher suite restriction:
wolfjsse.enabledCipherSuites=TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
```
-Example ECC curve restriction:
+Example named group restriction, using ECC curves or post-quantum and hybrid
+groups. Group names are matched case insensitively. Unknown groups and groups
+not supported by the native wolfSSL build are ignored. If no usable groups
+remain, connection establishment fails with an `SSLException`. See
+"Named Groups" below for precedence with other named group settings.
```
wolfjsse.enabledSupportedCurves=secp256r1, secp521r1
```
-Example signature algorithm restriction:
+Or, to restrict to post-quantum and hybrid groups:
+
+```
+wolfjsse.enabledSupportedCurves=X25519MLKEM768, SecP256r1MLKEM768, ML-KEM-768
+```
+
+Example signature algorithm restriction. Standalone scheme names such as
+`ED25519`, `ED448`, and `ML-DSA-44`/`ML-DSA-65`/`ML-DSA-87` are also accepted.
+Entries not supported by the native wolfSSL build are ignored. If no entry is
+supported, connection establishment fails with an `SSLException`. ML-DSA names
+additionally require a native wolfSSL release newer than 5.9.1 (see Chapter 6).
+On older releases they are skipped, so list a classical entry alongside them
+(for example, `ML-DSA-87:ECDSA+SHA384`).
```
wolfjsse.enabledSignatureAlgorithms=RSA+SHA256:ECDSA+SHA256
```
+When `wolfjsse.keystore.type.required` is set, wolfJSSE will not allow use of
+KeyStore instances of any other type. For example, this can be set to the
+wolfJCE "WKS" KeyStore type when using wolfCrypt FIPS 140-2/3, to help ensure
+only FIPS validated cryptography is used to load keys and certificates.
+
## System Properties
wolfJSSE supports both standard Java System properties and wolfJSSE-specific
-System properties.
+System properties. Since these are **System** properties and not **Security**
+properties, they will not be read from the `java.security` file.
### Standard Java System Properties
The following standard Java System properties are supported by wolfJSSE:
| Property | Description |
-| --- | --- |
+| ------------------------------------------------------------ | ---------------------------------------- |
| `javax.net.ssl.keyStore` | KeyStore file for KeyManager |
| `javax.net.ssl.keyStoreType` | KeyStore type for KeyManager |
| `javax.net.ssl.keyStorePassword` | KeyStore password for KeyManager |
@@ -84,20 +110,24 @@ The following standard Java System properties are supported by wolfJSSE:
| `javax.net.ssl.trustStoreType` | KeyStore type for TrustManager |
| `javax.net.ssl.trustStorePassword` | KeyStore password for TrustManager |
| `jdk.tls.client.enableSessionTicketExtension` | Enable client session tickets (Java 13+) |
-| `jdk.tls.server.enableSessionTicketExtension` | Enable server session tickets (Java 13+, client-side only currently) |
| `jdk.tls.client.SignatureSchemes` | Client signature algorithms (partial support) |
| `jdk.tls.server.SignatureSchemes` | Server signature algorithms (partial support) |
+| `jdk.tls.namedGroups` | Restrict enabled TLS named groups, client and server |
| `jdk.tls.useExtendedMasterSecret` | Enable/disable Extended Master Secret |
-| `jdk.tls.ephemeralDHKeySize` | Control ephemeral DH key size |
| `jdk.tls.trustNameService` | Enable reverse DNS lookup for hostname verification |
| `jsse.enableSNIExtension` | Enable/disable SNI extension (default: true) |
+Scheme names in `jdk.tls.client.SignatureSchemes` and
+`jdk.tls.server.SignatureSchemes` that are not recognized by wolfJSSE or not
+supported by native wolfSSL are ignored. If no configured scheme is supported,
+connection establishment fails with an `SSLException`.
+
### wolfJSSE-Specific System Properties
wolfJSSE supports several System properties:
| System Property | Default | To Enable | Description |
-| --- | --- | --- | --- |
+| ---------------------------------- | ------------ | ------------ | ------------------------------------------ |
| `wolfssl.debug` | "false" | "true" | Native wolfSSL debug logging |
| `wolfssljni.debug` | "false" | "true" | wolfJNI debug logging |
| `wolfjsse.debug` | "false" | "true" | wolfJSSE debug logging |
@@ -105,6 +135,7 @@ wolfJSSE supports several System properties:
| `wolfsslengine.debug` | "false" | "true" | SSLEngine debug logging |
| `wolfsslengine.io.debug` | "false" | "true" | SSLEngine I/O bytes logging |
| `wolfjsse.autoSNI` | "false" | "true" | Auto-set SNI from hostname |
+| `wolfssl.skipLibraryLoad` | "false" | "true" | Skip automatic native library loading |
## Debugging
@@ -144,10 +175,13 @@ wolfJSSE monitors native file descriptors for read/write events using either
By default, `poll()` is used unless:
- `WOLFJNI_USE_IO_SELECT` is defined when compiling the native JNI sources
+ (ex: `make CFLAGS=-DWOLFJNI_USE_IO_SELECT`)
- Running on Windows, which defaults to `select()`
The `poll()` function is preferred because `select()` has undefined behavior
-when file descriptor numbers exceed `FD_SETSIZE` (typically 1024).
+when file descriptor numbers exceed `FD_SETSIZE` (typically 1024). This limit
+does not apply to Windows, where `FD_SETSIZE` is the number of sockets an
+`fd_set` can hold rather than a limit on the socket value.
## ALPN Support
@@ -192,6 +226,125 @@ SSLEngine engine = ctx.createSSLEngine();
DTLS Connection ID (CID) is also supported through the native wolfSSL APIs
wrapped at the JNI level.
+## Named Groups
+
+TLS named groups (ECC curves and post-quantum ML-KEM/hybrid groups) can be
+restricted using one of three sources, listed from highest to lowest
+precedence. Only a single source is applied per session.
+
+1. `SSLParameters.setNamedGroups()` (JDK 20+)
+2. `jdk.tls.namedGroups` System property
+3. `wolfjsse.enabledSupportedCurves` Security property (JDK 8+)
+
+For example, to prefer the X25519MLKEM768 hybrid group with a classical
+fallback:
+
+```
+java -Djdk.tls.namedGroups=X25519MLKEM768,secp256r1 App
+```
+
+Or programmatically on JDK 20+:
+
+```java
+SSLParameters params = sslSocket.getSSLParameters();
+params.setNamedGroups(new String[] { "X25519MLKEM768", "secp256r1" });
+sslSocket.setSSLParameters(params);
+```
+
+Group names are matched case insensitively. Both compact (`MLKEM768`,
+`X25519MLKEM768`) and IETF (`ML-KEM-768`, `SecP256r1MLKEM768`) spellings are
+recognized for PQC and hybrid groups. Unknown groups and groups not supported
+by native wolfSSL are ignored. If no usable groups remain (for example all
+groups are PQC and TLS 1.3 is not enabled), connection establishment fails
+with an `SSLException`.
+
+## Pre-Shared Key (PSK) Usage
+
+PSK is configured on an `SSLSocket` or `SSLEngine` using `WolfSSLParameters`,
+a wolfJSSE subclass of `SSLParameters`, applied with the standard
+`setSSLParameters()` method. Since PSK does not use certificates, the
+`SSLContext` can be initialized without a KeyManager or TrustManager.
+
+Client side:
+
+```java
+import com.wolfssl.WolfSSLPskClientCallback;
+import com.wolfssl.provider.jsse.WolfSSLParameters;
+
+SSLContext ctx = SSLContext.getInstance("TLSv1.2", "wolfJSSE");
+ctx.init(null, null, null);
+
+SSLSocket sock = (SSLSocket)ctx.getSocketFactory().createSocket(host, port);
+
+WolfSSLParameters params = new WolfSSLParameters();
+params.setPskClientCb(new MyPskClientCallback());
+params.setCipherSuites(new String[] { "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256" });
+sock.setSSLParameters(params);
+sock.startHandshake();
+```
+
+On the server side, use `setPskServerCb()` with a `WolfSSLPskServerCallback`
+implementation, and optionally `setPskIdentityHint()` to send an identity hint
+to the client. PSK callback interfaces are the same ones used by the wolfSSL
+JNI `WolfSSLSession` API. See the PSK examples in Chapter 8 for complete client
+and server applications.
+
+## FIPS Usage with wolfJCE
+
+When wolfJSSE is used with wolfCrypt FIPS or FIPS Ready, wolfJSSE runs the
+wolfCrypt FIPS CASTs (Conditional Algorithm Self Tests) when it initializes.
+These run at most once per process.
+
+Applications that register both wolfJSSE (`WolfSSLProvider`) and wolfJCE
+(`WolfCryptProvider`) should avoid both providers running CASTs at the same
+time on different threads, which can cause `FIPS_NOT_ALLOWED_E` errors. The
+recommended order is:
+
+1. Run CASTs once with wolfJCE `Fips.runAllCast_fips()`
+2. Set the `wolfjsse.skipFIPSCAST` Security property to "true", either with
+ `Security.setProperty()` or in the `java.security` file
+3. Register both `WolfCryptProvider` and `WolfSSLProvider`
+
+```java
+import com.wolfssl.wolfcrypt.Fips;
+import com.wolfssl.provider.jce.WolfCryptProvider;
+import com.wolfssl.provider.jsse.WolfSSLProvider;
+
+if (Fips.runAllCast_fips() != 0) {
+ /* CAST failure, handle error */
+}
+Security.setProperty("wolfjsse.skipFIPSCAST", "true");
+
+Security.insertProviderAt(new WolfCryptProvider(), 1);
+Security.insertProviderAt(new WolfSSLProvider(), 2);
+```
+
+The `wolfjsse.skipFIPSCAST` property must be set before `WolfSSLProvider` is
+constructed. See the `DualProviderFIPSTest` example in Chapter 8.
+
+## Custom Native Library Loading
+
+By default, wolfSSL JNI loads the native wolfSSL and wolfSSL JNI shared
+libraries with `System.loadLibrary()`. Applications that need to load these
+libraries with their own logic, for example when extracting native libraries
+bundled inside a JAR at runtime, can set the `wolfssl.skipLibraryLoad` System
+property to "true". This must be set before `WolfSSL.loadLibrary()` is called,
+either directly or by the `WolfSSLProvider` constructor.
+
+```java
+System.setProperty("wolfssl.skipLibraryLoad", "true");
+
+/* Load native libraries with custom logic */
+System.load("/path/to/libwolfssl.so");
+System.load("/path/to/libwolfssljni.so");
+
+/* Then use wolfSSL as normal */
+WolfSSL.loadLibrary();
+```
+
+Applications can check if library loading was skipped with
+`WolfSSL.isLibraryLoadSkipped()`.
+
## Android Usage
### Application-Level
diff --git a/wolfSSL-JNI/src/chapter08.md b/wolfSSL-JNI/src/chapter08.md
index 875b0da3..de395bfc 100644
--- a/wolfSSL-JNI/src/chapter08.md
+++ b/wolfSSL-JNI/src/chapter08.md
@@ -56,9 +56,15 @@ wolfSSL JNI wrapper in a multi-threaded environment.
```
$ ./examples/SimpleThreadedServer.sh
-$ ./examples/SimpleThreadedClient.sh
+$ ./examples/SimpleThreadedClient.sh -n
```
+`SimpleThreadedServer` listens on `localhost:11111` and handles each client
+connection in a separate thread. `SimpleThreadedClient` makes concurrent
+connections to the server, 5 by default. It also implements a simple
+application-wide client session cache, storing native `WOLFSSL_SESSION`
+pointers and using them for session resumption where possible.
+
## X509v3CertificateGeneration.java
Example application demonstrating X.509v3 certificate generation using the
@@ -69,6 +75,8 @@ and sign X.509v3 certificates.
$ ./examples/X509v3CertificateGeneration.sh
```
+Generated certificates are written to `examples/certs/generated/`.
+
## X509CertRequest.java
Example application demonstrating X.509 Certificate Signing Request (CSR)
@@ -78,6 +86,8 @@ generation using the wolfSSL JNI `WolfSSLCertRequest` API.
$ ./examples/X509CertRequest.sh
```
+Generated CSRs are written to `examples/certs/generated/`.
+
# wolfJSSE Provider Examples
The `examples/provider` directory contains examples for the wolfSSL JSSE
@@ -110,6 +120,51 @@ $ ./examples/provider/ServerJSSE.sh
$ ./examples/provider/ClientJSSE.sh
```
+### Post-Quantum (ML-KEM, ML-DSA) with ServerJSSE and ClientJSSE
+
+`ServerJSSE` and `ClientJSSE` can be used to test post-quantum TLS 1.3
+connections when native wolfSSL has been compiled with `--enable-mlkem` and
+`--enable-mldsa`. All of the following require TLS 1.3 (`-v 4`).
+
+The `-pqc ` option selects a post-quantum or hybrid named group for key
+exchange. For example, to use the X25519MLKEM768 hybrid group with the default
+classical certificates:
+
+```
+$ ./examples/provider/ServerJSSE.sh -v 4 -pqc X25519MLKEM768
+$ ./examples/provider/ClientJSSE.sh -h 127.0.0.1 -v 4 -pqc X25519MLKEM768
+```
+
+See the Post-Quantum Cryptography section in Chapter 6 for the named groups
+accepted by `-pqc` and the native wolfSSL configure options each one requires.
+Use `./examples/provider/ServerJSSE.sh -?` for the full option list.
+
+ML-DSA certificates are loaded with the `-c` (entity cert/key) and `-A`
+(trusted CA) options. The following uses mutual ML-DSA-87 authentication with
+the SECP384R1MLKEM1024 hybrid group and AES-256-GCM, which matches the CNSA 2.0
+(NSA Commercial National Security Algorithm Suite 2.0) requirements:
+
+```
+$ ./examples/provider/ServerJSSE.sh -v 4 \
+ -pqc SECP384R1MLKEM1024 -l TLS_AES_256_GCM_SHA384 \
+ -c "../provider/server-mldsa87.jks:wolfSSL test" \
+ -A "../provider/ca-mldsa87.jks:wolfSSL test"
+$ ./examples/provider/ClientJSSE.sh -h 127.0.0.1 -v 4 \
+ -pqc SECP384R1MLKEM1024 -l TLS_AES_256_GCM_SHA384 \
+ -c "../provider/client-mldsa87.jks:wolfSSL test" \
+ -A "../provider/ca-mldsa87.jks:wolfSSL test"
+```
+
+For server-only ML-DSA authentication, omit `-A` on the server and `-c` on the
+client, so the client uses the default classical `client.jks`.
+
+Example ML-DSA keystores are located in `examples/provider/`:
+`server-mldsa{44,65,87}.jks`, `client-mldsa{44,65,87}.jks`, and
+`ca-mldsa{44,65,87}.jks` (password "wolfSSL test"). The keystore paths above
+are relative to the wrapper scripts' working directory (`examples/build/`).
+Loading ML-DSA private keys from a JKS requires JDK 24 or newer. Keystores can
+be regenerated with `./examples/provider/update-keystore-pqc.sh` (also JDK 24+).
+
## ClientSSLSocket.java
Very minimal JSSE client example using SSLSocket. Does not support all the
@@ -237,6 +292,61 @@ $ ./examples/provider/DtlsClientEngine.sh
The client connects to the server, sends a message, and receives the echoed response.
Both examples support various command-line options that can be viewed with the -? flag.
+## PSK Examples (SSLSocket and SSLEngine)
+
+Example client/server applications that demonstrate PSK (Pre-Shared Key)
+authentication using `WolfSSLParameters` with both `SSLSocket` and
+`SSLEngine`. PSK callbacks and cipher suites are configured through
+`WolfSSLParameters` and applied with `setSSLParameters()`.
+
+**PskServerSocket.java** - PSK server using SSLSocket \
+**PskClientSocket.java** - PSK client using SSLSocket \
+**PskServerEngine.java** - PSK server using SSLEngine \
+**PskClientEngine.java** - PSK client using SSLEngine
+
+SSLSocket examples:
+
+```
+$ ./examples/provider/PskServerSocket.sh
+$ ./examples/provider/PskClientSocket.sh
+```
+
+SSLEngine examples:
+
+```
+$ ./examples/provider/PskServerEngine.sh
+$ ./examples/provider/PskClientEngine.sh
+```
+
+Clients accept optional `[host] [port]` arguments and servers accept an
+optional `[port]` argument. The default host is `localhost` and the default
+port is `11111`.
+
+## DualProviderFIPSTest.java
+
+This example tests using both wolfJCE (`WolfCryptProvider`) and wolfJSSE
+(`WolfSSLProvider`) together with wolfCrypt FIPS or FIPS Ready. It follows the
+recommended workflow described in Chapter 7: running FIPS CASTs once through
+wolfJCE, setting the `wolfjsse.skipFIPSCAST` Security property, then
+registering both providers.
+
+This example is **not** compiled by `ant examples` because it depends on the
+wolfcrypt-jni (wolfJCE) JAR, which is not part of the wolfssljni package. It
+can be compiled and run manually:
+
+```
+$ cd
+$ javac -classpath \
+ lib/wolfssl.jar:lib/wolfssl-jsse.jar:/lib/wolfcrypt-jni.jar \
+ examples/provider/DualProviderFIPSTest.java
+$ WOLFCRYPTJNI_DIR= \
+ ./examples/provider/DualProviderFIPSTest.sh
+```
+
+The `WOLFCRYPTJNI_DIR` environment variable points to the wolfcrypt-jni build
+directory. If it is not set, it defaults to `../../wolfcryptjni`, relative to
+the wolfssljni root directory the script is run from.
+
## Java Remote Method Invocation (RMI) Example
Example client, server, and remote interface applications for Java Remote
@@ -248,7 +358,7 @@ Method Invocation implementation in wolfJSSE.
**RmiRemoteInterface.java** - Remote interface definition that both the server and client use.
-**RmiTLSClientSocketFactory.java** / **RmiTLSServerSocketFactory.java** - Custom TLS socket factory implementations for RMI, using wolfJSSE for the underlying SSL/TLS connections.
+**RmiTLSClientSocketFactory.java** / **RmiTLSServerSocketFactory.java** - Custom TLS socket factory implementations for RMI, using wolfJSSE for the underlying SSL/TLS connections. The server socket factory requires client certificate authentication, and the client socket factory enables HTTPS endpoint identification to verify the server certificate against the host it connects to.
Start the server and client:
```